diff --git a/call_hierarchy.v b/call_hierarchy.v index 9b5026f9..8b5a18bf 100644 --- a/call_hierarchy.v +++ b/call_hierarchy.v @@ -14,7 +14,7 @@ fn (mut app App) handle_prepare_call_hierarchy(request Request) Response { log('Failed to decode PrepareCallHierarchyParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -23,7 +23,7 @@ fn (mut app App) handle_prepare_call_hierarchy(request Request) Response { lines := content.split_into_lines() if params.position.line < 0 || params.position.line >= lines.len { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -31,14 +31,14 @@ fn (mut app App) handle_prepare_call_hierarchy(request Request) Response { start, end := find_word_bounds_at_col(line_text, params.position.char, app.position_encoding) if start < 0 || end <= start { return Response{ - id: request.id + id: request.id result: 'null' } } word := substr_by_char_bounds(line_text, start, end, app.position_encoding) if word == '' { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -51,12 +51,12 @@ fn (mut app App) handle_prepare_call_hierarchy(request Request) Response { } if item.name == '' { return Response{ - id: request.id + id: request.id result: 'null' } } return Response{ - id: request.id + id: request.id result: [item] } } @@ -70,14 +70,14 @@ fn (mut app App) handle_call_hierarchy_incoming(request Request) Response { log('Failed to decode CallHierarchyIncomingCallsParams: ${err}') } return Response{ - id: request.id + id: request.id result: []CallHierarchyIncomingCall{} } } fn_name := extract_simple_fn_name(params.item.name) if fn_name == '' { return Response{ - id: request.id + id: request.id result: []CallHierarchyIncomingCall{} } } @@ -90,7 +90,7 @@ fn (mut app App) handle_call_hierarchy_incoming(request Request) Response { for uri, fc in app.open_files { if request.id in app.cancelled_requests { return Response{ - id: request.id + id: request.id result: results } } @@ -108,7 +108,7 @@ fn (mut app App) handle_call_hierarchy_incoming(request Request) Response { for f in os.walk_ext(dir, '.v') { if request.id in app.cancelled_requests { return Response{ - id: request.id + id: request.id result: results } } @@ -125,7 +125,7 @@ fn (mut app App) handle_call_hierarchy_incoming(request Request) Response { } } return Response{ - id: request.id + id: request.id result: results } } @@ -138,7 +138,7 @@ fn (mut app App) handle_call_hierarchy_outgoing(request Request) Response { log('Failed to decode CallHierarchyOutgoingCallsParams: ${err}') } return Response{ - id: request.id + id: request.id result: []CallHierarchyOutgoingCall{} } } @@ -174,12 +174,12 @@ fn (mut app App) handle_call_hierarchy_outgoing(request Request) Response { continue } results << CallHierarchyOutgoingCall{ - to: callee + to: callee from_ranges: call_ranges } } return Response{ - id: request.id + id: request.id result: results } } @@ -208,10 +208,10 @@ fn find_fn_in_content(fn_name string, content string, uri string, enc PositionEn } if extract_simple_fn_name(sym.name) == fn_name { return CallHierarchyItem{ - name: sym.name - kind: sym.kind - uri: uri - range: sym.range + name: sym.name + kind: sym.kind + uri: uri + range: sym.range selection_range: sym.selection_range } } @@ -235,10 +235,10 @@ fn (mut app App) find_fn_declaration(fn_name string, search_dirs []string, inclu for dirs in dir_passes { if uri, sym := app.find_indexed_fn(fn_name, include_tests, dirs) { return CallHierarchyItem{ - name: sym.name - kind: sym.kind - uri: uri - range: sym.range + name: sym.name + kind: sym.kind + uri: uri + range: sym.range selection_range: sym.selection_range } } @@ -305,7 +305,7 @@ fn scan_for_callers(fn_name string, file_uri string, file_content string, enc Po line: li char: start_char } - end: Position{ + end: Position{ line: li char: end_char } @@ -315,11 +315,11 @@ fn scan_for_callers(fn_name string, file_uri string, file_content string, enc Po } if call_ranges.len > 0 { results << CallHierarchyIncomingCall{ - from: CallHierarchyItem{ - name: sym.name - kind: sym.kind - uri: file_uri - range: sym.range + from: CallHierarchyItem{ + name: sym.name + kind: sym.kind + uri: file_uri + range: sym.range selection_range: sym.selection_range } from_ranges: call_ranges @@ -380,7 +380,7 @@ fn find_fn_calls_in_line(line string, line_idx int, enc PositionEncoding, mut ca line: line_idx char: start_char } - end: Position{ + end: Position{ line: line_idx char: end_char } diff --git a/compilation_test.v b/compilation_test.v index 51ef750c..deb3e07c 100644 --- a/compilation_test.v +++ b/compilation_test.v @@ -16,7 +16,7 @@ fn test_smoke_incremental_edit_is_lossless() { line: 0 char: 1 } - end: Position{ + end: Position{ line: 0 char: 1 } diff --git a/diagnostics_scheduler.v b/diagnostics_scheduler.v index fbc884cc..fdb3117c 100644 --- a/diagnostics_scheduler.v +++ b/diagnostics_scheduler.v @@ -56,9 +56,9 @@ mut: fn new_diagnostics_scheduler() &DiagnosticsScheduler { return &DiagnosticsScheduler{ - generations: map[string]u64{} + generations: map[string]u64{} project_generations: map[string]u64{} - pending_jobs: map[string]DiagnosticsJob{} + pending_jobs: map[string]DiagnosticsJob{} } } @@ -107,9 +107,9 @@ fn (mut scheduler DiagnosticsScheduler) begin_project_mutation(project_key strin for affected_uri, _ in affected { scheduler.generations[affected_uri] = scheduler.generations[affected_uri] + 1 tickets << DiagnosticsTicket{ - uri: affected_uri - global_generation: scheduler.global_generation - generation: scheduler.generations[affected_uri] + uri: affected_uri + global_generation: scheduler.global_generation + generation: scheduler.generations[affected_uri] project_generation: project_generation } } @@ -225,7 +225,7 @@ fn (mut app App) begin_diagnostics_project_schedule(uri string) DiagnosticsProje project_key := app.generation_key(uri) return DiagnosticsProjectMutation{ project_key: project_key - tickets: scheduler.begin_project_schedule(uri, project_key) + tickets: scheduler.begin_project_schedule(uri, project_key) } } return DiagnosticsProjectMutation{} @@ -249,7 +249,7 @@ fn (mut app App) begin_diagnostics_project_mutation(uri string) DiagnosticsProje project_key := app.generation_key(uri) return DiagnosticsProjectMutation{ project_key: project_key - tickets: scheduler.begin_project_mutation(project_key, '') + tickets: scheduler.begin_project_mutation(project_key, '') } } return DiagnosticsProjectMutation{} @@ -283,19 +283,19 @@ fn (mut app App) enqueue_diagnostics_tickets(mut scheduler DiagnosticsScheduler, version = current_version } job := DiagnosticsJob{ - uri: ticket.uri - content: job_content - version: version - project_key: project_key - project_generation: ticket.project_generation - position_encoding: app.position_encoding - open_files: app.open_files.clone() + uri: ticket.uri + content: job_content + version: version + project_key: project_key + project_generation: ticket.project_generation + position_encoding: app.position_encoding + open_files: app.open_files.clone() project_generations: app.project_generations.clone() - write_mutex: app.write_mutex - tcp_conn: app.tcp_conn - global_generation: ticket.global_generation - generation: ticket.generation - ready_at: ready_at + write_mutex: app.write_mutex + tcp_conn: app.tcp_conn + global_generation: ticket.global_generation + generation: ticket.generation + ready_at: ready_at } if scheduler.enqueue(job) { should_start = true @@ -346,16 +346,16 @@ fn run_diagnostics_job(mut scheduler DiagnosticsScheduler, job DiagnosticsJob) { versions[job.uri] = version } mut worker := App{ - text: job.content - open_files: job.open_files + text: job.content + open_files: job.open_files open_files_versions: versions - temp_dir: temp_dir + temp_dir: temp_dir diagnostics_enabled: true - diag_cache: map[string]DiagCacheEntry{} + diag_cache: map[string]DiagCacheEntry{} project_generations: job.project_generations - position_encoding: job.position_encoding - write_mutex: job.write_mutex - tcp_conn: job.tcp_conn + position_encoding: job.position_encoding + write_mutex: job.write_mutex + tcp_conn: job.tcp_conn } notification := worker.build_diagnostics_notification(job.uri, job.content) scheduler.publish_if_current(mut worker, job, notification) diff --git a/document_highlight.v b/document_highlight.v index 49993502..d64f0b3f 100644 --- a/document_highlight.v +++ b/document_highlight.v @@ -165,9 +165,9 @@ fn collect_document_highlight_candidates(content string, lines []string, symbol } line := lines[position.line] candidates << DocumentHighlightCandidate{ - line_idx: position.line + line_idx: position.line start_byte: encoded_col_to_byte(line, position.start_char, enc) - end_byte: encoded_col_to_byte(line, position.end_char, enc) + end_byte: encoded_col_to_byte(line, position.end_char, enc) } } return candidates @@ -182,7 +182,7 @@ fn (mut app App) handle_document_highlight(request Request) Response { log('Failed to decode DocumentHighlightParams: ${err}') } return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } @@ -190,14 +190,14 @@ fn (mut app App) handle_document_highlight(request Request) Response { content := app.open_files[uri] or { os.read_file(uri_to_path(uri)) or { '' } } if content == '' { return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } lines := content.split_into_lines() if params.position.line < 0 || params.position.line >= lines.len { return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } @@ -205,21 +205,21 @@ fn (mut app App) handle_document_highlight(request Request) Response { start, end := find_word_bounds_at_col(line_text, params.position.char, app.position_encoding) if start < 0 || end <= start { return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } symbol := substr_by_char_bounds(line_text, start, end, app.position_encoding) if symbol == '' { return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } candidates := collect_document_highlight_candidates(content, lines, symbol, app.position_encoding) if candidates.len > document_highlight_semantic_max_candidates { return Response{ - id: request.id + id: request.id result: []DocumentHighlight{} } } @@ -246,7 +246,7 @@ fn (mut app App) handle_document_highlight(request Request) Response { mut kind := classify_highlight_kind(line, candidate.start_byte, candidate.end_byte) if a := anchor { occurrence := Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: candidate.line_idx @@ -264,16 +264,16 @@ fn (mut app App) handle_document_highlight(request Request) Response { line: candidate.line_idx char: start_char } - end: Position{ + end: Position{ line: candidate.line_idx char: end_char } } - kind: kind // Read/Write (P2-03) + kind: kind // Read/Write (P2-03) } } return Response{ - id: request.id + id: request.id result: highlights } } diff --git a/folding_range.v b/folding_range.v index a1ddd45e..a40741c7 100644 --- a/folding_range.v +++ b/folding_range.v @@ -13,7 +13,7 @@ fn (mut app App) handle_folding_range(request Request) Response { log('Failed to decode FoldingRangeParams: ${err}') } return Response{ - id: request.id + id: request.id result: []FoldingRange{} } } @@ -21,12 +21,12 @@ fn (mut app App) handle_folding_range(request Request) Response { content := app.open_files[uri] or { os.read_file(uri_to_path(uri)) or { '' } } if content == '' { return Response{ - id: request.id + id: request.id result: []FoldingRange{} } } return Response{ - id: request.id + id: request.id result: compute_folding_ranges(content) } } @@ -57,8 +57,8 @@ fn compute_folding_ranges(content string) []FoldingRange { if i > block_comment_start { ranges << FoldingRange{ start_line: block_comment_start - end_line: i - kind: 'comment' + end_line: i + kind: 'comment' } } block_comment_start = -1 @@ -83,8 +83,8 @@ fn compute_folding_ranges(content string) []FoldingRange { if import_start >= 0 && import_end > import_start { ranges << FoldingRange{ start_line: import_start - end_line: import_end - kind: 'imports' + end_line: import_end + kind: 'imports' } } import_start = -1 @@ -101,8 +101,8 @@ fn compute_folding_ranges(content string) []FoldingRange { if comment_start >= 0 && comment_end > comment_start { ranges << FoldingRange{ start_line: comment_start - end_line: comment_end - kind: 'comment' + end_line: comment_end + kind: 'comment' } } comment_start = -1 @@ -122,8 +122,8 @@ fn compute_folding_ranges(content string) []FoldingRange { if i > start { ranges << FoldingRange{ start_line: start - end_line: i - kind: 'region' + end_line: i + kind: 'region' } } } @@ -135,15 +135,15 @@ fn compute_folding_ranges(content string) []FoldingRange { if import_start >= 0 && import_end > import_start { ranges << FoldingRange{ start_line: import_start - end_line: import_end - kind: 'imports' + end_line: import_end + kind: 'imports' } } if comment_start >= 0 && comment_end > comment_start { ranges << FoldingRange{ start_line: comment_start - end_line: comment_end - kind: 'comment' + end_line: comment_end + kind: 'comment' } } diff --git a/handlers.v b/handlers.v index 23ecedf0..3dec3f8b 100644 --- a/handlers.v +++ b/handlers.v @@ -8,17 +8,17 @@ import time import v.pref const v_keywords = ['asm', 'as', 'assert', 'atomic', 'break', 'const', 'continue', 'defer', 'dump', - 'else', 'enum', 'false', 'fn', 'for', 'go', 'goto', 'if', 'ilike', 'implements', 'import', 'in', - 'interface', 'is', 'isreftype', 'like', 'lock', 'match', 'module', 'mut', 'nil', 'none', 'or', - 'pub', 'return', 'rlock', 'select', 'shared', 'sizeof', 'spawn', 'static', 'struct', 'true', - 'type', 'typeof', 'union', 'unsafe', 'volatile']! + 'else', 'enum', 'false', 'fn', 'for', 'go', 'goto', 'if', 'ilike', 'implements', 'import', + 'in', 'interface', 'is', 'isreftype', 'like', 'lock', 'match', 'module', 'mut', 'nil', 'none', + 'or', 'pub', 'return', 'rlock', 'select', 'shared', 'sizeof', 'spawn', 'static', 'struct', + 'true', 'type', 'typeof', 'union', 'unsafe', 'volatile']! const v_builtins = ['close', 'copy', 'eprintln', 'eprint', 'error', 'error_with_code', 'exit', 'flush_stderr', 'flush_stdout', 'free', 'isnil', 'panic', 'print', 'println']! -const v_builtin_types = ['any', 'array', 'bool', 'byte', 'byteptr', 'chan', 'char', 'charptr', 'f32', - 'f64', 'i8', 'i16', 'i32', 'i64', 'int', 'isize', 'IError', 'map', 'rune', 'string', 'thread', - 'u8', 'u16', 'u32', 'u64', 'usize', 'void', 'voidptr']! +const v_builtin_types = ['any', 'array', 'bool', 'byte', 'byteptr', 'chan', 'char', 'charptr', + 'f32', 'f64', 'i8', 'i16', 'i32', 'i64', 'int', 'isize', 'IError', 'map', 'rune', 'string', + 'thread', 'u8', 'u16', 'u32', 'u64', 'usize', 'void', 'voidptr']! struct IndexedCompletionResult { items []Detail @@ -140,7 +140,7 @@ fn source_call_target(content string, cursor Position, enc PositionEncoding) ?So name_start_in_line } return SourceCallTarget{ - position: Position{ + position: Position{ line: target_line char: byte_to_encoded_col(target_line_text, probe_byte, enc) } @@ -373,7 +373,7 @@ fn (mut app App) hover_with_written_declaration(uri string, position Position, r } return Hover{ contents: MarkupContent{ - kind: hover.contents.kind + kind: hover.contents.kind value: value[..body_start] + declaration + '\n' + value[body_start + close_offset..] } } @@ -389,7 +389,7 @@ fn (mut app App) source_hover_fallback(uri string, position Position) ?Hover { } return Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: '```v\n${declaration}\n```' } } @@ -697,7 +697,7 @@ fn (mut app App) local_binding_hover(uri string, position Position) ?Hover { if declared != '' { return Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: '```v\n${name} ${declared}\n```' } } @@ -708,7 +708,7 @@ fn (mut app App) local_binding_hover(uri string, position Position) ?Hover { } return Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: '```v\n${name} ${typ}\n```' } } @@ -734,9 +734,9 @@ fn (mut app App) source_signature_fallback(uri string, position Position) ?Signa } parameters := signature_parameters(label) return SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ - label: label + label: label parameters: parameters }, ] @@ -751,7 +751,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { log('Failed to decode TextDocumentPositionParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -760,7 +760,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { log('operation_at_pos: missing textDocument.uri') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -768,7 +768,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { // than indexing arrays with negative values (P1-09). if params.position.line < 0 || params.position.char < 0 { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -794,18 +794,18 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { } items := merge_completion_items(indexed.items, compiler_items) return Response{ - id: request.id + id: request.id result: CompletionList{ is_incomplete: false - items: items + items: items } } } return Response{ - id: request.id + id: request.id result: CompletionList{ is_incomplete: false - items: indexed.items + items: indexed.items } } } @@ -818,7 +818,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { if method in [.definition, .declaration, .type_definition, .implementation] { if location := app.resolve_indexed_definition(path, params.position) { return Response{ - id: request.id + id: request.id result: location } } @@ -827,7 +827,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { if method == .hover { if binding := app.local_binding_hover(path, params.position) { return Response{ - id: request.id + id: request.id result: binding } } @@ -837,7 +837,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { // the documentation with its answer. if member := app.member_selector_hover(path, params.position) { return Response{ - id: request.id + id: request.id result: member } } @@ -877,7 +877,7 @@ fn (mut app App) operation_at_pos(method Method, request Request) Response { log(result.str()) } return Response{ - id: request.id + id: request.id result: result } } @@ -922,7 +922,7 @@ fn (mut app App) indexed_completions(uri string, position Position) IndexedCompl if !has_local_binding { module_result := app.get_imported_module_member_completions(module_path, os.dir(uri_to_path(uri))) return IndexedCompletionResult{ - items: module_result.items + items: module_result.items use_compiler: module_result.use_compiler } } @@ -952,7 +952,7 @@ fn (mut app App) indexed_completions(uri string, position Position) IndexedCompl if struct_type != '' { field_result := app.indexed_struct_field_completions(uri, content, struct_type) return IndexedCompletionResult{ - items: field_result.items + items: field_result.items use_compiler: field_result.use_compiler || field_result.items.len == 0 } } @@ -972,8 +972,8 @@ fn (mut app App) indexed_completions(uri string, position Position) IndexedCompl for binding in parse_import_bindings(content) { if binding.alias != '' && binding.alias !in seen_labels { details << Detail{ - kind: 9 // CompletionItemKind.Module - label: binding.alias + kind: 9 // CompletionItemKind.Module + label: binding.alias detail: binding.module_path } seen_labels[binding.alias] = true @@ -992,7 +992,7 @@ fn (mut app App) indexed_completions(uri string, position Position) IndexedCompl } } return IndexedCompletionResult{ - items: details + items: details use_compiler: use_compiler } } @@ -1076,8 +1076,8 @@ fn binding_scope_header_starts_literal(source string) bool { } struct AnonymousFunctionHeader { - found bool - complete bool + found bool + complete bool parameter_names []string parameter_types map[string]string } @@ -1144,8 +1144,8 @@ fn anonymous_function_header(source string) AnonymousFunctionHeader { } } return AnonymousFunctionHeader{ - found: true - complete: true + found: true + complete: true parameter_names: names parameter_types: types } @@ -1156,8 +1156,8 @@ fn expression_line_is_continued(line string) bool { if trimmed == '' { return false } - return trimmed[trimmed.len - 1] in [`.`, `,`, `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `=`, `!`, - `<`, `>`, `?`, `:`] + return trimmed[trimmed.len - 1] in [`.`, `,`, `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `=`, + `!`, `<`, `>`, `?`, `:`] } fn struct_literal_cursor_is_at_field(prefix string, open_brace int, raw_lines []string) bool { @@ -1671,8 +1671,8 @@ fn (app &App) local_scope_bindings(content string, position Position) []LocalBin mut parameter_bindings := []LocalBinding{} for name in parameter_names { parameter_bindings << LocalBinding{ - name: name - line: function_start + name: name + line: function_start column: -1 } } @@ -1764,8 +1764,8 @@ fn (app &App) local_scope_bindings(content string, position Position) []LocalBin for name in outer_segment_names { if !scopes.last().any(it.name == name) { scopes[scopes.len - 1] << LocalBinding{ - name: name - line: line_idx + name: name + line: line_idx column: local_binding_column(segment, segment_start, name) } } @@ -1778,14 +1778,14 @@ fn (app &App) local_scope_bindings(content string, position Position) []LocalBin for name in block_names { if !scopes.last().any(it.name == name) { scopes[scopes.len - 1] << LocalBinding{ - name: name - line: block_line + name: name + line: block_line column: if binding_scope_header { local_binding_column(segment, segment_start, name) } else { pending_block_columns[name] or { -1 } } - typ: if closure_header.complete { + typ: if closure_header.complete { closure_header.parameter_types[name] or { '' } } else { '' @@ -1829,8 +1829,8 @@ fn (app &App) local_scope_bindings(content string, position Position) []LocalBin for name in tail_names { if !scopes.last().any(it.name == name) { scopes[scopes.len - 1] << LocalBinding{ - name: name - line: line_idx + name: name + line: line_idx column: local_binding_column(tail, segment_start, name) } } @@ -1863,8 +1863,8 @@ fn (app &App) local_scope_bindings(content string, position Position) []LocalBin if has_implicit_it_scope_at_cursor(active_code_lines.join('\n')) && scopes.len > 0 && !has_explicit_it { scopes[scopes.len - 1] << LocalBinding{ - name: 'it' - line: position.line + name: 'it' + line: position.line column: -1 } } @@ -1885,8 +1885,8 @@ fn (app &App) local_scope_completions(content string, position Position) []Detai } } return names.filter(it != '').map(Detail{ - kind: 6 // CompletionItemKind.Variable - label: it + kind: 6 // CompletionItemKind.Variable + label: it detail: 'local binding' }) } @@ -2014,8 +2014,8 @@ fn receiver_rhs_needs_continuation(rhs string, has_expression bool, scan_state & if trimmed == '' { return false } - return trimmed[trimmed.len - 1] in [`.`, `,`, `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `=`, `!`, - `<`, `>`, `?`, `:`] + return trimmed[trimmed.len - 1] in [`.`, `,`, `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `=`, + `!`, `<`, `>`, `?`, `:`] } struct ReceiverDeclaration { @@ -2054,9 +2054,9 @@ fn receiver_declaration_on_line(code string, receiver string, active_columns []i continue } latest = ReceiverDeclaration{ - rhs: raw_statement[assign_idx + 2..].trim_space() - binding_index: binding_index - binding_count: bindings.len + rhs: raw_statement[assign_idx + 2..].trim_space() + binding_index: binding_index + binding_count: bindings.len binding_column: statement_start + lhs_start + receiver_column assignment_end: statement_start + assign_idx + 2 } @@ -2421,10 +2421,10 @@ fn method_completion_from_lines(lines []string, symbol DocumentSymbol) ?Detail { } insert := build_fn_snippet(name, after_receiver[paren_idx..]) return Detail{ - kind: 2 - label: name - detail: '${if trimmed.starts_with('pub ') { 'pub ' } else { '' }}fn ${after_fn}'.all_before('{').trim_space() - insert_text: insert + kind: 2 + label: name + detail: '${if trimmed.starts_with('pub ') { 'pub ' } else { '' }}fn ${after_fn}'.all_before('{').trim_space() + insert_text: insert insert_text_format: if insert.contains('\$') { 2 } else { 1 } } } @@ -2518,13 +2518,13 @@ fn (mut app App) indexed_method_symbols(uri string, content string, receiver_typ } } matches << Location{ - uri: indexed_uri + uri: indexed_uri range: LSPRange{ start: Position{ line: symbol.range.start.line char: symbol.selection_range.start.char } - end: Position{ + end: Position{ line: symbol.range.start.line char: symbol.selection_range.end.char } @@ -2533,8 +2533,8 @@ fn (mut app App) indexed_method_symbols(uri string, content string, receiver_typ } } return IndexedMethodSymbolResult{ - locations: matches - items: items + locations: matches + items: items use_compiler: has_conditional } } @@ -2570,8 +2570,8 @@ fn field_completion_from_symbol(lines []string, code_lines []string, symbol Docu return none } return Detail{ - kind: 5 // CompletionItemKind.Field - label: symbol.name + kind: 5 // CompletionItemKind.Field + label: symbol.name detail: lines[line_idx].trim_space() } } @@ -2760,12 +2760,12 @@ fn (mut app App) indexed_struct_field_completions_visited(uri string, content st } } return IndexedCompletionResult{ - items: items - use_compiler: has_conditional || has_unresolved_embedded - embedded_types: embedded_types - field_types: field_types + items: items + use_compiler: has_conditional || has_unresolved_embedded + embedded_types: embedded_types + field_types: field_types field_declared_types: field_declared_types - resolved_type: resolved_type + resolved_type: resolved_type } } @@ -2854,10 +2854,10 @@ fn thread_wait_completion(receiver_type string) ?Detail { ' ${payload}' } return Detail{ - kind: 2 - label: 'wait' - detail: 'fn (${receiver}) wait()${result}' - insert_text: 'wait()' + kind: 2 + label: 'wait' + detail: 'fn (${receiver}) wait()${result}' + insert_text: 'wait()' insert_text_format: 1 } } @@ -2969,8 +2969,8 @@ fn (mut app App) indexed_enum_members(uri string, content string, type_name stri for symbol in entry.doc_symbols { if symbol.kind == sym_kind_enum && symbol.name == name { return symbol.children.filter(it.kind == sym_kind_enum_member).map(Detail{ - kind: 20 // CompletionItemKind.EnumMember - label: it.name + kind: 20 // CompletionItemKind.EnumMember + label: it.name detail: type_name }) } @@ -3025,7 +3025,8 @@ fn (mut app App) expected_enum_type(uri string, content string, lines []string, } for op in ['==', '!=', '='] { if before.ends_with(op) { - if op == '=' && before.len > 1 && before[before.len - 2] in [`:`, `<`, `>`, `+`, `-`, `*`, `/`, `%`, `|`, `&`, `^`] { + if op == '=' && before.len > 1 && before[before.len - 2] in [`:`, `<`, `>`, `+`, `-`, + `*`, `/`, `%`, `|`, `&`, `^`] { break } left := trailing_selector(before[..before.len - op.len].trim_right(' \t')) @@ -3314,11 +3315,11 @@ fn (mut app App) callback_argument_completions(uri string, content string, lines label, skeleton := callback_skeleton(fn_type, generic_default) or { return [] } return [ Detail{ - kind: 15 // CompletionItemKind.Snippet - label: label - detail: 'function literal' - sort_text: '0' - insert_text: skeleton + kind: 15 // CompletionItemKind.Snippet + label: label + detail: 'function literal' + sort_text: '0' + insert_text: skeleton insert_text_format: 2 }, ] @@ -3510,7 +3511,7 @@ fn parse_import_binding(text string) ?ImportedModuleBinding { return none } return ImportedModuleBinding{ - alias: alias + alias: alias module_path: module_path } } @@ -3586,7 +3587,7 @@ fn (mut app App) get_imported_module_member_completions(module_path string, work } } return IndexedModuleCompletionResult{ - items: items + items: items use_compiler: has_conditional || items.len == 0 } } @@ -3816,8 +3817,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := first_word(trimmed) if is_valid_v_identifier_name(name) { items << Detail{ - kind: 6 // CompletionItemKind.Variable - label: name + kind: 6 // CompletionItemKind.Variable + label: name detail: '__global' } } @@ -3841,8 +3842,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := const_block_assignment_name(trimmed) if name != '' && (!public_only || const_block_public) { items << Detail{ - kind: 21 // CompletionItemKind.Constant - label: name + kind: 21 // CompletionItemKind.Constant + label: name detail: if const_block_public { 'pub const' } else { 'const' } } } @@ -3870,10 +3871,10 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines detail_str := '${if is_public { 'pub ' } else { '' }}${complete_declaration}'.all_before('{').trim_space() insert := build_fn_snippet(fn_name, after_fn[paren_idx..]) items << Detail{ - kind: 3 // CompletionItemKind.Function - label: fn_name - detail: detail_str - insert_text: insert + kind: 3 // CompletionItemKind.Function + label: fn_name + detail: detail_str + insert_text: insert insert_text_format: if insert.contains('\$') { 2 } else { 1 } } continue @@ -3882,8 +3883,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := extract_const_name(declaration[6..]) if name != '' { items << Detail{ - kind: 21 - label: name + kind: 21 + label: name detail: trimmed.all_before('=').trim_space() } } @@ -3893,8 +3894,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := module_type_completion_name(declaration[7..]) if name != '' { items << Detail{ - kind: 22 // CompletionItemKind.Struct - label: name + kind: 22 // CompletionItemKind.Struct + label: name detail: trimmed.all_before('{').trim_space() } } @@ -3904,8 +3905,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := module_type_completion_name(declaration[6..]) if name != '' { items << Detail{ - kind: 22 // CompletionItemKind.Struct - label: name + kind: 22 // CompletionItemKind.Struct + label: name detail: trimmed.all_before('{').trim_space() } } @@ -3915,8 +3916,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := module_type_completion_name(declaration[5..]) if name != '' { items << Detail{ - kind: 13 // CompletionItemKind.Enum - label: name + kind: 13 // CompletionItemKind.Enum + label: name detail: trimmed.all_before('{').trim_space() } } @@ -3926,8 +3927,8 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := module_type_completion_name(declaration[10..]) if name != '' { items << Detail{ - kind: 8 // CompletionItemKind.Interface - label: name + kind: 8 // CompletionItemKind.Interface + label: name detail: trimmed.all_before('{').trim_space() } } @@ -3937,15 +3938,15 @@ fn parse_module_member_completions_from_lines(lines []string, conditional_lines name := module_type_completion_name(declaration[5..]) if name != '' { items << Detail{ - kind: 7 // CompletionItemKind.Class - label: name + kind: 7 // CompletionItemKind.Class + label: name detail: trimmed.all_before('=').trim_space() } } } } return ParsedModuleCompletionIndex{ - items: items + items: items has_conditional: has_conditional } } @@ -4035,8 +4036,8 @@ fn (mut app App) build_diagnostics_notification(uri string, content string) Noti return Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: uri - version: if uri in app.open_files_versions { + uri: uri + version: if uri in app.open_files_versions { ?i64(app.open_files_versions[uri]) } else { none @@ -4064,8 +4065,8 @@ fn (mut app App) build_diagnostics_notification(uri string, content string) Noti diagnostics << app.encode_diagnostic_range(v_error_to_lsp_diagnostic(v_err), lines) } pd_params := PublishDiagnosticsParams{ - uri: uri - version: if uri in app.open_files_versions { + uri: uri + version: if uri in app.open_files_versions { ?i64(app.open_files_versions[uri]) } else { none @@ -4176,7 +4177,7 @@ fn (app &App) encode_diagnostic_range(diag LSPDiagnostic, lines []string) LSPDia line: start_line char: start_char } - end: Position{ + end: Position{ line: end_line char: end_char } @@ -4245,14 +4246,14 @@ fn (mut app App) on_will_save_wait_until(request Request) Response { log('Failed to decode WillSaveTextDocumentParams: ${err}') } return Response{ - id: request.id + id: request.id result: []TextEdit{} } } uri := params.text_document.uri content := app.open_files[uri] or { return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -4262,7 +4263,7 @@ fn (mut app App) on_will_save_wait_until(request Request) Response { // would desynchronize the server from the editor (P0-07 item 7). edits, _ := app.format_content(uri, content) return Response{ - id: request.id + id: request.id result: edits } } @@ -4276,7 +4277,7 @@ fn (mut app App) handle_prepare_rename(request Request) Response { log('Failed to decode TextDocumentPositionParams for prepareRename: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4285,7 +4286,7 @@ fn (mut app App) handle_prepare_rename(request Request) Response { lines := content.split_into_lines() if params.position.line < 0 || params.position.line >= lines.len { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4293,14 +4294,14 @@ fn (mut app App) handle_prepare_rename(request Request) Response { start, end := find_word_bounds_at_col(line_text, params.position.char, app.position_encoding) if start < 0 || end <= start { return Response{ - id: request.id + id: request.id result: 'null' } } symbol := substr_by_char_bounds(line_text, start, end, app.position_encoding) if symbol == '' { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4308,26 +4309,26 @@ fn (mut app App) handle_prepare_rename(request Request) Response { first := symbol[0] if !is_ident_start(first) { return Response{ - id: request.id + id: request.id result: 'null' } } // Reject V keywords and built-in function names — they cannot be renamed. if symbol in v_keywords || symbol in v_builtins { return Response{ - id: request.id + id: request.id result: 'null' } } return Response{ - id: request.id + id: request.id result: PrepareRenameResult{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: params.position.line char: start } - end: Position{ + end: Position{ line: params.position.line char: end } @@ -4345,10 +4346,10 @@ fn add_workspace_symbol(mut results []WorkspaceSymbol, mut seen_symbols map[stri } seen_symbols[key] = true results << WorkspaceSymbol{ - name: name - kind: kind + name: name + kind: kind location: Location{ - uri: uri + uri: uri range: rng } } @@ -4410,7 +4411,7 @@ fn (mut app App) handle_workspace_symbol(request Request) Response { log('Failed to decode WorkspaceSymbolParams: ${err}') } return Response{ - id: request.id + id: request.id result: []WorkspaceSymbol{} } } @@ -4424,7 +4425,7 @@ fn (mut app App) handle_workspace_symbol(request Request) Response { results := app.query_workspace_symbols(query) app.end_progress(token, '') return Response{ - id: request.id + id: request.id result: results } } @@ -4556,7 +4557,7 @@ fn (mut app App) find_references(request Request) Response { log('Failed to decode ReferenceParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4568,7 +4569,7 @@ fn (mut app App) find_references(request Request) Response { symbol := app.get_word_at_position(path, line, col) if symbol == '' { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4598,13 +4599,13 @@ fn (mut app App) find_references(request Request) Response { } if locations.len == 0 { return Response{ - id: request.id + id: request.id result: 'null' } } return Response{ - id: request.id + id: request.id result: locations } } @@ -4616,7 +4617,7 @@ fn (mut app App) handle_rename(request Request) Response { log('Failed to decode RenameParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4629,7 +4630,7 @@ fn (mut app App) handle_rename(request Request) Response { symbol := app.get_word_at_position(path, line, col) if symbol == '' { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4642,7 +4643,7 @@ fn (mut app App) handle_rename(request Request) Response { if !app.index_is_complete_for_scope(scope) { log('rename: source index is incomplete; refusing a partial workspace edit') return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4655,7 +4656,7 @@ fn (mut app App) handle_rename(request Request) Response { anchor := app.resolve_symbol_anchor(path, line, col) or { log('rename: could not resolve a semantic anchor for "${symbol}"; refusing lexical rename (P1-04)') return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4666,7 +4667,7 @@ fn (mut app App) handle_rename(request Request) Response { if locations.len == 0 { log('rename: no scope-safe occurrences for "${symbol}" (unresolved or above candidate cap); refusing') return Response{ - id: request.id + id: request.id result: 'null' } } @@ -4681,9 +4682,9 @@ fn (mut app App) handle_rename(request Request) Response { loc.range.start.char + byte_to_encoded_col(symbol, symbol.len, app.position_encoding) } edit := TextEdit{ - range: LSPRange{ + range: LSPRange{ start: loc.range.start - end: Position{ + end: Position{ line: loc.range.start.line char: end_char } @@ -4704,17 +4705,17 @@ fn (mut app App) handle_rename(request Request) Response { } doc_changes << TextDocumentEdit{ text_document: OptionalVersionedTextDocumentIdentifier{ - uri: uri + uri: uri version: version } - edits: edits + edits: edits } } return Response{ - id: request.id + id: request.id result: WorkspaceEdit{ - changes: changes + changes: changes document_changes: doc_changes } } @@ -5728,7 +5729,7 @@ fn (mut app App) find_indexed_source_definition(dir string, symbol string, activ continue } matches << Location{ - uri: uri + uri: uri range: sym.selection_range } } @@ -5984,9 +5985,9 @@ fn get_import_completions(line string, work_dir string) []Detail { continue } results << Detail{ - kind: 9 // CompletionItemKind.Module - label: entry - detail: 'V stdlib module' + kind: 9 // CompletionItemKind.Module + label: entry + detail: 'V stdlib module' insert_text: entry } } @@ -6009,9 +6010,9 @@ fn get_import_completions(line string, work_dir string) []Detail { continue } results << Detail{ - kind: 9 - label: entry - detail: 'Local module' + kind: 9 + label: entry + detail: 'Local module' insert_text: entry } } @@ -6212,12 +6213,12 @@ fn (mut app App) format_content(uri string, content string) ([]TextEdit, string) end_char := byte_to_encoded_col(final_segment, final_segment.len, app.position_encoding) edit := TextEdit{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: end_line char: end_char } @@ -6232,7 +6233,7 @@ fn (mut app App) handle_formatting(request Request) Response { params := json2.decode[DocumentFormattingParams](request.params) or { log('Failed to decode DocumentFormattingParams: ${err}') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -6243,7 +6244,7 @@ fn (mut app App) handle_formatting(request Request) Response { os.read_file(real_path) or { log('Failed to read file for formatting: ${err}') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -6251,7 +6252,7 @@ fn (mut app App) handle_formatting(request Request) Response { edits, _ := app.format_content(path, content) return Response{ - id: request.id + id: request.id result: edits } } @@ -6261,7 +6262,7 @@ fn (mut app App) handle_document_symbols(request Request) Response { params := json2.decode[DocumentSymbolParams](request.params) or { log('Failed to decode DocumentSymbolParams: ${err}') return Response{ - id: request.id + id: request.id result: []DocumentSymbol{} } } @@ -6271,13 +6272,13 @@ fn (mut app App) handle_document_symbols(request Request) Response { app.reindex_uri(uri) if entry := app.symbol_index[uri] { return Response{ - id: request.id + id: request.id result: entry.doc_symbols } } content := app.open_files[uri] or { '' } return Response{ - id: request.id + id: request.id result: encode_document_symbols(parse_document_symbols(content), content.split_into_lines(), app.position_encoding) } } @@ -6286,14 +6287,14 @@ fn (mut app App) handle_document_symbols(request Request) Response { fn (mut app App) handle_inlay_hints(request Request) Response { if !app.inlay_hints_enabled { return Response{ - id: request.id + id: request.id result: []InlayHint{} } } params := json2.decode[InlayHintParams](request.params) or { log('Failed to decode InlayHintParams: ${err}') return Response{ - id: request.id + id: request.id result: []InlayHint{} } } @@ -6420,18 +6421,18 @@ fn (mut app App) handle_inlay_hints(request Request) Response { // byte offset is re-encoded into the client's encoding (P0-01/P2-07). name_col := raw.index(var_name) or { continue } hints << InlayHint{ - position: Position{ + position: Position{ line: line_idx char: byte_to_encoded_col(raw, name_col + var_name.len, app.position_encoding) } - label: ': ${inferred}' - kind: inlay_hint_kind_type + label: ': ${inferred}' + kind: inlay_hint_kind_type padding_left: false } } return Response{ - id: request.id + id: request.id result: hints } } @@ -6771,7 +6772,7 @@ fn make_symbol(name string, kind int, line_idx int, raw_line string) DocumentSym line: line_idx char: 0 } - end: Position{ + end: Position{ line: line_idx char: raw_line.len } @@ -6781,17 +6782,17 @@ fn make_symbol(name string, kind int, line_idx int, raw_line string) DocumentSym line: line_idx char: col_start } - end: Position{ + end: Position{ line: line_idx char: col_end } } return DocumentSymbol{ - name: name - kind: kind - range: line_range + name: name + kind: kind + range: line_range selection_range: sel_range - children: []DocumentSymbol{} + children: []DocumentSymbol{} } } @@ -6879,13 +6880,13 @@ fn (mut app App) search_symbol_in_dirs(symbol string, request_id int) []Location positions := occ[symbol] or { continue } for p in positions { locations << Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: p.line char: p.start_char } - end: Position{ + end: Position{ line: p.line char: p.end_char } @@ -6988,13 +6989,13 @@ fn (mut app App) collect_semantic_candidates(symbol string, scope IndexScope) [] positions := occ[symbol] or { continue } for p in positions { candidates << Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: p.line char: p.start_char } - end: Position{ + end: Position{ line: p.line char: p.end_char } @@ -7061,7 +7062,7 @@ fn (mut app App) handle_code_action(request Request) Response { log('Failed to decode CodeActionParams: ${err}') } return Response{ - id: request.id + id: request.id result: []CodeAction{} } } @@ -7103,12 +7104,12 @@ fn (mut app App) handle_code_action(request Request) Response { changes: { uri: [ TextEdit{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: line_nr char: 0 } - end: end_pos + end: end_pos } new_text: '' }, @@ -7116,11 +7117,11 @@ fn (mut app App) handle_code_action(request Request) Response { } } actions << CodeAction{ - title: 'Remove unknown import' - kind: code_action_kind_quickfix + title: 'Remove unknown import' + kind: code_action_kind_quickfix is_preferred: true - edit: edit - diagnostics: [diag] + edit: edit + diagnostics: [diag] } } } @@ -7137,7 +7138,7 @@ fn (mut app App) handle_code_action(request Request) Response { } return Response{ - id: request.id + id: request.id result: actions } } @@ -7208,12 +7209,12 @@ fn build_safe_organize_imports_action(uri string, content string, lines []string changes: { uri: [ TextEdit{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: first char: 0 } - end: Position{ + end: Position{ line: last char: byte_to_encoded_col(lines[last], lines[last].len, enc) } @@ -7225,8 +7226,8 @@ fn build_safe_organize_imports_action(uri string, content string, lines []string } return CodeAction{ title: 'Organize Imports' - kind: code_action_kind_source_organize_imports - edit: edit + kind: code_action_kind_source_organize_imports + edit: edit } } @@ -7303,7 +7304,7 @@ fn (mut app App) collect_module_completions(current_file_uri string, working_dir items << entry.module_completions } return IndexedModuleCompletionResult{ - items: items + items: items use_compiler: has_conditional } } @@ -7350,22 +7351,22 @@ fn make_keyword_completions() []Detail { mut items := []Detail{} for kw in v_keywords { items << Detail{ - kind: 14 // Keyword - label: kw + kind: 14 // Keyword + label: kw detail: kw } } for b in v_builtins { items << Detail{ - kind: 3 // Function - label: b + kind: 3 // Function + label: b detail: b } } for builtin_type in v_builtin_types { items << Detail{ - kind: 7 // Class - label: builtin_type + kind: 7 // Class + label: builtin_type detail: 'builtin type' } } @@ -7378,7 +7379,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { params := json2.decode[DocumentRangeFormattingParams](request.params) or { log('Failed to decode DocumentRangeFormattingParams: ${err}') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7388,7 +7389,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { os.read_file(real_path) or { log('Failed to read file for range formatting: ${err}') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7401,7 +7402,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { os.write_file(temp_file, content) or { log('Failed to write temp file for range formatting: ${err}') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7410,7 +7411,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { formatted := os.read_file(temp_file) or { os.rm(temp_file) or {} return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7421,7 +7422,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { } if result.exit_code != 0 || formatted == '' || formatted == content { return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7434,7 +7435,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { } if req_start >= original_lines.len || req_start > req_end { return Response{ - id: request.id + id: request.id result: []TextEdit{} } } @@ -7456,19 +7457,19 @@ fn (mut app App) handle_range_formatting(request Request) Response { if orig_hunk_start < req_start || orig_hunk_end - 1 > req_end { log('range formatting: changed hunk [${orig_hunk_start}..${orig_hunk_end}) outside requested range [${req_start}..${req_end}]; returning no edits') return Response{ - id: request.id + id: request.id result: []TextEdit{} } } fmt_hunk_end := formatted_lines.len - suf // exclusive new_text := formatted_lines[orig_hunk_start..fmt_hunk_end].join('\n') + '\n' edit := TextEdit{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: orig_hunk_start char: 0 } - end: Position{ + end: Position{ line: orig_hunk_end char: 0 } @@ -7476,7 +7477,7 @@ fn (mut app App) handle_range_formatting(request Request) Response { new_text: new_text } return Response{ - id: request.id + id: request.id result: [edit] } } @@ -7491,7 +7492,7 @@ fn (mut app App) handle_selection_range(request Request) Response { log('Failed to decode SelectionRangeParams: ${err}') } return Response{ - id: request.id + id: request.id result: []SelectionRange{} } } @@ -7504,7 +7505,7 @@ fn (mut app App) handle_selection_range(request Request) Response { results << SelectionRange{ range: LSPRange{ start: pos - end: pos + end: pos } } continue @@ -7517,7 +7518,7 @@ fn (mut app App) handle_selection_range(request Request) Response { line: pos.line char: 0 } - end: Position{ + end: Position{ line: pos.line char: byte_to_encoded_col(line_text, line_text.len, app.position_encoding) } @@ -7535,7 +7536,7 @@ fn (mut app App) handle_selection_range(request Request) Response { line: pos.line char: start } - end: Position{ + end: Position{ line: pos.line char: end } @@ -7544,12 +7545,12 @@ fn (mut app App) handle_selection_range(request Request) Response { range: line_range } results << SelectionRange{ - range: word_range + range: word_range parent: line_parent } } return Response{ - id: request.id + id: request.id result: results } } @@ -7891,7 +7892,7 @@ fn code_lens_range(line int, raw_line string, encoding PositionEncoding) LSPRang line: line char: 0 } - end: Position{ + end: Position{ line: line char: byte_to_encoded_col(raw_line, raw_line.len, encoding) } @@ -7906,7 +7907,7 @@ fn (mut app App) handle_code_lens(request Request) Response { log('Failed to decode CodeLensParams: ${err}') } return Response{ - id: request.id + id: request.id result: []CodeLens{} } } @@ -7921,35 +7922,35 @@ fn (mut app App) handle_code_lens(request Request) Response { fn_name := code_lens_fn_name(code) if fn_name == 'main' { lenses << CodeLens{ - range: code_lens_range(i, raw_line, app.position_encoding) + range: code_lens_range(i, raw_line, app.position_encoding) command: Command{ - title: 'Run Main' - command: 'vls.runFile' + title: 'Run Main' + command: 'vls.runFile' arguments: [uri] } } } if is_test_file && fn_name.starts_with('test_') { lenses << CodeLens{ - range: code_lens_range(i, raw_line, app.position_encoding) + range: code_lens_range(i, raw_line, app.position_encoding) command: Command{ - title: 'Run File' - command: 'vls.runTests' + title: 'Run File' + command: 'vls.runTests' arguments: [uri] } } lenses << CodeLens{ - range: code_lens_range(i, raw_line, app.position_encoding) + range: code_lens_range(i, raw_line, app.position_encoding) command: Command{ - title: 'Run Test' - command: 'vls.runTests' + title: 'Run Test' + command: 'vls.runTests' arguments: [uri, fn_name] } } } } return Response{ - id: request.id + id: request.id result: lenses } } @@ -7962,12 +7963,12 @@ fn (mut app App) handle_code_lens_resolve(request Request) Response { log('Failed to decode CodeLens for resolve: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } return Response{ - id: request.id + id: request.id result: lens } } @@ -8009,7 +8010,7 @@ fn (mut app App) handle_execute_command(request Request) Response { log('Failed to decode ExecuteCommandParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -8023,13 +8024,13 @@ fn (mut app App) handle_execute_command(request Request) Response { app.send_show_message('vls: the V compiler (`v`) was not found on PATH.', 1) } else { app.start_code_lens_run(CodeLensRunJob{ - kind: .main - title: 'Run Main' - uri: uri - path: path - open_files: app.open_files.clone() - write_mutex: app.write_mutex - tcp_conn: app.tcp_conn + kind: .main + title: 'Run Main' + uri: uri + path: path + open_files: app.open_files.clone() + write_mutex: app.write_mutex + tcp_conn: app.tcp_conn capture_output: app.capture_output }) } @@ -8057,14 +8058,14 @@ fn (mut app App) handle_execute_command(request Request) Response { app.send_show_message('vls: the V compiler (`v`) was not found on PATH.', 1) } else { app.start_code_lens_run(CodeLensRunJob{ - kind: kind - title: title - uri: uri - path: path - fn_name: fn_name - open_files: app.open_files.clone() - write_mutex: app.write_mutex - tcp_conn: app.tcp_conn + kind: kind + title: title + uri: uri + path: path + fn_name: fn_name + open_files: app.open_files.clone() + write_mutex: app.write_mutex + tcp_conn: app.tcp_conn capture_output: app.capture_output }) } @@ -8077,7 +8078,7 @@ fn (mut app App) handle_execute_command(request Request) Response { } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -8090,7 +8091,7 @@ fn (mut app App) handle_inline_value(request Request) Response { log('Failed to decode InlineValueParams: ${err}') } return Response{ - id: request.id + id: request.id result: []InlineValueText{} } } @@ -8124,16 +8125,16 @@ fn (mut app App) handle_inline_value(request Request) Response { line: i char: col_start } - end: Position{ + end: Position{ line: i char: col_start + var_name.len } } - text: ': ${inferred}' + text: ': ${inferred}' } } return Response{ - id: request.id + id: request.id result: values } } @@ -8147,7 +8148,7 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { log('Failed to decode TextDocumentPositionParams for linkedEditingRange: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -8156,7 +8157,7 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { lines := content.split_into_lines() if params.position.line < 0 || params.position.line >= lines.len { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -8164,7 +8165,7 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { start, end := find_word_bounds_at_col(line_text, params.position.char, app.position_encoding) if start < 0 || end <= start { return Response{ - id: request.id + id: request.id result: 'null' } } @@ -8185,7 +8186,7 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { line: params.position.line char: sc } - end: Position{ + end: Position{ line: params.position.line char: ec } @@ -8195,12 +8196,12 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { } if ranges.len == 0 { return Response{ - id: request.id + id: request.id result: 'null' } } return Response{ - id: request.id + id: request.id result: LinkedEditingRanges{ ranges: ranges } @@ -8211,7 +8212,7 @@ fn (mut app App) handle_linked_editing_range(request Request) Response { // For now it returns empty edits — triggering v fmt on every keystroke would be too expensive. fn (mut app App) handle_on_type_formatting(request Request) Response { return Response{ - id: request.id + id: request.id result: []TextEdit{} } } diff --git a/handlers_test.v b/handlers_test.v index c5a8cdaf..ef4044f9 100644 --- a/handlers_test.v +++ b/handlers_test.v @@ -25,15 +25,15 @@ fn create_test_app() &App { os.mkdir_all(temp_dir) or { assert false, 'Failed to create test temp dir: ${err}' return &App{ - text: '' + text: '' open_files: map[string]string{} - temp_dir: temp_dir + temp_dir: temp_dir } } return &App{ - text: '' + text: '' open_files: map[string]string{} - temp_dir: temp_dir + temp_dir: temp_dir } } @@ -56,10 +56,10 @@ fn test_on_did_open_tracks_file() { uri := path_to_uri(test_file) request := Request{ - id: 1 - method: 'textDocument/didOpen' + id: 1 + method: 'textDocument/didOpen' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -201,7 +201,7 @@ fn test_on_did_open_uses_text_document_payload() { app.on_did_open(Request{ params: json2.encode(DidOpenTextDocumentParams{ text_document: DidOpenTextDocumentItem{ - uri: uri + uri: uri text: content } }, @@ -224,7 +224,7 @@ fn test_on_did_open_uses_empty_text_payload_without_disk_fallback() { app.on_did_open(Request{ params: json2.encode(DidOpenTextDocumentParams{ text_document: DidOpenTextDocumentItem{ - uri: uri + uri: uri text: '' } }, @@ -335,11 +335,11 @@ fn test_on_did_change_updates_content() { // Then change it new_content := 'module main\n\nfn main() {\n\tprintln("changed")\n}' request := Request{ - id: 2 - method: 'textDocument/didChange' + id: 2 + method: 'textDocument/didChange' jsonrpc: '2.0' - params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + params: json2.encode(Params{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -427,7 +427,7 @@ fn test_on_did_change_returns_notification() { request := Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -461,8 +461,8 @@ fn test_on_did_change_schedules_diagnostics_without_blocking() { result := app.on_did_change(Request{ params: json2.encode(DidChangeTextDocumentParams{ - text_document: VersionedTextDocumentIdentifier{ - uri: uri + text_document: VersionedTextDocumentIdentifier{ + uri: uri version: 2 } content_changes: [ContentChange{ @@ -502,22 +502,22 @@ fn test_diagnostics_scheduler_coalesces_pending_jobs() { uri := 'file:///pending.v' global_first, generation_first := scheduler.next_generation(uri) should_start := scheduler.enqueue(DiagnosticsJob{ - uri: uri - content: 'first' + uri: uri + content: 'first' global_generation: global_first - generation: generation_first - ready_at: 100 - write_mutex: app.write_mutex + generation: generation_first + ready_at: 100 + write_mutex: app.write_mutex }) assert should_start global_latest, generation_latest := scheduler.next_generation(uri) should_restart := scheduler.enqueue(DiagnosticsJob{ - uri: uri - content: 'latest' + uri: uri + content: 'latest' global_generation: global_latest - generation: generation_latest - ready_at: 100 - write_mutex: app.write_mutex + generation: generation_latest + ready_at: 100 + write_mutex: app.write_mutex }) assert !should_restart @@ -558,8 +558,8 @@ fn test_diagnostics_scheduler_requeues_pending_sibling_with_latest_buffers() { result := app.on_did_change(Request{ params: json2.encode(DidChangeTextDocumentParams{ - text_document: VersionedTextDocumentIdentifier{ - uri: uri_b + text_document: VersionedTextDocumentIdentifier{ + uri: uri_b version: 2 } content_changes: [ContentChange{ @@ -604,7 +604,7 @@ fn test_diagnostics_scheduler_requeues_sibling_after_open() { assert app.on_did_open(Request{ params: json2.encode(DidOpenTextDocumentParams{ text_document: DidOpenTextDocumentItem{ - uri: uri_b + uri: uri_b text: content_b } }, @@ -649,7 +649,7 @@ fn test_diagnostics_scheduler_requeues_sibling_after_save_text() { text_document: TextDocumentIdentifier{ uri: uri_b } - text: new_content_b + text: new_content_b }, escape_unicode: true ) @@ -739,7 +739,7 @@ fn test_diagnostics_scheduler_requeues_job_after_watched_file_change() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: uri_b + uri: uri_b event_type: 2 }] }) @@ -766,13 +766,13 @@ fn test_diagnostics_scheduler_requeues_active_sibling() { tickets_a := scheduler.begin_project_schedule(uri_a, project_key) assert tickets_a.len == 1 active_job := DiagnosticsJob{ - uri: uri_a - project_key: project_key + uri: uri_a + project_key: project_key project_generation: tickets_a[0].project_generation - global_generation: tickets_a[0].global_generation - generation: tickets_a[0].generation - ready_at: 0 - write_mutex: app.write_mutex + global_generation: tickets_a[0].global_generation + generation: tickets_a[0].generation + ready_at: 0 + write_mutex: app.write_mutex } assert scheduler.enqueue(active_job) jobs, should_stop := scheduler.take_ready_jobs(0) @@ -807,10 +807,10 @@ fn test_diagnostics_scheduler_checks_staleness_while_publishing() { uri := 'file:///publish.v' global_generation, generation := scheduler.next_generation(uri) job := DiagnosticsJob{ - uri: uri + uri: uri global_generation: global_generation - generation: generation - write_mutex: app.write_mutex + generation: generation + write_mutex: app.write_mutex } notification := Notification{ method: 'textDocument/publishDiagnostics' @@ -858,7 +858,7 @@ fn test_on_did_change_multiple_changes() { for change in changes { request := Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -905,7 +905,7 @@ fn test_on_did_change_updates_tracked_file() { new_content := 'modified content' app.on_did_change(Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -928,7 +928,7 @@ fn test_apply_incremental_change_handles_utf8_columns() { line: 0 char: 1 } - end: Position{ + end: Position{ line: 0 char: 2 } @@ -947,7 +947,7 @@ fn test_apply_incremental_change_preserves_crlf() { line: 1 char: 0 } - end: Position{ + end: Position{ line: 1 char: 3 } @@ -963,7 +963,7 @@ fn test_apply_incremental_change_rejects_reversed_range() { line: 0 char: 4 } - end: Position{ + end: Position{ line: 0 char: 2 } @@ -982,7 +982,7 @@ fn test_incremental_change_is_valid_rejects_lines_past_eof() { line: 5 char: 0 } - end: Position{ + end: Position{ line: 6 char: 0 } @@ -994,7 +994,7 @@ fn test_incremental_change_is_valid_rejects_lines_past_eof() { line: 1 char: 0 } - end: Position{ + end: Position{ line: 9 char: 0 } @@ -1006,7 +1006,7 @@ fn test_incremental_change_is_valid_rejects_lines_past_eof() { line: 0 char: 1 } - end: Position{ + end: Position{ line: 1 char: 2 } @@ -1057,7 +1057,7 @@ fn test_semantic_candidate_cap_ignores_unrelated_workspace_root() { app.ensure_dirs_indexed(app.index_query_dirs()) current_scope := IndexScope{ - dir: '/root_a' + dir: '/root_a' recursive: true } candidates := app.collect_semantic_candidates('unique', current_scope) @@ -1076,7 +1076,7 @@ fn test_incremental_change_is_valid_rejects_char_past_line() { line: 0 char: 9 } - end: Position{ + end: Position{ line: 1 char: 1 } @@ -1087,7 +1087,7 @@ fn test_incremental_change_is_valid_rejects_char_past_line() { line: 0 char: 1 } - end: Position{ + end: Position{ line: 1 char: 9 } @@ -1100,7 +1100,7 @@ fn test_incremental_change_is_valid_rejects_char_past_line() { line: 0 char: 3 } - end: Position{ + end: Position{ line: 0 char: 3 } @@ -1115,7 +1115,7 @@ fn test_apply_incremental_change_handles_multiline_ranges() { line: 0 char: 1 } - end: Position{ + end: Position{ line: 1 char: 2 } @@ -1141,13 +1141,13 @@ fn test_operation_at_pos_completion_line_info() { app.open_files[uri] = content request := Request{ - id: 1 + id: 1 method: 'textDocument/completion' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 4 } @@ -1177,13 +1177,13 @@ fn test_operation_at_pos_definition_line_info() { app.open_files[uri] = content request := Request{ - id: 2 + id: 2 method: 'textDocument/definition' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } @@ -2238,8 +2238,8 @@ fn test_active_indexed_source_file_names_applies_compiler_build_rules() { must_mkdir_all(test_dir) inactive_os := $if windows { 'linux' } $else { 'windows' } source := 'module main\n\nfn helper() {}\n' - for name in ['main.v', 'plain_${inactive_os}.v', 'gated_d_somefeature.v', - 'gated_notd_somefeature.v', 'main_test.v', 'sibling_${inactive_os}_test.v'] { + for name in ['main.v', 'plain_${inactive_os}.v', 'gated_d_somefeature.v', 'gated_notd_somefeature.v', + 'main_test.v', 'sibling_${inactive_os}_test.v'] { must_write_file(os.join_path(test_dir, name), source) } // A file the client created but has not saved yet is not on disk, so the @@ -2716,7 +2716,7 @@ fn test_source_declaration_at_stops_non_braced_declarations() { app.open_files[uri] = content constant := app.source_declaration_at(Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: 3 @@ -2726,7 +2726,7 @@ fn test_source_declaration_at_stops_non_braced_declarations() { assert constant == 'answer = 42' alias := app.source_declaration_at(Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: 7 @@ -2736,7 +2736,7 @@ fn test_source_declaration_at_stops_non_braced_declarations() { assert alias == 'type Alias = int' function_alias := app.source_declaration_at(Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: 8 @@ -2746,7 +2746,7 @@ fn test_source_declaration_at_stops_non_braced_declarations() { assert function_alias == 'type Handler = fn (int) bool' function := app.source_declaration_at(Location{ - uri: uri + uri: uri range: LSPRange{ start: Position{ line: 12 @@ -2839,13 +2839,13 @@ fn test_operation_at_pos_signature_help_line_info() { app.open_files[uri] = content request := Request{ - id: 3 + id: 3 method: 'textDocument/signatureHelp' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 7 } @@ -2878,12 +2878,12 @@ fn test_operation_at_pos_preserves_request_id() { test_ids := [0, 1, 42, 999, 12345] for id in test_ids { request := Request{ - id: id + id: id params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 2 char: 0 } @@ -2898,7 +2898,7 @@ fn test_operation_at_pos_preserves_request_id() { fn test_json_encode_response() { response := Response{ - id: 1 + id: 1 result: 'null' } encoded := json2.encode(response, escape_unicode: true) @@ -2908,20 +2908,20 @@ fn test_json_encode_response() { fn test_json_encode_capabilities_response() { response := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 1 + change: 1 } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true + definition_provider: true } } } @@ -2934,20 +2934,20 @@ fn test_json_encode_capabilities_response() { fn test_json_encode_completion_response() { details := [ Detail{ - kind: 6 - label: 'println' - detail: 'fn println(s string)' + kind: 6 + label: 'println' + detail: 'fn println(s string)' documentation: 'Prints to stdout' }, Detail{ - kind: 6 - label: 'print' - detail: 'fn print(s string)' + kind: 6 + label: 'print' + detail: 'fn print(s string)' documentation: 'Prints without newline' }, ] response := Response{ - id: 2 + id: 2 result: details } encoded := json2.encode(response, escape_unicode: true) @@ -2957,15 +2957,15 @@ fn test_json_encode_completion_response() { fn test_json_encode_location_response() { response := Response{ - id: 3 + id: 3 result: Location{ - uri: 'file:///test/main.v' + uri: 'file:///test/main.v' range: LSPRange{ start: Position{ line: 10 char: 5 } - end: Position{ + end: Position{ line: 10 char: 15 } @@ -2979,11 +2979,11 @@ fn test_json_encode_location_response() { fn test_json_encode_signature_help_response() { response := Response{ - id: 4 + id: 4 result: SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ - label: 'fn test(a int, b string)' + label: 'fn test(a int, b string)' parameters: [ ParameterInformation{ label: 'a int' @@ -3008,20 +3008,20 @@ fn test_json_encode_notification() { notification := Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [ LSPDiagnostic{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 5 char: 0 } - end: Position{ + end: Position{ line: 5 char: 10 } } - message: 'undefined identifier' + message: 'undefined identifier' severity: 1 }, ] @@ -3107,17 +3107,17 @@ fn test_diagnostics_deduplication() { errors := [ JsonError{ line_nr: 5 - col: 10 + col: 10 message: 'error 1' }, JsonError{ line_nr: 5 - col: 10 + col: 10 message: 'error 2' }, // duplicate position JsonError{ line_nr: 6 - col: 5 + col: 5 message: 'error 3' }, ] @@ -3141,17 +3141,17 @@ fn test_diagnostics_deduplication_same_line_different_col() { errors := [ JsonError{ line_nr: 5 - col: 1 + col: 1 message: 'error 1' }, JsonError{ line_nr: 5 - col: 10 + col: 10 message: 'error 2' }, JsonError{ line_nr: 5 - col: 20 + col: 20 message: 'error 3' }, ] @@ -3198,7 +3198,7 @@ fn test_response_result_string() { fn test_response_result_details() { details := [ Detail{ - kind: 6 + kind: 6 label: 'test' }, ] @@ -3273,11 +3273,11 @@ fn test_app_exit_flag_default() { fn test_v_error_to_lsp_diagnostic_basic() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'undefined identifier `foo`' line_nr: 10 - col: 5 - len: 3 + col: 5 + len: 3 } diag := v_error_to_lsp_diagnostic(v_err) @@ -3292,11 +3292,11 @@ fn test_v_error_to_lsp_diagnostic_basic() { fn test_v_error_to_lsp_diagnostic_first_line() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'syntax error' line_nr: 1 - col: 1 - len: 1 + col: 1 + len: 1 } diag := v_error_to_lsp_diagnostic(v_err) @@ -3307,11 +3307,11 @@ fn test_v_error_to_lsp_diagnostic_first_line() { fn test_v_error_to_lsp_diagnostic_long_error() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'unexpected token' line_nr: 100 - col: 50 - len: 20 + col: 50 + len: 20 } diag := v_error_to_lsp_diagnostic(v_err) @@ -3322,11 +3322,11 @@ fn test_v_error_to_lsp_diagnostic_long_error() { fn test_v_error_to_lsp_diagnostic_zero_length() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'error at position' line_nr: 5 - col: 10 - len: 0 + col: 10 + len: 0 } diag := v_error_to_lsp_diagnostic(v_err) @@ -3347,8 +3347,8 @@ fn test_v_error_to_lsp_diagnostic_preserves_message() { v_err := JsonError{ message: msg line_nr: 1 - col: 1 - len: 1 + col: 1 + len: 1 } diag := v_error_to_lsp_diagnostic(v_err) assert diag.message == msg @@ -3357,11 +3357,11 @@ fn test_v_error_to_lsp_diagnostic_preserves_message() { fn test_v_error_to_lsp_diagnostic_always_error_severity() { v_err := JsonError{ - path: '/test.v' + path: '/test.v' message: 'any error' line_nr: 1 - col: 1 - len: 1 + col: 1 + len: 1 } diag := v_error_to_lsp_diagnostic(v_err) assert diag.severity == 1 // Always Error severity @@ -3438,7 +3438,7 @@ fn test_multifile_change_single_file() { new_content := 'module main\n\nfn main() { changed }' app.on_did_change(Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: main_uri } content_changes: [ContentChange{ @@ -3472,10 +3472,10 @@ fn test_handle_formatting_formats_code() { app.open_files[uri] = unformatted request := Request{ - id: 1 - method: 'textDocument/formatting' + id: 1 + method: 'textDocument/formatting' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -3519,10 +3519,10 @@ fn test_handle_formatting_already_formatted() { app.open_files[uri] = formatted request := Request{ - id: 2 - method: 'textDocument/formatting' + id: 2 + method: 'textDocument/formatting' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -3552,10 +3552,10 @@ fn test_handle_formatting_nonexistent_file() { uri := path_to_uri(nonexistent) request := Request{ - id: 3 - method: 'textDocument/formatting' + id: 3 + method: 'textDocument/formatting' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -3592,10 +3592,10 @@ fn test_handle_formatting_uses_open_file_content() { app.open_files[uri] = 'module main\n\nfn new( ) {}' request := Request{ - id: 4 - method: 'textDocument/formatting' + id: 4 + method: 'textDocument/formatting' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -3633,17 +3633,17 @@ fn test_find_references_returns_null_when_no_symbol_at_position() { app.open_files[uri] = content resp := app.find_references(Request{ - id: 901 + id: 901 method: 'textDocument/references' params: json2.encode(ReferenceParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 1 char: 0 } - context: ReferenceContext{ + context: ReferenceContext{ include_declaration: true } }, @@ -3672,17 +3672,17 @@ fn test_handle_rename_returns_null_when_no_symbol_at_position() { app.open_files[uri] = content resp := app.handle_rename(Request{ - id: 902 + id: 902 method: 'textDocument/rename' params: json2.encode(RenameParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 1 char: 0 } - new_name: 'renamed' + new_name: 'renamed' }, escape_unicode: true ) @@ -3740,7 +3740,7 @@ fn test_did_close_reindexes_noncanonical_uri_under_disk_uri() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: disk_uri + uri: disk_uri event_type: 2 }] }) @@ -3770,17 +3770,17 @@ fn test_handle_rename_refuses_incomplete_oversized_sibling_index() { app.open_files[uri] = content resp := app.handle_rename(Request{ - id: 903 + id: 903 method: 'textDocument/rename' params: json2.encode(RenameParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 2 char: 4 } - new_name: 'renamed' + new_name: 'renamed' }, escape_unicode: true ) @@ -4043,7 +4043,7 @@ fn test_handle_document_symbols_empty_file() { app.open_files[uri] = '' request := Request{ - id: 10 + id: 10 method: 'textDocument/documentSymbol' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ @@ -4071,7 +4071,7 @@ fn test_handle_document_symbols_no_tracked_file() { // URI not in open_files — should still return an empty symbol list, not crash request := Request{ - id: 11 + id: 11 method: 'textDocument/documentSymbol' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ @@ -4101,7 +4101,7 @@ fn test_handle_document_symbols_returns_correct_symbols() { app.open_files[uri] = 'module main\n\nfn hello() {}\n\nstruct Config {}\n\nenum Mode { on off }\n\nconst version = 1\n' request := Request{ - id: 12 + id: 12 method: 'textDocument/documentSymbol' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ @@ -4138,7 +4138,7 @@ fn test_handle_document_symbols_preserves_request_id() { for id in [1, 99, 1000, 0] { request := Request{ - id: id + id: id method: 'textDocument/documentSymbol' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ @@ -4176,7 +4176,7 @@ const my_const = 42 ' request := Request{ - id: 20 + id: 20 method: 'textDocument/documentSymbol' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ @@ -4513,13 +4513,13 @@ fn main() { char: start_col + 1 } response := app.operation_at_pos(.hover, Request{ - id: 904 + id: 904 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: position + position: position }, escape_unicode: true ) @@ -4690,18 +4690,18 @@ obj := MyStruct{} app.open_files[uri] = content request := Request{ - id: 30 + id: 30 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 9 char: 0 } @@ -4741,18 +4741,18 @@ x := 99 app.open_files[uri] = content request := Request{ - id: 31 + id: 31 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 4 char: 0 } @@ -4788,18 +4788,18 @@ fn test_handle_inlay_hints_empty_file() { app.open_files[uri] = '' request := Request{ - id: 32 + id: 32 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 0 } @@ -4831,18 +4831,18 @@ mut count := 0 app.open_files[uri] = content request := Request{ - id: 33 + id: 33 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 2 char: 0 } @@ -4880,18 +4880,18 @@ const is_debug = false app.open_files[uri] = content request := Request{ - id: 34 + id: 34 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 7 char: 0 } @@ -4935,18 +4935,18 @@ enabled = true app.open_files[uri] = content request := Request{ - id: 35 + id: 35 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 9 char: 0 } @@ -4986,18 +4986,18 @@ fn test_handle_inlay_hints_local_fn_call() { app.open_files[uri] = 'module main\n\nfn main() {\n\tmsg := get_greeting()\n}\n' request := Request{ - id: 40 + id: 40 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 5 char: 0 } @@ -5031,18 +5031,18 @@ fn test_handle_inlay_hints_error_result_fn() { app.open_files[uri] = 'module main\n\nfn main() {\n\tdata := read_data() or { return }\n}\n' request := Request{ - id: 41 + id: 41 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 5 char: 0 } @@ -5081,18 +5081,18 @@ greeting := get_greeting() app.open_files[uri] = content request := Request{ - id: 50 + id: 50 method: 'textDocument/inlayHint' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 9 char: 0 } @@ -5657,13 +5657,13 @@ fn test_operation_at_pos_completion_includes_current_file_fns() { app.text = content request := Request{ - id: 1 + id: 1 method: 'textDocument/completion' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 4 } @@ -5703,13 +5703,13 @@ fn test_operation_at_pos_dot_completion_includes_imported_module_members() { app.text = content response := app.operation_at_pos(.completion, Request{ - id: 9001 + id: 9001 method: 'textDocument/completion' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 8 } @@ -5751,13 +5751,13 @@ fn test_operation_at_pos_dot_completion_includes_aliased_import_module_members() app.text = content response := app.operation_at_pos(.completion, Request{ - id: 9002 + id: 9002 method: 'textDocument/completion' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 4 } @@ -5897,13 +5897,13 @@ fn test_operation_at_pos_completion_and_definition_resolve_cross_file_receiver_m assert show_col >= 0 completion := app.operation_at_pos(.completion, Request{ - id: 9100 + id: 9100 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: show_col } @@ -5916,13 +5916,13 @@ fn test_operation_at_pos_completion_and_definition_resolve_cross_file_receiver_m assert completion_items.any(it.label == 'show' && it.kind == 2) definition := app.operation_at_pos(.definition, Request{ - id: 9101 + id: 9101 method: 'textDocument/definition' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: show_col + 2 } @@ -5956,13 +5956,13 @@ fn test_operation_at_pos_completion_includes_indexed_struct_fields() { completion_line := lines.index('\tuser.') assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9200 + id: 9200 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6001,13 +6001,13 @@ fn test_receiver_inference_does_not_reuse_declaration_from_earlier_function() { assert beta_col >= 0 completion := app.operation_at_pos(.completion, Request{ - id: 9201 + id: 9201 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: call_line char: dot_col + 1 } @@ -6021,13 +6021,13 @@ fn test_receiver_inference_does_not_reuse_declaration_from_earlier_function() { assert !items.any(it.label == 'alpha') definition := app.operation_at_pos(.definition, Request{ - id: 9202 + id: 9202 method: 'textDocument/definition' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: call_line char: beta_col + 2 } @@ -6066,13 +6066,13 @@ fn test_imported_module_completion_resolves_from_project_root() { completion_line := lines.index('\tmylib.') assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9203 + id: 9203 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6104,13 +6104,13 @@ fn test_bare_completion_includes_local_and_top_level_scope_symbols() { completion_line := lines.index('\tlocal_') assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9300 + id: 9300 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6162,13 +6162,13 @@ fn test_literal_and_container_receiver_completion_falls_back_to_compiler() { expected_member := if case_idx == 0 { 'after' } else { 'filter' } assert indexed.items.any(it.label == expected_member), completion_case.str() response := app.operation_at_pos(.completion, Request{ - id: 9301 + case_idx + id: 9301 + case_idx method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6211,13 +6211,13 @@ fn test_typed_container_receiver_does_not_infer_nested_struct_type() { assert !indexed.use_compiler, declaration assert !indexed.items.any(it.label in ['name', 'save']), declaration response := app.operation_at_pos(.completion, Request{ - id: 9350 + id: 9350 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6252,13 +6252,13 @@ fn test_receiver_completion_honors_local_binding_that_shadows_import() { completion_line := lines.index('\tclock.') assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9303 + id: 9303 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6297,13 +6297,13 @@ fn test_imported_module_completion_uses_unsaved_open_buffer() { assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9304 + id: 9304 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6343,13 +6343,13 @@ fn test_member_completion_recognizes_typed_prefix() { completion_line := lines.index(source_line) assert completion_line >= 0 response := app.operation_at_pos(.completion, Request{ - id: 9400 + completion_line + id: 9400 + completion_line method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -6387,13 +6387,13 @@ fn test_local_scope_completion_drops_bindings_after_nested_block() { assert !app.local_scope_completions(content, position).any(it.label == 'clock') response := app.operation_at_pos(.completion, Request{ - id: 9401 + id: 9401 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: position + position: position }, escape_unicode: true ) @@ -6526,13 +6526,13 @@ fn test_hover_prefers_shadowing_closure_parameter_type() { x_col := lines[line].index('x') or { -1 } assert x_col >= 0 response := app.operation_at_pos(.hover, Request{ - id: 9501 + id: 9501 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: line char: x_col + 1 } @@ -6573,13 +6573,13 @@ fn test_hover_does_not_treat_member_selector_as_local_binding() { char: field_col }) == none field_response := app.operation_at_pos(.hover, Request{ - id: 9531 + id: 9531 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: line char: field_col } @@ -6729,13 +6729,13 @@ fn test_hover_keeps_reference_and_option_parameter_types() { // uses, and returns the text of the answer. fn public_hover_text(mut app App, uri string, line int, character int) string { response := app.operation_at_pos(.hover, Request{ - id: 9700 + line + id: 9700 + line method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: line char: character } @@ -6877,13 +6877,13 @@ fn test_hover_on_a_call_keeps_the_declaration_as_written() { // The compiler re-prints a function type without its parameter names, so the // declaration written in the source is the better answer. response := app.operation_at_pos(.hover, Request{ - id: 9601 + id: 9601 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: line char: col + 2 } @@ -6902,7 +6902,7 @@ fn test_hover_on_a_field_of_a_chain_answers_for_that_field() { } test_dir := os.join_path(app.temp_dir, 'chain_field_hover') must_mkdir_all(test_dir) - content := "module main\n\nstruct Child {\n\tvalue int\n}\n\nstruct Node {\n\tchild Child\n}\n\nstruct Listener {\n\tnode Node\n}\n\nfn main() {\n\tlistener := Listener{}\n\tprintln(listener.node.child.value)\n}\n" + content := 'module main\n\nstruct Child {\n\tvalue int\n}\n\nstruct Node {\n\tchild Child\n}\n\nstruct Listener {\n\tnode Node\n}\n\nfn main() {\n\tlistener := Listener{}\n\tprintln(listener.node.child.value)\n}\n' main_file := os.join_path(test_dir, 'main.v') must_write_file(main_file, content) uri := path_to_uri(main_file) @@ -6933,7 +6933,7 @@ fn test_hover_on_a_deep_chain_inside_nested_closures() { } test_dir := os.join_path(app.temp_dir, 'nested_chain_hover') must_mkdir_all(test_dir) - content := "module main\n\nstruct Leaf {\n\tflag bool\n}\n\nstruct Child {\n\tleaf Leaf\n}\n\nstruct Node {\n\tchild Child\n}\n\nstruct Listener {\n\tnode Node\n}\n\nfn main() {\n\tlisteners := []Listener{}\n\touter := fn (x Listener) bool {\n\t\tinner := fn (y Listener) bool {\n\t\t\treturn y.node.child.leaf.flag\n\t\t}\n\t\treturn inner(x) && x.node.child.leaf.flag\n\t}\n\tprintln(listeners.filter(outer))\n}\n" + content := 'module main\n\nstruct Leaf {\n\tflag bool\n}\n\nstruct Child {\n\tleaf Leaf\n}\n\nstruct Node {\n\tchild Child\n}\n\nstruct Listener {\n\tnode Node\n}\n\nfn main() {\n\tlisteners := []Listener{}\n\touter := fn (x Listener) bool {\n\t\tinner := fn (y Listener) bool {\n\t\t\treturn y.node.child.leaf.flag\n\t\t}\n\t\treturn inner(x) && x.node.child.leaf.flag\n\t}\n\tprintln(listeners.filter(outer))\n}\n' main_file := os.join_path(test_dir, 'main.v') must_write_file(main_file, content) uri := path_to_uri(main_file) @@ -7028,10 +7028,10 @@ fn test_hover_on_nested_closure_parameters_keeps_each_type() { // Three parameters of the same name, one inside the other: each hover has to // answer with the type written next to that one. for source_line, expected in { - '\touter := fn (x Listener) bool {': 'x Listener' - '\t\tinner := fn (x Child) bool {': 'x Child' - '\t\t\treturn x.value == 1': 'x Child' - '\t\treturn inner(x.node.child)': 'x Listener' + '\touter := fn (x Listener) bool {': 'x Listener' + '\t\tinner := fn (x Child) bool {': 'x Child' + '\t\t\treturn x.value == 1': 'x Child' + '\t\treturn inner(x.node.child)': 'x Listener' } { line := lines.index(source_line) assert line >= 0, source_line @@ -7065,9 +7065,9 @@ fn test_hover_types_a_binding_holding_a_function_literal() { // A function literal writes its own type down: the signature, without the // capture list and without the body. for name, expected in { - 'f': 'f fn (a int)' - 'g': 'g fn (a int, b string) !int' - 'h': 'h fn ()' + 'f': 'f fn (a int)' + 'g': 'g fn (a int, b string) !int' + 'h': 'h fn ()' 'c': 'c fn (a int) int' 'cb': 'cb fn (int) int' } { @@ -7097,7 +7097,7 @@ fn test_hover_types_bindings_whose_value_names_no_type() { } test_dir := os.join_path(app.temp_dir, 'inferred_binding_hover') must_mkdir_all(test_dir) - content := "module main\n\nfn make_int() !int {\n\treturn 3\n}\n\nfn work() int {\n\treturn 4\n}\n\nfn main() {\n\tres := make_int() or {\n\t\tprintln(err)\n\t\t0\n\t}\n\tth := spawn work()\n\tif v := make_int() {\n\t\tprintln(v)\n\t}\n\tprintln(res)\n\tprintln(th.wait())\n}\n" + content := 'module main\n\nfn make_int() !int {\n\treturn 3\n}\n\nfn work() int {\n\treturn 4\n}\n\nfn main() {\n\tres := make_int() or {\n\t\tprintln(err)\n\t\t0\n\t}\n\tth := spawn work()\n\tif v := make_int() {\n\t\tprintln(v)\n\t}\n\tprintln(res)\n\tprintln(th.wait())\n}\n' main_file := os.join_path(test_dir, 'main.v') must_write_file(main_file, content) uri := path_to_uri(main_file) @@ -7433,13 +7433,13 @@ fn test_embedded_struct_receiver_completion_includes_promoted_members() { assert !indexed.items.any(it.label == 'Base') response := app.operation_at_pos(.completion, Request{ - id: 9700 + id: 9700 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: position + position: position }, escape_unicode: true ) @@ -7961,13 +7961,13 @@ fn test_conditional_bare_completion_requests_compiler_fallback() { assert !indexed.items.any(it.label == 'platform_only') response := app.operation_at_pos(.completion, Request{ - id: 9600 + id: 9600 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: position + position: position }, escape_unicode: true ) @@ -8032,13 +8032,13 @@ fn test_conditional_methods_request_receiver_completion_fallback() { assert indexed.items.any(it.label == 'start') assert !indexed.items.any(it.label == 'reload') response := app.operation_at_pos(.completion, Request{ - id: 9601 + id: 9601 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: completion_line char: lines[completion_line].len } @@ -8163,13 +8163,13 @@ fn test_chained_definition_resolves_nested_receiver_not_import_alias() { assert indexed_location.uri == uri assert indexed_location.range.start.line == lines.index('fn (timer Timer) start() {}') definition := app.operation_at_pos(.definition, Request{ - id: 9602 + id: 9602 method: 'textDocument/definition' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: position + position: position }, escape_unicode: true ) @@ -8441,7 +8441,7 @@ fn test_semantic_tokens_returns_data_for_known_content() { app.open_files[uri] = content resp := app.handle_semantic_tokens(Request{ - id: 800 + id: 800 method: 'textDocument/semanticTokens/full' params: json2.encode(SemanticTokensParams{ text_document: TextDocumentIdentifier{ @@ -8531,7 +8531,7 @@ fn test_semantic_tokens_returns_empty_object_for_empty_file() { app.open_files[uri] = '' resp := app.handle_semantic_tokens(Request{ - id: 801 + id: 801 method: 'textDocument/semanticTokens/full' params: json2.encode(SemanticTokensParams{ text_document: TextDocumentIdentifier{ @@ -8556,7 +8556,7 @@ fn test_semantic_tokens_range_returns_empty_for_missing_document() { } resp := app.handle_semantic_tokens_range(Request{ - id: 802 + id: 802 method: 'textDocument/semanticTokens/range' params: '{}' }) @@ -8582,12 +8582,12 @@ fn test_semantic_tokens_range_filters_by_character() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 50 } @@ -8596,7 +8596,7 @@ fn test_semantic_tokens_range_filters_by_character() { escape_unicode: true ) full := app.handle_semantic_tokens_range(Request{ - id: 1 + id: 1 params: full_params }) ftok := full.result as SemanticTokens @@ -8612,12 +8612,12 @@ fn test_semantic_tokens_range_filters_by_character() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 8 } - end: Position{ + end: Position{ line: 0 char: 50 } @@ -8626,7 +8626,7 @@ fn test_semantic_tokens_range_filters_by_character() { escape_unicode: true ) narrow := app.handle_semantic_tokens_range(Request{ - id: 2 + id: 2 params: narrow_params }) ntok := narrow.result as SemanticTokens @@ -8648,7 +8648,7 @@ fn test_code_lens_returns_run_lens_for_main() { app.open_files[uri] = content resp := app.handle_code_lens(Request{ - id: 810 + id: 810 method: 'textDocument/codeLens' params: json2.encode(CodeLensParams{ text_document: TextDocumentIdentifier{ @@ -8681,7 +8681,7 @@ fn test_code_lens_range_uses_negotiated_position_encoding() { uri := 'file:///tmp/codelens_unicode.v' app.open_files[uri] = 'module main\n\nfn main() {} // 🚀\n' request := Request{ - id: 814 + id: 814 method: 'textDocument/codeLens' params: json2.encode(CodeLensParams{ text_document: TextDocumentIdentifier{ @@ -8724,7 +8724,7 @@ fn test_code_lens_returns_test_lens_for_test_fn() { app.open_files[uri] = content resp := app.handle_code_lens(Request{ - id: 811 + id: 811 method: 'textDocument/codeLens' params: json2.encode(CodeLensParams{ text_document: TextDocumentIdentifier{ @@ -8766,7 +8766,7 @@ fn test_code_lens_ignores_declarations_in_comments_and_non_test_files() { app.open_files[uri] = 'module main\n\n/*\nfn main() {}\nfn test_hidden() {}\n*/\nfn helper() {}\n' resp := app.handle_code_lens(Request{ - id: 813 + id: 813 method: 'textDocument/codeLens' params: json2.encode(CodeLensParams{ text_document: TextDocumentIdentifier{ @@ -8787,25 +8787,25 @@ fn test_code_lens_resolve_returns_same_lens() { cleanup_test_app(app) } lens := CodeLens{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 2 char: 0 } - end: Position{ + end: Position{ line: 2 char: 10 } } command: Command{ - title: '▶ Run' - command: 'vls.runFile' + title: '▶ Run' + command: 'vls.runFile' arguments: ['file:///tmp/a.v'] } } resp := app.handle_code_lens_resolve(Request{ - id: 812 + id: 812 method: 'codeLens/resolve' params: json2.encode(lens, escape_unicode: true) }) @@ -8826,7 +8826,7 @@ fn test_execute_command_returns_null_result() { app.capture_output = true resp := app.handle_execute_command(Request{ - id: 820 + id: 820 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ command: 'vls.runFile' @@ -8866,10 +8866,10 @@ fn test_execute_run_file_invokes_compiler() { app.execute_commands_synchronously = true resp := app.handle_execute_command(Request{ - id: 822 + id: 822 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runFile' + command: 'vls.runFile' arguments: [uri] }, escape_unicode: true @@ -8886,8 +8886,7 @@ fn test_execute_run_file_invokes_compiler() { main_column := main_source.split_into_lines()[7].index('@COLUMN') or { 0 } expected_paths := [os.real_path(project_dir), os.real_path(helper_path), 'helper.v:8', '${os.real_path(helper_path)}:8, main.code_lens_sibling_paths', (helper_column + 1).str(), - os.real_path(path), 'main.v:8', '${os.real_path(path)}:8, main.main', - (main_column + 1).str()] + os.real_path(path), 'main.v:8', '${os.real_path(path)}:8, main.main', (main_column + 1).str()] assert (os.read_file(compile_time_output_path) or { '' }) == expected_paths.join('\n') assert (os.read_file(vmod_output_path) or { '' }) == vmod_source assert (os.read_file(helper_path) or { '' }) == helper_source @@ -8907,10 +8906,10 @@ fn test_execute_run_file_materializes_new_unsaved_buffer() { app.execute_commands_synchronously = true resp := app.handle_execute_command(Request{ - id: 824 + id: 824 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runFile' + command: 'vls.runFile' arguments: [uri] }, escape_unicode: true @@ -8937,10 +8936,10 @@ fn test_execute_run_file_returns_before_long_running_program_finishes() { started_at := time.now().unix_milli() resp := app.handle_execute_command(Request{ - id: 825 + id: 825 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runFile' + command: 'vls.runFile' arguments: [path_to_uri(path)] }, escape_unicode: true @@ -8979,10 +8978,10 @@ fn test_execute_run_file_replaces_active_target() { app.capture_output = true first_resp := app.handle_execute_command(Request{ - id: 826 + id: 826 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runFile' + command: 'vls.runFile' arguments: [uri] }, escape_unicode: true @@ -9001,10 +9000,10 @@ fn test_execute_run_file_replaces_active_target() { app.open_files[uri] = 'module main\n\nimport os\nimport time\n\nfn main() {\n\tos.write_file(${marker_literal}, "second") or { return }\n\ttime.sleep(5 * time.second)\n}\n' second_resp := app.handle_execute_command(Request{ - id: 827 + id: 827 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runFile' + command: 'vls.runFile' arguments: [uri] }, escape_unicode: true @@ -9095,10 +9094,10 @@ fn test_execute_run_test_selects_one_function() { app.execute_commands_synchronously = true resp := app.handle_execute_command(Request{ - id: 823 + id: 823 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ - command: 'vls.runTests' + command: 'vls.runTests' arguments: [uri, 'test_selected'] }, escape_unicode: true @@ -9118,7 +9117,7 @@ fn test_execute_command_unknown_still_returns_null() { } resp := app.handle_execute_command(Request{ - id: 821 + id: 821 method: 'workspace/executeCommand' params: json2.encode(ExecuteCommandParams{ command: 'unknownCommand' @@ -9144,18 +9143,18 @@ fn test_inline_value_returns_values_for_simple_assignment() { app.open_files[uri] = content resp := app.handle_inline_value(Request{ - id: 830 + id: 830 method: 'textDocument/inlineValue' params: json2.encode(InlineValueParams{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 5 char: 0 } @@ -9181,18 +9180,18 @@ fn test_inline_value_returns_empty_for_no_assignments() { app.open_files[uri] = 'module main\n\nfn main() {}\n' resp := app.handle_inline_value(Request{ - id: 831 + id: 831 method: 'textDocument/inlineValue' params: json2.encode(InlineValueParams{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 2 char: 0 } @@ -9221,13 +9220,13 @@ fn test_linked_editing_range_returns_ranges_for_identifier() { app.open_files[uri] = content resp := app.handle_linked_editing_range(Request{ - id: 840 + id: 840 method: 'textDocument/linkedEditingRange' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 2 } @@ -9253,13 +9252,13 @@ fn test_linked_editing_range_returns_null_when_not_on_identifier() { // Position on an empty line resp := app.handle_linked_editing_range(Request{ - id: 841 + id: 841 method: 'textDocument/linkedEditingRange' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 1 char: 0 } @@ -9285,13 +9284,13 @@ fn test_selection_range_returns_one_entry_per_position() { app.open_files[uri] = content resp := app.handle_selection_range(Request{ - id: 850 + id: 850 method: 'textDocument/selectionRange' params: json2.encode(SelectionRangeParams{ text_document: TextDocumentIdentifier{ uri: uri } - positions: [Position{ + positions: [Position{ line: 3 char: 2 }, Position{ @@ -9319,13 +9318,13 @@ fn test_selection_range_word_range_has_parent_line_range() { app.open_files[uri] = content resp := app.handle_selection_range(Request{ - id: 851 + id: 851 method: 'textDocument/selectionRange' params: json2.encode(SelectionRangeParams{ text_document: TextDocumentIdentifier{ uri: uri } - positions: [Position{ + positions: [Position{ line: 3 char: 2 }] @@ -9353,17 +9352,17 @@ fn test_on_type_formatting_returns_empty_edits() { } resp := app.handle_on_type_formatting(Request{ - id: 860 + id: 860 method: 'textDocument/onTypeFormatting' params: json2.encode(OnTypeFormattingParams{ text_document: TextDocumentIdentifier{ uri: 'file:///tmp/fmt.v' } - position: Position{ + position: Position{ line: 3 char: 0 } - ch: '}' + ch: '}' }, escape_unicode: true ) @@ -9393,19 +9392,19 @@ fn test_call_hierarchy_outgoing_returns_callees() { app.workspace_roots = [root] resp := app.handle_call_hierarchy_outgoing(Request{ - id: 870 + id: 870 method: 'callHierarchy/outgoingCalls' params: json2.encode(CallHierarchyOutgoingCallsParams{ item: CallHierarchyItem{ - name: 'main' - kind: sym_kind_function - uri: uri - range: LSPRange{ + name: 'main' + kind: sym_kind_function + uri: uri + range: LSPRange{ start: Position{ line: 4 char: 0 } - end: Position{ + end: Position{ line: 6 char: 1 } @@ -9415,7 +9414,7 @@ fn test_call_hierarchy_outgoing_returns_callees() { line: 4 char: 3 } - end: Position{ + end: Position{ line: 4 char: 7 } @@ -9448,19 +9447,19 @@ fn test_call_hierarchy_incoming_returns_callers() { app.workspace_roots = [root] resp := app.handle_call_hierarchy_incoming(Request{ - id: 871 + id: 871 method: 'callHierarchy/incomingCalls' params: json2.encode(CallHierarchyIncomingCallsParams{ item: CallHierarchyItem{ - name: 'helper' - kind: sym_kind_function - uri: uri - range: LSPRange{ + name: 'helper' + kind: sym_kind_function + uri: uri + range: LSPRange{ start: Position{ line: 2 char: 0 } - end: Position{ + end: Position{ line: 2 char: 15 } @@ -9470,7 +9469,7 @@ fn test_call_hierarchy_incoming_returns_callers() { line: 2 char: 3 } - end: Position{ + end: Position{ line: 2 char: 9 } @@ -9501,11 +9500,11 @@ fn test_organize_imports_refuses_non_contiguous_block() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{} - context: CodeActionContext{} + range: LSPRange{} + context: CodeActionContext{} } resp := app.handle_code_action(Request{ - id: 1 + id: 1 params: json2.encode(params, escape_unicode: true) }) assert resp.result is []CodeAction @@ -9526,11 +9525,11 @@ fn test_organize_imports_sorts_contiguous_block() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{} - context: CodeActionContext{} + range: LSPRange{} + context: CodeActionContext{} } resp := app.handle_code_action(Request{ - id: 2 + id: 2 params: json2.encode(params, escape_unicode: true) }) assert resp.result is []CodeAction @@ -9557,13 +9556,13 @@ fn test_organize_imports_preserves_crlf_line_endings() { uri := 'file:///tmp/oi_crlf.v' app.open_files[uri] = 'module main\r\n\r\nimport time\r\nimport os\r\n\r\nfn main() {}\r\n' resp := app.handle_code_action(Request{ - id: 3 + id: 3 params: json2.encode(CodeActionParams{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{} - context: CodeActionContext{} + range: LSPRange{} + context: CodeActionContext{} }, escape_unicode: true ) @@ -9599,12 +9598,12 @@ fn test_remove_unknown_import_range_at_eof_without_newline() { app.open_files[uri] = 'module main\nimport foo' diag := LSPDiagnostic{ message: 'cannot import module "foo" (not found)' - range: LSPRange{ + range: LSPRange{ start: Position{ line: 1 char: 0 } - end: Position{ + end: Position{ line: 1 char: 10 } @@ -9614,13 +9613,13 @@ fn test_remove_unknown_import_range_at_eof_without_newline() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{} - context: CodeActionContext{ + range: LSPRange{} + context: CodeActionContext{ diagnostics: [diag] } } resp := app.handle_code_action(Request{ - id: 1 + id: 1 params: json2.encode(params, escape_unicode: true) }) actions := resp.result as []CodeAction @@ -9651,12 +9650,12 @@ fn test_remove_unknown_import_range_with_trailing_newline() { app.open_files[uri] = 'import foo\nmodule main\n' diag := LSPDiagnostic{ message: 'unknown module `foo`' - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 10 } @@ -9666,13 +9665,13 @@ fn test_remove_unknown_import_range_with_trailing_newline() { text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{} - context: CodeActionContext{ + range: LSPRange{} + context: CodeActionContext{ diagnostics: [diag] } } resp := app.handle_code_action(Request{ - id: 1 + id: 1 params: json2.encode(params, escape_unicode: true) }) actions := resp.result as []CodeAction @@ -9780,7 +9779,7 @@ fn test_apply_incremental_change_non_bmp_utf16() { line: 0 char: 3 // after 🚀 in UTF-16 units (a=1, 🚀=2) } - end: Position{ + end: Position{ line: 0 char: 4 } @@ -9876,13 +9875,13 @@ fn test_document_highlight_returns_empty_over_semantic_cap() { app.open_files[uri] = content response := app.handle_document_highlight(Request{ - id: 900 + id: 900 method: 'textDocument/documentHighlight' params: json2.encode(DocumentHighlightParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 5 } @@ -9908,19 +9907,19 @@ fn test_on_did_change_invalid_range_does_not_advance_version() { // must NOT advance (P0-07). app.on_did_change(Request{ params: json2.encode(DidChangeTextDocumentParams{ - text_document: VersionedTextDocumentIdentifier{ - uri: uri + text_document: VersionedTextDocumentIdentifier{ + uri: uri version: 2 } content_changes: [ ContentChange{ - text: 'X' + text: 'X' range: LSPRange{ start: Position{ line: 0 char: 5 } - end: Position{ + end: Position{ line: 0 char: 2 } @@ -9968,13 +9967,13 @@ fn test_operation_at_pos_hover_returns_symbol_information() { app.text = content response := app.operation_at_pos(.hover, Request{ - id: 901 + id: 901 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 8 char: 13 } @@ -10047,13 +10046,13 @@ fn main() { } response := app.operation_at_pos(.hover, Request{ - id: 902 + id: 902 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: call_line char: new_col + 1 } @@ -10077,13 +10076,13 @@ fn main() { return } imported_response := app.operation_at_pos(.hover, Request{ - id: 903 + id: 903 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: imported_line char: imported_col + 1 } @@ -10114,17 +10113,17 @@ fn test_find_references_returns_declaration_and_calls() { app.workspace_roots = [test_dir] response := app.find_references(Request{ - id: 902 + id: 902 method: 'textDocument/references' params: json2.encode(ReferenceParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 7 char: 10 } - context: ReferenceContext{ + context: ReferenceContext{ include_declaration: true } }, @@ -10158,17 +10157,17 @@ fn test_handle_rename_returns_complete_workspace_edit() { app.workspace_roots = [test_dir] response := app.handle_rename(Request{ - id: 903 + id: 903 method: 'textDocument/rename' params: json2.encode(RenameParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 7 char: 11 } - new_name: 'renamed_value' + new_name: 'renamed_value' }, escape_unicode: true ) @@ -10200,7 +10199,7 @@ fn test_folding_range_covers_imports_comments_and_code_blocks() { app.open_files[uri] = 'module main\n\nimport os\nimport time\n\n// first line\n// second line\n\nfn main() {\n\tprintln(os.args)\n}\n' response := app.handle_folding_range(Request{ - id: 904 + id: 904 method: 'textDocument/foldingRange' params: json2.encode(FoldingRangeParams{ text_document: TextDocumentIdentifier{ @@ -10233,13 +10232,13 @@ fn test_document_highlight_returns_reads_and_writes() { app.open_files[uri] = content response := app.handle_document_highlight(Request{ - id: 905 + id: 905 method: 'textDocument/documentHighlight' params: json2.encode(DocumentHighlightParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 2 } @@ -10273,15 +10272,15 @@ fn test_workspace_configuration_toggles_feature_behavior() { assert !app.diagnostics_enabled hint_response := app.handle_inlay_hints(Request{ - id: 906 + id: 906 method: 'textDocument/inlayHint' params: json2.encode(InlayHintParams{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{} - end: Position{ + end: Position{ line: 5 } } @@ -10364,13 +10363,13 @@ fn test_will_save_wait_until_formats_without_mutating_open_document() { app.open_files[uri] = content response := app.on_will_save_wait_until(Request{ - id: 907 + id: 907 method: 'textDocument/willSaveWaitUntil' params: json2.encode(WillSaveTextDocumentParams{ text_document: TextDocumentIdentifier{ uri: uri } - reason: 1 + reason: 1 }, escape_unicode: true ) @@ -10398,22 +10397,22 @@ fn test_range_formatting_returns_only_contained_changed_hunk() { app.open_files[uri] = content response := app.handle_range_formatting(Request{ - id: 908 + id: 908 method: 'textDocument/rangeFormatting' params: json2.encode(DocumentRangeFormattingParams{ text_document: TextDocumentIdentifier{ uri: uri } - range: LSPRange{ + range: LSPRange{ start: Position{ line: 3 } - end: Position{ + end: Position{ line: 3 char: 4 } } - options: FormattingOptions{ + options: FormattingOptions{ tab_size: 4 } }, @@ -10439,13 +10438,13 @@ fn test_prepare_call_hierarchy_returns_function_item() { app.open_files[uri] = 'module main\n\nfn helper() {}\n\nfn main() {\n\thelper()\n}\n' response := app.handle_prepare_call_hierarchy(Request{ - id: 909 + id: 909 method: 'textDocument/prepareCallHierarchy' params: json2.encode(PrepareCallHierarchyParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } @@ -10538,12 +10537,12 @@ fn test_unary_ampersand_operand_is_guarded() { uri := path_to_uri(os.join_path(app.temp_dir, 'guarded_ampersand.v')) content := 'module main\n\nfn main() {}\n' app.open_files[uri] = content - assert app.expression_type(uri, content, '&', Position{line: 0, char: 0}) == '' - assert app.expression_type(uri, content, '(&)', Position{line: 0, char: 0}) == '' + assert app.expression_type(uri, content, '&', Position{ line: 0, char: 0 }) == '' + assert app.expression_type(uri, content, '(&)', Position{ line: 0, char: 0 }) == '' } fn test_index_key_with_dotdot_in_string_literal_is_not_treated_as_slice() { - result := indexed_completions_at_line_end('map_key_dotdot_completion', 'module main\n\nstruct Point {\n\tx int\n}\n\nfn main() {\n\tm := map[string]Point{}\n\tm[\'a..b\'].\n}\n', '\tm[\'a..b\'].') + result := indexed_completions_at_line_end('map_key_dotdot_completion', "module main\n\nstruct Point {\n\tx int\n}\n\nfn main() {\n\tm := map[string]Point{}\n\tm['a..b'].\n}\n", "\tm['a..b'].") labels := result.items.map(it.label) assert 'x' in labels, labels.str() assert 'keys' !in labels, labels.str() @@ -11081,8 +11080,9 @@ fn array_completion_items(dir_name string, decl string) []Detail { fn test_array_receivers_complete_their_builtin_methods() { ints := array_completion_items('array_int_literal', 'arr := [3, 1, 2]') int_labels := ints.map(it.label) - for name in ['len', 'cap', 'filter', 'map', 'sort', 'sorted', 'contains', 'index', 'first', 'last', - 'pop', 'insert', 'prepend', 'delete', 'clear', 'reverse', 'clone', 'any', 'all', 'count', 'trim'] { + for name in ['len', 'cap', 'filter', 'map', 'sort', 'sorted', 'contains', 'index', 'first', + 'last', 'pop', 'insert', 'prepend', 'delete', 'clear', 'reverse', 'clone', 'any', 'all', + 'count', 'trim'] { assert name in int_labels, '${name} missing: ${int_labels}' } assert 'join' !in int_labels diff --git a/index.v b/index.v index 81456c67..3218418b 100644 --- a/index.v +++ b/index.v @@ -20,11 +20,11 @@ import time struct IndexEntry { fingerprint int // content.hash(); used to skip re-parsing unchanged files module_name string - doc_symbols []DocumentSymbol // hierarchical symbols (as parse_document_symbols returns) + doc_symbols []DocumentSymbol // hierarchical symbols (as parse_document_symbols returns) docs map[string]string // simple symbol name -> leading vdoc comment - fn_completions []Detail // free-function completion items for this file - module_completions []Detail // all same-module top-level completion items - public_module_completions []Detail // exported completion items for imported modules + fn_completions []Detail // free-function completion items for this file + module_completions []Detail // all same-module top-level completion items + public_module_completions []Detail // exported completion items for imported modules has_conditional_module_completions bool has_conditional_public_completions bool conditional_lines []bool // declarations guarded by $if/$else or @[if] @@ -52,16 +52,16 @@ fn build_index_entry(content string, enc PositionEncoding) IndexEntry { } } return IndexEntry{ - fingerprint: content.hash() - module_name: get_module_name(content) - doc_symbols: doc_syms - docs: docs - fn_completions: module_completion_index.items.filter(it.kind == 3) - module_completions: module_completion_index.items - public_module_completions: public_module_completion_index.items + fingerprint: content.hash() + module_name: get_module_name(content) + doc_symbols: doc_syms + docs: docs + fn_completions: module_completion_index.items.filter(it.kind == 3) + module_completions: module_completion_index.items + public_module_completions: public_module_completion_index.items has_conditional_module_completions: module_completion_index.has_conditional has_conditional_public_completions: public_module_completion_index.has_conditional - conditional_lines: conditional_lines + conditional_lines: conditional_lines } } @@ -75,12 +75,12 @@ fn encode_document_symbols(syms []DocumentSymbol, lines []string, enc PositionEn mut out := []DocumentSymbol{cap: syms.len} for sym in syms { out << DocumentSymbol{ - name: sym.name - kind: sym.kind - tags: sym.tags - range: encode_range_chars(sym.range, lines, enc) + name: sym.name + kind: sym.kind + tags: sym.tags + range: encode_range_chars(sym.range, lines, enc) selection_range: encode_range_chars(sym.selection_range, lines, enc) - children: encode_document_symbols(sym.children, lines, enc) + children: encode_document_symbols(sym.children, lines, enc) } } return out @@ -104,7 +104,7 @@ fn encode_range_chars(r LSPRange, lines []string, enc PositionEncoding) LSPRange line: r.start.line char: byte_to_encoded_col(start_line, r.start.char, enc) } - end: Position{ + end: Position{ line: r.end.line char: byte_to_encoded_col(end_line, r.end.char, enc) } @@ -156,9 +156,9 @@ fn add_identifier_occurrence(line_text string, line_idx int, start int, end int, } name := line_text[start..end] occ[name] << TokenOccurrence{ - line: line_idx + line: line_idx start_char: byte_to_encoded_col(line_text, start, enc) - end_char: byte_to_encoded_col(line_text, end, enc) + end_char: byte_to_encoded_col(line_text, end, enc) } } @@ -305,7 +305,7 @@ fn (mut app App) occurrences_for(uri string) map[string][]TokenOccurrence { occ := extract_identifier_occurrences(content, app.position_encoding) app.ref_occurrences[uri] = OccEntry{ fingerprint: fp - occ: occ + occ: occ } return occ } @@ -763,13 +763,13 @@ fn (app &App) index_scope_for_uri(uri string) IndexScope { if project_root != '' && project_root != '/' && (workspace_root == '' || path_is_within(project_root, workspace_root)) { return IndexScope{ - dir: project_root + dir: project_root recursive: true } } if workspace_root != '' { return IndexScope{ - dir: workspace_root + dir: workspace_root recursive: true } } diff --git a/index_test.v b/index_test.v index 3f459705..2afa8fc1 100644 --- a/index_test.v +++ b/index_test.v @@ -9,7 +9,7 @@ import time fn index_test_app() &App { return &App{ open_files: map[string]string{} - temp_dir: os.temp_dir() + temp_dir: os.temp_dir() } } @@ -105,7 +105,7 @@ fn test_watched_file_reindex_drops_oversized_disk_entry() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: uri + uri: uri event_type: 1 }] }) @@ -121,7 +121,7 @@ fn test_watched_file_reindex_drops_oversized_disk_entry() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: uri + uri: uri event_type: 2 }] }) @@ -148,7 +148,7 @@ fn test_watched_file_reindex_obeys_total_entry_limit() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: uri + uri: uri event_type: 1 }] }) @@ -177,7 +177,7 @@ fn test_watched_file_reuses_equivalent_open_document_uri() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: event_uri + uri: event_uri event_type: 2 }] }) @@ -1027,7 +1027,7 @@ fn test_index_large_multifile_project_stays_complete_and_incremental() { app.on_did_change_watched_files(Request{ params: json2.encode(DidChangeWatchedFilesParams{ changes: [FileEvent{ - uri: changed_uri + uri: changed_uri event_type: 2 }] }) diff --git a/integration_test.v b/integration_test.v index d3410bdf..c89df040 100644 --- a/integration_test.v +++ b/integration_test.v @@ -59,9 +59,9 @@ fn create_integration_test_env() (&App, string) { integration_test_must_mkdir_all(project_dir) app := &App{ - text: '' + text: '' open_files: map[string]string{} - temp_dir: temp_dir + temp_dir: temp_dir } return app, project_dir } @@ -165,20 +165,20 @@ fn test_integration_stdio_initialize_completion_and_hover() { fn test_integration_initialize_capabilities() { // Simulate what the server returns for initialize response := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 1 + change: 1 } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true + definition_provider: true } } } @@ -199,7 +199,7 @@ fn test_integration_initialize_capabilities() { fn test_integration_initialize_response_structure() { // Verify response has proper JSON-RPC structure response := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ definition_provider: true @@ -217,7 +217,7 @@ fn test_integration_initialize_response_structure() { fn test_integration_initialize_does_not_advertise_client_snippet_support() { response := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ completion_provider: CompletionProvider{ @@ -233,14 +233,14 @@ fn test_integration_initialize_does_not_advertise_client_snippet_support() { fn test_integration_initialize_workspace_capabilities() { response := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ execute_command_provider: ExecuteCommandOptions{ commands: ['vls.runFile', 'vls.runTests'] } - workspace: WorkspaceCapability{ - file_operations: WorkspaceFileOperations{ + workspace: WorkspaceCapability{ + file_operations: WorkspaceFileOperations{ will_create: FileOperationRegistrationOptions{ filters: [ FileOperationFilter{ @@ -270,7 +270,7 @@ fn test_integration_initialize_workspace_capabilities() { } } workspace_folders: WorkspaceFoldersServerCapability{ - supported: true + supported: true change_notifications: true } } @@ -301,10 +301,10 @@ fn test_integration_document_lifecycle() { // 1. Open document open_request := Request{ - id: 1 - method: 'textDocument/didOpen' + id: 1 + method: 'textDocument/didOpen' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } @@ -320,11 +320,11 @@ fn test_integration_document_lifecycle() { // 2. Change document new_content := "module main\n\nfn main() {\n\tprintln('world')\n}\n" change_request := Request{ - id: 2 - method: 'textDocument/didChange' + id: 2 + method: 'textDocument/didChange' jsonrpc: '2.0' - params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + params: json2.encode(Params{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -539,7 +539,7 @@ fn test_integration_diagnostics_syntax_error() { // Trigger change to get diagnostics change_request := Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -585,7 +585,7 @@ fn test_integration_diagnostics_valid_code() { change_request := Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -639,17 +639,17 @@ fn test_integration_diagnostics_deduplication() { errors := [ JsonError{ line_nr: 5 - col: 10 + col: 10 message: 'first error' }, JsonError{ line_nr: 5 - col: 10 + col: 10 message: 'duplicate error' }, // Same position JsonError{ line_nr: 6 - col: 1 + col: 1 message: 'different position' }, ] @@ -691,7 +691,7 @@ fn test_integration_diagnostics_empty_file() { // Empty content should be processed and return diagnostics for the empty file result := app.on_did_change(Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -736,14 +736,14 @@ fn test_integration_completion_request() { // Request completion at the position after "os." request := Request{ - id: 1 - method: 'textDocument/completion' + id: 1 + method: 'textDocument/completion' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 4 } // After "os." @@ -774,12 +774,12 @@ fn test_integration_completion_request_id_preserved() { // Test with various IDs for id in [1, 42, 100, 999] { request := Request{ - id: id + id: id params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 2 char: 0 } @@ -807,12 +807,12 @@ fn test_integration_completion_at_function_call() { app.open_files[uri] = content request := Request{ - id: 1 + id: 1 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 3 char: 9 } @@ -851,14 +851,14 @@ fn test_integration_definition_request() { // Request definition at the call site of helper() request := Request{ - id: 2 - method: 'textDocument/definition' + id: 2 + method: 'textDocument/definition' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } // At "helper()" @@ -920,12 +920,12 @@ fn test_integration_definition_multifile() { // Request definition from main file request := Request{ - id: 3 + id: 3 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 3 char: 2 } @@ -973,13 +973,13 @@ fn test_integration_cross_module_features_use_unsaved_project_overlay() { app.text = open_content definition := app.operation_at_pos(.definition, Request{ - id: 31 + id: 31 method: 'textDocument/definition' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 5 char: 20 } @@ -993,13 +993,13 @@ fn test_integration_cross_module_features_use_unsaved_project_overlay() { assert definition_location.range.start.line == 2 hover := app.operation_at_pos(.hover, Request{ - id: 32 + id: 32 method: 'textDocument/hover' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 5 char: 20 } @@ -1011,13 +1011,13 @@ fn test_integration_cross_module_features_use_unsaved_project_overlay() { assert (hover.result as Hover).contents.value.contains('answer') signature := app.operation_at_pos(.signature_help, Request{ - id: 33 + id: 33 method: 'textDocument/signatureHelp' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 5 char: 25 } @@ -1030,13 +1030,13 @@ fn test_integration_cross_module_features_use_unsaved_project_overlay() { assert signature_help.signatures.any(it.label.contains('answer')) completion := app.operation_at_pos(.completion, Request{ - id: 34 + id: 34 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 5 char: 18 } @@ -1070,17 +1070,17 @@ fn (a VlangVCallAnchor) decl_path(root string) string { // vlib/v, `builder.compile` before that. const vlang_v_module_call_anchors = [ VlangVCallAnchor{ - call: 'driver.run(' + call: 'driver.run(' qualifier: 'driver.' - name: 'run' - decl_rel: 'vlib/v/driver/driver.v' + name: 'run' + decl_rel: 'vlib/v/driver/driver.v' decl_text: 'fn run(' }, VlangVCallAnchor{ - call: "builder.compile('build'" + call: "builder.compile('build'" qualifier: 'builder.' - name: 'compile' - decl_rel: 'vlib/v/builder/compile.v' + name: 'compile' + decl_rel: 'vlib/v/builder/compile.v' decl_text: 'fn compile(' }, ] @@ -1088,17 +1088,17 @@ const vlang_v_module_call_anchors = [ // Method calls on a local variable, for receiver-type inference. const vlang_v_method_call_anchors = [ VlangVCallAnchor{ - call: 'process.set_args(' + call: 'process.set_args(' qualifier: 'process.' - name: 'set_args' - decl_rel: 'vlib/os/process.v' + name: 'set_args' + decl_rel: 'vlib/os/process.v' decl_text: 'fn (mut p Process) set_args(' }, VlangVCallAnchor{ - call: "timers.show('v start'" + call: "timers.show('v start'" qualifier: 'timers.' - name: 'show' - decl_rel: 'vlib/v/util/timers.v' + name: 'show' + decl_rel: 'vlib/v/util/timers.v' decl_text: 'fn (mut t Timers) show(' }, ] @@ -1171,12 +1171,12 @@ fn test_integration_vlang_v_cross_module_features_from_env() { for i, method in [Method.definition, .declaration, .type_definition, .implementation] { response := app.operation_at_pos(method, Request{ - id: 40 + i + id: 40 + i params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: compile_col + 2 } @@ -1191,12 +1191,12 @@ fn test_integration_vlang_v_cross_module_features_from_env() { } hover := app.operation_at_pos(.hover, Request{ - id: 44 + id: 44 params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: compile_col + 2 } @@ -1211,12 +1211,12 @@ fn test_integration_vlang_v_cross_module_features_from_env() { open_paren_col := lines[call_line].index(call_text) or { -1 } assert open_paren_col >= 0 signature := app.operation_at_pos(.signature_help, Request{ - id: 45 + id: 45 params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: open_paren_col + call_text.len } @@ -1235,12 +1235,12 @@ fn test_integration_vlang_v_cross_module_features_from_env() { app.open_files[main_uri] = completion_content app.text = completion_content completion := app.operation_at_pos(.completion, Request{ - id: 46 + id: 46 params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: call_line char: dot_col + anchor.qualifier.len } @@ -1288,13 +1288,13 @@ fn test_integration_vlang_v_indexed_completion_and_receiver_definition_from_env( app.workspace_roots = [root] module_completion := app.operation_at_pos(.completion, Request{ - id: 47 + id: 47 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: compile_line char: compile_dot_col } @@ -1306,13 +1306,13 @@ fn test_integration_vlang_v_indexed_completion_and_receiver_definition_from_env( assert (module_completion.result as CompletionList).items.any(it.label == module_anchor.name) receiver_completion := app.operation_at_pos(.completion, Request{ - id: 48 + id: 48 method: 'textDocument/completion' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: timer_line char: timer_dot_col } @@ -1324,13 +1324,13 @@ fn test_integration_vlang_v_indexed_completion_and_receiver_definition_from_env( assert (receiver_completion.result as CompletionList).items.any(it.label == method_anchor.name) definition := app.operation_at_pos(.definition, Request{ - id: 49 + id: 49 method: 'textDocument/definition' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: timer_line char: show_col + 2 } @@ -1374,14 +1374,14 @@ fn test_integration_signature_help_request() { // Request signature help after opening paren request := Request{ - id: 3 - method: 'textDocument/signatureHelp' + id: 3 + method: 'textDocument/signatureHelp' jsonrpc: '2.0' - params: json2.encode(Params{ + params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 7 } // After "greet(" @@ -1415,12 +1415,12 @@ fn test_integration_signature_help_with_params() { // At second parameter position request := Request{ - id: 4 + id: 4 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 7 } @@ -1584,7 +1584,7 @@ fn test_integration_json_error_with_special_chars() { fn test_integration_response_encoding() { response := Response{ - id: 42 + id: 42 result: 'null' } @@ -1600,20 +1600,20 @@ fn test_integration_notification_encoding() { notification := Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [ LSPDiagnostic{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 5 } } - message: 'test error' + message: 'test error' severity: 1 }, ] @@ -1663,19 +1663,19 @@ fn test_integration_begin_progress_with_client_support_emits_create_and_begin() fn test_integration_completion_response_encoding() { details := [ Detail{ - kind: 6 - label: 'println' + kind: 6 + label: 'println' detail: 'fn println(s string)' }, Detail{ - kind: 6 - label: 'print' + kind: 6 + label: 'print' detail: 'fn print(s string)' }, ] response := Response{ - id: 1 + id: 1 result: details } @@ -1686,15 +1686,15 @@ fn test_integration_completion_response_encoding() { fn test_integration_location_response_encoding() { response := Response{ - id: 1 + id: 1 result: Location{ - uri: 'file:///test/main.v' + uri: 'file:///test/main.v' range: LSPRange{ start: Position{ line: 10 char: 5 } - end: Position{ + end: Position{ line: 10 char: 15 } @@ -1709,11 +1709,11 @@ fn test_integration_location_response_encoding() { fn test_integration_signature_help_response_encoding() { response := Response{ - id: 1 + id: 1 result: SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ - label: 'fn test(a int, b string)' + label: 'fn test(a int, b string)' parameters: [ ParameterInformation{ label: 'a int' @@ -1752,13 +1752,13 @@ fn test_integration_request_id_preserved() { // Test with different request IDs for id in [1, 42, 999, 0] { request := Request{ - id: id + id: id method: 'textDocument/completion' params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 2 char: 0 } @@ -1871,17 +1871,17 @@ fn test_integration_full_lifecycle() { // 2. Simulate initialize (verify capabilities) caps := Capabilities{ capabilities: Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 1 + change: 1 } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true + definition_provider: true } } assert caps.capabilities.definition_provider == true @@ -1902,7 +1902,7 @@ fn test_integration_full_lifecycle() { modified_content := 'module main\n\nfn helper() {}\n\nfn main() {\n\thelper()\n}\n' app.on_did_change(Request{ params: json2.encode(Params{ - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: uri } content_changes: [ContentChange{ @@ -1916,12 +1916,12 @@ fn test_integration_full_lifecycle() { // 5. Request completion comp_response := app.operation_at_pos(.completion, Request{ - id: 1 + id: 1 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } @@ -1933,12 +1933,12 @@ fn test_integration_full_lifecycle() { // 6. Request definition def_response := app.operation_at_pos(.definition, Request{ - id: 2 + id: 2 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } @@ -1955,7 +1955,7 @@ fn test_integration_full_lifecycle() { fn test_integration_shutdown_response() { // Verify shutdown response structure shutdown_resp := Response{ - id: 1 + id: 1 result: 'null' } @@ -2429,12 +2429,12 @@ fn test_integration_completion_includes_sibling_pub_fn() { // Request completion at `helper` on line 3, col 1 (not after '.') response := app.operation_at_pos(.completion, Request{ - id: 1 + id: 1 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 3 char: 1 } @@ -2475,12 +2475,12 @@ fn test_integration_completion_includes_private_sibling_fn() { app.text = main_content response := app.operation_at_pos(.completion, Request{ - id: 1 + id: 1 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: main_uri } - position: Position{ + position: Position{ line: 3 char: 2 } @@ -2514,12 +2514,12 @@ fn test_integration_completion_includes_current_file_fns() { app.text = content response := app.operation_at_pos(.completion, Request{ - id: 1 + id: 1 params: json2.encode(Params{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 // inside fn main, after `he` char: 2 } @@ -2614,13 +2614,13 @@ fn test_integration_prepare_rename_returns_symbol_range() { app.open_files[uri] = content response := app.handle_prepare_rename(Request{ - id: 301 + id: 301 method: 'textDocument/prepareRename' params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 4 char: 12 } @@ -2649,7 +2649,7 @@ fn test_integration_workspace_symbol_query_matches() { app.open_files[uri] = content response := app.handle_workspace_symbol(Request{ - id: 302 + id: 302 method: 'workspace/symbol' params: json2.encode(WorkspaceSymbolParams{ query: 'name' @@ -2682,7 +2682,7 @@ fn test_integration_workspace_symbol_indexes_loose_module_sibling() { assert find_project_root(project_dir) == '' response := app.handle_workspace_symbol(Request{ - id: 303 + id: 303 method: 'workspace/symbol' params: json2.encode(WorkspaceSymbolParams{ query: 'unopened_loose' @@ -2714,13 +2714,13 @@ fn test_integration_alias_navigation_methods_preserve_id() { mut request_id := 410 for m in methods { resp := app.operation_at_pos(m, Request{ - id: request_id + id: request_id method: m.str() params: json2.encode(TextDocumentPositionParams{ text_document: TextDocumentIdentifier{ uri: uri } - position: Position{ + position: Position{ line: 5 char: 2 } @@ -2735,17 +2735,17 @@ fn test_integration_alias_navigation_methods_preserve_id() { fn test_integration_capability_flags_for_new_features() { caps := Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 2 - save: SaveOptions{ + change: 2 + save: SaveOptions{ include_text: true } } - declaration_provider: true - type_definition_provider: true - implementation_provider: true - rename_provider: RenameOptions{ + declaration_provider: true + type_definition_provider: true + implementation_provider: true + rename_provider: RenameOptions{ prepare_provider: true } workspace_symbol_provider: true @@ -2795,8 +2795,10 @@ fn test_integration_sublime_text_lsp_handshake() { root_uri := path_to_uri(project_dir) initialize := '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":42,"clientInfo":{"name":"Sublime Text LSP","version":"2.13.0"},"locale":"en","rootUri":"${root_uri}","rootPath":"${project_dir}","workspaceFolders":[{"uri":"${root_uri}","name":"test_project"}],"capabilities":{"general":{"positionEncodings":["utf-16"]},"workspace":{"workspaceFolders":true,"configuration":true,"didChangeWatchedFiles":{"dynamicRegistration":true,"relativePatternSupport":true}},"textDocument":{"synchronization":{"dynamicRegistration":true,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":true,"completionItem":{"snippetSupport":true,"documentationFormat":["markdown","plaintext"]}},"hover":{"dynamicRegistration":true,"contentFormat":["markdown","plaintext"]},"publishDiagnostics":{"versionSupport":true}},"window":{"workDoneProgress":true}},"initializationOptions":{}}}' initialized := '{"jsonrpc":"2.0","method":"initialized","params":{}}' - output := integration_run_frames(mut app, project_dir, 'sublime_handshake', [initialize, - initialized]) + output := integration_run_frames(mut app, project_dir, 'sublime_handshake', [ + initialize, + initialized, + ]) assert app.received_initialize assert app.workspace_roots == [project_dir] diff --git a/interop.v b/interop.v index 0aad112f..3a91ac2c 100644 --- a/interop.v +++ b/interop.v @@ -267,7 +267,8 @@ fn build_v_check_args_multifile(is_library_module bool) []string { } fn build_v_line_info_args_multifile(rel_file string, line_info string) []string { - return ['-w', '-check', '-nocolor', '-vls-mode', '-line-info', '${rel_file}:${line_info}', '.'] + return ['-w', '-check', '-nocolor', '-vls-mode', '-line-info', '${rel_file}:${line_info}', + '.'] } fn build_v_line_info_args_single(file_to_check string, line_info string, compile_target string) []string { @@ -284,8 +285,8 @@ fn build_v_line_info_args_single(file_to_check string, line_info string, compile // than assumed from a version number. enum LineInfoMode { unknown // not probed yet — try the options as-is - direct // the compiler answers `-vls-mode` / `-line-info` itself - compat // reaching the checker needs `-old-compiler` + direct // the compiler answers `-vls-mode` / `-line-info` itself + compat // reaching the checker needs `-old-compiler` missing // no compatibility compiler either — answer from VLS's own index } @@ -465,11 +466,11 @@ fn parse_v_check_diagnostic_header(line string, source_dir string) ?JsonError { if marker_idx > best_marker_idx { best_marker_idx = marker_idx best = JsonError{ - path: path + path: path message: line[marker_idx + marker.len..] line_nr: line_nr_text.int() - col: col_text.int() - level: if level.contains('error') { 'error' } else { level } + col: col_text.int() + level: if level.contains('error') { 'error' } else { level } } } break @@ -517,8 +518,8 @@ fn (mut app App) cache_v_check_result(path string, content_hash int, generation } app.diag_cache[path] = DiagCacheEntry{ content_hash: content_hash - generation: generation - errors: errors + generation: generation + errors: errors } } @@ -553,7 +554,7 @@ fn run_v_argv(args []string, work_folder string) os.Result { log(msg) return os.Result{ exit_code: 1 - output: msg + output: msg } } v_exe := resolve_v_compiler_exe() @@ -615,12 +616,12 @@ fn run_v_argv(args []string, work_folder string) os.Result { if timed_out { return os.Result{ exit_code: compiler_exit_timeout - output: '' + output: '' } } return os.Result{ exit_code: code - output: out.str() + output: out.str() } } @@ -728,12 +729,12 @@ fn (mut app App) prepare_compilation_overlay(real_path string) !CompilationOverl } } return CompilationOverlay{ - source_root: source_root + source_root: source_root source_display_root: source_display_root - temp_root: temp_root - source_work_dir: source_work_dir - temp_work_dir: temp_work_dir - temp_source_file: os.join_path(temp_root, file_rel) + temp_root: temp_root + source_work_dir: source_work_dir + temp_work_dir: temp_work_dir + temp_source_file: os.join_path(temp_root, file_rel) } } @@ -840,12 +841,12 @@ fn (mut app App) run_v_check(path string, text string) []JsonError { err_file := source_path_from_overlay(err.path, overlay) if normalized_index_path(err_file) == normalized_index_path(real_path) { updated_err := JsonError{ - path: real_path + path: real_path message: err.message line_nr: err.line_nr - col: err.col - len: err.len - level: err.level + col: err.col + len: err.len + level: err.level } filtered_errors << updated_err log('INCLUDING ERROR from err_file=${err_file}: ${err.message}') @@ -1513,7 +1514,7 @@ fn (mut app App) line_info_unavailable_result(method Method, path string, line_i } return Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: doc } } @@ -1696,7 +1697,7 @@ fn (mut app App) run_v_line_info(method Method, path string, line_info string) R } result = Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: value } } @@ -1704,7 +1705,7 @@ fn (mut app App) run_v_line_info(method Method, path string, line_info string) R // Compiler returned no info but we found a vdoc comment result = Hover{ contents: MarkupContent{ - kind: 'markdown' + kind: 'markdown' value: doc } } @@ -1749,13 +1750,13 @@ fn (app &App) compiler_location(path string, line int, byte_col int) Location { target_uri := index_uri_for_path(path, app.open_index_uris_by_path()) client_col := app.byte_col_to_client_col(target_uri, line, byte_col) return Location{ - uri: target_uri + uri: target_uri range: LSPRange{ start: Position{ line: line char: client_col } - end: Position{ + end: Position{ line: line char: client_col } diff --git a/interop_test.v b/interop_test.v index 3f03a75a..3e2a86ee 100644 --- a/interop_test.v +++ b/interop_test.v @@ -164,8 +164,8 @@ fn test_normalize_overlay_path_preserves_posix_backslashes() { fn test_source_path_from_overlay_normalizes_windows_relative_join() { overlay := CompilationOverlay{ source_display_root: r'C:\repo' - temp_root: r'C:\temp\overlay' - temp_work_dir: r'C:\temp\overlay\src' + temp_root: r'C:\temp\overlay' + temp_work_dir: r'C:\temp\overlay\src' } mapped := source_path_from_overlay_with_windows_rules('./main.v', overlay, true) assert mapped == 'C:/repo/src/main.v' @@ -257,7 +257,7 @@ fn test_compiler_location_reuses_equivalent_open_uri() { canonical_uri := path_to_uri(path) open_uri := canonical_uri.replace_once('file:///', 'file://localhost/') mut app := &App{ - open_files: map[string]string{} + open_files: map[string]string{} position_encoding: .utf16 } app.open_files[open_uri] = '🚀 target\n' @@ -641,12 +641,12 @@ fn test_parse_v_check_diagnostics_reads_v3_output() { diagnostics := parse_v_check_diagnostics(output, '') assert diagnostics.len == 2 assert diagnostics[0] == JsonError{ - path: '/tmp/main.v' + path: '/tmp/main.v' message: 'undefined variable: `missing_name`' line_nr: 4 - col: 7 - len: 12 - level: 'error' + col: 7 + len: 12 + level: 'error' } assert diagnostics[1].level == 'warning' assert diagnostics[1].line_nr == 8 @@ -661,12 +661,12 @@ fn test_parse_v_check_diagnostics_maps_v3_builder_error_to_error() { ' diagnostics := parse_v_check_diagnostics(output, '') assert diagnostics == [JsonError{ - path: '/tmp/main.v' + path: '/tmp/main.v' message: 'cannot import module "missing" (not found)' line_nr: 3 - col: 1 - len: 14 - level: 'error' + col: 1 + len: 14 + level: 'error' }] } @@ -743,8 +743,8 @@ fn test_cache_v_check_result_retries_failure_without_diagnostics() { path := 'file:///tmp/main.v' app.diag_cache[path] = DiagCacheEntry{ content_hash: 1 - generation: 1 - errors: [] + generation: 1 + errors: [] } app.cache_v_check_result(path, 2, 2, [], compiler_exit_timeout, 0) assert path !in app.diag_cache @@ -755,16 +755,16 @@ fn test_cache_v_check_result_retries_timeout_with_partial_diagnostics() { path := 'file:///tmp/main.v' app.diag_cache[path] = DiagCacheEntry{ content_hash: 1 - generation: 1 - errors: [] + generation: 1 + errors: [] } partial_errors := [ JsonError{ - path: '/tmp/main.v' + path: '/tmp/main.v' message: 'partial compiler output' line_nr: 1 - col: 1 - level: 'error' + col: 1 + level: 'error' }, ] app.cache_v_check_result(path, 2, 2, partial_errors, compiler_exit_timeout, partial_errors.len) @@ -799,11 +799,11 @@ fn test_run_v_argv_reports_missing_working_dir() { fn test_v_error_to_lsp_diagnostic_basic() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'undefined identifier `foo`' line_nr: 10 - col: 5 - len: 3 + col: 5 + len: 3 } diag := v_error_to_lsp_diagnostic(v_err) @@ -818,11 +818,11 @@ fn test_v_error_to_lsp_diagnostic_basic() { fn test_v_error_to_lsp_diagnostic_first_line() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'syntax error' line_nr: 1 - col: 1 - len: 1 + col: 1 + len: 1 } diag := v_error_to_lsp_diagnostic(v_err) @@ -833,11 +833,11 @@ fn test_v_error_to_lsp_diagnostic_first_line() { fn test_v_error_to_lsp_diagnostic_long_error() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'unexpected token' line_nr: 100 - col: 50 - len: 20 + col: 50 + len: 20 } diag := v_error_to_lsp_diagnostic(v_err) @@ -848,11 +848,11 @@ fn test_v_error_to_lsp_diagnostic_long_error() { fn test_v_error_to_lsp_diagnostic_zero_length() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'error at position' line_nr: 5 - col: 10 - len: 0 + col: 10 + len: 0 } diag := v_error_to_lsp_diagnostic(v_err) @@ -862,11 +862,11 @@ fn test_v_error_to_lsp_diagnostic_zero_length() { fn test_v_error_to_lsp_diagnostic_large_line_numbers() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'error in large file' line_nr: 10000 - col: 200 - len: 50 + col: 200 + len: 50 } diag := v_error_to_lsp_diagnostic(v_err) @@ -877,11 +877,11 @@ fn test_v_error_to_lsp_diagnostic_large_line_numbers() { fn test_v_error_to_lsp_diagnostic_column_one() { v_err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'error at start of line' line_nr: 5 - col: 1 - len: 5 + col: 1 + len: 5 } diag := v_error_to_lsp_diagnostic(v_err) @@ -917,7 +917,7 @@ fn test_lsp_range_struct() { line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 10 } @@ -932,7 +932,7 @@ fn test_lsp_range_multiline() { line: 5 char: 10 } - end: Position{ + end: Position{ line: 10 char: 5 } @@ -942,17 +942,17 @@ fn test_lsp_range_multiline() { fn test_lsp_diagnostic_struct() { diag := LSPDiagnostic{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 5 char: 0 } - end: Position{ + end: Position{ line: 5 char: 10 } } - message: 'test error' + message: 'test error' severity: 1 } assert diag.message == 'test error' @@ -965,8 +965,8 @@ fn test_lsp_diagnostic_severities() { severities := [1, 2, 3, 4] // Error, Warning, Information, Hint for sev in severities { diag := LSPDiagnostic{ - range: LSPRange{} - message: 'test' + range: LSPRange{} + message: 'test' severity: sev } assert diag.severity == sev @@ -975,13 +975,13 @@ fn test_lsp_diagnostic_severities() { fn test_location_struct() { loc := Location{ - uri: 'file:///test/file.v' + uri: 'file:///test/file.v' range: LSPRange{ start: Position{ line: 10 char: 5 } - end: Position{ + end: Position{ line: 10 char: 15 } @@ -999,9 +999,9 @@ fn test_location_empty() { fn test_detail_struct() { detail := Detail{ - kind: 6 // Function - label: 'my_function' - detail: 'fn my_function() string' + kind: 6 // Function + label: 'my_function' + detail: 'fn my_function() string' documentation: 'A helper function' } assert detail.kind == 6 @@ -1014,7 +1014,7 @@ fn test_detail_kinds() { kinds := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] // Text, Method, Function, etc. for k in kinds { detail := Detail{ - kind: k + kind: k label: 'test' } assert detail.kind == k @@ -1023,11 +1023,11 @@ fn test_detail_kinds() { fn test_detail_struct_with_snippet() { detail := Detail{ - kind: 6 - label: 'println' - detail: 'fn println(s string)' - documentation: 'Prints a string' - insert_text: 'println(\${1:s})' + kind: 6 + label: 'println' + detail: 'fn println(s string)' + documentation: 'Prints a string' + insert_text: 'println(\${1:s})' insert_text_format: 2 // Snippet format } assert detail.insert_text? == 'println(\${1:s})' @@ -1036,7 +1036,7 @@ fn test_detail_struct_with_snippet() { fn test_detail_without_snippet() { detail := Detail{ - kind: 6 + kind: 6 label: 'println' } assert detail.insert_text == none @@ -1045,9 +1045,9 @@ fn test_detail_without_snippet() { fn test_signature_help_struct() { sig := SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ - label: 'fn my_func(a int, b string) bool' + label: 'fn my_func(a int, b string) bool' parameters: [ ParameterInformation{ label: 'a int' @@ -1068,7 +1068,7 @@ fn test_signature_help_struct() { fn test_signature_help_multiple_signatures() { sig := SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ label: 'fn overload1(a int)' }, @@ -1096,17 +1096,17 @@ fn test_signature_help_empty() { fn test_capabilities_struct() { cap := Capabilities{ capabilities: Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 1 + change: 1 } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true + definition_provider: true } } assert cap.capabilities.definition_provider == true @@ -1127,11 +1127,11 @@ fn test_capabilities_minimal() { fn test_request_struct() { req := Request{ - id: 1 - method: 'textDocument/completion' + id: 1 + method: 'textDocument/completion' jsonrpc: '2.0' - params: json2.encode(Params{ - position: Position{ + params: json2.encode(Params{ + position: Position{ line: 5 char: 10 } @@ -1162,7 +1162,7 @@ fn test_request_params_decode_malformed_returns_error() { fn test_response_struct() { resp := Response{ - id: 1 + id: 1 result: 'null' } assert resp.id == 1 @@ -1171,7 +1171,7 @@ fn test_response_struct() { fn test_response_with_capabilities() { resp := Response{ - id: 0 + id: 0 result: Capabilities{ capabilities: Capability{ definition_provider: true @@ -1188,7 +1188,7 @@ fn test_notification_struct() { notif := Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [] } } @@ -1200,16 +1200,16 @@ fn test_notification_with_diagnostics() { notif := Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [ LSPDiagnostic{ - range: LSPRange{} - message: 'error 1' + range: LSPRange{} + message: 'error 1' severity: 1 }, LSPDiagnostic{ - range: LSPRange{} - message: 'error 2' + range: LSPRange{} + message: 'error 2' severity: 1 }, ] @@ -1252,7 +1252,7 @@ fn test_write_tracked_files_to_temp_single_file() { interop_test_must_write_file(test_file, 'module main') mut app := &App{ - temp_dir: temp_dir + temp_dir: temp_dir open_files: map[string]string{} } @@ -1290,7 +1290,7 @@ fn test_write_tracked_files_to_temp_multiple_files() { } mut app := &App{ - temp_dir: temp_dir + temp_dir: temp_dir open_files: map[string]string{} } @@ -1331,7 +1331,7 @@ fn test_write_tracked_files_to_temp_nested_directories() { interop_test_must_write_file(nested_file, 'module internal') mut app := &App{ - temp_dir: temp_dir + temp_dir: temp_dir open_files: map[string]string{} } @@ -1371,7 +1371,7 @@ fn test_prepare_compilation_overlay_preserves_nested_symlink_layout() { main_uri := path_to_uri(main_file) unsaved_content := 'module main\n\nfn unsaved() {}\n' mut app := &App{ - temp_dir: app_temp_dir + temp_dir: app_temp_dir open_files: { main_uri: unsaved_content } @@ -1412,7 +1412,7 @@ fn test_prepare_compilation_overlay_preserves_posix_backslashes() { assert uri_to_path(main_uri) == main_file unsaved_content := 'module main\n\nfn unsaved() {}\n' mut app := &App{ - temp_dir: app_temp_dir + temp_dir: app_temp_dir open_files: { main_uri: unsaved_content } @@ -1450,7 +1450,7 @@ fn test_write_tracked_files_skips_files_outside_working_dir() { interop_test_must_write_file(other_file, 'module other') mut app := &App{ - temp_dir: temp_dir + temp_dir: temp_dir open_files: map[string]string{} } @@ -1911,8 +1911,8 @@ fn test_json_error_negative_values() { // to 0 rather than emitted as negative positions (P1-09). err := JsonError{ line_nr: -1 - col: -1 - len: -1 + col: -1 + len: -1 } diag := v_error_to_lsp_diagnostic(err) assert diag.severity == 1 @@ -1939,11 +1939,11 @@ fn test_params_struct_complete() { content_changes: [ContentChange{ text: 'test' }] - position: Position{ + position: Position{ line: 5 char: 10 } - text_document: TextDocumentIdentifier{ + text_document: TextDocumentIdentifier{ uri: 'file:///test.v' } } @@ -1971,7 +1971,7 @@ fn test_signature_help_options_triggers() { fn test_text_document_sync_options() { sync := TextDocumentSyncOptions{ open_close: true - change: 1 // Full sync + change: 1 // Full sync } assert sync.open_close == true assert sync.change == 1 @@ -1980,7 +1980,7 @@ fn test_text_document_sync_options() { fn test_text_document_sync_incremental() { sync := TextDocumentSyncOptions{ open_close: true - change: 2 // Incremental sync + change: 2 // Incremental sync } assert sync.change == 2 } @@ -1994,7 +1994,7 @@ fn test_parameter_information() { fn test_signature_information_with_params() { sig := SignatureInformation{ - label: 'fn test(a int, b string, c bool)' + label: 'fn test(a int, b string, c bool)' parameters: [ ParameterInformation{ label: 'a int' @@ -2013,11 +2013,11 @@ fn test_signature_information_with_params() { fn test_publish_diagnostics_params() { params := PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [ LSPDiagnostic{ - range: LSPRange{} - message: 'error' + range: LSPRange{} + message: 'error' severity: 1 }, ] diff --git a/lsp.v b/lsp.v index dc1fd27b..600824f8 100644 --- a/lsp.v +++ b/lsp.v @@ -39,7 +39,7 @@ struct Params { position Position range LSPRange text_document TextDocumentIdentifier @[json: 'textDocument'] - new_name string @[json: 'newName'] + new_name string @[json: 'newName'] } // Optional JSON integers use i64 because V3 emits a generic option ABI for struct fields, while @@ -118,7 +118,7 @@ type ResponseResult = string struct WorkspaceSymbol { name string kind int - tags ?[]int @[json: 'tags'] + tags ?[]int @[json: 'tags'] container_name ?string @[json: 'containerName'] location Location } @@ -176,8 +176,8 @@ struct LSPDiagnostic { message string severity int source ?string @[json: 'source'] // diagnostic source identifier, e.g. 'vlang' - code ?string @[json: 'code'] // optional diagnostic code, e.g. 'unused_variable' - tags ?[]int @[json: 'tags'] // 1 = unnecessary, 2 = deprecated + code ?string @[json: 'code'] // optional diagnostic code, e.g. 'unused_variable' + tags ?[]int @[json: 'tags'] // 1 = unnecessary, 2 = deprecated } // LSPRange represents a range in a text document. @@ -188,17 +188,17 @@ struct LSPRange { // Detail represents a completion or symbol detail item. struct Detail { - kind int // The type of item (e.g., Method, Function, Field) + kind int // The type of item (e.g., Method, Function, Field) label string // The name of the completion item detail string // Additional info like the function signature or return type declaration string // Full fn declaration, e.g. "fn greet(name string) string" documentation string // The documentation for the item - sort_text ?string @[json: 'sortText'] // sort key, defaults to label + sort_text ?string @[json: 'sortText'] // sort key, defaults to label filter_text ?string @[json: 'filterText'] // filter key, defaults to label insert_text ?string @[json: 'insertText'] - insert_text_format ?i64 @[json: 'insertTextFormat'] // 1 for PlainText, 2 for Snippet - tags ?[]int @[json: 'tags'] // 1 = deprecated - deprecated ?bool @[json: 'deprecated'] // legacy deprecated flag + insert_text_format ?i64 @[json: 'insertTextFormat'] // 1 for PlainText, 2 for Snippet + tags ?[]int @[json: 'tags'] // 1 = deprecated + deprecated ?bool @[json: 'deprecated'] // legacy deprecated flag } // Capabilities describes the server's capabilities. @@ -256,7 +256,7 @@ struct WorkspaceFoldersServerCapability { // WorkspaceCapability advertises workspace-level server features. struct WorkspaceCapability { - file_operations ?WorkspaceFileOperations @[json: 'fileOperations'] + file_operations ?WorkspaceFileOperations @[json: 'fileOperations'] workspace_folders ?WorkspaceFoldersServerCapability @[json: 'workspaceFolders'] } @@ -267,39 +267,39 @@ struct CodeLensOptions { // Capability lists supported LSP features for the server. struct Capability { - completion_provider CompletionProvider @[json: 'completionProvider'] - text_document_sync TextDocumentSyncOptions @[json: 'textDocumentSync'] - signature_help_provider SignatureHelpOptions @[json: 'signatureHelpProvider'] - definition_provider bool @[json: 'definitionProvider'] - declaration_provider bool @[json: 'declarationProvider'] - type_definition_provider bool @[json: 'typeDefinitionProvider'] - implementation_provider bool @[json: 'implementationProvider'] - hover_provider bool @[json: 'hoverProvider'] - references_provider bool @[json: 'referencesProvider'] - rename_provider RenameOptions @[json: 'renameProvider'] - execute_command_provider ?ExecuteCommandOptions @[json: 'executeCommandProvider'] - document_formatting_provider bool @[json: 'documentFormattingProvider'] - document_range_formatting_provider bool @[json: 'documentRangeFormattingProvider'] - document_symbol_provider bool @[json: 'documentSymbolProvider'] - workspace_symbol_provider bool @[json: 'workspaceSymbolProvider'] - inlay_hint_provider bool @[json: 'inlayHintProvider'] - code_action_provider bool @[json: 'codeActionProvider'] - code_lens_provider ?CodeLensOptions @[json: 'codeLensProvider'] - inline_value_provider bool @[json: 'inlineValueProvider'] - linked_editing_range_provider bool @[json: 'linkedEditingRangeProvider'] + completion_provider CompletionProvider @[json: 'completionProvider'] + text_document_sync TextDocumentSyncOptions @[json: 'textDocumentSync'] + signature_help_provider SignatureHelpOptions @[json: 'signatureHelpProvider'] + definition_provider bool @[json: 'definitionProvider'] + declaration_provider bool @[json: 'declarationProvider'] + type_definition_provider bool @[json: 'typeDefinitionProvider'] + implementation_provider bool @[json: 'implementationProvider'] + hover_provider bool @[json: 'hoverProvider'] + references_provider bool @[json: 'referencesProvider'] + rename_provider RenameOptions @[json: 'renameProvider'] + execute_command_provider ?ExecuteCommandOptions @[json: 'executeCommandProvider'] + document_formatting_provider bool @[json: 'documentFormattingProvider'] + document_range_formatting_provider bool @[json: 'documentRangeFormattingProvider'] + document_symbol_provider bool @[json: 'documentSymbolProvider'] + workspace_symbol_provider bool @[json: 'workspaceSymbolProvider'] + inlay_hint_provider bool @[json: 'inlayHintProvider'] + code_action_provider bool @[json: 'codeActionProvider'] + code_lens_provider ?CodeLensOptions @[json: 'codeLensProvider'] + inline_value_provider bool @[json: 'inlineValueProvider'] + linked_editing_range_provider bool @[json: 'linkedEditingRangeProvider'] on_type_formatting_provider ?OnTypeFormattingOptions @[json: 'documentOnTypeFormattingProvider'] - semantic_tokens_provider SemanticTokensOptions @[json: 'semanticTokensProvider'] - folding_range_provider bool @[json: 'foldingRangeProvider'] - call_hierarchy_provider bool @[json: 'callHierarchyProvider'] - document_highlight_provider bool @[json: 'documentHighlightProvider'] - selection_range_provider bool @[json: 'selectionRangeProvider'] + semantic_tokens_provider SemanticTokensOptions @[json: 'semanticTokensProvider'] + folding_range_provider bool @[json: 'foldingRangeProvider'] + call_hierarchy_provider bool @[json: 'callHierarchyProvider'] + document_highlight_provider bool @[json: 'documentHighlightProvider'] + selection_range_provider bool @[json: 'selectionRangeProvider'] workspace WorkspaceCapability position_encoding ?string @[json: 'positionEncoding'] } // OnTypeFormattingOptions describes the triggers for on-type formatting. struct OnTypeFormattingOptions { - first_trigger_character string @[json: 'firstTriggerCharacter'] + first_trigger_character string @[json: 'firstTriggerCharacter'] more_trigger_characters []string @[json: 'moreTriggerCharacters'] } @@ -676,8 +676,8 @@ struct OnTypeFormattingParams { // InitializeParams holds client startup parameters relevant to server workspace scope. struct InitializeParams { - root_uri ?string @[json: 'rootUri'] - root_path ?string @[json: 'rootPath'] + root_uri ?string @[json: 'rootUri'] + root_path ?string @[json: 'rootPath'] workspace_folders ?[]WorkspaceFolder @[json: 'workspaceFolders'] capabilities ?ClientCapabilities } @@ -706,7 +706,7 @@ struct SaveOptions { // TextDocumentSyncOptions describes document synchronization options. struct TextDocumentSyncOptions { open_close bool @[json: 'openClose'] - change int // 1 for Full, 2 for Incremental + change int // 1 for Full, 2 for Incremental save SaveOptions // emit {"includeText":true} to receive text in didSave will_save bool @[json: 'willSave'] will_save_wait_until bool @[json: 'willSaveWaitUntil'] @@ -785,7 +785,7 @@ const inlay_hint_kind_type = 1 struct InlayHint { position Position label string - kind int @[json: 'kind'] + kind int @[json: 'kind'] padding_left bool @[json: 'paddingLeft'] } @@ -964,7 +964,7 @@ struct DidOpenTextDocumentParams { // DidChangeTextDocumentParams for didChange struct DidChangeTextDocumentParams { text_document VersionedTextDocumentIdentifier @[json: 'textDocument'] - content_changes []ContentChange @[json: 'contentChanges'] + content_changes []ContentChange @[json: 'contentChanges'] } // DidCloseTextDocumentParams for didClose @@ -1007,7 +1007,7 @@ struct RenameParams { // FormattingOptions carries client formatting preferences (LSP §3.17). // VLS ignores these and always delegates to `v fmt`. struct FormattingOptions { - tab_size int @[json: 'tabSize'] + tab_size int @[json: 'tabSize'] insert_spaces bool @[json: 'insertSpaces'] } diff --git a/lsp_test.v b/lsp_test.v index 0949ec75..dbc5d5f4 100644 --- a/lsp_test.v +++ b/lsp_test.v @@ -242,9 +242,8 @@ fn test_method_roundtrip_all_values() { .workspace_did_change_configuration, .workspace_did_change_workspace_folders, .document_highlight, .selection_range, .semantic_tokens_range, .range_formatting, .will_save, .will_save_wait_until, .did_change_watched_files, .code_lens, .code_lens_resolve, - .execute_command, .inline_value, .linked_editing_range, .will_create_files, - .will_rename_files, .will_delete_files, .on_type_formatting, .set_trace, .cancel_request, - .shutdown, .exit] + .execute_command, .inline_value, .linked_editing_range, .will_create_files, .will_rename_files, + .will_delete_files, .on_type_formatting, .set_trace, .cancel_request, .shutdown, .exit] for m in methods { assert Method.from_string(m.str()) == m } @@ -472,7 +471,7 @@ fn test_lsp_range_same_line() { line: 5 char: 10 } - end: Position{ + end: Position{ line: 5 char: 20 } @@ -487,7 +486,7 @@ fn test_lsp_range_multi_line() { line: 5 char: 0 } - end: Position{ + end: Position{ line: 10 char: 15 } @@ -501,7 +500,7 @@ fn test_lsp_range_json_encoding() { line: 1 char: 2 } - end: Position{ + end: Position{ line: 3 char: 4 } @@ -593,8 +592,8 @@ fn test_request_default_values() { fn test_request_with_values() { req := Request{ - id: 1 - method: 'textDocument/completion' + id: 1 + method: 'textDocument/completion' jsonrpc: '2.0' } assert req.id == 1 @@ -644,7 +643,7 @@ fn test_request_json_decoding_initialize() { fn test_response_default_jsonrpc() { resp := Response{ - id: 1 + id: 1 result: 'null' } assert resp.jsonrpc == '2.0' @@ -652,7 +651,7 @@ fn test_response_default_jsonrpc() { fn test_response_json_encoding() { resp := Response{ - id: 42 + id: 42 result: 'null' } encoded := json2.encode(resp, escape_unicode: true) @@ -662,7 +661,7 @@ fn test_response_json_encoding() { fn test_encode_response_payload_uses_json_null_for_null_result() { resp := Response{ - id: 2 + id: 2 result: 'null' } encoded := encode_response_payload(resp) @@ -672,7 +671,7 @@ fn test_encode_response_payload_uses_json_null_for_null_result() { fn test_encode_response_payload_preserves_non_null_results() { resp := Response{ - id: 3 + id: 3 result: []TextEdit{} } encoded := encode_response_payload(resp) @@ -681,7 +680,7 @@ fn test_encode_response_payload_preserves_non_null_results() { fn test_encode_response_payload_strips_sum_type_tag_from_capabilities() { resp := Response{ - id: 4 + id: 4 result: Capabilities{ capabilities: Capability{ definition_provider: true @@ -695,14 +694,14 @@ fn test_encode_response_payload_strips_sum_type_tag_from_capabilities() { fn test_encode_response_payload_strips_sum_type_tag_from_prepare_rename() { resp := Response{ - id: 5 + id: 5 result: PrepareRenameResult{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 1 char: 2 } - end: Position{ + end: Position{ line: 1 char: 7 } @@ -717,15 +716,15 @@ fn test_encode_response_payload_strips_sum_type_tag_from_prepare_rename() { fn test_workspace_edit_closed_document_has_explicit_null_version() { resp := Response{ - id: 6 + id: 6 result: WorkspaceEdit{ document_changes: [TextDocumentEdit{ text_document: OptionalVersionedTextDocumentIdentifier{ - uri: 'file:///tmp/closed.v' + uri: 'file:///tmp/closed.v' version: json2.null } - edits: [TextEdit{ - range: LSPRange{} + edits: [TextEdit{ + range: LSPRange{} new_text: 'renamed' }] }] @@ -924,7 +923,7 @@ fn test_notification_json_encoding() { notif := Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [] } } @@ -935,8 +934,8 @@ fn test_notification_json_encoding() { fn test_lsp_diagnostic_error_severity() { diag := LSPDiagnostic{ - range: LSPRange{} - message: 'error message' + range: LSPRange{} + message: 'error message' severity: 1 } assert diag.severity == 1 // Error @@ -945,8 +944,8 @@ fn test_lsp_diagnostic_error_severity() { fn test_lsp_diagnostic_warning_severity() { diag := LSPDiagnostic{ - range: LSPRange{} - message: 'warning message' + range: LSPRange{} + message: 'warning message' severity: 2 } assert diag.severity == 2 // Warning @@ -954,17 +953,17 @@ fn test_lsp_diagnostic_warning_severity() { fn test_lsp_diagnostic_json_encoding() { diag := LSPDiagnostic{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 5 char: 0 } - end: Position{ + end: Position{ line: 5 char: 10 } } - message: 'undefined identifier' + message: 'undefined identifier' severity: 1 } encoded := json2.encode(diag, escape_unicode: true) @@ -974,9 +973,9 @@ fn test_lsp_diagnostic_json_encoding() { fn test_detail_function_kind() { detail := Detail{ - kind: 6 // Function - label: 'my_function' - detail: 'fn my_function() string' + kind: 6 // Function + label: 'my_function' + detail: 'fn my_function() string' documentation: 'A helper function' } assert detail.kind == 6 @@ -985,9 +984,9 @@ fn test_detail_function_kind() { fn test_detail_variable_kind() { detail := Detail{ - kind: 6 - label: 'my_var' - detail: 'int' + kind: 6 + label: 'my_var' + detail: 'int' documentation: 'A variable' } assert detail.label == 'my_var' @@ -995,10 +994,10 @@ fn test_detail_variable_kind() { fn test_detail_with_snippet() { detail := Detail{ - kind: 6 - label: 'println' - detail: 'fn println(s string)' - insert_text: 'println(\${1:s})' + kind: 6 + label: 'println' + detail: 'fn println(s string)' + insert_text: 'println(\${1:s})' insert_text_format: 2 // Snippet } assert detail.insert_text? == 'println(\${1:s})' @@ -1007,7 +1006,7 @@ fn test_detail_with_snippet() { fn test_detail_json_encoding() { detail := Detail{ - kind: 6 + kind: 6 label: 'test_fn' } encoded := json2.encode(detail, escape_unicode: true) @@ -1017,13 +1016,13 @@ fn test_detail_json_encoding() { fn test_location_basic() { loc := Location{ - uri: 'file:///test/file.v' + uri: 'file:///test/file.v' range: LSPRange{ start: Position{ line: 10 char: 5 } - end: Position{ + end: Position{ line: 10 char: 15 } @@ -1035,13 +1034,13 @@ fn test_location_basic() { fn test_location_json_encoding() { loc := Location{ - uri: 'file:///path/to/file.v' + uri: 'file:///path/to/file.v' range: LSPRange{ start: Position{ line: 0 char: 0 } - end: Position{ + end: Position{ line: 0 char: 5 } @@ -1061,9 +1060,9 @@ fn test_signature_help_empty() { fn test_signature_help_with_signature() { sig := SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ - label: 'fn test(a int, b string)' + label: 'fn test(a int, b string)' parameters: [ ParameterInformation{ label: 'a int' @@ -1084,7 +1083,7 @@ fn test_signature_help_with_signature() { fn test_signature_help_json_encoding() { sig := SignatureHelp{ - signatures: [ + signatures: [ SignatureInformation{ label: 'fn example()' }, @@ -1100,17 +1099,17 @@ fn test_signature_help_json_encoding() { fn test_capabilities_full() { caps := Capabilities{ capabilities: Capability{ - text_document_sync: TextDocumentSyncOptions{ + text_document_sync: TextDocumentSyncOptions{ open_close: true - change: 1 + change: 1 } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true + definition_provider: true } } assert caps.capabilities.definition_provider == true @@ -1147,7 +1146,7 @@ fn test_completion_item_capability_snippet_support() { fn test_text_document_sync_full() { sync := TextDocumentSyncOptions{ open_close: true - change: 1 // Full + change: 1 // Full } assert sync.open_close == true assert sync.change == 1 @@ -1156,7 +1155,7 @@ fn test_text_document_sync_full() { fn test_text_document_sync_incremental() { sync := TextDocumentSyncOptions{ open_close: true - change: 2 // Incremental + change: 2 // Incremental } assert sync.change == 2 } @@ -1181,7 +1180,7 @@ fn test_response_result_string() { fn test_response_result_details() { details := [ Detail{ - kind: 6 + kind: 6 label: 'test' }, ] @@ -1234,7 +1233,7 @@ fn test_response_result_location() { fn test_publish_diagnostics_params_empty() { params := PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [] } assert params.uri == 'file:///test.v' @@ -1243,16 +1242,16 @@ fn test_publish_diagnostics_params_empty() { fn test_publish_diagnostics_params_with_diagnostics() { params := PublishDiagnosticsParams{ - uri: 'file:///test.v' + uri: 'file:///test.v' diagnostics: [ LSPDiagnostic{ - range: LSPRange{} - message: 'error 1' + range: LSPRange{} + message: 'error 1' severity: 1 }, LSPDiagnostic{ - range: LSPRange{} - message: 'error 2' + range: LSPRange{} + message: 'error 2' severity: 1 }, ] @@ -1262,11 +1261,11 @@ fn test_publish_diagnostics_params_with_diagnostics() { fn test_json_error_struct() { err := JsonError{ - path: '/test/file.v' + path: '/test/file.v' message: 'undefined identifier' line_nr: 10 - col: 5 - len: 3 + col: 5 + len: 3 } assert err.path == '/test/file.v' assert err.message == 'undefined identifier' @@ -1305,11 +1304,11 @@ fn test_json_var_ac_with_details() { ac := JsonVarAC{ details: [ Detail{ - kind: 6 + kind: 6 label: 'fn1' }, Detail{ - kind: 6 + kind: 6 label: 'fn2' }, ] @@ -1340,14 +1339,14 @@ fn test_document_symbol_default_values() { fn test_document_symbol_with_values() { sym := DocumentSymbol{ - name: 'greet' - kind: sym_kind_function - range: LSPRange{ + name: 'greet' + kind: sym_kind_function + range: LSPRange{ start: Position{ line: 2 char: 0 } - end: Position{ + end: Position{ line: 2 char: 20 } @@ -1357,12 +1356,12 @@ fn test_document_symbol_with_values() { line: 2 char: 3 } - end: Position{ + end: Position{ line: 2 char: 8 } } - children: []DocumentSymbol{} + children: []DocumentSymbol{} } assert sym.name == 'greet' assert sym.kind == sym_kind_function @@ -1372,14 +1371,14 @@ fn test_document_symbol_with_values() { fn test_document_symbol_json_encoding() { sym := DocumentSymbol{ - name: 'Person' - kind: sym_kind_struct - range: LSPRange{ + name: 'Person' + kind: sym_kind_struct + range: LSPRange{ start: Position{ line: 5 char: 0 } - end: Position{ + end: Position{ line: 5 char: 14 } @@ -1389,12 +1388,12 @@ fn test_document_symbol_json_encoding() { line: 5 char: 7 } - end: Position{ + end: Position{ line: 5 char: 13 } } - children: []DocumentSymbol{} + children: []DocumentSymbol{} } encoded := json2.encode(sym, escape_unicode: true) assert encoded.contains('"name":"Person"') @@ -1417,17 +1416,17 @@ fn test_document_symbol_json_decoding() { fn test_document_symbol_with_children() { sym := DocumentSymbol{ - name: 'App' - kind: sym_kind_struct - range: LSPRange{} + name: 'App' + kind: sym_kind_struct + range: LSPRange{} selection_range: LSPRange{} - children: [ + children: [ DocumentSymbol{ - name: 'run' - kind: sym_kind_method - range: LSPRange{} + name: 'run' + kind: sym_kind_method + range: LSPRange{} selection_range: LSPRange{} - children: []DocumentSymbol{} + children: []DocumentSymbol{} }, ] } @@ -1508,10 +1507,10 @@ fn test_method_roundtrip_new_methods() { fn test_response_result_workspace_symbols() { result := ResponseResult([ WorkspaceSymbol{ - name: 'main' - kind: sym_kind_function + name: 'main' + kind: sym_kind_function location: Location{ - uri: 'file:///tmp/main.v' + uri: 'file:///tmp/main.v' range: LSPRange{} } }, @@ -1526,12 +1525,12 @@ fn test_response_result_workspace_symbols() { fn test_response_result_prepare_rename_result() { result := ResponseResult(PrepareRenameResult{ - range: LSPRange{ + range: LSPRange{ start: Position{ line: 1 char: 2 } - end: Position{ + end: Position{ line: 1 char: 5 } @@ -1559,18 +1558,18 @@ fn test_response_result_document_symbols_empty() { fn test_response_result_document_symbols_with_data() { syms := [ DocumentSymbol{ - name: 'main' - kind: sym_kind_function - range: LSPRange{} + name: 'main' + kind: sym_kind_function + range: LSPRange{} selection_range: LSPRange{} - children: []DocumentSymbol{} + children: []DocumentSymbol{} }, DocumentSymbol{ - name: 'App' - kind: sym_kind_struct - range: LSPRange{} + name: 'App' + kind: sym_kind_struct + range: LSPRange{} selection_range: LSPRange{} - children: []DocumentSymbol{} + children: []DocumentSymbol{} }, ] result := ResponseResult(syms) @@ -1588,14 +1587,14 @@ fn test_response_result_document_symbols_with_data() { fn test_response_with_document_symbols_json_encoding() { syms := [ DocumentSymbol{ - name: 'greet' - kind: sym_kind_function - range: LSPRange{ + name: 'greet' + kind: sym_kind_function + range: LSPRange{ start: Position{ line: 2 char: 0 } - end: Position{ + end: Position{ line: 2 char: 25 } @@ -1605,16 +1604,16 @@ fn test_response_with_document_symbols_json_encoding() { line: 2 char: 3 } - end: Position{ + end: Position{ line: 2 char: 8 } } - children: []DocumentSymbol{} + children: []DocumentSymbol{} }, ] resp := Response{ - id: 7 + id: 7 result: syms } encoded := json2.encode(resp, escape_unicode: true) @@ -1640,7 +1639,7 @@ fn test_capability_document_symbol_provider_json_encoding() { caps := Capabilities{ capabilities: Capability{ document_symbol_provider: true - definition_provider: true + definition_provider: true } } encoded := json2.encode(caps, escape_unicode: true) @@ -1802,13 +1801,13 @@ fn test_encode_response_payload_strips_type_from_array_variant() { // Array-of-struct result variants (e.g. []WorkspaceSymbol) must also have // their per-element `_type` discriminators stripped (P1-10). resp := Response{ - id: 9 + id: 9 result: [ WorkspaceSymbol{ - name: 'helper_fn' - kind: sym_kind_function + name: 'helper_fn' + kind: sym_kind_function location: Location{ - uri: 'file:///tmp/lib.v' + uri: 'file:///tmp/lib.v' range: LSPRange{} } }, diff --git a/main.v b/main.v index 23ab684e..c5bb4fe5 100644 --- a/main.v +++ b/main.v @@ -12,47 +12,47 @@ import io // App represents the context of the server during its lifetime. pub struct App { cur_mod string = 'main' - exit bool = os.args.contains('exit') + exit bool = os.args.contains('exit') mut: - text string // Current file content + text string // Current file content open_files map[string]string // Map of file URI to file content - open_files_versions map[string]i64 // Per-URI document version from the client - temp_dir string // Temporary directory for multi-file compilation - workspace_roots []string // Workspace root directories from initialize - removed_workspace_roots []string // Roots explicitly removed by the client - capture_output bool // Test hook: capture outbound transport messages instead of writing - captured_output []string // Test hook buffer for outbound transport messages - supports_dynamic_watched_files_registration bool // Client supports dynamic workspace watcher registration - supports_work_done_progress bool // Client supports window/workDoneProgress + $/progress - sent_watched_files_registration bool // client/registerCapability watcher registration was sent - watched_files_registration_id string // Raw id of the watcher registration request, to match its response - watched_files_active bool // True once the client acknowledged watcher registration (not rejected) + open_files_versions map[string]i64 // Per-URI document version from the client + temp_dir string // Temporary directory for multi-file compilation + workspace_roots []string // Workspace root directories from initialize + removed_workspace_roots []string // Roots explicitly removed by the client + capture_output bool // Test hook: capture outbound transport messages instead of writing + captured_output []string // Test hook buffer for outbound transport messages + supports_dynamic_watched_files_registration bool // Client supports dynamic workspace watcher registration + supports_work_done_progress bool // Client supports window/workDoneProgress + $/progress + sent_watched_files_registration bool // client/registerCapability watcher registration was sent + watched_files_registration_id string // Raw id of the watcher registration request, to match its response + watched_files_active bool // True once the client acknowledged watcher registration (not rejected) inlay_hints_enabled bool = true // toggled via workspace/didChangeConfiguration diagnostics_enabled bool = true // toggled via workspace/didChangeConfiguration diag_cache map[string]DiagCacheEntry // Per-URI cached diagnostics - open_files_generation int // Incremented on every workspace file mutation - project_generations map[string]int // Per-project-dir revision, for scoped cache invalidation - cancelled_requests map[int]bool // Request ids cancelled via $/cancelRequest - cancelled_raw_ids map[string]bool // String/raw request ids cancelled via $/cancelRequest - current_request_raw_id string // Raw JSON id of the request being processed (echoed verbatim) + open_files_generation int // Incremented on every workspace file mutation + project_generations map[string]int // Per-project-dir revision, for scoped cache invalidation + cancelled_requests map[int]bool // Request ids cancelled via $/cancelRequest + cancelled_raw_ids map[string]bool // String/raw request ids cancelled via $/cancelRequest + current_request_raw_id string // Raw JSON id of the request being processed (echoed verbatim) position_encoding PositionEncoding = .utf16 // Negotiated LSP position encoding (default UTF-16) - symbol_index map[string]IndexEntry // Persistent per-URI symbol index (see index.v) - indexed_dirs map[string]bool // Project dirs already walked into the index - indexed_dir_walk_ms map[string]i64 // Last walk time per dir, for watcher-less refresh - ref_occurrences map[string]OccEntry // Per-URI identifier occurrences for references (see index.v) - index_skipped_uris map[string]bool // Disk files omitted from the bounded index - index_incomplete_scopes map[string]bool // Index walks that could not finish + symbol_index map[string]IndexEntry // Persistent per-URI symbol index (see index.v) + indexed_dirs map[string]bool // Project dirs already walked into the index + indexed_dir_walk_ms map[string]i64 // Last walk time per dir, for watcher-less refresh + ref_occurrences map[string]OccEntry // Per-URI identifier occurrences for references (see index.v) + index_skipped_uris map[string]bool // Disk files omitted from the bounded index + index_incomplete_scopes map[string]bool // Index walks that could not finish vlib_fn_cache map[string]map[string]string // Per-vlib-module fn→return-type index (immutable during a session) - expression_type_depth int // Nesting of expression_type, which a binding's declaration re-enters - line_info_mode LineInfoMode // How the configured `v` reaches the `-line-info` checker (see interop.v) + expression_type_depth int // Nesting of expression_type, which a binding's declaration re-enters + line_info_mode LineInfoMode // How the configured `v` reaches the `-line-info` checker (see interop.v) tcp_conn ?&net.TcpConn // Non-nil when serving a TCP client - is_shutdown bool // True after shutdown request was acknowledged - exit_was_requested bool // True when the exit notification was received - received_initialize bool // True after initialize request was processed + is_shutdown bool // True after shutdown request was acknowledged + exit_was_requested bool // True when the exit notification was received + received_initialize bool // True after initialize request was processed next_request_id int = 1 // Counter for server-initiated request ids diagnostics_scheduler ?&DiagnosticsScheduler // Production-only async diagnostics - run_command_manager ?&RunCommandManager // Async code-lens process lifecycle - execute_commands_synchronously bool // Test hook for deterministic command assertions + run_command_manager ?&RunCommandManager // Async code-lens process lifecycle + execute_commands_synchronously bool // Test hook for deterministic command assertions write_mutex &sync.Mutex = sync.new_mutex() // Serializes worker and request-loop writes } @@ -203,7 +203,7 @@ fn (mut reader StdinBufferedReader) read_line(config io.BufferedReadLineConfig) fn new_stdin_buffered_reader_for_fd(fd int, cap int) &StdinBufferedReader { return &StdinBufferedReader{ - fd: fd + fd: fd buf: []u8{len: cap} } } @@ -254,9 +254,9 @@ fn main() { return } mut app := &App{ - text: '' - open_files: map[string]string{} - temp_dir: temp_dir + text: '' + open_files: map[string]string{} + temp_dir: temp_dir diagnostics_scheduler: new_diagnostics_scheduler() } // os.File.read uses C fread, which waits for the entire buffer on an open @@ -330,10 +330,10 @@ fn handle_tcp_client(mut conn net.TcpConn) { return } mut app := &App{ - text: '' - open_files: map[string]string{} - temp_dir: temp_dir - tcp_conn: &conn + text: '' + open_files: map[string]string{} + temp_dir: temp_dir + tcp_conn: &conn diagnostics_scheduler: new_diagnostics_scheduler() } mut reader := io.new_buffered_reader(reader: conn, cap: transport_buffer_cap) @@ -617,10 +617,10 @@ fn (mut app App) handle_requests[T](mut reader T) { continue } lsp_request := Request{ - id: raw_id_to_int(app.current_request_raw_id) - method: body.method + id: raw_id_to_int(app.current_request_raw_id) + method: body.method jsonrpc: body.jsonrpc - params: body.params + params: body.params } log('\n\nRECV (pretty): ${content}') method := Method.from_string(lsp_request.method) @@ -670,7 +670,8 @@ fn (mut app App) handle_requests[T](mut reader T) { } } match method { - .completion, .signature_help, .definition, .hover, .declaration, .type_definition, .implementation { + .completion, .signature_help, .definition, .hover, .declaration, .type_definition, + .implementation { resp := app.operation_at_pos(method, lsp_request) app.write_response_or_cancelled(lsp_request.id, resp) } @@ -718,7 +719,7 @@ fn (mut app App) handle_requests[T](mut reader T) { } // Return all supported capabilities, matching the LSP spec and what is implemented. response := Response{ - id: lsp_request.id + id: lsp_request.id result: Capabilities{ capabilities: Capability{ // NOTE: Placeholder/stub capabilities are intentionally NOT @@ -727,66 +728,66 @@ fn (mut app App) handle_requests[T](mut reader T) { // (wrong abstraction), file-operation hooks (no-ops), and // willSave (never dispatched). Advertising only working // features gives a better editor experience than broken UI. - text_document_sync: TextDocumentSyncOptions{ - open_close: true - change: 2 // Incremental - save: SaveOptions{ + text_document_sync: TextDocumentSyncOptions{ + open_close: true + change: 2 // Incremental + save: SaveOptions{ include_text: true } - will_save: false + will_save: false will_save_wait_until: true } - completion_provider: CompletionProvider{ + completion_provider: CompletionProvider{ trigger_characters: ['.'] } - signature_help_provider: SignatureHelpOptions{ + signature_help_provider: SignatureHelpOptions{ trigger_characters: ['(', ','] } - definition_provider: true - declaration_provider: true - type_definition_provider: true - implementation_provider: true - hover_provider: true - references_provider: true - rename_provider: RenameOptions{ + definition_provider: true + declaration_provider: true + type_definition_provider: true + implementation_provider: true + hover_provider: true + references_provider: true + rename_provider: RenameOptions{ prepare_provider: true } - document_formatting_provider: true - document_symbol_provider: true - workspace_symbol_provider: true - inlay_hint_provider: true - code_action_provider: true - execute_command_provider: ExecuteCommandOptions{ + document_formatting_provider: true + document_symbol_provider: true + workspace_symbol_provider: true + inlay_hint_provider: true + code_action_provider: true + execute_command_provider: ExecuteCommandOptions{ commands: ['vls.runFile', 'vls.runTests'] } - code_lens_provider: CodeLensOptions{} - semantic_tokens_provider: SemanticTokensOptions{ + code_lens_provider: CodeLensOptions{} + semantic_tokens_provider: SemanticTokensOptions{ legend: SemanticTokensLegend{ - token_types: semantic_token_types() + token_types: semantic_token_types() token_modifiers: semantic_token_modifiers() } - full: true - range: true + full: true + range: true } - folding_range_provider: true - call_hierarchy_provider: true - document_highlight_provider: true - selection_range_provider: true + folding_range_provider: true + call_hierarchy_provider: true + document_highlight_provider: true + selection_range_provider: true // Range formatting is NOT advertised: v fmt only formats whole // files, so a correct range implementation needs a // character-accurate, EOL-preserving diff restricted to the // requested range, which is not yet implemented (P0-08). document_range_formatting_provider: false - position_encoding: position_encoding_string(app.position_encoding) - workspace: WorkspaceCapability{ + position_encoding: position_encoding_string(app.position_encoding) + workspace: WorkspaceCapability{ workspace_folders: WorkspaceFoldersServerCapability{ - supported: true + supported: true change_notifications: true } } } - server_info: ServerInfo{ - name: 'vls' + server_info: ServerInfo{ + name: 'vls' version: '0.0.2' } } @@ -816,7 +817,7 @@ fn (mut app App) handle_requests[T](mut reader T) { app.write_notification(Notification{ method: 'textDocument/publishDiagnostics' params: PublishDiagnosticsParams{ - uri: params.text_document.uri + uri: params.text_document.uri diagnostics: [] } }) @@ -920,7 +921,7 @@ fn (mut app App) handle_requests[T](mut reader T) { .will_create_files, .will_rename_files, .will_delete_files { // Return null — vls has no pre-operation file mutations to apply. app.write_response(Response{ - id: lsp_request.id + id: lsp_request.id result: 'null' }) } @@ -1312,7 +1313,7 @@ fn (mut app App) accept_shutdown(id int) { app.stop_run_commands() app.is_shutdown = true app.write_response(Response{ - id: id + id: id result: 'null' }) } @@ -1354,17 +1355,17 @@ fn v_error_to_lsp_diagnostic(e JsonError) LSPDiagnostic { code, tags := derive_diagnostic_code_and_tags(e.message) return LSPDiagnostic{ - message: e.message + message: e.message severity: severity - source: 'vlang' - code: code - tags: tags - range: LSPRange{ + source: 'vlang' + code: code + tags: tags + range: LSPRange{ start: Position{ line: start_line char: start_char } - end: Position{ + end: Position{ line: start_line char: end_char } @@ -1399,7 +1400,14 @@ fn derive_diagnostic_code_and_tags(message string) (?string, ?[]int) { fn method_requires_response(method Method) bool { return match method { - .initialize, .completion, .signature_help, .definition, .hover, .declaration, .type_definition, .implementation, .references, .rename, .prepare_rename, .workspace_symbol, .formatting, .document_symbols, .inlay_hint, .shutdown, .code_action, .semantic_tokens, .folding_range, .callhierarchy_prepare, .callhierarchy_incoming, .callhierarchy_outgoing, .document_highlight, .selection_range, .semantic_tokens_range, .range_formatting, .code_lens, .code_lens_resolve, .execute_command, .inline_value, .linked_editing_range, .will_create_files, .will_rename_files, .will_delete_files, .on_type_formatting { + .initialize, .completion, .signature_help, .definition, .hover, .declaration, + .type_definition, .implementation, .references, .rename, .prepare_rename, + .workspace_symbol, .formatting, .document_symbols, .inlay_hint, .shutdown, .code_action, + .semantic_tokens, .folding_range, .callhierarchy_prepare, .callhierarchy_incoming, + .callhierarchy_outgoing, .document_highlight, .selection_range, .semantic_tokens_range, + .range_formatting, .code_lens, .code_lens_resolve, .execute_command, .inline_value, + .linked_editing_range, .will_create_files, .will_rename_files, .will_delete_files, + .on_type_formatting { true } else { @@ -1414,7 +1422,9 @@ fn method_requires_response(method Method) bool { // regardless of whether a client mistakenly attaches an id. fn method_is_notification_only(method Method) bool { return match method { - .initialized, .did_open, .did_change, .did_close, .did_save, .did_change_watched_files, .workspace_did_change_configuration, .workspace_did_change_workspace_folders, .set_trace, .cancel_request, .will_save { + .initialized, .did_open, .did_change, .did_close, .did_save, .did_change_watched_files, + .workspace_did_change_configuration, .workspace_did_change_workspace_folders, .set_trace, + .cancel_request, .will_save { true } else { @@ -1437,9 +1447,9 @@ fn (app &App) request_is_cancelled(id int) bool { fn make_invalid_request_error_response(id int, message string) ErrorResponse { msg := if message != '' { message } else { 'Invalid request' } return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_invalid_request + code: jsonrpc_err_invalid_request message: msg } } @@ -1447,9 +1457,9 @@ fn make_invalid_request_error_response(id int, message string) ErrorResponse { fn make_server_not_initialized_error_response(id int) ErrorResponse { return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_server_not_initialized + code: jsonrpc_err_server_not_initialized message: 'Server not yet initialized' } } @@ -1457,9 +1467,9 @@ fn make_server_not_initialized_error_response(id int) ErrorResponse { fn make_server_already_initialized_error_response(id int) ErrorResponse { return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_invalid_request + code: jsonrpc_err_invalid_request message: 'Server already initialized' } } @@ -1467,9 +1477,9 @@ fn make_server_already_initialized_error_response(id int) ErrorResponse { fn make_server_shutdown_error_response(id int) ErrorResponse { return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_invalid_request + code: jsonrpc_err_invalid_request message: 'Server has been shut down' } } @@ -1477,9 +1487,9 @@ fn make_server_shutdown_error_response(id int) ErrorResponse { fn make_cancelled_error_response(id int) ErrorResponse { return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_request_cancelled + code: jsonrpc_err_request_cancelled message: 'Request cancelled' } } @@ -1488,9 +1498,9 @@ fn make_cancelled_error_response(id int) ErrorResponse { fn make_parse_error_response(message string) ErrorResponse { msg := if message != '' { message } else { 'Invalid JSON' } return ErrorResponse{ - id: 0 + id: 0 error: ResponseError{ - code: jsonrpc_err_parse_error + code: jsonrpc_err_parse_error message: msg } } @@ -1498,9 +1508,9 @@ fn make_parse_error_response(message string) ErrorResponse { fn make_method_not_found_error_response(id int, method string) ErrorResponse { return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_method_not_found + code: jsonrpc_err_method_not_found message: 'Method not found: ${method}' } } @@ -1509,9 +1519,9 @@ fn make_method_not_found_error_response(id int, method string) ErrorResponse { fn make_invalid_params_error_response(id int, message string) ErrorResponse { msg := if message != '' { message } else { 'Invalid params' } return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_invalid_params + code: jsonrpc_err_invalid_params message: msg } } @@ -1520,9 +1530,9 @@ fn make_invalid_params_error_response(id int, message string) ErrorResponse { fn make_internal_error_response(id int, message string) ErrorResponse { msg := if message != '' { message } else { 'Internal error' } return ErrorResponse{ - id: id + id: id error: ResponseError{ - code: jsonrpc_err_internal_error + code: jsonrpc_err_internal_error message: msg } } @@ -1542,7 +1552,8 @@ fn validate_request_params(method Method, params_json string) ?string { } } } - .completion, .signature_help, .definition, .hover, .declaration, .type_definition, .implementation, .prepare_rename, .document_highlight { + .completion, .signature_help, .definition, .hover, .declaration, .type_definition, + .implementation, .prepare_rename, .document_highlight { params := json2.decode[TextDocumentPositionParams](params_json) or { return 'Invalid textDocument/position params: ${err.msg()}' } @@ -1805,7 +1816,7 @@ fn (mut app App) write_raw_request(id int, method string, params_json string) { // level: 1=Error, 2=Warning, 3=Info, 4=Log. fn (mut app App) send_show_message(msg string, level int) { params := ShowMessageParams{ - type_: level + type_: level message: msg } app.write_raw_notification('window/showMessage', json2.encode(params, escape_unicode: true)) @@ -1815,7 +1826,7 @@ fn (mut app App) send_show_message(msg string, level int) { // level: 1=Error, 2=Warning, 3=Info, 4=Log. fn (mut app App) send_log_message(msg string, level int) { params := LogMessageParams{ - type_: level + type_: level message: msg } app.write_raw_notification('window/logMessage', json2.encode(params, escape_unicode: true)) @@ -1853,7 +1864,7 @@ fn (mut app App) report_progress(token string, message string, percentage int) { return } report := WorkDoneProgressReport{ - message: message + message: message percentage: percentage } progress_json := '{"token":"${token}","value":${json2.encode(report, escape_unicode: true)}}' @@ -1885,12 +1896,12 @@ fn (mut app App) on_initialized(_ Request) { } reg_id := app.next_request_id reg := RegisterCapabilityRequest{ - id: reg_id + id: reg_id params: WatcherRegistrationParams{ registrations: [ WatcherRegistration{ - id: 'vls-file-watcher' - method: 'workspace/didChangeWatchedFiles' + id: 'vls-file-watcher' + method: 'workspace/didChangeWatchedFiles' register_options: WatcherRegisterOptions{ watchers: [ FileSystemWatcher{ diff --git a/run_command.v b/run_command.v index 1acde127..a4c5905b 100644 --- a/run_command.v +++ b/run_command.v @@ -365,8 +365,8 @@ mut: fn new_run_command_manager() &RunCommandManager { return &RunCommandManager{ - workers: sync.new_waitgroup() - processes: map[u64]&os.Process{} + workers: sync.new_waitgroup() + processes: map[u64]&os.Process{} active_targets: map[string]u64{} } } @@ -506,7 +506,7 @@ fn run_managed_process(mut manager RunCommandManager, id u64, target string, exe return ManagedRunResult{ result: os.Result{ exit_code: 1 - output: 'Working dir does not exist: ${work_folder}' + output: 'Working dir does not exist: ${work_folder}' } } } @@ -548,9 +548,9 @@ fn run_managed_process(mut manager RunCommandManager, id u64, target string, exe exit_code := process.code process.close() return ManagedRunResult{ - result: os.Result{ + result: os.Result{ exit_code: exit_code - output: output.str() + output: output.str() } cancelled: !registered || manager.job_is_cancelled(id, target) } @@ -598,11 +598,11 @@ fn run_code_lens_job(mut manager RunCommandManager, id u64, target string, } temp_dir := os.join_path(os.temp_dir(), 'vls_run_${os.getpid()}_${id}_${time.now().unix_nano()}') mut worker := App{ - open_files: job.open_files - temp_dir: temp_dir + open_files: job.open_files + temp_dir: temp_dir capture_output: job.capture_output - write_mutex: job.write_mutex - tcp_conn: job.tcp_conn + write_mutex: job.write_mutex + tcp_conn: job.tcp_conn } os.mkdir_all(temp_dir) or { worker.send_show_message('vls: ${job.title} could not create a temporary directory: ${err}', 1) diff --git a/semantic_tokens.v b/semantic_tokens.v index ace6b3e1..28ae36c6 100644 --- a/semantic_tokens.v +++ b/semantic_tokens.v @@ -119,9 +119,9 @@ fn tokenize_v_line(line string, line_idx int, mut state TokenizeState, mut token } if col > start { tokens << SemToken{ - line: line_idx - start: start - length: col - start + line: line_idx + start: start + length: col - start type_idx: sem_tok_comment } } @@ -163,9 +163,9 @@ fn tokenize_v_code(line string, from int, to int, line_idx int, mut state Tokeni state.in_block_comment = true } tokens << SemToken{ - line: line_idx - start: start - length: col - start + line: line_idx + start: start + length: col - start type_idx: sem_tok_comment } continue @@ -174,9 +174,9 @@ fn tokenize_v_code(line string, from int, to int, line_idx int, mut state Tokeni // Line comment: // … if col + 1 < n && c == `/` && line[col + 1] == `/` { tokens << SemToken{ - line: line_idx - start: col - length: n - col + line: line_idx + start: col + length: n - col type_idx: sem_tok_comment } return @@ -200,9 +200,9 @@ fn tokenize_v_code(line string, from int, to int, line_idx int, mut state Tokeni col++ } tokens << SemToken{ - line: line_idx - start: start - length: col - start + line: line_idx + start: start + length: col - start type_idx: sem_tok_string } continue @@ -226,9 +226,9 @@ fn tokenize_v_code(line string, from int, to int, line_idx int, mut state Tokeni } } tokens << SemToken{ - line: line_idx - start: start - length: col - start + line: line_idx + start: start + length: col - start type_idx: sem_tok_number } continue @@ -249,13 +249,13 @@ fn tokenize_v_code(line string, from int, to int, line_idx int, mut state Tokeni tok_type := classify_v_identifier_at(line, start, col, word, state.import_aliases) if tok_type >= 0 { tokens << SemToken{ - line: line_idx - start: start - length: col - start + line: line_idx + start: start + length: col - start type_idx: tok_type mod_bits: if tok_type == sem_tok_variable && (variable_binding_key(state.variable_scope, word) in state.readonly_variables - || variable_binding_key(0, word) in state.readonly_variables) { + || variable_binding_key(0, word) in state.readonly_variables) { sem_mod_readonly } else { 0 @@ -505,9 +505,9 @@ fn tokenize_v_string(line string, start int, to int, line_idx int, mut state Tok fn append_string_token(mut tokens []SemToken, line_idx int, start int, end int) { if end > start { tokens << SemToken{ - line: line_idx - start: start - length: end - start + line: line_idx + start: start + length: end - start type_idx: sem_tok_string } } @@ -579,7 +579,7 @@ fn convert_tokens_to_encoding(tokens []SemToken, lines []string, enc PositionEnc enc_end := byte_to_encoded_col(line, tok.start + tok.length, enc) out << SemToken{ ...tok - start: enc_start + start: enc_start length: enc_end - enc_start } } @@ -615,7 +615,7 @@ fn (mut app App) handle_semantic_tokens(request Request) Response { log('Failed to decode SemanticTokensParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -624,7 +624,7 @@ fn (mut app App) handle_semantic_tokens(request Request) Response { if content == '' { // An empty document has an empty token set, not a null result (P2-01). return Response{ - id: request.id + id: request.id result: SemanticTokens{ data: [] } @@ -634,7 +634,7 @@ fn (mut app App) handle_semantic_tokens(request Request) Response { raw_tokens := convert_tokens_to_encoding(tokenize_v_source(content), lines, app.position_encoding) encoded := encode_semantic_tokens(raw_tokens) return Response{ - id: request.id + id: request.id result: SemanticTokens{ data: encoded } @@ -650,7 +650,7 @@ fn (mut app App) handle_semantic_tokens_range(request Request) Response { log('Failed to decode SemanticTokensRangeParams: ${err}') } return Response{ - id: request.id + id: request.id result: 'null' } } @@ -658,7 +658,7 @@ fn (mut app App) handle_semantic_tokens_range(request Request) Response { content := app.open_files[uri] or { os.read_file(uri_to_path(uri)) or { '' } } if content == '' { return Response{ - id: request.id + id: request.id result: SemanticTokens{ data: [] } @@ -679,7 +679,7 @@ fn (mut app App) handle_semantic_tokens_range(request Request) Response { && (it.line < end_line || (it.line == end_line && it.start < end_char))) encoded := encode_semantic_tokens(range_tokens) return Response{ - id: request.id + id: request.id result: SemanticTokens{ data: encoded }