aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2022-11-01 21:42:55 +0100
committerGitHub <noreply@github.com>2022-11-01 21:42:55 +0100
commita62ef88da1f0b069068f9218d9136001726b7007 (patch)
tree0c372c0aa4a889f136b7768820d176c976168f0a
parentb7f489b4215b922a40fa88417e1ed777a2690a49 (diff)
Try to use recursion map on pointers to prevent stackoverflow crashes (#160)
* use recursion map on pointers to prevent stack overflow crashes * improve odinfmt on if statements * Add support for matrix types * Add new config to disable the `core:odin/parser` errors * semantic token is now treating variable procedures and non-mutable the same
-rw-r--r--.gitignore1
-rwxr-xr-xbuild.sh2
-rw-r--r--editors/vscode/package.json2
-rw-r--r--editors/vscode/syntaxes/odin.tmLanguage.json6
-rw-r--r--ols.json9
-rw-r--r--src/common/ast.odin5
-rw-r--r--src/common/config.odin1
-rw-r--r--src/common/util_windows.odin15
-rw-r--r--src/main.odin11
-rw-r--r--src/odin/printer/document.odin93
-rw-r--r--src/odin/printer/printer.odin12
-rw-r--r--src/odin/printer/visit.odin49
-rw-r--r--src/server/analysis.odin454
-rw-r--r--src/server/collector.odin53
-rw-r--r--src/server/completion.odin59
-rw-r--r--src/server/definition.odin18
-rw-r--r--src/server/documents.odin2
-rw-r--r--src/server/hover.odin27
-rw-r--r--src/server/memory_index.odin2
-rw-r--r--src/server/references.odin9
-rw-r--r--src/server/requests.odin2
-rw-r--r--src/server/semantic_tokens.odin151
-rw-r--r--src/server/snippets.odin6
-rw-r--r--src/server/symbol.odin11
-rw-r--r--src/server/types.odin1
-rw-r--r--src/server/unmarshal.odin8
-rw-r--r--src/testing/testing.odin19
-rw-r--r--tests/completions_test.odin294
-rw-r--r--tests/hover_test.odin14
-rw-r--r--tests/signatures_test.odin51
-rw-r--r--tools/odinfmt/tests/.snapshots/if.odin25
-rw-r--r--tools/odinfmt/tests/if.odin19
32 files changed, 1000 insertions, 431 deletions
diff --git a/.gitignore b/.gitignore
index 2a136bc..fa9ecb8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,5 @@
*.exp
*.sqlite
*.suo
+*node_modules
diff --git a/build.sh b/build.sh
index 8103d00..4a20064 100755
--- a/build.sh
+++ b/build.sh
@@ -7,7 +7,7 @@ then
#BUG in odin test, it makes the executable with the same name as a folder and gets confused.
cd tests
- odin test ../tests -collection:shared=../src -opt:2
+ odin test ../tests -collection:shared=../src -o:speed
if ([ $? -ne 0 ])
then
diff --git a/editors/vscode/package.json b/editors/vscode/package.json
index a17b6a6..cf4fb6d 100644
--- a/editors/vscode/package.json
+++ b/editors/vscode/package.json
@@ -7,7 +7,7 @@
"type": "git",
"url": "git://github.com/DanielGavin/ols.git"
},
- "version": "0.1.4",
+ "version": "0.1.6",
"engines": {
"vscode": "^1.65.0"
},
diff --git a/editors/vscode/syntaxes/odin.tmLanguage.json b/editors/vscode/syntaxes/odin.tmLanguage.json
index d155e2d..90c5bd8 100644
--- a/editors/vscode/syntaxes/odin.tmLanguage.json
+++ b/editors/vscode/syntaxes/odin.tmLanguage.json
@@ -90,7 +90,7 @@
},
{
"name": "keyword.control.odin",
- "match": "\\b(if|else|or_else|when|for|in|defer|switch|return|or_return)\\b"
+ "match": "\\b(if|else|or_else|when|for|in|not_in|defer|switch|return|or_return)\\b"
},
{
"name": "keyword.control.odin",
@@ -126,7 +126,7 @@
},
{
"name": "storage.type.odin",
- "match": "\\b(struct|enum|union|map|set|bit_set|typeid)\\b"
+ "match": "\\b(struct|enum|union|map|set|bit_set|typeid|matrix)\\b"
},
{
"name": "keyword.function.odin",
@@ -267,7 +267,7 @@
},
{
"name": "support.type.odin",
- "match": "\\b((f16|f32|f64)|(complex32|complex64|complex128))\\b"
+ "match": "\\b((f16|f32|f64)|(complex32|complex64|complex128)|(quaternion64|quaternion128|quaternion256))\\b"
},
{
"name": "support.type.odin",
diff --git a/ols.json b/ols.json
index b56b6b1..5261a9c 100644
--- a/ols.json
+++ b/ols.json
@@ -1,16 +1,13 @@
{
"collections": [
{
- "name": "core",
- "path": "C:\\Users\\danie\\OneDrive\\Desktop\\Computer_Science\\Odin\\core"
- },
- {
"name": "shared",
"path": "src"
}
],
"enable_document_symbols": true,
"enable_semantic_tokens": true,
- "enable_hover": true,
- "enable_snippets": true
+ "enable_snippets": true,
+ "enable_references": true,
+ "verbose": false
}
diff --git a/src/common/ast.odin b/src/common/ast.odin
index 44bd643..732c736 100644
--- a/src/common/ast.odin
+++ b/src/common/ast.odin
@@ -8,6 +8,7 @@ import "core:strings"
import path "core:path/slashpath"
keyword_map: map[string]bool = {
+ "typeid" = true,
"int" = true,
"uint" = true,
"string" = true,
@@ -938,7 +939,7 @@ build_string_node :: proc(
}
}
case ^Typeid_Type:
- strings.write_string(builder, "$")
+ strings.write_string(builder, "typeid")
build_string(n.specialization, builder, remove_pointers)
case ^Helper_Type:
build_string(n.type, builder, remove_pointers)
@@ -1002,7 +1003,7 @@ repeat :: proc(
count: int,
allocator := context.allocator,
) -> string {
- if count == 0 {
+ if count <= 0 {
return ""
}
return strings.repeat(value, count, allocator)
diff --git a/src/common/config.odin b/src/common/config.odin
index 397545a..9c8e678 100644
--- a/src/common/config.odin
+++ b/src/common/config.odin
@@ -19,6 +19,7 @@ Config :: struct {
enable_rename: bool,
enable_std_references: bool,
enable_import_fixer: bool,
+ disable_parser_errors: bool,
thread_count: int,
file_log: bool,
odin_command: string,
diff --git a/src/common/util_windows.odin b/src/common/util_windows.odin
index a8c6243..691fcab 100644
--- a/src/common/util_windows.odin
+++ b/src/common/util_windows.odin
@@ -16,15 +16,7 @@ foreign import kernel32 "system:kernel32.lib"
@(default_calling_convention = "std")
foreign kernel32 {
@(link_name = "FormatMessageA")
- format_message_a :: proc(
- flags: u32,
- source: rawptr,
- message_id: u32,
- langauge_id: u32,
- buffer: cstring,
- size: u32,
- va: rawptr,
- ) -> u32 ---
+ format_message_a :: proc(flags: u32, source: rawptr, message_id: u32, langauge_id: u32, buffer: cstring, size: u32, va: rawptr) -> u32 ---
}
get_case_sensitive_path :: proc(
@@ -43,8 +35,9 @@ get_case_sensitive_path :: proc(
)
if (file == win32.INVALID_HANDLE) {
+ log.errorf("Failed on get_case_sensitive_path(%v)", path)
log_last_error()
- return ""
+ return path
}
buffer := make([]u16, 512, context.temp_allocator)
@@ -169,4 +162,4 @@ run_executable :: proc(
win32.CloseHandle(stdout_read)
return exit_code, true, stdout[0:index]
-} \ No newline at end of file
+}
diff --git a/src/main.odin b/src/main.odin
index 3842c58..7823828 100644
--- a/src/main.odin
+++ b/src/main.odin
@@ -95,13 +95,11 @@ run :: proc(reader: ^server.Reader, writer: ^server.Writer) {
end :: proc() {
}
-
main :: proc() {
reader := server.make_reader(os_read, cast(rawptr)&os.stdin)
writer := server.make_writer(os_write, cast(rawptr)&os.stdout)
-
/*
fh, err := os.open("log.txt", os.O_RDWR|os.O_CREATE)
@@ -116,14 +114,7 @@ main :: proc() {
set_stacktrace()
}
- when ODIN_OS == .Darwin {
- init_global_temporary_allocator(mem.Megabyte * 100)
- } else {
- init_global_temporary_allocator(mem.Megabyte * 100)
- //Gives weird allocation errors
- //growing_arena: common.Growing_Arena
- //context.temp_allocator = common.growing_arena_allocator(&growing_arena)
- }
+ init_global_temporary_allocator(mem.Megabyte * 100)
run(&reader, &writer)
diff --git a/src/odin/printer/document.odin b/src/odin/printer/document.odin
index 953a846..3dd9eda 100644
--- a/src/odin/printer/document.odin
+++ b/src/odin/printer/document.odin
@@ -10,9 +10,8 @@ Document :: union {
Document_Break,
Document_Group,
Document_Cons,
- Document_If_Break,
+ Document_If_Break_Or,
Document_Align,
- Document_Nest_If_Break,
Document_Break_Parent,
Document_Line_Suffix,
}
@@ -37,18 +36,15 @@ Document_Nest :: struct {
document: ^Document,
}
-Document_Nest_If_Break :: struct {
- document: ^Document,
- group_id: string,
-}
-
Document_Break :: struct {
value: string,
newline: bool,
}
-Document_If_Break :: struct {
- value: string,
+Document_If_Break_Or :: struct {
+ break_document: ^Document,
+ fit_document: ^Document,
+ group_id: string,
}
Document_Group :: struct {
@@ -127,12 +123,12 @@ nest_if_break :: proc(
group_id := "",
allocator := context.allocator,
) -> ^Document {
- document := new(Document, allocator)
- document^ = Document_Nest_If_Break {
- document = nested_document,
- group_id = group_id,
- }
- return document
+ return if_break_or_document(
+ nest(nested_document, allocator),
+ nested_document,
+ group_id,
+ allocator,
+ )
}
hang :: proc(
@@ -186,9 +182,39 @@ align :: proc(
}
if_break :: proc(value: string, allocator := context.allocator) -> ^Document {
+ return if_break_or_document(text(value, allocator), nil, "", allocator)
+}
+
+if_break_or :: proc {
+ if_break_or_string,
+ if_break_or_document,
+}
+
+if_break_or_string :: proc(
+ break_value: string,
+ fit_value: string,
+ group_id := "",
+ allocator := context.allocator,
+) -> ^Document {
+ return if_break_or_document(
+ text(break_value, allocator),
+ text(fit_value, allocator),
+ group_id,
+ allocator,
+ )
+}
+
+if_break_or_document :: proc(
+ break_document: ^Document,
+ fit_document: ^Document,
+ group_id := "",
+ allocator := context.allocator,
+) -> ^Document {
document := new(Document, allocator)
- document^ = Document_If_Break {
- value = value,
+ document^ = Document_If_Break_Or {
+ break_document = break_document,
+ fit_document = fit_document,
+ group_id = group_id,
}
return document
}
@@ -387,28 +413,24 @@ fits :: proc(width: int, list: ^[dynamic]Tuple) -> bool {
} else {
width -= len(v.value)
}
- case Document_If_Break:
- if data.mode == .Break {
- width -= len(v.value)
- }
- case Document_Nest_If_Break:
+ case Document_If_Break_Or:
if data.mode == .Break {
append(
list,
Tuple{
- indentation = data.indentation + 1,
+ indentation = data.indentation,
mode = data.mode,
- document = v.document,
+ document = v.break_document,
alignment = data.alignment,
},
)
- } else {
+ } else if v.fit_document != nil {
append(
list,
Tuple{
indentation = data.indentation,
mode = data.mode,
- document = v.document,
+ document = v.fit_document,
alignment = data.alignment,
},
)
@@ -560,30 +582,25 @@ format :: proc(
strings.write_string(builder, v.value)
consumed += len(v.value)
}
- case Document_If_Break:
- if data.mode == .Break {
- strings.write_string(builder, v.value)
- consumed += len(v.value)
- }
- case Document_Nest_If_Break:
+ case Document_If_Break_Or:
mode := v.group_id != "" ? p.group_modes[v.group_id] : data.mode
if mode == .Break {
append(
list,
Tuple{
- indentation = data.indentation + 1,
+ indentation = data.indentation,
mode = data.mode,
- document = v.document,
+ document = v.break_document,
alignment = data.alignment,
},
)
- } else {
+ } else if v.fit_document != nil {
append(
list,
Tuple{
indentation = data.indentation,
mode = data.mode,
- document = v.document,
+ document = v.fit_document,
alignment = data.alignment,
},
)
@@ -630,7 +647,9 @@ format :: proc(
alignment = data.alignment,
},
)
- } else if fits(width - consumed, &list_fits) && v.mode != .Break && v.mode != .Fit {
+ } else if fits(width - consumed, &list_fits) &&
+ v.mode != .Break &&
+ v.mode != .Fit {
append(
list,
Tuple{
diff --git a/src/odin/printer/printer.odin b/src/odin/printer/printer.odin
index dd724c9..d918cf2 100644
--- a/src/odin/printer/printer.odin
+++ b/src/odin/printer/printer.odin
@@ -31,10 +31,10 @@ Printer :: struct {
}
Disabled_Info :: struct {
- text: string,
- empty: bool,
+ text: string,
+ empty: bool,
start_line: int,
- end_line: int,
+ end_line: int,
}
Config :: struct {
@@ -137,9 +137,9 @@ build_disabled_lines_info :: proc(p: ^Printer) {
disabled_info := Disabled_Info {
start_line = disable_position.line,
- end_line = comment.pos.line,
- text = p.src[begin:end],
- empty = empty,
+ end_line = comment.pos.line,
+ text = p.src[begin:end],
+ empty = empty,
}
for line := disable_position.line;
diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin
index 70cc8dd..85ab6b7 100644
--- a/src/odin/printer/visit.odin
+++ b/src/odin/printer/visit.odin
@@ -984,35 +984,54 @@ visit_stmt :: proc(
)
}
- if_document := text("if")
+ begin_document := text("if")
+ end_document := empty()
if v.init != nil {
- if_document = cons_with_nopl(
- if_document,
- cons(group(visit_stmt(p, v.init)), text(";")),
+ begin_document = cons_with_nopl(
+ begin_document,
+ cons(
+ group(
+ visit_stmt(p, v.init),
+ Document_Group_Options{id = "init"},
+ ),
+ text(";"),
+ ),
)
}
if v.cond != nil && v.init != nil {
- if_document = cons(
- if_document,
+ end_document = cons(
group(cons(break_with_space(), group(visit_expr(p, v.cond)))),
)
} else if v.cond != nil {
- if_document = cons_with_nopl(
- if_document,
+ end_document = cons(
+ break_with_no_newline(),
group(visit_expr(p, v.cond)),
)
}
- if v.init != nil && is_value_decl_statement_ending_with_call(v.init) {
- document = cons(document, group(if_document))
- } else if v.cond != nil &&
- v.init == nil &&
- is_value_expression_call(v.cond) {
- document = cons(document, group(if_document))
+
+ if v.init != nil && is_value_decl_statement_ending_with_call(v.init) ||
+ v.cond != nil && v.init == nil && is_value_expression_call(v.cond) {
+ document = cons(
+ document,
+ group(
+ cons(
+ begin_document,
+ if_break_or(
+ end_document,
+ hang(3, end_document),
+ "init",
+ ),
+ ),
+ ),
+ )
} else {
- document = cons(document, group(hang(3, if_document)))
+ document = cons(
+ document,
+ group(hang(3, cons(begin_document, end_document))),
+ )
}
set_source_position(p, v.body.pos)
diff --git a/src/server/analysis.odin b/src/server/analysis.odin
index c7081c5..2eef852 100644
--- a/src/server/analysis.odin
+++ b/src/server/analysis.odin
@@ -70,28 +70,28 @@ DocumentLocal :: struct {
}
AstContext :: struct {
- locals: map[int]map[string][dynamic]DocumentLocal, //locals all the way to the document position
- globals: map[string]common.GlobalExpr,
- variables: map[string]bool,
- parameters: map[string]bool,
- in_package: map[string]string, //sometimes you have to extract types from arrays/maps and you lose package information
- usings: [dynamic]string,
- file: ast.File,
- allocator: mem.Allocator,
- imports: []Package, //imports for the current document
- current_package: string,
- document_package: string,
- use_globals: bool,
- use_locals: bool,
- local_id: int,
- call: ^ast.Call_Expr, //used to determene the types for generics and the correct function for overloaded functions
- position: common.AbsolutePosition,
- value_decl: ^ast.Value_Decl,
- field_name: ast.Ident,
- uri: string,
- fullpath: string,
- recursion_counter: int, //Sometimes the ast is so malformed that it causes infinite recursion.
- non_mutable_only: bool,
+ locals: map[int]map[string][dynamic]DocumentLocal, //locals all the way to the document position
+ globals: map[string]common.GlobalExpr,
+ variables: map[string]bool,
+ parameters: map[string]bool,
+ in_package: map[string]string, //sometimes you have to extract types from arrays/maps and you lose package information
+ recursion_map: map[rawptr]bool,
+ usings: [dynamic]string,
+ file: ast.File,
+ allocator: mem.Allocator,
+ imports: []Package, //imports for the current document
+ current_package: string,
+ document_package: string,
+ use_globals: bool,
+ use_locals: bool,
+ local_id: int,
+ call: ^ast.Call_Expr, //used to determene the types for generics and the correct function for overloaded functions
+ position: common.AbsolutePosition,
+ value_decl: ^ast.Value_Decl,
+ field_name: ast.Ident,
+ uri: string,
+ fullpath: string,
+ non_mutable_only: bool,
}
make_ast_context :: proc(
@@ -113,6 +113,7 @@ make_ast_context :: proc(
usings = make([dynamic]string, allocator),
parameters = make(map[string]bool, 0, allocator),
in_package = make(map[string]string, 0, allocator),
+ recursion_map = make(map[rawptr]bool, 0, allocator),
file = file,
imports = imports,
use_locals = true,
@@ -129,6 +130,12 @@ make_ast_context :: proc(
return ast_context
}
+reset_ast_context :: proc(ast_context: ^AstContext) {
+ ast_context.use_globals = true
+ ast_context.use_locals = true
+ clear(&ast_context.recursion_map)
+}
+
tokenizer_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) {
}
@@ -862,7 +869,7 @@ resolve_function_overload :: proc(
for arg_expr in group.args {
next_fn: if f, ok := resolve_type_expression(ast_context, arg_expr);
- ok {
+ ok {
if call_expr == nil || len(call_expr.args) == 0 {
append(&candidates, f)
break next_fn
@@ -1029,12 +1036,26 @@ resolve_basic_directive :: proc(
)
ident.name = "Source_Code_Location"
ast_context.current_package = ast_context.document_package
- return resolve_type_identifier(ast_context, ident^)
+ return internal_resolve_type_identifier(ast_context, ident^)
}
return {}, false
}
+check_node_recursion :: proc(
+ ast_context: ^AstContext,
+ node: ^ast.Node,
+) -> bool {
+ raw := cast(rawptr)node
+
+ if raw in ast_context.recursion_map {
+ return true
+ }
+
+ ast_context.recursion_map[raw] = true
+
+ return false
+}
resolve_type_expression :: proc(
ast_context: ^AstContext,
@@ -1043,6 +1064,17 @@ resolve_type_expression :: proc(
Symbol,
bool,
) {
+ clear(&ast_context.recursion_map)
+ return internal_resolve_type_expression(ast_context, node)
+}
+
+internal_resolve_type_expression :: proc(
+ ast_context: ^AstContext,
+ node: ^ast.Expr,
+) -> (
+ Symbol,
+ bool,
+) {
if node == nil {
return {}, false
}
@@ -1053,25 +1085,23 @@ resolve_type_expression :: proc(
ast_context.current_package = saved_package
}
- if ast_context.recursion_counter > 200 {
- log.error("Recursion passed 200 attempts - giving up", node)
+ if check_node_recursion(ast_context, node) {
+ //log.error("Recursion detected")
return {}, false
}
- ast_context.recursion_counter += 1
-
- defer {
- ast_context.recursion_counter -= 1
- }
-
using ast
#partial switch v in node.derived {
+ case ^ast.Typeid_Type:
+ ident := new_type(ast.Ident, v.pos, v.end, context.temp_allocator)
+ ident.name = "typeid"
+ return make_symbol_basic_type_from_ast(ast_context, ident), true
case ^ast.Value_Decl:
if v.type != nil {
- return resolve_type_expression(ast_context, v.type)
+ return internal_resolve_type_expression(ast_context, v.type)
} else if len(v.values) > 0 {
- return resolve_type_expression(ast_context, v.values[0])
+ return internal_resolve_type_expression(ast_context, v.values[0])
}
case ^Union_Type:
return make_symbol_union_from_ast(
@@ -1112,6 +1142,13 @@ resolve_type_expression :: proc(
ast_context.field_name,
),
true
+ case ^Matrix_Type:
+ return make_symbol_matrix_from_ast(
+ ast_context,
+ v^,
+ ast_context.field_name,
+ ),
+ true
case ^Dynamic_Array_Type:
return make_symbol_dynamic_array_from_ast(
ast_context,
@@ -1144,53 +1181,56 @@ resolve_type_expression :: proc(
case ^Basic_Directive:
return resolve_basic_directive(ast_context, v^)
case ^Binary_Expr:
- return resolve_first_symbol_from_binary_expression(ast_context, v)
+ return resolve_binary_expression(ast_context, v)
case ^Ident:
- return resolve_type_identifier(ast_context, v^)
+ delete_key(&ast_context.recursion_map, v)
+ return internal_resolve_type_identifier(ast_context, v^)
case ^Basic_Lit:
return resolve_basic_lit(ast_context, v^)
case ^Type_Cast:
- return resolve_type_expression(ast_context, v.type)
+ return internal_resolve_type_expression(ast_context, v.type)
case ^Auto_Cast:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Comp_Lit:
- return resolve_type_expression(ast_context, v.type)
+ return internal_resolve_type_expression(ast_context, v.type)
case ^Unary_Expr:
if v.op.kind == .And {
- symbol, ok := resolve_type_expression(ast_context, v.expr)
+ symbol, ok := internal_resolve_type_expression(ast_context, v.expr)
symbol.pointers += 1
return symbol, ok
} else {
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
}
case ^Deref_Expr:
- symbol, ok := resolve_type_expression(ast_context, v.expr)
+ symbol, ok := internal_resolve_type_expression(ast_context, v.expr)
symbol.pointers -= 1
return symbol, ok
case ^Paren_Expr:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Slice_Expr:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Tag_Expr:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Helper_Type:
- return resolve_type_expression(ast_context, v.type)
+ return internal_resolve_type_expression(ast_context, v.type)
case ^Ellipsis:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Implicit:
ident := new_type(Ident, v.node.pos, v.node.end, ast_context.allocator)
ident.name = v.tok.text
- return resolve_type_identifier(ast_context, ident^)
+ return internal_resolve_type_identifier(ast_context, ident^)
case ^Type_Assertion:
if unary, ok := v.type.derived.(^ast.Unary_Expr); ok {
if unary.op.kind == .Question {
- if symbol, ok := resolve_type_expression(ast_context, v.expr);
- ok {
+ if symbol, ok := internal_resolve_type_expression(
+ ast_context,
+ v.expr,
+ ); ok {
if union_value, ok := symbol.value.(SymbolUnionValue); ok {
if len(union_value.types) != 1 {
return {}, false
}
- return resolve_type_expression(
+ return internal_resolve_type_expression(
ast_context,
union_value.types[0],
)
@@ -1198,23 +1238,30 @@ resolve_type_expression :: proc(
}
}
} else {
- return resolve_type_expression(ast_context, v.type)
+ return internal_resolve_type_expression(ast_context, v.type)
}
case ^Proc_Lit:
if v.type.results != nil {
if len(v.type.results.list) == 1 {
- return resolve_type_expression(
+ return internal_resolve_type_expression(
ast_context,
v.type.results.list[0].type,
)
}
}
case ^Pointer_Type:
- symbol, ok := resolve_type_expression(ast_context, v.elem)
+ symbol, ok := internal_resolve_type_expression(ast_context, v.elem)
symbol.pointers += 1
return symbol, ok
+ case ^Matrix_Index_Expr:
+ if symbol, ok := internal_resolve_type_expression(ast_context, v.expr);
+ ok {
+ if mat, ok := symbol.value.(SymbolMatrixValue); ok {
+ return internal_resolve_type_expression(ast_context, mat.expr)
+ }
+ }
case ^Index_Expr:
- indexed, ok := resolve_type_expression(ast_context, v.expr)
+ indexed, ok := internal_resolve_type_expression(ast_context, v.expr)
if !ok {
return {}, false
@@ -1224,15 +1271,18 @@ resolve_type_expression :: proc(
#partial switch v2 in indexed.value {
case SymbolDynamicArrayValue:
- symbol, ok = resolve_type_expression(ast_context, v2.expr)
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
case SymbolSliceValue:
- symbol, ok = resolve_type_expression(ast_context, v2.expr)
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
case SymbolFixedArrayValue:
- symbol, ok = resolve_type_expression(ast_context, v2.expr)
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
case SymbolMapValue:
- symbol, ok = resolve_type_expression(ast_context, v2.value)
+ symbol, ok = internal_resolve_type_expression(
+ ast_context,
+ v2.value,
+ )
case SymbolMultiPointer:
- symbol, ok = resolve_type_expression(ast_context, v2.expr)
+ symbol, ok = internal_resolve_type_expression(ast_context, v2.expr)
}
symbol.type = indexed.type
@@ -1240,13 +1290,16 @@ resolve_type_expression :: proc(
return symbol, ok
case ^Call_Expr:
ast_context.call = cast(^Call_Expr)node
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Implicit_Selector_Expr:
return Symbol{}, false
case ^Selector_Call_Expr:
- return resolve_type_expression(ast_context, v.expr)
+ return internal_resolve_type_expression(ast_context, v.expr)
case ^Selector_Expr:
- if selector, ok := resolve_type_expression(ast_context, v.expr); ok {
+ if selector, ok := internal_resolve_type_expression(
+ ast_context,
+ v.expr,
+ ); ok {
ast_context.use_locals = false
#partial switch s in selector.value {
@@ -1276,7 +1329,10 @@ resolve_type_expression :: proc(
ast_context.current_package =
ast_context.document_package
}
- symbol, ok := resolve_type_expression(ast_context, s.expr)
+ symbol, ok := internal_resolve_type_expression(
+ ast_context,
+ s.expr,
+ )
symbol.type = .Variable
return symbol, ok
} else {
@@ -1303,7 +1359,10 @@ resolve_type_expression :: proc(
)
selector_expr.expr = s.return_types[0].type
selector_expr.field = v.field
- return resolve_type_expression(ast_context, selector_expr)
+ return internal_resolve_type_expression(
+ ast_context,
+ selector_expr,
+ )
}
case SymbolStructValue:
if selector.pkg != "" {
@@ -1315,7 +1374,7 @@ resolve_type_expression :: proc(
for name, i in s.names {
if v.field != nil && name == v.field.name {
ast_context.field_name = v.field^
- symbol, ok := resolve_type_expression(
+ symbol, ok := internal_resolve_type_expression(
ast_context,
s.types[i],
)
@@ -1341,7 +1400,7 @@ resolve_type_expression :: proc(
return Symbol{}, false
}
case:
- log.warnf("default node kind, resolve_type_expression: %T", v)
+ log.warnf("default node kind, internal_resolve_type_expression: %T", v)
if v == nil {
return {}, false
}
@@ -1474,10 +1533,20 @@ resolve_type_identifier :: proc(
Symbol,
bool,
) {
+ return internal_resolve_type_identifier(ast_context, node)
+}
+
+internal_resolve_type_identifier :: proc(
+ ast_context: ^AstContext,
+ node: ast.Ident,
+) -> (
+ Symbol,
+ bool,
+) {
using ast
- if ast_context.recursion_counter > 200 {
- log.error("Recursion passed 200 attempts - giving up", node)
+ if check_node_recursion(ast_context, node.derived.(^ast.Ident)) {
+ //log.error("Recursion detected")
return {}, false
}
@@ -1487,12 +1556,6 @@ resolve_type_identifier :: proc(
ast_context.current_package = saved_package
}
- ast_context.recursion_counter += 1
-
- defer {
- ast_context.recursion_counter -= 1
- }
-
if pkg, ok := ast_context.in_package[node.name]; ok {
ast_context.current_package = pkg
}
@@ -1561,7 +1624,10 @@ resolve_type_identifier :: proc(
#partial switch v in local.derived {
case ^Ident:
- return_symbol, ok = resolve_type_identifier(ast_context, v^)
+ return_symbol, ok = internal_resolve_type_identifier(
+ ast_context,
+ v^,
+ )
case ^Union_Type:
return_symbol, ok =
make_symbol_union_from_ast(ast_context, v^, node), true
@@ -1611,6 +1677,9 @@ resolve_type_identifier :: proc(
case ^Dynamic_Array_Type:
return_symbol, ok =
make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
+ case ^Matrix_Type:
+ return_symbol, ok =
+ make_symbol_matrix_from_ast(ast_context, v^, node), true
case ^Map_Type:
return_symbol, ok =
make_symbol_map_from_ast(ast_context, v^, node), true
@@ -1655,7 +1724,10 @@ resolve_type_identifier :: proc(
#partial switch v in global.expr.derived {
case ^Ident:
- return_symbol, ok = resolve_type_identifier(ast_context, v^)
+ return_symbol, ok = internal_resolve_type_identifier(
+ ast_context,
+ v^,
+ )
case ^Struct_Type:
return_symbol, ok =
make_symbol_struct_from_ast(ast_context, v^, node), true
@@ -1705,6 +1777,9 @@ resolve_type_identifier :: proc(
case ^Dynamic_Array_Type:
return_symbol, ok =
make_symbol_dynamic_array_from_ast(ast_context, v^, node), true
+ case ^Matrix_Type:
+ return_symbol, ok =
+ make_symbol_matrix_from_ast(ast_context, v^, node), true
case ^Map_Type:
return_symbol, ok =
make_symbol_map_from_ast(ast_context, v^, node), true
@@ -1713,7 +1788,7 @@ resolve_type_identifier :: proc(
return_symbol.name = node.name
return_symbol.type = global.mutable ? .Variable : .Constant
case:
- return_symbol, ok = resolve_type_expression(
+ return_symbol, ok = internal_resolve_type_expression(
ast_context,
global.expr,
)
@@ -2013,8 +2088,7 @@ resolve_location_selector :: proc(
Symbol,
bool,
) {
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
ast_context.current_package = ast_context.document_package
symbol, ok := resolve_type_expression(ast_context, selector.expr)
@@ -2059,10 +2133,7 @@ resolve_first_symbol_from_binary_expression :: proc(
Symbol,
bool,
) {
- //Fairly simple function to find the earliest identifier symbol in binary expression.
-
if binary.left != nil {
-
if ident, ok := binary.left.derived.(^ast.Ident); ok {
if s, ok := resolve_type_identifier(ast_context, ident^); ok {
return s, ok
@@ -2095,6 +2166,117 @@ resolve_first_symbol_from_binary_expression :: proc(
return {}, false
}
+resolve_binary_expression :: proc(
+ ast_context: ^AstContext,
+ binary: ^ast.Binary_Expr,
+) -> (
+ Symbol,
+ bool,
+) {
+ if binary.left == nil || binary.right == nil {
+ return {}, false
+ }
+
+ symbol_a, symbol_b: Symbol
+ ok_a, ok_b: bool
+
+ if expr, ok := binary.left.derived.(^ast.Binary_Expr); ok {
+ symbol_a, ok_a = resolve_binary_expression(ast_context, expr)
+ } else {
+ ast_context.use_locals = true
+ symbol_a, ok_a = resolve_type_expression(ast_context, binary.left)
+ }
+
+ if expr, ok := binary.right.derived.(^ast.Binary_Expr); ok {
+ symbol_b, ok_b = resolve_binary_expression(ast_context, expr)
+ } else {
+ ast_context.use_locals = true
+ symbol_b, ok_b = resolve_type_expression(ast_context, binary.right)
+ }
+
+ if !ok_a || !ok_b {
+ return {}, false
+ }
+
+ if symbol, ok := symbol_a.value.(SymbolProcedureValue);
+ ok && len(symbol.return_types) > 0 {
+ symbol_a, ok_a = resolve_type_expression(
+ ast_context,
+ symbol.return_types[0].type != nil \
+ ? symbol.return_types[0].type \
+ : symbol.return_types[0].default_value,
+ )
+ }
+
+ if symbol, ok := symbol_b.value.(SymbolProcedureValue);
+ ok && len(symbol.return_types) > 0 {
+ symbol_b, ok_b = resolve_type_expression(
+ ast_context,
+ symbol.return_types[0].type != nil \
+ ? symbol.return_types[0].type \
+ : symbol.return_types[0].default_value,
+ )
+ }
+
+ if !ok_a || !ok_b {
+ return {}, false
+ }
+
+
+ matrix_value_a, is_matrix_a := symbol_a.value.(SymbolMatrixValue)
+ matrix_value_b, is_matrix_b := symbol_b.value.(SymbolMatrixValue)
+
+ vector_value_a, is_vector_a := symbol_a.value.(SymbolFixedArrayValue)
+ vector_value_b, is_vector_b := symbol_b.value.(SymbolFixedArrayValue)
+
+ //Handle matrix multication specially because it can actual change the return type dimension
+ if is_matrix_a && is_matrix_b && binary.op.kind == .Mul {
+ symbol_a.value = SymbolMatrixValue {
+ expr = matrix_value_a.expr,
+ x = matrix_value_a.x,
+ y = matrix_value_b.y,
+ }
+ return symbol_a, true
+ } else if is_matrix_a && is_vector_b && binary.op.kind == .Mul {
+ symbol_a.value = SymbolFixedArrayValue {
+ expr = matrix_value_a.expr,
+ len = matrix_value_a.y,
+ }
+ return symbol_a, true
+
+ } else if is_vector_a && is_matrix_b && binary.op.kind == .Mul {
+ symbol_a.value = SymbolFixedArrayValue {
+ expr = matrix_value_b.expr,
+ len = matrix_value_b.x,
+ }
+ return symbol_a, true
+ } else if is_vector_a &&
+ !is_matrix_b &&
+ !is_vector_b &&
+ binary.op.kind == .Mul {
+ return symbol_a, true
+ } else if is_vector_b &&
+ !is_matrix_a &&
+ !is_vector_a &&
+ binary.op.kind == .Mul {
+ return symbol_b, true
+ } else if is_matrix_a &&
+ !is_matrix_b &&
+ !is_vector_b &&
+ binary.op.kind == .Mul {
+ return symbol_a, true
+ } else if is_matrix_b &&
+ !is_matrix_a &&
+ !is_vector_a &&
+ binary.op.kind == .Mul {
+ return symbol_b, true
+ }
+
+
+ //Otherwise just choose the first type, we do not handle error cases - that is done with the checker
+ return symbol_a, ok_a
+}
+
find_position_in_call_param :: proc(
ast_context: ^AstContext,
call: ast.Call_Expr,
@@ -2235,7 +2417,7 @@ make_symbol_array_from_ast :: proc(
) -> Symbol {
symbol := Symbol {
range = common.get_token_range(v.node, ast_context.file.src),
- type = .Variable,
+ type = .Constant,
pkg = get_package_from_node(v.node),
name = name.name,
}
@@ -2261,7 +2443,7 @@ make_symbol_dynamic_array_from_ast :: proc(
) -> Symbol {
symbol := Symbol {
range = common.get_token_range(v.node, ast_context.file.src),
- type = .Variable,
+ type = .Constant,
pkg = get_package_from_node(v.node),
name = name.name,
}
@@ -2273,6 +2455,28 @@ make_symbol_dynamic_array_from_ast :: proc(
return symbol
}
+make_symbol_matrix_from_ast :: proc(
+ ast_context: ^AstContext,
+ v: ast.Matrix_Type,
+ name: ast.Ident,
+) -> Symbol {
+ symbol := Symbol {
+ range = common.get_token_range(v.node, ast_context.file.src),
+ type = .Constant,
+ pkg = get_package_from_node(v.node),
+ name = name.name,
+ }
+
+ symbol.value = SymbolMatrixValue {
+ expr = v.elem,
+ x = v.row_count,
+ y = v.column_count,
+ }
+
+ return symbol
+}
+
+
make_symbol_multi_pointer_from_ast :: proc(
ast_context: ^AstContext,
v: ast.Multi_Pointer_Type,
@@ -2280,7 +2484,7 @@ make_symbol_multi_pointer_from_ast :: proc(
) -> Symbol {
symbol := Symbol {
range = common.get_token_range(v.node, ast_context.file.src),
- type = .Variable,
+ type = .Constant,
pkg = get_package_from_node(v.node),
name = name.name,
}
@@ -2299,7 +2503,7 @@ make_symbol_map_from_ast :: proc(
) -> Symbol {
symbol := Symbol {
range = common.get_token_range(v.node, ast_context.file.src),
- type = .Variable,
+ type = .Constant,
pkg = get_package_from_node(v.node),
name = name.name,
}
@@ -2314,8 +2518,7 @@ make_symbol_map_from_ast :: proc(
make_symbol_basic_type_from_ast :: proc(
ast_context: ^AstContext,
- n: ^ast.Node,
- v: ^ast.Ident,
+ n: ^ast.Ident,
) -> Symbol {
symbol := Symbol {
range = common.get_token_range(n^, ast_context.file.src),
@@ -2324,7 +2527,7 @@ make_symbol_basic_type_from_ast :: proc(
}
symbol.value = SymbolBasicValue {
- ident = v,
+ ident = n,
}
return symbol
@@ -2657,8 +2860,7 @@ get_generic_assignment :: proc(
) {
using ast
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
#partial switch v in value.derived {
case ^Or_Return_Expr:
@@ -2788,8 +2990,7 @@ get_locals_stmt :: proc(
document_position: ^DocumentPositionContext,
save_assign := false,
) {
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
ast_context.current_package = ast_context.document_package
using ast
@@ -3420,8 +3621,8 @@ resolve_entire_decl :: proc(
}
data := cast(^Visit_Data)visitor.data
ast_context := data.ast_context
- ast_context.use_locals = true
- ast_context.use_globals = true
+
+ reset_ast_context(ast_context)
data.last_visit = node
@@ -3509,7 +3710,7 @@ resolve_entire_decl :: proc(
}
case ^ast.Selector_Expr:
if symbol, ok := resolve_type_expression(ast_context, &v.node);
- ok {
+ ok {
data.symbols[cast(uintptr)node] = SymbolAndNode {
node = v,
symbol = symbol,
@@ -3522,7 +3723,7 @@ resolve_entire_decl :: proc(
}
case ^ast.Call_Expr:
if symbol, ok := resolve_type_expression(ast_context, &v.node);
- ok {
+ ok {
data.symbols[cast(uintptr)node] = SymbolAndNode {
node = v,
symbol = symbol,
@@ -3549,7 +3750,7 @@ resolve_entire_decl :: proc(
)
if symbol, ok := resolve_location_selector(ast_context, v);
- ok {
+ ok {
data.symbols[cast(uintptr)node] = SymbolAndNode {
node = v.field,
symbol = symbol,
@@ -3593,7 +3794,7 @@ resolve_entire_decl :: proc(
}
if symbol, ok := resolve_location_identifier(ast_context, v^);
- ok {
+ ok {
data.symbols[cast(uintptr)node] = SymbolAndNode {
node = v,
symbol = symbol,
@@ -3777,9 +3978,20 @@ get_signature :: proc(
is_variable := symbol.type == .Variable
+
+ pointer_prefix := common.repeat(
+ "^",
+ symbol.pointers,
+ context.temp_allocator,
+ )
+
+
#partial switch v in symbol.value {
case SymbolBasicValue:
- return common.node_to_string(v.ident)
+ return strings.concatenate(
+ {pointer_prefix, common.node_to_string(v.ident)},
+ ast_context.allocator,
+ )
case SymbolBitSetValue:
return common.node_to_string(v.expr)
case SymbolEnumValue:
@@ -3791,6 +4003,7 @@ get_signature :: proc(
case SymbolMapValue:
return strings.concatenate(
a = {
+ pointer_prefix,
"map[",
common.node_to_string(v.key),
"]",
@@ -3802,34 +4015,41 @@ get_signature :: proc(
return "proc"
case SymbolStructValue:
if is_variable {
- return symbol.name
+ return strings.concatenate(
+ {pointer_prefix, symbol.name},
+ ast_context.allocator,
+ )
} else {
return "struct"
}
case SymbolUnionValue:
if is_variable {
- return symbol.name
+ return strings.concatenate(
+ {pointer_prefix, symbol.name},
+ ast_context.allocator,
+ )
} else {
return "union"
}
case SymbolMultiPointer:
return strings.concatenate(
- a = {"[^]", common.node_to_string(v.expr)},
+ a = {pointer_prefix, "[^]", common.node_to_string(v.expr)},
allocator = ast_context.allocator,
)
case SymbolDynamicArrayValue:
return strings.concatenate(
- a = {"[dynamic]", common.node_to_string(v.expr)},
+ a = {pointer_prefix, "[dynamic]", common.node_to_string(v.expr)},
allocator = ast_context.allocator,
)
case SymbolSliceValue:
return strings.concatenate(
- a = {"[]", common.node_to_string(v.expr)},
+ a = {pointer_prefix, "[]", common.node_to_string(v.expr)},
allocator = ast_context.allocator,
)
case SymbolFixedArrayValue:
return strings.concatenate(
a = {
+ pointer_prefix,
"[",
common.node_to_string(v.len),
"]",
@@ -3837,6 +4057,20 @@ get_signature :: proc(
},
allocator = ast_context.allocator,
)
+ case SymbolMatrixValue:
+ return strings.concatenate(
+ a = {
+ pointer_prefix,
+ "matrix",
+ "[",
+ common.node_to_string(v.x),
+ ",",
+ common.node_to_string(v.y),
+ "]",
+ common.node_to_string(v.expr),
+ },
+ allocator = ast_context.allocator,
+ )
case SymbolPackageValue:
return "package"
case SymbolUntypedValue:
@@ -4489,6 +4723,14 @@ get_document_position_node :: proc(
}
case ^Undef:
case ^Basic_Lit:
+ case ^Matrix_Index_Expr:
+ get_document_position(n.expr, position_context)
+ get_document_position(n.row_index, position_context)
+ get_document_position(n.column_index, position_context)
+ case ^Matrix_Type:
+ get_document_position(n.row_count, position_context)
+ get_document_position(n.column_count, position_context)
+ get_document_position(n.elem, position_context)
case ^Ellipsis:
get_document_position(n.expr, position_context)
case ^Proc_Lit:
diff --git a/src/server/collector.odin b/src/server/collector.odin
index 11b6b89..b065a9e 100644
--- a/src/server/collector.odin
+++ b/src/server/collector.odin
@@ -320,6 +320,36 @@ collect_dynamic_array :: proc(
return SymbolDynamicArrayValue{expr = elem}
}
+collect_matrix :: proc(
+ collection: ^SymbolCollection,
+ mat: ast.Matrix_Type,
+ package_map: map[string]string,
+) -> SymbolMatrixValue {
+ elem := clone_type(
+ mat.elem,
+ collection.allocator,
+ &collection.unique_strings,
+ )
+
+ y := clone_type(
+ mat.column_count,
+ collection.allocator,
+ &collection.unique_strings,
+ )
+
+ x := clone_type(
+ mat.row_count,
+ collection.allocator,
+ &collection.unique_strings,
+ )
+
+ replace_package_alias(elem, package_map, collection)
+ replace_package_alias(x, package_map, collection)
+ replace_package_alias(y, package_map, collection)
+
+ return SymbolMatrixValue{expr = elem, x = x, y = y}
+}
+
collect_multi_pointer :: proc(
collection: ^SymbolCollection,
array: ast.Multi_Pointer_Type,
@@ -336,6 +366,7 @@ collect_multi_pointer :: proc(
return SymbolMultiPointer{expr = elem}
}
+
collect_generic :: proc(
collection: ^SymbolCollection,
expr: ^ast.Expr,
@@ -410,6 +441,10 @@ collect_symbols :: proc(
}
#partial switch v in col_expr.derived {
+ case ^ast.Matrix_Type:
+ token = v^
+ token_type = .Variable
+ symbol.value = collect_matrix(collection, v^, package_map)
case ^ast.Proc_Lit:
token = v^
token_type = .Function
@@ -492,6 +527,15 @@ collect_symbols :: proc(
token = v^
token_type = .Variable
symbol.value = collect_multi_pointer(collection, v^, package_map)
+ case ^ast.Typeid_Type:
+ if v.specialization == nil {
+ continue
+ }
+
+ ident := new_type(ast.Ident, v.pos, v.end, context.temp_allocator)
+ ident.name = "typeid"
+
+ symbol.value = collect_generic(collection, ident, package_map, uri)
case ^ast.Basic_Lit:
token = v^
symbol.value = collect_generic(
@@ -500,11 +544,6 @@ collect_symbols :: proc(
package_map,
uri,
)
- if expr.mutable {
- token_type = .Variable
- } else {
- token_type = .Constant
- }
case ^ast.Ident:
token = v^
symbol.value = collect_generic(
@@ -513,6 +552,7 @@ collect_symbols :: proc(
package_map,
uri,
)
+
if expr.mutable {
token_type = .Variable
} else {
@@ -526,14 +566,17 @@ collect_symbols :: proc(
package_map,
uri,
)
+
if expr.mutable {
token_type = .Variable
} else {
token_type = .Unresolved
}
+
token = expr.expr
}
+
symbol.range = common.get_token_range(expr.name_expr, file.src)
symbol.name = get_index_unique_string(collection, name)
symbol.type = token_type
diff --git a/src/server/completion.odin b/src/server/completion.odin
index bb29bfb..59e762c 100644
--- a/src/server/completion.odin
+++ b/src/server/completion.odin
@@ -101,10 +101,15 @@ get_completion_list :: proc(
completion_type = .Package
}
- if position_context.switch_type_stmt != nil &&
- position_context.case_clause != nil &&
- position_context.switch_type_stmt.pos.offset >
- position_context.switch_stmt.pos.offset {
+ done: if position_context.switch_type_stmt != nil &&
+ position_context.case_clause != nil {
+
+ if position_context.switch_stmt != nil &&
+ position_context.switch_type_stmt.pos.offset <=
+ position_context.switch_stmt.pos.offset {
+ break done
+ }
+
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
@@ -270,8 +275,7 @@ get_selector_completion :: proc(
selector: Symbol
ok: bool
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
selector, ok = resolve_type_expression(
ast_context,
@@ -443,9 +447,13 @@ get_selector_completion :: proc(
documentation = symbol.doc,
}
+ //Might be a hack...
+ _, is_selector := type.derived.(^ast.Selector_Expr)
+
if symbol.pkg == ast_context.document_package ||
base == "runtime" ||
- base == "$builtin" {
+ base == "$builtin" ||
+ is_selector {
item.label = fmt.aprintf(
"(%v%v)",
common.repeat(
@@ -495,7 +503,7 @@ get_selector_completion :: proc(
}
if symbol, ok := resolve_type_expression(ast_context, v.types[i]);
- ok {
+ ok {
if expr, ok := position_context.selector.derived.(^ast.Selector_Expr);
ok {
if expr.op.text == "->" && symbol.type != .Function {
@@ -604,8 +612,7 @@ get_implicit_completion :: proc(
selector: Symbol
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
if selector.pkg != "" {
ast_context.current_package = selector.pkg
@@ -819,7 +826,7 @@ get_implicit_completion :: proc(
}
}
} else if s, ok := unwrap_bitset(ast_context, comp_symbol);
- ok {
+ ok {
for enum_name in s.names {
item := CompletionItem {
label = enum_name,
@@ -844,15 +851,15 @@ get_implicit_completion :: proc(
enum_node: ^ast.Expr
if position_in_node(
- position_context.binary.right,
- position_context.position,
- ) {
+ 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,
- ) {
+ position_context.binary.left,
+ position_context.position,
+ ) {
context_node = position_context.binary.left
enum_node = position_context.binary.right
}
@@ -886,7 +893,7 @@ get_implicit_completion :: proc(
} else {
//procedures are the only types that can return more than one value
if symbol, ok := resolve_type_expression(ast_context, elem);
- ok {
+ ok {
if procedure, ok := symbol.value.(SymbolProcedureValue);
ok {
if procedure.return_types == nil {
@@ -972,7 +979,7 @@ get_implicit_completion :: proc(
call^,
)
if symbol, ok := resolve_type_expression(ast_context, call.expr);
- ok && parameter_ok {
+ ok && parameter_ok {
if proc_value, ok := symbol.value.(SymbolProcedureValue); ok {
if len(proc_value.arg_types) <= parameter_index {
return
@@ -1080,8 +1087,7 @@ get_identifier_completion :: proc(
}
}
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
ast_context.current_package = ast_context.document_package
ident := new_type(
@@ -1126,8 +1132,8 @@ get_identifier_completion :: proc(
k,
)
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
+
ast_context.current_package = ast_context.document_package
ident := new_type(
@@ -1144,7 +1150,7 @@ get_identifier_completion :: proc(
build_procedure_symbol_signature(&symbol)
if score, ok := common.fuzzy_match(matcher, ident.name);
- ok == 1 {
+ ok == 1 {
append(
&combined,
CombinedResult{
@@ -1438,8 +1444,7 @@ get_type_switch_completion :: proc(
}
}
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
if assign, ok := position_context.switch_type_stmt.tag.derived.(^ast.Assign_Stmt);
ok && assign.rhs != nil && len(assign.rhs) == 1 {
@@ -1589,8 +1594,6 @@ append_magic_map_completion :: proc(
append(items, item)
}
-
-
}
append_magic_dynamic_array_completion :: proc(
diff --git a/src/server/definition.odin b/src/server/definition.odin
index 309cde1..fbea155 100644
--- a/src/server/definition.odin
+++ b/src/server/definition.odin
@@ -67,9 +67,9 @@ get_definition_location :: proc(
if position_in_node(base, position_context.position) {
if resolved, ok := resolve_location_identifier(
- &ast_context,
- ident^,
- ); ok {
+ &ast_context,
+ ident^,
+ ); ok {
location.range = resolved.range
if resolved.uri == "" {
@@ -88,17 +88,17 @@ get_definition_location :: proc(
}
if resolved, ok := resolve_location_selector(
- &ast_context,
- position_context.selector_expr,
- ); ok {
+ &ast_context,
+ position_context.selector_expr,
+ ); ok {
location.range = resolved.range
uri = resolved.uri
}
} else if position_context.identifier != nil {
if resolved, ok := resolve_location_identifier(
- &ast_context,
- position_context.identifier.derived.(^ast.Ident)^,
- ); ok {
+ &ast_context,
+ position_context.identifier.derived.(^ast.Ident)^,
+ ); ok {
location.range = resolved.range
uri = resolved.uri
} else {
diff --git a/src/server/documents.odin b/src/server/documents.odin
index 5adfdfb..7f99e52 100644
--- a/src/server/documents.odin
+++ b/src/server/documents.odin
@@ -331,7 +331,7 @@ document_refresh :: proc(
return .ParseError
}
- if writer != nil && len(errors) > 0 {
+ if writer != nil && len(errors) > 0 && !config.disable_parser_errors {
document.diagnosed_errors = true
params := NotificationPublishDiagnosticsParams {
diff --git a/src/server/hover.odin b/src/server/hover.odin
index 0b1661b..602258d 100644
--- a/src/server/hover.odin
+++ b/src/server/hover.odin
@@ -139,8 +139,9 @@ get_hover_information :: proc(
position_context.identifier^,
ast_context.file.src,
)
- ast_context.use_locals = true
- ast_context.use_globals = true
+
+ reset_ast_context(&ast_context)
+
ast_context.current_package = ast_context.document_package
//if the base selector is the client wants to go to.
@@ -150,9 +151,9 @@ get_hover_information :: proc(
if position_in_node(base, position_context.position) {
if resolved, ok := resolve_type_identifier(
- &ast_context,
- ident,
- ); ok {
+ &ast_context,
+ ident,
+ ); ok {
resolved.signature = get_signature(
&ast_context,
ident,
@@ -199,9 +200,9 @@ get_hover_information :: proc(
for name, i in v.names {
if name == field {
if symbol, ok := resolve_type_expression(
- &ast_context,
- v.types[i],
- ); ok {
+ &ast_context,
+ v.types[i],
+ ); ok {
symbol.name = name //TODO refractor - never set symbol name after creation - change writer_hover_content
symbol.pkg = selector.name
symbol.signature = common.node_to_string(v.types[i])
@@ -218,9 +219,9 @@ get_hover_information :: proc(
if ident, ok := position_context.field.derived.(^ast.Ident);
ok {
if symbol, ok := resolve_type_identifier(
- &ast_context,
- ident^,
- ); ok {
+ &ast_context,
+ ident^,
+ ); ok {
hover.contents = write_hover_content(
&ast_context,
symbol,
@@ -231,8 +232,8 @@ get_hover_information :: proc(
}
}
} else if position_context.identifier != nil {
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(&ast_context)
+
ast_context.current_package = ast_context.document_package
ident := position_context.identifier.derived.(^ast.Ident)^
diff --git a/src/server/memory_index.odin b/src/server/memory_index.odin
index f609ca2..a211b94 100644
--- a/src/server/memory_index.odin
+++ b/src/server/memory_index.odin
@@ -65,7 +65,7 @@ memory_index_fuzzy_search :: proc(
if pkg, ok := index.collection.packages[pkg]; ok {
for _, symbol in pkg {
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/references.odin b/src/server/references.odin
index d7ffb9e..de5b3cb 100644
--- a/src/server/references.odin
+++ b/src/server/references.odin
@@ -75,8 +75,7 @@ resolve_references :: proc(
walk_directories,
)
- ast_context.use_locals = true
- ast_context.use_globals = true
+ reset_ast_context(ast_context)
if position_context.struct_type != nil &&
position_in_struct_names(
@@ -92,9 +91,9 @@ resolve_references :: proc(
return {}, true
} else if position_context.selector_expr != nil {
if resolved, ok := resolve_type_expression(
- ast_context,
- position_context.selector,
- ); ok {
+ ast_context,
+ position_context.selector,
+ ); ok {
if _, is_package := resolved.value.(SymbolPackageValue);
!is_package {
return {}, true
diff --git a/src/server/requests.odin b/src/server/requests.odin
index 586a2a1..96df6e3 100644
--- a/src/server/requests.odin
+++ b/src/server/requests.odin
@@ -429,6 +429,8 @@ request_initialize :: proc(
if unmarshal(value, ols_config, context.temp_allocator) ==
nil {
+ config.disable_parser_errors =
+ ols_config.disable_parser_errors
config.thread_count = ols_config.thread_pool_count
config.enable_document_symbols =
ols_config.enable_document_symbols.(bool) or_else true
diff --git a/src/server/semantic_tokens.odin b/src/server/semantic_tokens.odin
index b22d53f..f2ca16f 100644
--- a/src/server/semantic_tokens.odin
+++ b/src/server/semantic_tokens.odin
@@ -32,11 +32,12 @@ SemanticTokenTypes :: enum {
Method,
}
-SemanticTokenModifiers :: enum (u32) {
+SemanticTokenModifiers :: enum (u8) {
None = 0,
- Declaration = 2,
- Definition = 4,
- Deprecated = 8,
+ Declaration = 1,
+ Definition = 2,
+ Deprecated = 4,
+ ReadOnly = 8,
}
SemanticTokensClientCapabilities :: struct {
@@ -84,7 +85,7 @@ SemanticTokenBuilder :: struct {
make_token_builder :: proc(
allocator := context.temp_allocator,
) -> SemanticTokenBuilder {
- return {tokens = make([dynamic]u32, 1000, context.temp_allocator)}
+ return {tokens = make([dynamic]u32, 10000, context.temp_allocator)}
}
get_tokens :: proc(builder: SemanticTokenBuilder) -> SemanticTokens {
@@ -259,19 +260,39 @@ visit_node :: proc(
)
visit(n.expr, builder, ast_context)
case ^Ident:
+ modifier: SemanticTokenModifiers
+
if symbol_and_node, ok := builder.symbols[cast(uintptr)node]; ok {
- if symbol_and_node.symbol.type == .Variable ||
+ if symbol_and_node.symbol.type == .Constant ||
+ symbol_and_node.symbol.type != .Variable {
+ //modifier = .ReadOnly
+ }
+
+ if .Distinct in symbol_and_node.symbol.flags &&
symbol_and_node.symbol.type == .Constant {
write_semantic_node(
builder,
node,
ast_context.file.src,
- .Variable,
+ .Type,
.None,
)
return
}
+ _, is_proc := symbol_and_node.symbol.value.(SymbolProcedureValue)
+
+ if symbol_and_node.symbol.type == .Variable && !is_proc {
+ write_semantic_node(
+ builder,
+ node,
+ ast_context.file.src,
+ .Variable,
+ modifier,
+ )
+ return
+ }
+
#partial switch v in symbol_and_node.symbol.value {
case SymbolPackageValue:
write_semantic_node(
@@ -287,7 +308,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Struct,
- .None,
+ modifier,
)
case SymbolEnumValue:
write_semantic_node(
@@ -295,7 +316,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Enum,
- .None,
+ modifier,
)
case SymbolUnionValue:
write_semantic_node(
@@ -303,7 +324,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Enum,
- .None,
+ modifier,
)
case SymbolProcedureValue:
write_semantic_node(
@@ -311,7 +332,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Function,
- .None,
+ modifier,
)
case SymbolProcedureGroupValue:
write_semantic_node(
@@ -319,7 +340,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Function,
- .None,
+ modifier,
)
case SymbolUntypedValue:
write_semantic_node(
@@ -327,7 +348,7 @@ visit_node :: proc(
node,
ast_context.file.src,
.Type,
- .None,
+ modifier,
)
case SymbolBasicValue:
write_semantic_node(
@@ -335,7 +356,15 @@ visit_node :: proc(
node,
ast_context.file.src,
.Type,
- .None,
+ modifier,
+ )
+ case SymbolMatrixValue:
+ write_semantic_node(
+ builder,
+ node,
+ ast_context.file.src,
+ .Type,
+ modifier,
)
case:
//log.errorf("Unexpected symbol value: %v", symbol.value);
@@ -373,6 +402,22 @@ visit_node :: proc(
visit(n.stmts, builder, ast_context)
case ^Expr_Stmt:
visit(n.expr, builder, ast_context)
+ case ^Matrix_Type:
+ write_semantic_string(
+ builder,
+ n.tok_pos,
+ "matrix",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit(n.row_count, builder, ast_context)
+ visit(n.column_count, builder, ast_context)
+ visit(n.elem, builder, ast_context)
+ case ^ast.Matrix_Index_Expr:
+ visit(n.expr, builder, ast_context)
+ visit(n.row_index, builder, ast_context)
+ visit(n.column_index, builder, ast_context)
case ^Branch_Stmt:
write_semantic_token(
builder,
@@ -702,6 +747,48 @@ visit_node :: proc(
visit(n.cond, builder, ast_context)
visit(n.x, builder, ast_context)
visit(n.y, builder, ast_context)
+ case ^Union_Type:
+ write_semantic_string(
+ builder,
+ n.pos,
+ "union",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit(n.variants, builder, ast_context)
+ case ^ast.Enum_Type:
+ write_semantic_string(
+ builder,
+ n.pos,
+ "enum",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit_enum_fields(n^, builder, ast_context)
+ case ^Proc_Type:
+ write_semantic_string(
+ builder,
+ n.pos,
+ "proc",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit_proc_type(n, builder, ast_context)
+ case ^Proc_Lit:
+ write_semantic_string(
+ builder,
+ n.pos,
+ "proc",
+ ast_context.file.src,
+ .Keyword,
+ .None,
+ )
+ visit_proc_type(n.type, builder, ast_context)
+
+ visit(n.body, builder, ast_context)
case:
//log.errorf("unhandled semantic token node %v", n);
//panic(fmt.tprintf("Missed semantic token handling %v", n));
@@ -778,15 +865,7 @@ visit_value_decl :: proc(
.Enum,
.None,
)
- write_semantic_string(
- builder,
- v.pos,
- "union",
- ast_context.file.src,
- .Keyword,
- .None,
- )
- visit(v.variants, builder, ast_context)
+ visit(value_decl.values[0], builder, ast_context)
case ^Struct_Type:
write_semantic_node(
builder,
@@ -795,15 +874,7 @@ visit_value_decl :: proc(
.Struct,
.None,
)
- write_semantic_string(
- builder,
- v.pos,
- "struct",
- ast_context.file.src,
- .Keyword,
- .None,
- )
- visit_struct_fields(v^, builder, ast_context)
+ visit(value_decl.values[0], builder, ast_context)
case ^Enum_Type:
write_semantic_node(
builder,
@@ -812,15 +883,7 @@ visit_value_decl :: proc(
.Enum,
.None,
)
- write_semantic_string(
- builder,
- v.pos,
- "enum",
- ast_context.file.src,
- .Keyword,
- .None,
- )
- visit_enum_fields(v^, builder, ast_context)
+ visit(value_decl.values[0], builder, ast_context)
case ^Proc_Group:
write_semantic_node(
builder,
@@ -856,6 +919,8 @@ visit_value_decl :: proc(
.Function,
.None,
)
+ visit(value_decl.values[0], builder, ast_context)
+ case ^ast.Proc_Type:
write_semantic_string(
builder,
v.pos,
@@ -864,9 +929,7 @@ visit_value_decl :: proc(
.Keyword,
.None,
)
- visit_proc_type(v.type, builder, ast_context)
-
- visit(v.body, builder, ast_context)
+ visit_proc_type(v, builder, ast_context)
case:
for name in value_decl.names {
write_semantic_node(
diff --git a/src/server/snippets.odin b/src/server/snippets.odin
index c6a93aa..cd790a9 100644
--- a/src/server/snippets.odin
+++ b/src/server/snippets.odin
@@ -17,7 +17,11 @@ snippets: map[string]Snippet_Info = {
packages = []string{"fmt"},
detail = "println",
},
- "if" = {insert = "if ${1} {\n\t${0}\n}", packages = {}, detail = "if statement"},
+ "if" = {
+ insert = "if ${1} {\n\t${0}\n}",
+ packages = {},
+ detail = "if statement",
+ },
"forr" = {
insert = "for ${2:elem} in ${1:range} {\n\t${0}\n}",
packages = {},
diff --git a/src/server/symbol.odin b/src/server/symbol.odin
index 0c6a4dc..215e01c 100644
--- a/src/server/symbol.odin
+++ b/src/server/symbol.odin
@@ -89,6 +89,12 @@ SymbolMapValue :: struct {
value: ^ast.Expr,
}
+SymbolMatrixValue :: struct {
+ x: ^ast.Expr,
+ y: ^ast.Expr,
+ expr: ^ast.Expr,
+}
+
/*
Generic symbol that is used by the indexer for any variable type(constants, defined global variables, etc),
*/
@@ -113,6 +119,7 @@ SymbolValue :: union {
SymbolSliceValue,
SymbolBasicValue,
SymbolUntypedValue,
+ SymbolMatrixValue,
}
SymbolFlag :: enum {
@@ -178,6 +185,10 @@ free_symbol :: proc(symbol: Symbol, allocator: mem.Allocator) {
}
switch v in symbol.value {
+ case SymbolMatrixValue:
+ common.free_ast(v.expr, allocator)
+ common.free_ast(v.x, allocator)
+ common.free_ast(v.y, allocator)
case SymbolMultiPointer:
common.free_ast(v.expr, allocator)
case SymbolProcedureValue:
diff --git a/src/server/types.odin b/src/server/types.odin
index 7e034bc..cbb168f 100644
--- a/src/server/types.odin
+++ b/src/server/types.odin
@@ -327,6 +327,7 @@ OlsConfig :: struct {
enable_snippets: bool,
enable_inlay_hints: bool,
enable_references: bool,
+ disable_parser_errors: bool,
verbose: bool,
file_log: bool,
odin_command: string,
diff --git a/src/server/unmarshal.odin b/src/server/unmarshal.odin
index bda15a7..7f520fc 100644
--- a/src/server/unmarshal.odin
+++ b/src/server/unmarshal.odin
@@ -41,10 +41,10 @@ unmarshal :: proc(
//TEMP most likely have to rewrite the entire unmarshal using tags instead, because i sometimes have to support names like 'context', which can't be written like that
if field[len(field) - 1] == '_' {
if ret := unmarshal(
- j[field[:len(field) - 1]],
- a,
- allocator,
- ); ret != nil {
+ j[field[:len(field) - 1]],
+ a,
+ allocator,
+ ); ret != nil {
return ret
}
} else {
diff --git a/src/testing/testing.odin b/src/testing/testing.odin
index 65694e6..0d97870 100644
--- a/src/testing/testing.odin
+++ b/src/testing/testing.odin
@@ -58,9 +58,9 @@ setup :: proc(src: ^Source) {
} else if current == '\n' {
current_line += 1
current_character = 0
- } else if current == '*' {
+ } else if src.main[current_index:current_index + 3] == "{*}" {
dst_slice := transmute([]u8)src.main[current_index:]
- src_slice := transmute([]u8)src.main[current_index + 1:]
+ src_slice := transmute([]u8)src.main[current_index + 3:]
copy(dst_slice, src_slice)
src.position.character = current_character
src.position.line = current_line
@@ -92,9 +92,9 @@ setup :: proc(src: ^Source) {
fullpath := uri.path
p := parser.Parser {
- //err = parser.default_error_handler,
- err = server.log_error_handler,
- warn = server.log_warning_handler,
+ err = parser.default_error_handler,
+ warn = parser.default_error_handler,
+ flags = {.Optional_Semicolons},
}
dir := filepath.base(filepath.dir(fullpath, context.temp_allocator))
@@ -122,11 +122,10 @@ setup :: proc(src: ^Source) {
}
if ret := server.collect_symbols(
- &server.indexer.index.collection,
- file,
- uri.uri,
- );
- ret != .None {
+ &server.indexer.index.collection,
+ file,
+ uri.uri,
+ ); ret != .None {
return
}
}
diff --git a/tests/completions_test.odin b/tests/completions_test.odin
index 930ede3..21b89a2 100644
--- a/tests/completions_test.odin
+++ b/tests/completions_test.odin
@@ -18,7 +18,7 @@ ast_simple_struct_completion :: proc(t: ^testing.T) {
main :: proc() {
my_struct: My_Struct;
- my_struct.*
+ my_struct.{*}
}
`,
packages = {},
@@ -45,7 +45,7 @@ ast_index_array_completion :: proc(t: ^testing.T) {
main :: proc() {
my_struct: [] My_Struct;
- my_struct[2].*
+ my_struct[2].{*}
}
`,
packages = {},
@@ -72,7 +72,7 @@ ast_struct_pointer_completion :: proc(t: ^testing.T) {
main :: proc() {
my_struct: ^My_Struct;
- my_struct.*
+ my_struct.{*}
}
`,
packages = {},
@@ -100,7 +100,7 @@ ast_struct_take_address_completion :: proc(t: ^testing.T) {
main :: proc() {
my_struct: My_Struct;
my_pointer := &my_struct;
- my_pointer.*
+ my_pointer.{*}
}
`,
packages = {},
@@ -128,7 +128,7 @@ ast_struct_deref_completion :: proc(t: ^testing.T) {
main :: proc() {
my_struct: ^^My_Struct;
my_deref := my_struct^;
- my_deref.*
+ my_deref.{*}
}
`,
packages = {},
@@ -157,7 +157,7 @@ ast_range_map :: proc(t: ^testing.T) {
my_map: map[int]My_Struct;
for key, value in my_map {
- value.*
+ value.{*}
}
}
@@ -188,7 +188,7 @@ ast_range_array :: proc(t: ^testing.T) {
my_array: []My_Struct;
for value in my_array {
- value.*
+ value.{*}
}
}
@@ -224,7 +224,7 @@ ast_completion_identifier_proc_group :: proc(t: ^testing.T) {
};
main :: proc() {
- grou*
+ grou{*}
}
`,
packages = {},
@@ -250,7 +250,7 @@ ast_completion_in_comp_lit_type :: proc(t: ^testing.T) {
}
main :: proc() {
- my_comp := My_* {
+ my_comp := My_{*} {
};
}
`,
@@ -274,7 +274,7 @@ ast_completion_range_struct_selector_strings :: proc(t: ^testing.T) {
my_struct: My_Struct;
for value in my_struct.array {
- val*
+ val{*}
}
}
`,
@@ -286,7 +286,6 @@ ast_completion_range_struct_selector_strings :: proc(t: ^testing.T) {
@(test)
ast_completion_selector_on_indexed_array :: proc(t: ^testing.T) {
-
source := test.Source {
main = `package test
@@ -302,7 +301,7 @@ ast_completion_selector_on_indexed_array :: proc(t: ^testing.T) {
main :: proc() {
my_struct: My_Struct;
- my_struct.array[len(my_struct.array)-1].*
+ my_struct.array[len(my_struct.array)-1].{*}
}
`,
packages = {},
@@ -341,7 +340,7 @@ index_package_completion :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
- my_package.*
+ my_package.{*}
}
`,
packages = packages[:],
@@ -378,7 +377,7 @@ ast_generic_make_slice :: proc(t: ^testing.T) {
main :: proc() {
my_slice := make_slice([]My_Struct, 23);
- my_slic*
+ my_slic{*}
}
`,
packages = {},
@@ -407,7 +406,7 @@ ast_named_procedure_1 :: proc(t: ^testing.T) {
main :: proc() {
my_bool := my_group(b = false, a = 2);
- my_boo*
+ my_boo{*}
}
`,
packages = {},
@@ -430,7 +429,7 @@ ast_named_procedure_2 :: proc(t: ^testing.T) {
main :: proc() {
my_bool := my_group(b = false);
- my_boo*
+ my_boo{*}
}
`,
packages = {},
@@ -445,7 +444,7 @@ ast_swizzle_completion :: proc(t: ^testing.T) {
main = `package test
main :: proc() {
my_array: [4] f32;
- my_array.*
+ my_array.{*}
}
`,
packages = {},
@@ -474,7 +473,7 @@ ast_swizzle_completion_one_component :: proc(t: ^testing.T) {
main = `package test
main :: proc() {
my_array: [4] f32;
- my_array.x*
+ my_array.x{*}
}
`,
packages = {},
@@ -494,7 +493,7 @@ ast_swizzle_completion_few_components :: proc(t: ^testing.T) {
main = `package test
main :: proc() {
my_array: [2] f32;
- my_array.x*
+ my_array.x{*}
}
`,
packages = {},
@@ -516,7 +515,7 @@ ast_swizzle_resolve_one_components :: proc(t: ^testing.T) {
main :: proc() {
my_array: [4]f32;
my_swizzle := my_array.x;
- my_swizz*
+ my_swizz{*}
}
`,
packages = {},
@@ -532,7 +531,7 @@ ast_swizzle_resolve_two_components :: proc(t: ^testing.T) {
main :: proc() {
my_array: [4]f32;
my_swizzle := my_array.xx;
- my_swizz*
+ my_swizz{*}
}
`,
packages = {},
@@ -551,7 +550,7 @@ ast_swizzle_resolve_one_component_struct_completion :: proc(t: ^testing.T) {
};
main :: proc() {
my_array: [4] My_Struct;
- my_array.x.*
+ my_array.x.{*}
}
`,
packages = {},
@@ -581,7 +580,7 @@ ast_for_in_identifier_completion :: proc(t: ^testing.T) {
for my_element in my_array {
- my_elem*
+ my_elem{*}
}
}
@@ -610,7 +609,7 @@ ast_completion_poly_struct_proc :: proc(t: ^testing.T) {
}
execute_lighting_pass2 :: proc(pass : RenderPass(LightingAccumPass2)) {
- pass.*
+ pass.{*}
}
`,
packages = {},
@@ -649,7 +648,7 @@ ast_generic_make_completion :: proc(t: ^testing.T) {
main :: proc() {
allocator: Allocator;
my_array := make([dynamic]My_Struct, 343);
- my_array[2].*
+ my_array[2].{*}
}
`,
packages = {},
@@ -689,7 +688,7 @@ ast_generic_make_completion_2 :: proc(t: ^testing.T) {
main :: proc() {
allocator: Allocator;
my_array := make([]My_Struct, 343);
- my_array[2].*
+ my_array[2].{*}
}
`,
packages = {},
@@ -718,7 +717,7 @@ ast_struct_for_in_switch_stmt_completion :: proc(t: ^testing.T) {
switch (message) {
case win32.WM_SIZE:
for w in platform_context.windows {
- w.*
+ w.{*}
}
}
}
@@ -745,7 +744,7 @@ ast_overload_with_autocast_completion :: proc(t: ^testing.T) {
main :: proc() {
my_uint: uint = 0;
my_value := my_group(my_uint);
- my_val*
+ my_val{*}
}
`,
packages = {},
@@ -772,7 +771,7 @@ ast_overload_with_any_int_completion :: proc(t: ^testing.T) {
main :: proc() {
my_uint: uint = 0;
my_value := my_group(my_uint);
- my_val*
+ my_val{*}
}
`,
packages = {},
@@ -798,7 +797,7 @@ ast_overload_with_any_int_with_poly_completion :: proc(t: ^testing.T) {
main :: proc() {
my_uint: uint = 0;
my_value := my_group([dynamic]f32, my_uint);
- my_val*
+ my_val{*}
}
`,
packages = {},
@@ -821,7 +820,7 @@ ast_completion_in_between_struct :: proc(t: ^testing.T) {
current_token: ^Format_Token,
previous_token: ^Format_Token,
line: ^Unwrapped_Line,
- a*
+ a{*}
indent: int,
width: int,
penalty: f32,
@@ -864,7 +863,7 @@ ast_overload_with_any_int_index_completion :: proc(t: ^testing.T) {
main :: proc() {
my_uint: uint = 0;
my_value := my_package.my_group([dynamic]f32, my_uint);
- my_val*
+ my_val{*}
}
`,
packages = packages[:],
@@ -900,7 +899,7 @@ ast_package_procedure_completion :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
- my_package.*
+ my_package.{*}
}
`,
packages = packages[:],
@@ -928,7 +927,7 @@ ast_poly_with_comp_lit_empty_completion :: proc(t: ^testing.T) {
main :: proc() {
t := new_type(My_Struct, {}, {})
- t.*
+ t.{*}
}
`,
packages = {},
@@ -946,7 +945,7 @@ ast_global_struct_completion :: proc(t: ^testing.T) {
Foo :: struct { x: int }
foo := Foo{}
main :: proc() {
- x := foo.*
+ x := foo.{*}
}
`,
packages = {},
@@ -962,7 +961,7 @@ ast_global_non_mutable_completion :: proc(t: ^testing.T) {
Foo :: struct { x: int }
main :: proc() {
- x := Foo.*
+ x := Foo.{*}
}
`,
packages = {},
@@ -978,7 +977,7 @@ ast_basic_value_untyped_completion :: proc(t: ^testing.T) {
main :: proc() {
xaa := 2
- xa*
+ xa{*}
}
`,
packages = {},
@@ -995,7 +994,7 @@ ast_basic_value_binary_completion :: proc(t: ^testing.T) {
main :: proc() {
xaa := 2
xb2 := xaa - 2
- xb*
+ xb{*}
}
`,
packages = {},
@@ -1024,7 +1023,7 @@ ast_file_private_completion :: proc(t: ^testing.T) {
main = `package main
import "my_package"
main :: proc() {
- my_package.*
+ my_package.{*}
}
`,
packages = packages[:],
@@ -1052,7 +1051,7 @@ ast_non_mutable_variable_struct_completion :: proc(t: ^testing.T) {
main = `package main
import "my_package"
main :: proc() {
- my_package.*
+ my_package.{*}
}
`,
packages = packages[:],
@@ -1080,7 +1079,7 @@ ast_mutable_variable_struct_completion :: proc(t: ^testing.T) {
main = `package main
import "my_package"
main :: proc() {
- my_package.var.*
+ my_package.var.{*}
}
`,
packages = packages[:],
@@ -1097,7 +1096,7 @@ ast_out_of_block_scope_completion :: proc(t: ^testing.T) {
{
aabb := 2
}
- aab*
+ aab{*}
}
`,
}
@@ -1112,7 +1111,7 @@ ast_value_decl_multiple_name_same_type :: proc(t: ^testing.T) {
main :: proc() {
xaaaa, yaaaa: string
xaaaa = "hi"
- yaaa*
+ yaaa{*}
}
`,
}
@@ -1132,7 +1131,7 @@ ast_value_decl_comp_lit :: proc(t: ^testing.T) {
a = 2,
}
- my_struct.*
+ my_struct.{*}
}
`,
}
@@ -1146,7 +1145,7 @@ ast_multi_pointer_completion :: proc(t: ^testing.T) {
main = `package main
main :: proc() {
faa: [^]int
- fa*
+ fa{*}
}
`,
}
@@ -1161,7 +1160,7 @@ ast_multi_pointer_indexed_completion :: proc(t: ^testing.T) {
main :: proc() {
faa: [^]int
sap := faa[1]
- sa*
+ sa{*}
}
`,
}
@@ -1181,7 +1180,7 @@ ast_implicit_named_comp_lit_bitset :: proc(t: ^testing.T) {
main :: proc() {
inst := My_Struct {
- bits = {.*}
+ bits = {.{*}}
}
}
`,
@@ -1203,7 +1202,7 @@ ast_implicit_unnamed_comp_lit_bitset :: proc(t: ^testing.T) {
main :: proc() {
inst := My_Struct {
- {.A}, {.*},
+ {.A}, {.{*}},
}
}
`,
@@ -1225,7 +1224,7 @@ ast_implicit_unnamed_comp_lit_enum :: proc(t: ^testing.T) {
main :: proc() {
inst := My_Struct {
- .A, .*
+ .A, .{*}
}
}
`,
@@ -1250,7 +1249,7 @@ ast_implicit_mixed_named_and_unnamed_comp_lit_bitset :: proc(t: ^testing.T) {
main :: proc() {
inst := My_Struct {
- foo = {{.A}, {.*}, {.B} }
+ foo = {{.A}, {.{*}}, {.B} }
}
}
`,
@@ -1274,7 +1273,7 @@ ast_comp_lit_in_complit_completion :: proc(t: ^testing.T) {
main :: proc() {
inst := My_Struct {
foo = {
- a*
+ a{*}
}
}
}
@@ -1302,7 +1301,7 @@ ast_inlined_struct :: proc(t: ^testing.T) {
main :: proc() {
inst: My_Struct
- inst.foo.*
+ inst.foo.{*}
}
`,
}
@@ -1326,7 +1325,7 @@ ast_inlined_union :: proc(t: ^testing.T) {
main :: proc() {
inst: My_Struct
- inst.*
+ inst.{*}
}
`,
}
@@ -1348,7 +1347,7 @@ ast_union_identifier_completion :: proc(t: ^testing.T) {
}
main :: proc() {
- a: My_*
+ a: My_{*}
}
`,
}
@@ -1364,7 +1363,7 @@ ast_union_poly :: proc(t: ^testing.T) {
main :: proc() {
m: My_Union(int)
- m.*
+ m.{*}
}
`,
}
@@ -1381,7 +1380,7 @@ ast_maybe_first_value :: proc(t: ^testing.T) {
main :: proc() {
m: Maybe(int)
v, ok := m.?
- v*
+ v{*}
}
`,
}
@@ -1396,7 +1395,7 @@ ast_maybe_second_value :: proc(t: ^testing.T) {
main :: proc() {
m: Maybe(int)
v, ok := m.?
- ok*
+ ok{*}
}
`,
}
@@ -1412,7 +1411,7 @@ ast_maybe_array :: proc(t: ^testing.T) {
main :: proc() {
m: My_Union([5]u8)
- m.*
+ m.{*}
}
`,
}
@@ -1440,7 +1439,7 @@ ast_maybe_index_completion :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
m: my_package.Maybe(int)
- m.*
+ m.{*}
}
`,
packages = packages[:],
@@ -1457,7 +1456,7 @@ ast_distinct_u32_completion :: proc(t: ^testing.T) {
Distinct_Type :: distinct u32
d: Distinct_Type
- d*
+ d{*}
}
`,
}
@@ -1474,7 +1473,7 @@ ast_new_completion :: proc(t: ^testing.T) {
main :: proc() {
adzz := new(int);
- adzz*
+ adzz{*}
}
`,
@@ -1494,7 +1493,7 @@ ast_new_clone_completion :: proc(t: ^testing.T) {
main :: proc() {
adzz := new_clone(Foo{});
- adzz*
+ adzz{*}
}
`,
@@ -1511,7 +1510,7 @@ ast_rawtr_cast_completion :: proc(t: ^testing.T) {
main :: proc() {
raw: rawptr
my_int := cast(int)raw;
- my_i*
+ my_i{*}
}
`,
@@ -1538,7 +1537,7 @@ ast_overload_with_procedure_return :: proc(t: ^testing.T) {
test_int :: proc() -> int {}
main :: proc() {
my_in := my_group([]int, test_int())
- my_in*
+ my_in{*}
}
`,
}
@@ -1568,7 +1567,7 @@ ast_index_proc_parameter_completion :: proc(t: ^testing.T) {
main = `package main
import "my_package"
f :: proc(param: my_package.My_Struct) {
- para*
+ para{*}
}
`,
packages = packages[:],
@@ -1590,7 +1589,7 @@ ast_implicit_completion_in_enum_array_comp_lit :: proc(t: ^testing.T) {
foo :: enum{ one, two }
bar := [foo]int{
.one = 1,
- .*two = 2,
+ .{*}two = 2,
}
}
`,
@@ -1606,7 +1605,7 @@ ast_implicit_enum_value_decl_type :: proc(t: ^testing.T) {
main = `package main
Foo :: enum { Aa, Ab, Ac, Ad }
main :: proc() {
- foo: Foo = .*
+ foo: Foo = .{*}
}
`,
}
@@ -1621,7 +1620,7 @@ ast_implicit_bitset_value_decl :: proc(t: ^testing.T) {
Foo :: enum { Aa, Ab, Ac, Ad }
Foo_Set :: bit_set[Foo]
main :: proc() {
- foo_set := Foo_Set { .* }
+ foo_set := Foo_Set { .{*} }
}
`,
}
@@ -1637,7 +1636,7 @@ ast_implicit_bitset_add :: proc(t: ^testing.T) {
Foo_Set :: bit_set[Foo]
main :: proc() {
foo_set: Foo_Set
- foo_set += .*
+ foo_set += .{*}
}
`,
}
@@ -1651,7 +1650,7 @@ ast_enum_complete :: proc(t: ^testing.T) {
main = `package main
Foo :: enum { Aa, Ab, Ac, Ad }
main :: proc() {
- foo := Foo.*
+ foo := Foo.{*}
}
`,
}
@@ -1688,7 +1687,7 @@ ast_comp_lit_with_all_symbols_indexed_enum_implicit :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
a := my_package.Bar {
- c = .*
+ c = .{*}
}
}
`,
@@ -1725,7 +1724,7 @@ ast_package_uppercase_test :: proc(t: ^testing.T) {
main = `package main
import "My_package"
main :: proc() {
- My_package.*
+ My_package.{*}
}
`,
packages = packages[:],
@@ -1763,7 +1762,7 @@ ast_index_enum_infer :: proc(t: ^testing.T) {
main :: proc() {
my_enum: My_package.Foo
- if my_enum == *.
+ if my_enum == {*}.
}
`,
packages = packages[:],
@@ -1777,7 +1776,7 @@ ast_index_builtin_ODIN_OS :: proc(t: ^testing.T) {
source := test.Source {
main = `package test
main :: proc() {
- when ODIN_OS == .*
+ when ODIN_OS == .{*}
}
`,
packages = {},
@@ -1794,7 +1793,7 @@ ast_for_in_range_half_completion_1 :: proc(t: ^testing.T) {
ints: []int
for int_idx in 0..<len(ints) {
- ints[int_idx] = int_i*
+ ints[int_idx] = int_i{*}
}
}
`,
@@ -1810,7 +1809,7 @@ ast_for_in_range_half_completion_2 :: proc(t: ^testing.T) {
main = `package test
advance_rune_n :: proc(t: ^Tokenizer, n: int) {
for in 0..<n {
- advance_rune(n*)
+ advance_rune(n{*})
}
}
`,
@@ -1841,7 +1840,7 @@ ast_for_in_switch_type :: proc(t: ^testing.T) {
switch v in my_union {
case My_Struct:
for item in v.my {
- item.*
+ item.{*}
}
}
}
@@ -1860,7 +1859,7 @@ ast_procedure_in_procedure_non_mutable_completion :: proc(t: ^testing.T) {
Int :: int
my_procedure_two :: proc() {
- b : In*
+ b : In{*}
}
}
`,
@@ -1884,7 +1883,7 @@ ast_switch_completion_for_maybe_enum :: proc(t: ^testing.T) {
switch v in a {
case My_Enum:
switch v {
- case .*
+ case .{*}
}
}
@@ -1895,3 +1894,140 @@ ast_switch_completion_for_maybe_enum :: proc(t: ^testing.T) {
test.expect_completion_details(t, &source, ".", {"One", "Two"})
}
+
+@(test)
+ast_union_with_type_from_different_package :: proc(t: ^testing.T) {
+ packages := make([dynamic]test.Package)
+
+ append(
+ &packages,
+ test.Package{
+ pkg = "my_package",
+ source = `package my_package
+ My_Int :: int
+ `,
+ },
+ )
+
+ source := test.Source {
+ main = `package main
+ import "my_package"
+
+ My_Union :: union {
+ bool,
+ my_package.My_Int,
+ }
+
+ main :: proc() {
+ my_union: My_Union
+ my_union.{*}
+ }
+ `,
+ packages = packages[:],
+ }
+
+ test.expect_completion_labels(t, &source, ".", {"(my_package.My_Int)"})
+}
+
+@(test)
+ast_completion_union_with_typeid :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+ Maybe :: union($T: typeid) {T}
+
+ main :: proc() {
+ my_maybe: Maybe(typeid)
+ my_maybe.{*}
+ }
+ `,
+ }
+
+ test.expect_completion_labels(t, &source, ".", {"(typeid)"})
+}
+
+@(test)
+ast_completion_with_pointer :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+
+ main :: proc() {
+ my_pointer: ^int
+ my_p{*}
+ }
+ `,
+ }
+
+ test.expect_completion_details(t, &source, "", {"test.my_pointer: ^int"})
+}
+
+
+@(test)
+ast_matrix_completion_index :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+ main :: proc() {
+ m := matrix[2, 3]f32 {
+ 1, 9, -13,
+ 20, 5, -6,
+ }
+
+ my_float := m[2, 3]
+ my_f{*}
+ }
+ `,
+ }
+
+ test.expect_completion_details(t, &source, "", {"test.my_float: f32"})
+}
+
+@(test)
+ast_matrix_with_matrix_mult :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+ main :: proc() {
+ a := matrix[2, 3]f32 {
+ 2, 3, 1,
+ 4, 5, 0,
+ }
+
+ b := matrix[3, 2]f32 {
+ 1, 2,
+ 3, 4,
+ 5, 6,
+ }
+
+ my_matrix := a * b
+
+ my_matri{*}
+ }
+ `,
+ }
+
+ test.expect_completion_details(
+ t,
+ &source,
+ "",
+ {"test.my_matrix: matrix[2,2]f32"},
+ )
+}
+
+@(test)
+ast_vector_with_matrix_mult :: proc(t: ^testing.T) {
+ source := test.Source {
+ main = `package main
+
+ My_Matrix :: matrix[2, 4]f32
+
+ main :: proc() {
+ m := My_Matrix{1, 2, 3, 4, 5, 5, 4, 2}
+ v := [4]f32{1, 5, 4, 3}
+
+ my_vector := m * v
+
+ my_vecto{*}
+ }
+ `,
+ }
+
+ test.expect_completion_details(t, &source, "", {"test.my_vector: [4]f32"})
+}
diff --git a/tests/hover_test.odin b/tests/hover_test.odin
index 1c975cc..910f0be 100644
--- a/tests/hover_test.odin
+++ b/tests/hover_test.odin
@@ -11,7 +11,7 @@ ast_hover_default_intialized_parameter :: proc(t: ^testing.T) {
main = `package test
my_function :: proc(a := false) {
- b := a*;
+ b := a{*};
}
`,
@@ -29,7 +29,7 @@ ast_hover_default_parameter_enum :: proc(t: ^testing.T) {
}
main :: proc() {
- procedure*
+ procedure{*}
}
`,
packages = {},
@@ -47,7 +47,7 @@ ast_hover_parameter :: proc(t: ^testing.T) {
main = `package test
main :: proc(cool: int) {
- cool*
+ cool{*}
}
`,
packages = {},
@@ -77,7 +77,7 @@ ast_hover_external_package_parameter :: proc(t: ^testing.T) {
main = `package test
import "my_package"
main :: proc(cool: my_package.My_Struct) {
- cool*
+ cool{*}
}
`,
packages = packages[:],
@@ -106,7 +106,7 @@ ast_hover_procedure_package_parameter :: proc(t: ^testing.T) {
source := test.Source {
main = `package test
import "my_package"
- main :: proc(cool: my_packa*ge.My_Struct) {
+ main :: proc(cool: my_packa{*}ge.My_Struct) {
}
`,
@@ -127,7 +127,7 @@ ast_hover_procedure_with_default_comp_lit :: proc(t: ^testing.T) {
a: int,
}
- fa* :: proc(color_ : Color = { 255, 255, 255, 255 })
+ fa{*} :: proc(color_ : Color = { 255, 255, 255, 255 })
`,
}
@@ -149,7 +149,7 @@ ast_hover_same_name_in_selector_and_field :: proc(t: ^testing.T) {
f :: proc() {
color: Color
- color.colo*r
+ color.colo{*}r
}
`,
}
diff --git a/tests/signatures_test.odin b/tests/signatures_test.odin
index 9795710..b6de667 100644
--- a/tests/signatures_test.odin
+++ b/tests/signatures_test.odin
@@ -10,7 +10,7 @@ import test "shared:testing"
ast_declare_proc_signature :: proc(t: ^testing.T) {
source := test.Source {
main = `package test
- main :: proc(*)
+ main :: proc({*})
`,
packages = {},
}
@@ -28,7 +28,7 @@ ast_naked_parens :: proc(t: ^testing.T) {
return;
}
- (*)
+ ({*})
switch n in node.derived {
}
@@ -48,7 +48,7 @@ ast_simple_proc_signature :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(*)
+ cool_function({*})
}
`,
packages = {},
@@ -69,7 +69,7 @@ ast_default_assignment_proc_signature :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(*)
+ cool_function({*})
}
`,
packages = {},
@@ -90,7 +90,7 @@ ast_proc_signature_argument_last_position :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(2,*
+ cool_function(2,{*}
}
`,
packages = {},
@@ -107,7 +107,7 @@ ast_proc_signature_argument_first_position :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(2*,)
+ cool_function(2{*},)
}
`,
packages = {},
@@ -125,7 +125,7 @@ ast_proc_signature_argument_move_position :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(2,3*, 3);
+ cool_function(2,3{*}, 3);
}
`,
packages = {},
@@ -142,7 +142,7 @@ ast_proc_signature_argument_complex :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(a(2,5,b(3,sdf[2],{})), *);
+ cool_function(a(2,5,b(3,sdf[2],{})), {*});
}
`,
packages = {},
@@ -159,7 +159,7 @@ ast_proc_signature_argument_open_brace_position :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(2,3, 3*
+ cool_function(2,3, 3{*}
}
`,
packages = {},
@@ -176,7 +176,7 @@ ast_proc_signature_argument_any_ellipsis_position :: proc(t: ^testing.T) {
}
main :: proc() {
- cool_function(3, 4, 5*)
+ cool_function(3, 4, 5{*})
}
`,
packages = {},
@@ -201,7 +201,7 @@ ast_proc_group_signature_empty_call :: proc(t: ^testing.T) {
};
main :: proc() {
- group_function(*)
+ group_function({*})
}
`,
packages = {},
@@ -228,7 +228,7 @@ ast_proc_signature_generic :: proc(t: ^testing.T) {
}
main :: proc() {
- clone_array(*)
+ clone_array({*})
}
`,
packages = {},
@@ -259,7 +259,7 @@ ast_proc_group_signature_basic_types :: proc(t: ^testing.T) {
};
main :: proc() {
- group_function(2, true, *)
+ group_function(2, true, {*})
}
`,
packages = {},
@@ -295,7 +295,7 @@ ast_proc_group_signature_distinct_basic_types :: proc(t: ^testing.T) {
a: My_Int;
- group_function(a, *)
+ group_function(a, {*})
}
`,
packages = {},
@@ -339,7 +339,7 @@ ast_proc_group_signature_struct :: proc(t: ^testing.T) {
main :: proc() {
a: int;
b: My_Struct;
- group_function(a, b, *)
+ group_function(a, b, {*})
}
`,
packages = {},
@@ -374,7 +374,7 @@ index_simple_signature :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
- my_package.my_function(*)
+ my_package.my_function({*})
}
`,
packages = packages[:],
@@ -392,7 +392,7 @@ ast_index_builtin_len_proc :: proc(t: ^testing.T) {
source := test.Source {
main = `package test
main :: proc() {
- len(*)
+ len({*})
}
`,
packages = {},
@@ -411,7 +411,7 @@ ast_signature_on_invalid_package :: proc(t: ^testing.T) {
main = `package test
import "core:totallyReal"
main :: proc() {
- a := totallyReal.read_cycle_counter(*)
+ a := totallyReal.read_cycle_counter({*})
}
`,
packages = {},
@@ -431,7 +431,7 @@ ast_signature_variable_pointer :: proc(t: ^testing.T) {
main :: proc() {
my_fun_ptr: My_Fun;
- my_fun_ptr(*)
+ my_fun_ptr({*})
}
`,
packages = {},
@@ -453,7 +453,7 @@ ast_signature_global_variable_pointer :: proc(t: ^testing.T) {
my_fun_ptr: My_Fun;
main :: proc() {
- my_fun_ptr(*)
+ my_fun_ptr({*})
}
`,
packages = {},
@@ -484,7 +484,7 @@ index_variable_pointer_signature :: proc(t: ^testing.T) {
import "my_package"
main :: proc() {
- my_package.my_fun_ptr(*)
+ my_package.my_fun_ptr({*})
}
`,
packages = packages[:],
@@ -507,7 +507,7 @@ shared_value_decl_type_signature :: proc(t: ^testing.T) {
}
main :: proc() {
- my_function(*)
+ my_function({*})
}
`,
packages = {},
@@ -532,7 +532,7 @@ proc_with_struct_poly :: proc(t: ^testing.T) {
}
main :: proc() {
- uf(*)
+ uf({*})
}
`,
packages = {},
@@ -549,7 +549,7 @@ proc_signature_move_outside :: proc(t: ^testing.T) {
}
main :: proc() {
- my_cool_function()*
+ my_cool_function(){*}
}
`,
packages = {},
@@ -562,7 +562,6 @@ proc_signature_move_outside :: proc(t: ^testing.T) {
)
}
-
/*
@(test)
signature_function_inside_when :: proc(t: ^testing.T) {
@@ -574,7 +573,7 @@ signature_function_inside_when :: proc(t: ^testing.T) {
}
main :: proc() {
- ProcAllocationFunction(*)
+ ProcAllocationFunction({*})
}
`,
packages = {},
diff --git a/tools/odinfmt/tests/.snapshots/if.odin b/tools/odinfmt/tests/.snapshots/if.odin
new file mode 100644
index 0000000..e1c05d1
--- /dev/null
+++ b/tools/odinfmt/tests/.snapshots/if.odin
@@ -0,0 +1,25 @@
+package odinfmt_test
+
+
+if_one :: proc() {
+ if i := strings.index(imp.fullpath, ":");
+ i != -1 && i > 1 && i < len(imp.fullpath) - 1 {
+ }
+}
+
+if_two :: proc() {
+ if ret := unmarshal(
+ j[field[:len(field) - 1]],
+ a,
+ allocadsdsdsdsdsdsdsdtor,
+ ); ret != nil {
+ }
+}
+
+if_three :: proc() {
+ if position_in_node(
+ position_context.binary.raaaaaaaaaaaaaaaaaaaight,
+ position_context.position,
+ ) {
+ }
+}
diff --git a/tools/odinfmt/tests/if.odin b/tools/odinfmt/tests/if.odin
new file mode 100644
index 0000000..26ada3d
--- /dev/null
+++ b/tools/odinfmt/tests/if.odin
@@ -0,0 +1,19 @@
+package odinfmt_test
+
+
+if_one :: proc() {
+ if i := strings.index(imp.fullpath, ":"); i != -1 && i > 1 && i < len(imp.fullpath) - 1 {
+ }
+}
+
+if_two :: proc() {
+ if ret := unmarshal(j[field[:len(field) - 1]], a, allocadsdsdsdsdsdsdsdtor); ret != nil {
+ }
+}
+
+if_three :: proc() {
+ if position_in_node(
+ position_context.binary.raaaaaaaaaaaaaaaaaaaight,
+ position_context.position) {
+ }
+} \ No newline at end of file