├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ ├── prerelease.yml │ └── tree-sitter-v-ci.yml ├── .gitignore ├── CAPABILITIES.md ├── LICENSE ├── README.md ├── analyzer ├── README.md ├── an_test_utils │ └── an_test_utils.v ├── ast.v ├── builtin.v ├── context.v ├── errors │ ├── errors.v │ ├── formatter.v │ └── formatter_test.v ├── formatter.v ├── imports.v ├── imports_misc.v ├── imports_test.v ├── readme_assets │ └── vls-flow.jpg ├── report.v ├── reporter.v ├── scope.v ├── scope_test.v ├── semantic_analyzer.v ├── semantic_analyzer_compliance_test_.skipvv ├── semantic_analyzer_test.v ├── store.v ├── symbol.v ├── symbol_registration.v ├── symbol_registration_test.v ├── test_files │ ├── imports │ │ ├── abc │ │ │ └── abc.v │ │ ├── aliased.test.txt │ │ ├── def │ │ │ └── src │ │ │ │ ├── def.v │ │ │ │ └── ghi │ │ │ │ └── src │ │ │ │ └── ghi.v │ │ ├── invalid.test.txt │ │ ├── local.test.txt │ │ ├── nested.test.txt │ │ ├── simple.test.txt │ │ └── with_src_folder.test.txt │ ├── semantic_analyzer │ │ ├── array.test.txt │ │ ├── assert_statement.test.txt │ │ ├── assignment_statement.test.txt │ │ ├── binary_expression.test.txt │ │ ├── break_statement.test.txt │ │ ├── call_expression.test.txt │ │ ├── enum_declaration.test.txt │ │ ├── for_statement.test.txt │ │ ├── function_declaration.test.txt │ │ ├── if_expression.test.txt │ │ ├── import_symbols.test.txt │ │ ├── match_expression.test.txt │ │ ├── parenthesized_expression.test.txt │ │ ├── selector_expression.test.txt │ │ ├── send_statement.test.txt │ │ ├── spread_operator.test.txt │ │ ├── type_cast_expression.test.txt │ │ ├── type_declaration.test.txt │ │ ├── type_expression.test.txt │ │ └── type_initializer.test.txt │ └── symbol_registration │ │ ├── abc │ │ └── abc.v │ │ ├── const_decl.test.txt │ │ ├── efg │ │ └── efg.v │ │ ├── enum_decl.test.txt │ │ ├── fn_decl.test.txt │ │ ├── for_loop.test.txt │ │ ├── imported_fn.test.txt │ │ ├── match_expr.test.txt │ │ ├── method_decl.test.txt │ │ ├── short_var_decl.test.txt │ │ ├── struct_decl.test.txt │ │ ├── type_decl.test.txt │ │ └── unsafe_expr.test.txt ├── text.v └── tree_cursor.v ├── ast ├── parser.v └── tree_walker.v ├── build.vsh ├── cmd └── vls │ ├── connection_test.v │ ├── host.v │ ├── main.v │ ├── streams.v │ └── utils.v ├── images └── instructions.png ├── jsonrpc ├── jsonrpc.v ├── jsonrpc_test.v ├── server.v ├── server_test.v └── server_test_utils │ └── server_test_utils.v ├── lsp ├── README.md ├── capabilities.v ├── client.v ├── code_action.v ├── code_lens.v ├── color_presentation.v ├── completion.v ├── declaration.v ├── definition.v ├── diagnostics.v ├── document_color.v ├── document_highlight.v ├── document_link.v ├── document_symbol.v ├── file_resource.v ├── folding_range.v ├── formatting.v ├── hover.v ├── implementation.v ├── initialize.v ├── log │ ├── log.v │ └── log_test.v ├── lsp.v ├── lsp_test.v ├── references.v ├── rename.v ├── signature_help.v ├── symbol.v ├── text_document.v ├── text_sync.v ├── window.v └── workspace.v ├── server ├── ast.v ├── diagnostics.v ├── features.v ├── features_code_lens.v ├── features_completion.v ├── features_document_link.v ├── features_hover.v ├── file.v ├── general.v ├── general_test.v ├── os_utils_default.c.v ├── os_utils_windows.c.v ├── positions.v ├── tests │ ├── code_lens_test.v │ ├── completion_test.v │ ├── definition_test.v │ ├── diagnostics_test.v │ ├── document_link_test.v │ ├── document_symbols_test.v │ ├── folding_range_test.v │ ├── formatting_test.v │ ├── hover_test.v │ ├── implementation_test.v │ ├── positions_test.v │ ├── regression_test.v │ ├── signature_help_test.v │ ├── test_files │ │ ├── code_lens │ │ │ └── simple.vv │ │ ├── completion │ │ │ ├── .do_not_import │ │ │ │ └── .gitkeep │ │ │ ├── abc │ │ │ │ ├── abc.v │ │ │ │ └── def │ │ │ │ │ ├── def.v │ │ │ │ │ └── ghi │ │ │ │ │ └── .gitkeep │ │ │ ├── assign.vv │ │ │ ├── binded_symbol.vv │ │ │ ├── blank.vv │ │ │ ├── call_args.vv │ │ │ ├── embedded_struct_field.vv │ │ │ ├── enum_member.vv │ │ │ ├── enum_method.vv │ │ │ ├── enum_val_in_struct.vv │ │ │ ├── filtered_fields_in_selector.vv │ │ │ ├── filtered_methods_in_immutable_var.vv │ │ │ ├── filtered_methods_in_mutable_var.vv │ │ │ ├── fn_literal.vv │ │ │ ├── gfx │ │ │ │ └── gfx.v │ │ │ ├── import_symbols.vv │ │ │ ├── incomplete_call_expr_selector.vv │ │ │ ├── incomplete_enum_selector.vv │ │ │ ├── incomplete_module.vv │ │ │ ├── incomplete_nested_selector.vv │ │ │ ├── incomplete_selector.vv │ │ │ ├── invalid_call.vv │ │ │ ├── local_results.vv │ │ │ ├── module_selector.vv │ │ │ ├── module_symbols_selector.vv │ │ │ ├── self_reference_var_in_struct_field.vv │ │ │ ├── struct_init.vv │ │ │ ├── struct_init_string_field.vv │ │ │ └── type_decl.vv │ │ ├── connection │ │ │ └── hello.vv │ │ ├── definition │ │ │ ├── call_arg.vv │ │ │ ├── call_expr.vv │ │ │ ├── enum_val.vv │ │ │ ├── expr_in_array.vv │ │ │ ├── expr_in_map_key.vv │ │ │ ├── expr_in_map_value.vv │ │ │ ├── fn_literal.vv │ │ │ ├── fn_param_type.vv │ │ │ ├── fn_return_type.vv │ │ │ ├── index_expr.vv │ │ │ ├── interface_field.vv │ │ │ ├── interface_method_skip.vv │ │ │ ├── node_error.vv │ │ │ ├── selector_expr.vv │ │ │ ├── stmt.vv │ │ │ ├── struct_field_type.vv │ │ │ ├── struct_init.vv │ │ │ ├── struct_init_field_name.vv │ │ │ ├── struct_init_field_value.vv │ │ │ ├── var.vv │ │ │ └── var_receiver.vv │ │ ├── diagnostics │ │ │ ├── error_highlight.vv │ │ │ └── simple.vv │ │ ├── document_link │ │ │ └── simple.vv │ │ ├── document_symbols │ │ │ └── simple.vv │ │ ├── folding_range │ │ │ ├── comment_skip.vv │ │ │ └── simple_skip.vv │ │ ├── formatting │ │ │ ├── cjk_1.out │ │ │ ├── cjk_1.vv │ │ │ ├── cjk_2.out │ │ │ ├── cjk_2.vv │ │ │ ├── empty.vv │ │ │ ├── simple_skip_windows.out │ │ │ ├── simple_skip_windows.vv │ │ │ └── with_error.vv │ │ ├── hover │ │ │ ├── call_expr_method.vv │ │ │ ├── call_expr_simple.vv │ │ │ ├── enum.vv │ │ │ ├── fn_literal.vv │ │ │ ├── function.vv │ │ │ ├── function_param.vv │ │ │ ├── import.vv │ │ │ ├── interface_spec.vv │ │ │ ├── interface_spec_params.vv │ │ │ ├── module.vv │ │ │ ├── node_error_skip.vv │ │ │ ├── selector_expr.vv │ │ │ ├── struct.vv │ │ │ ├── struct_field.vv │ │ │ ├── struct_init_a.vv │ │ │ ├── struct_init_b.vv │ │ │ ├── type_alias.vv │ │ │ ├── type_fn.vv │ │ │ ├── type_sum.vv │ │ │ ├── variable.vv │ │ │ └── with_call_expr_below.vv │ │ ├── implementation │ │ │ └── simple.vv │ │ ├── pos_compute_offset │ │ │ ├── crlf.vv │ │ │ └── lf.vv │ │ ├── pos_to_lsp_pos │ │ │ └── simple.vv │ │ ├── pos_to_lsp_range │ │ │ ├── simple.vv │ │ │ └── with_last_line.vv │ │ ├── regressions │ │ │ ├── function_in_struct_decl_skip_macos.vv │ │ │ ├── incomplete_fn.vv │ │ │ ├── option_interface_name.vv │ │ │ ├── simple_vweb_app_skip.vv │ │ │ └── string_literal_selector.vv │ │ ├── signature_help │ │ │ ├── empty_middle_arg.vv │ │ │ ├── empty_second_arg.vv │ │ │ ├── simple.vv │ │ │ ├── with_content.vv │ │ │ └── with_content_b.vv │ │ ├── workspace_did_change │ │ │ ├── changed_be_ignored.vv │ │ │ ├── should_be_deleted.vv │ │ │ └── should_be_renamed.vv │ │ └── workspace_symbols │ │ │ ├── file1.vv │ │ │ └── file2.vv │ ├── workspace_did_change_test.v │ └── workspace_symbols_test.v ├── text_synchronization.v ├── vls.v ├── window.v ├── window_test.v └── workspace.v ├── structures ├── depgraph │ ├── depgraph.v │ └── depgraph_test.v └── ropes │ ├── ropes.v │ └── ropes_test.v ├── test_utils ├── test_file_parser.v ├── test_file_parser_test.v ├── test_utils.v └── test_utils_test.v ├── tree_sitter ├── lib │ ├── alloc.c │ ├── alloc.h │ ├── api.h │ ├── array.h │ ├── clock.h │ ├── error_costs.h │ ├── get_changed_ranges.c │ ├── get_changed_ranges.h │ ├── host.h │ ├── language.c │ ├── language.h │ ├── length.h │ ├── lexer.c │ ├── lexer.h │ ├── lib.c │ ├── node.c │ ├── parser.c │ ├── parser.h │ ├── point.h │ ├── query.c │ ├── reduce_action.h │ ├── reusable_node.h │ ├── stack.c │ ├── stack.h │ ├── subtree.c │ ├── subtree.h │ ├── tree.c │ ├── tree.h │ ├── tree_cursor.c │ ├── tree_cursor.h │ ├── ts_atomic.h │ ├── unicode.h │ └── unicode │ │ ├── ICU_SHA │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ptypes.h │ │ ├── umachine.h │ │ ├── urename.h │ │ ├── utf.h │ │ ├── utf16.h │ │ └── utf8.h ├── tree_sitter.v └── ts_version.json ├── tree_sitter_v ├── .github │ └── workflows │ │ └── ci.yml ├── .gitignore ├── .npmignore ├── Cargo.toml ├── LICENSE ├── README.md ├── binding.gyp ├── bindings.v ├── bindings │ ├── node │ │ ├── binding.cc │ │ └── index.js │ ├── rust │ │ ├── build.rs │ │ └── lib.rs │ └── v │ │ ├── bindings.h │ │ └── bindings.v ├── generate_types.vsh ├── grammar.js ├── node_types.v ├── package.json ├── queries │ └── highlights.scm ├── src │ ├── grammar.json │ ├── node-types.json │ ├── parser.c │ ├── scanner.c │ └── tree_sitter │ │ └── parser.h ├── test │ └── corpus │ │ ├── array.txt │ │ ├── array_fixed.txt │ │ ├── as_type_cast_expression.txt │ │ ├── asm_statement.txt │ │ ├── assert_statement.txt │ │ ├── assignment_statement.txt │ │ ├── attribute_declaration.txt │ │ ├── binary_expression.txt │ │ ├── binary_expression_receive.txt │ │ ├── bit_not.txt │ │ ├── c_fn_call.txt │ │ ├── c_fn_decl.txt │ │ ├── call_expression.txt │ │ ├── call_expression_embed.txt │ │ ├── cast_expression.txt │ │ ├── comptime_for_statement.txt │ │ ├── comptime_identifier.txt │ │ ├── comptime_if_expression.txt │ │ ├── comptime_selector_expression.txt │ │ ├── const_declaration.txt │ │ ├── const_declaration_pub.txt │ │ ├── const_declaration_single.txt │ │ ├── const_declaration_single_multi.txt │ │ ├── defer_statement.txt │ │ ├── empty_function.txt │ │ ├── empty_labelled_statement.txt │ │ ├── enum_declaration.txt │ │ ├── enum_declaration_pub.txt │ │ ├── float_literal.txt │ │ ├── fn_literal.txt │ │ ├── for_statement.txt │ │ ├── for_statement_cstyle.txt │ │ ├── for_statement_in.txt │ │ ├── function_declaration.txt │ │ ├── function_declaration_generic.txt │ │ ├── function_overload.txt │ │ ├── function_type.txt │ │ ├── global_var_declaration.txt │ │ ├── go_statement.txt │ │ ├── goto_statement.txt │ │ ├── hash_statement.txt │ │ ├── if_expression.txt │ │ ├── if_expression_is.txt │ │ ├── if_expression_var.txt │ │ ├── import_declaration.txt │ │ ├── import_declaration_symbols.txt │ │ ├── import_declaratoin_alias.txt │ │ ├── index_expression.txt │ │ ├── interface_declaration.txt │ │ ├── interface_declaration_embed.txt │ │ ├── interface_declaration_field.txt │ │ ├── interface_declaration_pub.txt │ │ ├── interpreted_string_literal_interp.txt │ │ ├── js_fn_call.txt │ │ ├── js_fn_decl.txt │ │ ├── labeled_statement.txt │ │ ├── lock.txt │ │ ├── map.txt │ │ ├── match_expression.txt │ │ ├── module_clause.txt │ │ ├── multi_return_type.txt │ │ ├── mutable_argument.txt │ │ ├── mutable_match_expression.txt │ │ ├── pseudo_comptime_identifier.txt │ │ ├── qualified_type.txt │ │ ├── relational_operator.txt │ │ ├── return_statement.txt │ │ ├── rune_literal.txt │ │ ├── select_expression.txt │ │ ├── selector_expression.txt │ │ ├── selector_expression_incomplete.txt │ │ ├── send_statement.txt │ │ ├── short_var_declaration.txt │ │ ├── slice_expression.txt │ │ ├── spawn_statement.txt │ │ ├── spread_operator.txt │ │ ├── sql_expression.txt │ │ ├── string_interpolation_format_specifier.txt │ │ ├── string_literal.txt │ │ ├── struct_declaration.txt │ │ ├── struct_declaration_embed.txt │ │ ├── struct_declaration_generic.txt │ │ ├── struct_declaration_pub.txt │ │ ├── struct_declaration_typedef_c.txt │ │ ├── struct_declaration_typedef_js.txt │ │ ├── type_declaration.txt │ │ ├── type_declaration_sum_type.txt │ │ ├── type_initializer.txt │ │ ├── type_initializer_array.txt │ │ ├── type_initializer_binded.txt │ │ ├── type_initializer_chan.txt │ │ ├── type_initializer_generic.txt │ │ ├── type_initializer_incomplete.txt │ │ ├── type_initializer_map_alt.txt │ │ ├── type_initializer_map_empty.txt │ │ ├── type_selector_expression.txt │ │ ├── unsafe_expression.txt │ │ └── vsh_mode.txt ├── tools │ └── project-checker.js ├── v.mod └── yarn.lock ├── update_tree_sitter.vsh └── v.mod /.gitattributes: -------------------------------------------------------------------------------- 1 | *.v linguist-language=V text=auto eol=lf 2 | *.vsh linguist-language=V text=auto eol=lf 3 | server/tests/test_files/pos_compute_offset/crlf.vv linguist-language=V text=auto eol=crlf 4 | server/tests/test_files/pos_compute_offset/lf.vv linguist-language=V text=auto eol=lf 5 | tree_sitter/** linguist-vendored 6 | tree_sitter_v/** linguist-vendored -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Do you encounter a crash or found an unusual bug? Post them here. 4 | title: '' 5 | labels: 'bug' 6 | assignees: '' 7 | # When updating, make sure to update the template in 'cmd/vls/host.v' too 8 | --- 9 | 10 | ## System Information 11 | ### V doctor 12 | ``` 13 | Paste the output of 'v doctor' here 14 | ``` 15 | 16 | ### VLS info 17 | ``` 18 | Paste the output of 'vls --version' here 19 | ``` 20 | 21 | ## Problem Description 22 | 23 | 24 | 25 | ## Expected Output 26 | 27 | 28 | ## Actual Output 29 | 30 | 31 | ## Steps to Reproduce 32 | 33 | 34 | ## Last Recorded LSP Requests 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Do you have an idea that you think is missing in the language server? Post them here. 4 | title: '' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | -------------------------------------------------------------------------------- /.github/workflows/tree-sitter-v-ci.yml: -------------------------------------------------------------------------------- 1 | # Taken from: https://github.com/tree-sitter/tree-sitter-go/tree/eb306e6e60f393df346cfc8cbfaf52667a37128a/.github/workflows 2 | name: tree-sitter-v/build/test 3 | on: 4 | push: 5 | branches: 6 | - "**" 7 | env: 8 | EM_VERSION: 1.39.18 9 | EM_CACHE_FOLDER: "emsdk-cache" 10 | 11 | jobs: 12 | tree_sitter_v_test: 13 | runs-on: ${{ matrix.os }} 14 | defaults: 15 | run: 16 | working-directory: ./tree_sitter_v 17 | strategy: 18 | fail-fast: true 19 | matrix: 20 | os: [macos-latest, ubuntu-latest] 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: actions/setup-node@v2 24 | with: 25 | node-version: 14 26 | - run: npm install 27 | - run: npm test 28 | 29 | tree_sitter_v_test_windows: 30 | runs-on: windows-2019 31 | defaults: 32 | run: 33 | working-directory: ./tree_sitter_v 34 | steps: 35 | - uses: actions/checkout@v2 36 | - uses: actions/setup-node@v2 37 | with: 38 | node-version: 14 39 | - run: npm install 40 | - run: npm run-script test 41 | 42 | tree_sitter_v_vlib_test: 43 | runs-on: ubuntu-latest 44 | defaults: 45 | run: 46 | working-directory: ./tree_sitter_v 47 | strategy: 48 | fail-fast: true 49 | steps: 50 | - uses: actions/checkout@v2 51 | - uses: actions/setup-node@v2 52 | with: 53 | node-version: 14 54 | - name: Clone & Build vmaster/v 55 | run: | 56 | git clone --depth=1 https://github.com/vlang/v vmaster/ 57 | - run: npm install 58 | - name: Run VLib parsing test 59 | id: run_vlib_test 60 | continue-on-error: true 61 | run: | 62 | node tools/project-checker.js vmaster/vlib/ --hideRanges --errorsOnly 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Editor files 4 | *.code-workspace 5 | 6 | # Debugging 7 | *.dSYM 8 | 9 | # Other 10 | cmd/vls/vls 11 | .vscode 12 | 13 | bin/* 14 | 15 | *.so 16 | 17 | *.dll 18 | 19 | vls.log 20 | -------------------------------------------------------------------------------- /CAPABILITIES.md: -------------------------------------------------------------------------------- 1 | # Capabilities Roadmap 2 | As of this moment, VLS does not provide all the methods as described in the Language Server Protocol spec. And the following is a list of methods that have been or have yet to be implemented by VLS. 3 | 4 | - [ ] Queue support (support for cancelling requests) 5 | 6 | ### General 7 | - [x] `initialize` (Activates features based on VSCode's capabilities for now.) 8 | - [x] `initialized` 9 | - [x] `shutdown` 10 | - [x] `exit` 11 | - [ ] `$/cancelRequest` 12 | 13 | ### Window 14 | - [x] `showMessage` 15 | - [x] `showMessageRequest` 16 | - [x] `logMessage` 17 | - [ ] `progress/create` 18 | - [ ] `progress/cancel` 19 | ### Telemetry 20 | - [ ] `event` (Implemented but not usable) 21 | ### Client 22 | - [ ] `registerCapability` 23 | - [ ] `unregisterCapability` 24 | ### Workspace 25 | - [ ] `workspaceFolders` 26 | - [ ] `didChangeWorkspaceFolder` 27 | - [ ] `didChangeConfiguration` 28 | - [ ] `configuration` 29 | - [x] `didChangeWatchedFiles` 30 | - [x] `symbol` 31 | - [ ] `executeCommand` 32 | - [ ] `applyEdit` 33 | ### Text Synchronization 34 | - [x] `didOpen` 35 | - [x] `didChange` 36 | - [x] `willSave` (**stub**) 37 | - [ ] `willSaveWaitUntil` 38 | - [x] `didSave` 39 | - [x] `didClose` 40 | ### Diagnostics 41 | - [x] `publishDiagnostics` 42 | ### Language Features 43 | - [x] `completion` 44 | - [ ] `completion resolve` 45 | - [x] `hover` 46 | - [x] `signatureHelp` 47 | - [ ] `declaration` 48 | - [x] `definition` 49 | - [ ] `typeDefinition` 50 | - [x] `implementation` 51 | - [ ] `references` 52 | - [ ] `documentHighlight` 53 | - [x] `documentSymbol` 54 | - [ ] `codeAction` 55 | - [x] `codeLens` (**stub**) 56 | - [ ] `codeLens resolve` 57 | - [x] `documentLink` (**stub**) 58 | - [ ] `documentLink resolve` 59 | - [ ] `documentColor` 60 | - [ ] `colorPresentation` 61 | - [x] `formatting` 62 | - [ ] `rangeFormatting` 63 | - [ ] `onTypeFormatting` 64 | - [ ] `rename` 65 | - [ ] `prepareRename` 66 | - [x] `foldingRange` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 The V Programming Language 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /analyzer/ast.v: -------------------------------------------------------------------------------- 1 | module analyzer 2 | 3 | fn within_range(node_range C.TSRange, start_line u32, end_line u32) bool { 4 | return (node_range.start_point.row >= start_line && node_range.start_point.row <= end_line) 5 | || (node_range.end_point.row >= start_line && node_range.end_point.row <= end_line) 6 | } 7 | -------------------------------------------------------------------------------- /analyzer/errors/formatter_test.v: -------------------------------------------------------------------------------- 1 | import analyzer.errors 2 | 3 | fn simple_data_formatter(data errors.ErrorData) string { 4 | if data is string { 5 | return *data 6 | } else { 7 | return '$data' 8 | } 9 | } 10 | 11 | fn test_format() { 12 | assert errors.format(simple_data_formatter, 'hello %s', 'world') == 'hello world' 13 | assert errors.format(simple_data_formatter, errors.undefined_operation_error, 'int', 14 | '+', 'int') == 'undefined operation `int` + `int`' 15 | } 16 | 17 | fn test_format_map() { 18 | assert errors.format(simple_data_formatter, errors.selective_const_import_error, { 19 | 'var': 'foo' 20 | 'module': 'modz' 21 | }) == 'cannot selective import constant `foo` from `modz`, import `modz` and use `modz.foo` instead' 22 | } 23 | -------------------------------------------------------------------------------- /analyzer/readme_assets/vls-flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/analyzer/readme_assets/vls-flow.jpg -------------------------------------------------------------------------------- /analyzer/report.v: -------------------------------------------------------------------------------- 1 | module analyzer 2 | 3 | pub struct AnalyzerError { 4 | Error 5 | msg string 6 | file_path string 7 | range C.TSRange 8 | } 9 | 10 | pub fn (err AnalyzerError) msg() string { 11 | start := '${err.range.start_point.row}:${err.range.start_point.column}' 12 | end := '${err.range.end_point.row}:${err.range.end_point.column}' 13 | return '[${start} -> ${end}] ${err.msg}' 14 | } 15 | 16 | pub fn (err AnalyzerError) str() string { 17 | return err.msg() 18 | } 19 | 20 | fn report_error(msg string, range C.TSRange) IError { 21 | return AnalyzerError{ 22 | msg: msg 23 | range: range 24 | } 25 | } 26 | 27 | // report_error reports the AnalyzerError to the messages array 28 | pub fn (mut ss Store) report_error(err IError) { 29 | if err is AnalyzerError { 30 | ss.report( 31 | kind: .error 32 | message: err.msg 33 | range: err.range 34 | file_path: err.file_path 35 | ) 36 | } 37 | } 38 | 39 | // report_error_with_path reports AnalyzerError to the messages array, and allow 40 | // you to specify file path of this error with an argument. 41 | pub fn (mut ss Store) report_error_with_path(err IError, file_path string) { 42 | if err is AnalyzerError { 43 | ss.report( 44 | kind: .error 45 | message: err.msg 46 | range: err.range 47 | file_path: file_path 48 | ) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /analyzer/reporter.v: -------------------------------------------------------------------------------- 1 | module analyzer 2 | 3 | pub interface ReportData {} 4 | 5 | [json_as_number] 6 | pub enum ReportKind { 7 | error 8 | warning 9 | notice 10 | } 11 | 12 | pub struct Report { 13 | pub: 14 | kind ReportKind 15 | code string 16 | message string 17 | file_path string 18 | source string 19 | range C.TSRange 20 | data ReportData = 1 21 | } 22 | 23 | pub struct ReporterPreferences { 24 | mut: 25 | limit int = 100 26 | warns_are_errors bool 27 | } 28 | 29 | pub interface Reporter { 30 | count() int 31 | mut: 32 | prefs ReporterPreferences 33 | report(r Report) 34 | } 35 | 36 | pub fn (r Reporter) reached_limit() bool { 37 | return r.count() >= r.prefs.limit 38 | } 39 | 40 | pub struct Collector { 41 | pub mut: 42 | prefs ReporterPreferences 43 | errors []Report 44 | warnings []Report 45 | notices []Report 46 | } 47 | 48 | pub fn (mut c Collector) clear() { 49 | c.errors.clear() 50 | c.warnings.clear() 51 | c.notices.clear() 52 | } 53 | 54 | pub fn (mut c Collector) report(r Report) { 55 | match r.kind { 56 | .error { 57 | c.errors << r 58 | } 59 | .warning { 60 | if c.prefs.warns_are_errors { 61 | c.report(Report{ 62 | ...r 63 | kind: .error 64 | }) 65 | return 66 | } 67 | c.warnings << r 68 | } 69 | .notice { 70 | c.notices << r 71 | } 72 | } 73 | } 74 | 75 | pub fn (c &Collector) count() int { 76 | return c.errors.len + c.warnings.len + c.notices.len 77 | } 78 | -------------------------------------------------------------------------------- /analyzer/scope_test.v: -------------------------------------------------------------------------------- 1 | fn test_scope_tree() { 2 | // mut scope_tree := ScopeTree{} 3 | 4 | // scope_tree.register() 5 | } 6 | -------------------------------------------------------------------------------- /analyzer/test_files/imports/abc/abc.v: -------------------------------------------------------------------------------- 1 | module abc 2 | -------------------------------------------------------------------------------- /analyzer/test_files/imports/aliased.test.txt: -------------------------------------------------------------------------------- 1 | import strings as str_utils 2 | 3 | --- 4 | 5 | (str_utils "$VLIB/strings" [0,7]-[0,14]) -------------------------------------------------------------------------------- /analyzer/test_files/imports/def/src/def.v: -------------------------------------------------------------------------------- 1 | module def 2 | 3 | pub fn hello() {} 4 | -------------------------------------------------------------------------------- /analyzer/test_files/imports/def/src/ghi/src/ghi.v: -------------------------------------------------------------------------------- 1 | module ghi 2 | 3 | pub fn world() {} 4 | -------------------------------------------------------------------------------- /analyzer/test_files/imports/invalid.test.txt: -------------------------------------------------------------------------------- 1 | import invalid_module 2 | 3 | --- -------------------------------------------------------------------------------- /analyzer/test_files/imports/local.test.txt: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | --- 4 | 5 | (abc "./abc" [0,7]-[0,10]) -------------------------------------------------------------------------------- /analyzer/test_files/imports/nested.test.txt: -------------------------------------------------------------------------------- 1 | import x.json2 2 | 3 | --- 4 | 5 | (json2 "$VLIB/x/json2" [0,7]-[0,14]) -------------------------------------------------------------------------------- /analyzer/test_files/imports/simple.test.txt: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | --- 4 | 5 | (os "$VLIB/os" [0,7]-[0,9]) 6 | -------------------------------------------------------------------------------- /analyzer/test_files/imports/with_src_folder.test.txt: -------------------------------------------------------------------------------- 1 | import def 2 | import def.ghi 3 | 4 | --- 5 | 6 | (def "./def/src" [0,7]-[0,10]) 7 | (ghi "./def/src/ghi/src" [1,7]-[1,14]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/array.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | ['tes', 2] 3 | } 4 | 5 | --- 6 | 7 | (error "invalid array element: expected `string`, not `int`" [1,12]-[1,13]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/assert_statement.test.txt: -------------------------------------------------------------------------------- 1 | fn test_assert() { 2 | expected := 1 3 | assert expected == 'test' 4 | assert 1 + 1 5 | } 6 | 7 | --- 8 | 9 | (error "mismatched types `int` and `string`" [2,11]-[2,29]) 10 | (error "assert can be used only with `bool` expressions, but found `void` instead" [2,11]-[2,29]) 11 | (error "assert can be used only with `bool` expressions, but found `int literal` instead" [3,11]-[3,16]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/assignment_statement.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | mut str := 'test' 3 | str = 1 4 | str *= 'world' 5 | 6 | mut num := 1 7 | num /= 'wrong' 8 | num = -'welp' 9 | _ = 2 10 | 11 | ch := chan string{} 12 | mut obj := 9 13 | obj = <-ch 14 | 15 | xy = 2 16 | 17 | _ += 1 18 | } 19 | 20 | const shouldnot_modify = 2 21 | 22 | fn main2() { 23 | shouldnot_modify -= 1 24 | shouldnot_modify++ 25 | a := 1 26 | a = 0 27 | a++ 28 | a-- 29 | } 30 | 31 | --- 32 | 33 | (error "cannot assign to `str`: expected `string`, not `int`" [2,4]-[2,11]) 34 | (error "undefined operation `string` * `string`" [3,8]-[3,10]) 35 | (error "mismatched types `int` and `string`" [6,4]-[6,18]) 36 | (error "cannot assign to `num`: expected `int`, not `void`" [7,10]-[7,11]) 37 | (error "cannot assign to `obj`: expected `int`, not `string`" [12,10]-[12,12]) 38 | (error "undefined ident: `xy` (use `:=` to declare a variable)" [14,4]-[14,6]) 39 | (error "cannot modify blank `_` identifier" [16,4]-[16,5]) 40 | (error "cannot modify constant `shouldnot_modify`" [22,4]-[22,20]) 41 | (error "cannot modify constant `shouldnot_modify`" [23,4]-[23,20]) 42 | (error "`a` is immutable, declare it with `mut` to make it mutable" [25,4]-[25,5]) 43 | (error "`a` is immutable, declare it with `mut` to make it mutable" [26,4]-[26,5]) 44 | (error "`a` is immutable, declare it with `mut` to make it mutable" [27,4]-[27,5]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/binary_expression.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | mut an := [1] 3 | an << 'test' 4 | an2 := an << 2 5 | 1 * 'hey' 6 | concat := 'hello' + 3 7 | 'mul' * 'tiply' 8 | invalid_eq := 1 != 'test' 9 | invalid_or := 1 && 3 10 | 11 | x2 := test() == "" 12 | 13 | println(3.0 % 2.0) 14 | println(f32(3.0) % f32(2.0)) 15 | } 16 | 17 | fn test() ?string { 18 | return "" 19 | } 20 | 21 | --- 22 | 23 | (error "cannot append `string` to `[]int`" [2,10]-[2,16]) 24 | (error "array append cannot be used in an expression" [3,14]-[3,16]) 25 | (error "mismatched types `int literal` and `string`" [4,4]-[4,13]) 26 | (error "mismatched types `string` and `int literal`" [5,14]-[5,25]) 27 | (error "undefined operation `string` * `string`" [6,4]-[6,19]) 28 | (error "mismatched types `int literal` and `string`" [7,18]-[7,29]) 29 | (error "mismatched types `int literal` and `int literal`" [8,18]-[8,24]) 30 | (error "unwrapped optional cannot be used in an infix expression" [10,10]-[10,16]) 31 | (error "float modulo not allowed, use math.fmod() instead" [13,12]-[13,20]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/break_statement.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | break 3 | } 4 | 5 | --- 6 | 7 | (error "break statement not within a loop" [1,2]-[1,7]) 8 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/call_expression.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | foo(3) 3 | a := ret_zero()? 4 | println(ret_none()) 5 | } 6 | 7 | fn ret_none() ?int { 8 | return none 9 | } 10 | 11 | fn ret_zero() int { 12 | return 0 13 | } 14 | 15 | fn opt_call() int { 16 | a := ret_none()? 17 | return a 18 | } 19 | 20 | fn multi_print(inp int, inp2 int) { 21 | print(inp) 22 | print(inp2) 23 | } 24 | 25 | fn main2() { 26 | ret_zero(1) 27 | multi_print(3,4,5) 28 | print(1,2) 29 | } 30 | --- 31 | 32 | (error "unknown function: foo" [1,4]-[1,10]) 33 | (error "unexpected `?`, the function `ret_zero` does neither return an optional nor a result" [2,19]-[2,20]) 34 | (error "ret_none() returns an option, so it should have either an `or {}` block, or `?` at the end" [3,9]-[3,19]) 35 | (error "to propagate the optional call, `opt_call` must return an optional" [15,16]-[15,17]) 36 | (error "expected 0 arguments, but got 1" [25,1]-[25,12]) 37 | (error "expected 2 arguments, but got 3" [26,1]-[26,19]) 38 | (error "expected 1 argument, but got 2" [27,1]-[27,11]) 39 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/enum_declaration.test.txt: -------------------------------------------------------------------------------- 1 | enum Empty {} 2 | 3 | enum Color { 4 | green = 'green' 5 | blue 6 | green 7 | yellow = 2147483647 8 | red 9 | alpha = 1 10 | purple = 1 11 | } 12 | 13 | mut foo := 1 14 | foo = Color.red 15 | 16 | mut foo2 := Color.blue 17 | foo2 = 1 18 | --- 19 | 20 | (error "enum cannot be empty" [0,5]-[0,10]) 21 | (error "default value for enum has to be an integer" [3,10]-[3,17]) 22 | (error "field name `green` duplicate" [5,2]-[5,7]) 23 | (error "enum value overflows" [7,2]-[7,5]) 24 | (error "enum value `1` already exists" [9,11]-[9,12]) 25 | (error "cannot assign to `foo`: expected `int`, not `Color`" [13,0]-[13,15]) 26 | (error "cannot assign to `foo2`: expected `Color`, not `int`" [16,0]-[16,8]) 27 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/for_statement.test.txt: -------------------------------------------------------------------------------- 1 | for true { 2 | defer { 3 | break 4 | } 5 | } 6 | 7 | --- 8 | 9 | (error "`break` is not allowed in defer statements" [2,4]-[2,9]) 10 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/if_expression.test.txt: -------------------------------------------------------------------------------- 1 | if (1 == 1) {} 2 | 3 | a := 1 4 | b := 2 5 | c := if a == 1 { a } else { 'a' } 6 | d := if a { a } else { b } 7 | e := if true { 0 } 8 | 9 | --- 10 | 11 | (error "unnecessary `()` in `if` condition, use `if expr {` instead of `if (expr) {`" [0,3]-[0,11]) 12 | (error "mismatched types `int literal` and `int literal`" [0,4]-[0,10]) (error "non-bool type `void` used as if condition" [0,3]-[0,11]) 13 | (error "mismatched types `int` and `int literal`" [4,8]-[4,14]) 14 | (error "non-bool type `void` used as if condition" [4,8]-[4,14]) 15 | (error "non-bool type `int` used as if condition" [5,8]-[5,9]) 16 | (error "`if` expression needs `else` clause" [6,5]-[6,18]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/import_symbols.test.txt: -------------------------------------------------------------------------------- 1 | import os { non_existing_method, executable_fallback, max_path_len } 2 | 3 | --- 4 | 5 | (error "Symbol `non_existing_method` in module `os` not found" [0,12]-[0,31]) 6 | (error "Symbol `executable_fallback` in module `os` not public" [0,33]-[0,52]) 7 | (error "cannot selective import constant `max_path_len` from `os`, import `os` and use `os.max_path_len` instead" [0,54]-[0,66]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/match_expression.test.txt: -------------------------------------------------------------------------------- 1 | match 1 { 2 | `0`..`9` {} 3 | } 4 | 5 | match 'test' { 6 | 1 {} 7 | } 8 | 9 | a := match 1 { 10 | 2 {} 11 | 3 { return 0 } 12 | } 13 | 14 | b := match 2 { 15 | 2 { 'a' } 16 | 3 { 0 } 17 | 3 { 'b' } 18 | } 19 | 20 | --- 21 | 22 | (error "mismatched range types" [1,4]-[1,7]) 23 | (error "cannot match `string` with `int`" [5,4]-[5,5]) 24 | (error "`match` expression requires an expression as the last statement of every branch" [9,4]-[9,8]) 25 | (error "`match` expression requires an expression as the last statement of every branch" [10,4]-[10,18]) 26 | (error "return type mismatch, it should be `string`" [15,4]-[15,11]) 27 | (error "match case `3` is handled more than once" [16,4]-[16,5]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/parenthesized_expression.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | (1 * 'test') 3 | an := ([1] << 2).len 4 | } 5 | 6 | --- 7 | 8 | (error "mismatched types `int literal` and `string`" [1,5]-[1,15]) 9 | (error "array append cannot be used in an expression" [2,15]-[2,17]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/selector_expression.test.txt: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | name int = 5 3 | } 4 | struct Bar { 5 | Foo 6 | Foo2 7 | } 8 | 9 | struct Foo2 { 10 | name string 11 | } 12 | fn (f Foo2) test() { 13 | println(f) 14 | } 15 | 16 | fn (f Foo) test() { 17 | println(f) 18 | } 19 | 20 | fn main() { 21 | b := Bar{} 22 | b.test() 23 | n := b.name 24 | println(b.sdd()) 25 | println(b.ada) 26 | println(abc().status_code) 27 | } 28 | 29 | struct HttpResult { 30 | status_code int 31 | } 32 | 33 | fn abc() ?HttpResult { 34 | return HttpResult{} 35 | } 36 | 37 | --- 38 | 39 | (error "ambiguous method `test`" [21,1]-[21,9]) 40 | (error "ambiguous field `name`" [22,8]-[22,12]) 41 | (error "unknown method or field: `Bar.sdd`" [23,9]-[23,14]) 42 | (error "type `Bar` has no field named `ada`" [24,9]-[24,14]) 43 | (error "cannot access fields of an optional, handle the error with `or {...}` or propagate it with `?`" [25,15]-[25,26]) 44 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/send_statement.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | not_chan := 2 3 | not_chan <- 3 4 | 5 | num_chan := chan int{} 6 | num_chan <- 'test' 7 | } 8 | 9 | --- 10 | 11 | (error "cannot push on non-channel `int`" [2,4]-[2,12]) 12 | (error "cannot push `string` on `chan int`" [5,16]-[5,22]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/spread_operator.test.txt: -------------------------------------------------------------------------------- 1 | fn varargs(a ...int) { println(a) } 2 | 3 | varargs(...123) 4 | 5 | --- 6 | 7 | (error "decomposition can only be used on arrays" [2,11]-[2,14]) 8 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/type_cast_expression.test.txt: -------------------------------------------------------------------------------- 1 | enum Color { red green = 10 blue } 2 | 3 | [flag] 4 | enum Permissions { read write execute } 5 | 6 | num := int(print('')) 7 | println(num) 8 | 9 | println(Color(0)) 10 | println(Color(-10)) 11 | 12 | println(Permissions(0b101)) 13 | println(Permissions(0b1010)) 14 | println(Permissions(-1)) 15 | 16 | println(string(true)) 17 | println(string(false)) 18 | --- 19 | 20 | (error "expression does not return a value so it cannot be cast" [5,11]-[5,20]) 21 | (error "0 does not represent a value of enum Color" [8,14]-[8,15]) 22 | (error "5 does not represent a value of enum Permissions" [11,20]-[11,25]) 23 | (error "10 does not represent a value of enum Permissions" [12,20]-[12,26]) 24 | (error "cannot cast type `bool` to string, use `true.str()` instead." [15,8]-[15,20]) 25 | (error "cannot cast type `bool` to string, use `false.str()` instead." [16,8]-[16,21]) 26 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/type_declaration.test.txt: -------------------------------------------------------------------------------- 1 | type Miscellaneous = Inexistant | Nope | int 2 | type Text = Strign 3 | type WordSet = map[string]bool 4 | 5 | fn main() { 6 | _ := WordSet{} 7 | } 8 | 9 | --- 10 | 11 | (error "unknown type `Inexistant`" [0,21]-[0,31]) 12 | (error "unknown type `Nope`" [0,34]-[0,38]) 13 | (error "unknown type `Strign`" [1,12]-[1,18]) 14 | (error "direct map alias init is not possible, use `WordSet(map[string]bool{})` instead" [5,6]-[5,15]) 15 | -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/type_expression.test.txt: -------------------------------------------------------------------------------- 1 | type Foo = Bar 2 | type Text = string | Baz 3 | 4 | --- 5 | 6 | (error "unknown type `Bar`" [0,11]-[0,14]) 7 | (error "unknown type `Baz`" [1,21]-[1,24]) -------------------------------------------------------------------------------- /analyzer/test_files/semantic_analyzer/type_initializer.test.txt: -------------------------------------------------------------------------------- 1 | type Foo = string | int 2 | 3 | fn main() { 4 | mut foo := [10]Foo{} 5 | mut foo2 := []Foo{len: 10} 6 | 7 | mp := map[Uri]string{} 8 | mp2 := map[string]Baz{} 9 | 10 | chn := chan Boo{} 11 | } 12 | 13 | struct Node { 14 | child &Node 15 | } 16 | 17 | fn return_node() Node { 18 | return Node{} 19 | } 20 | 21 | --- 22 | 23 | (error "cannot initialize sum type array without default value" [3,15]-[3,24]) 24 | (error "cannot initialize sum type array without default value" [4,16]-[4,21]) 25 | (error "unknown type `Uri`" [6,14]-[6,17]) 26 | (error "unknown type `Baz`" [7,22]-[7,25]) 27 | (error "unknown type `Boo`" [9,16]-[9,19]) 28 | (error "reference field `Node.child` must be initialized" [17,11]-[17,17]) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/abc/abc.v: -------------------------------------------------------------------------------- 1 | module abc 2 | 3 | pub struct Def {} 4 | -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/const_decl.test.txt: -------------------------------------------------------------------------------- 1 | pub const foo = 1 2 | const bar = 'hello' 3 | 4 | fn opt() ?string { 5 | return 'test' 6 | } 7 | 8 | const res = opt() or { 'hey' } 9 | const abc = if foo == 1 { 'def' } else { 'ghi' } 10 | const unsafe_const = unsafe { 'hey' } 11 | --- 12 | 13 | (pub variable foo int [0,10]-[0,13]) 14 | (variable bar string [1,6]-[1,9]) 15 | (function opt ?string [3,3]-[3,6]) 16 | (variable res string [7,6]-[7,9]) 17 | (variable abc string [8,6]-[8,9]) 18 | (variable unsafe_const string [9,6]-[9,18]) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/efg/efg.v: -------------------------------------------------------------------------------- 1 | module efg 2 | 3 | pub struct Vector { 4 | x int 5 | y int 6 | } 7 | -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/enum_decl.test.txt: -------------------------------------------------------------------------------- 1 | enum Color { 2 | red 3 | blue 4 | yellow 5 | } 6 | 7 | --- 8 | 9 | (enum Color [0,5]-[0,10] 10 | (field red Color [1,4]-[1,7]) 11 | (field blue Color [2,4]-[2,8]) 12 | (field yellow Color [3,4]-[3,10])) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/fn_decl.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | } 4 | 5 | pub fn greet(name string) []string { 6 | return ['hello $name!'] 7 | } 8 | 9 | fn hello() { 10 | test := 123 11 | name1, name2 := 'Bob', 'John' 12 | mut a := 1 13 | mut b, c, mut d := 'Foo', 2, 3.14 14 | e, mut f, g := 1, 2 15 | } 16 | 17 | fn inside_if() { 18 | defer { } 19 | name := 'hello' 20 | 21 | if name.ends_with('lo') { 22 | test := 123 23 | mut bar := 'bar' 24 | return 25 | } 26 | 27 | unsafe { 28 | mut unsafe_var := 1 29 | } 30 | } 31 | 32 | fn mutate_arr(mut s []string) {} 33 | 34 | fn fn__arr(handler fn (s int) int) { 35 | handler(1) 36 | } 37 | 38 | fn get_nums(nums ...int) {} 39 | 40 | --- 41 | 42 | (function main [0,3]-[0,7]) 43 | (pub function greet []string [4,7]-[4,12] 44 | (variable name string [4,13]-[4,17])) 45 | (function hello [8,3]-[8,8] 46 | (variable test int [9,4]-[9,8]) 47 | (variable name1 string [10,4]-[10,9]) 48 | (variable name2 string [10,11]-[10,16]) 49 | (mut variable a int [11,8]-[11,9]) 50 | (mut variable b string [12,8]-[12,9]) 51 | (variable c int [12,11]-[12,12]) 52 | (mut variable d f32 [12,18]-[12,19]) 53 | (variable e int [13,4]-[13,5]) 54 | (mut variable f int [13,11]-[13,12])) 55 | (function inside_if [16,3]-[16,12] 56 | (variable name string [18,4]-[18,8]) 57 | (scope [308]-[375] 58 | (variable test int [21,8]-[21,12]) 59 | (mut variable bar string [22,12]-[22,15])) 60 | (scope [388]-[423] 61 | (mut variable unsafe_var int [27,12]-[27,22]))) 62 | (function mutate_arr [31,3]-[31,13] 63 | (mut variable s []string [31,18]-[31,19])) 64 | (function fn__arr [33,3]-[33,10] 65 | (variable handler fn (s int) int [33,11]-[33,18])) 66 | (function get_nums [37,3]-[37,11] 67 | (variable nums ...int [37,12]-[37,16])) 68 | -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/for_loop.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | mut names := ['bob', 'foo'] 3 | for name in names { 4 | println(name) 5 | } 6 | 7 | for i, name in names {} 8 | } 9 | 10 | struct Point { 11 | x int 12 | y int 13 | } 14 | 15 | fn main2() { 16 | mut points := [&Point{1, 2}, &Point{2, 3}] 17 | 18 | for mut p in points { 19 | println(p) 20 | } 21 | 22 | for i, mut p2 in points {} 23 | } 24 | 25 | struct Iterator {} 26 | 27 | fn (i Iterator) next() ?f32 { return 1.2 } 28 | 29 | fn main3() { 30 | i := Iterator{} 31 | for num in i {} 32 | 33 | for j := 0; j < 3; j++ {} 34 | } 35 | 36 | --- 37 | 38 | (function main [0,3]-[0,7] 39 | (mut variable names []string [1,8]-[1,13]) 40 | (scope [52]-[95] 41 | (variable name string [2,8]-[2,12])) 42 | (scope [105]-[124] 43 | (variable i int [6,8]-[6,9]) 44 | (variable name string [6,11]-[6,15]))) 45 | 46 | (struct Point [9,7]-[9,12] 47 | (field x int [10,4]-[10,5]) 48 | (field y int [11,4]-[11,5])) 49 | 50 | (function main2 [14,3]-[14,8] 51 | (mut variable points []&Point [15,8]-[15,14]) 52 | (scope [239]-[277] 53 | (mut variable p Point [17,12]-[17,13])) 54 | (scope [287]-[309] 55 | (variable i int [21,8]-[21,9]) 56 | (mut variable p2 Point [21,15]-[21,17]))) 57 | 58 | (struct Iterator [24,7]-[24,15] 59 | (function next ?f32 [26,16]-[26,20] 60 | (variable i Iterator [26,4]-[26,5]))) 61 | 62 | (function main3 [28,3]-[28,8] 63 | (variable i Iterator [29,4]-[29,5]) 64 | (scope [418]-[429] 65 | (variable num f32 [30,8]-[30,11])) 66 | (scope [439]-[460] 67 | (mut variable j int [32,8]-[32,9]))) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/imported_fn.test.txt: -------------------------------------------------------------------------------- 1 | import abc 2 | import efg { Vector } 3 | 4 | fn hello(def &abc.Def) &abc.Def { 5 | return def 6 | } 7 | 8 | fn vector(vec Vector) Vector { 9 | return vec 10 | } 11 | 12 | --- 13 | 14 | (function hello &abc.Def [3,3]-[3,8] 15 | (variable def &abc.Def [3,9]-[3,12])) 16 | (function vector Vector [7,3]-[7,9] 17 | (variable vec Vector [7,10]-[7,13])) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/match_expr.test.txt: -------------------------------------------------------------------------------- 1 | enum Color { 2 | red 3 | yellow 4 | blue 5 | } 6 | 7 | fn main() { 8 | color := Color.red 9 | cstr := match color { 10 | .red { 'red' } 11 | .yellow { 'yellow' } 12 | .blue { 'blue' } 13 | } 14 | 15 | cstr2 := match color { 16 | .red { 2 } 17 | .yellow { 'hey' } 18 | else { 'what' } 19 | } 20 | } 21 | 22 | --- 23 | 24 | (enum Color [0,5]-[0,10] 25 | (field red Color [1,4]-[1,7]) 26 | (field yellow Color [2,4]-[2,10]) 27 | (field blue Color [3,4]-[3,8])) 28 | 29 | (function main [6,3]-[6,7] 30 | (variable color Color [7,4]-[7,9]) 31 | (variable cstr string [8,4]-[8,8])) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/method_decl.test.txt: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | mut: 3 | names []string 4 | } 5 | 6 | fn (f &Foo) get_all_names() []string { 7 | return f.names 8 | } 9 | 10 | fn (mut f Foo) insert_name() []string { 11 | f.names << 'test' 12 | names := f.get_all_names() 13 | return names 14 | } 15 | 16 | --- 17 | 18 | (struct Foo [0,7]-[0,10] 19 | (mut field names []string [2,4]-[2,9]) 20 | (function get_all_names []string [5,12]-[5,25] 21 | (variable f &Foo [5,4]-[5,5])) 22 | (function insert_name []string [9,15]-[9,26] 23 | (mut variable f Foo [9,8]-[9,9]) 24 | (variable names []string [11,4]-[11,9]))) 25 | -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/short_var_decl.test.txt: -------------------------------------------------------------------------------- 1 | fn opt() ?string { 2 | return 'test' 3 | } 4 | 5 | fn separate_name(name string) (string, string) { 6 | splitted := name.split(' ') 7 | return splitted[0], splitted[1] 8 | } 9 | 10 | fn main() { 11 | test := opt() or { '' } 12 | a := 1 13 | b, mut x := 1, 3.14 14 | 15 | if test2 := opt() {} 16 | 17 | c, e := if a == 1 { 1, 3 } else { 4, 6 } 18 | non_a := if b == 22 { a } else { xx } 19 | unsafe_var := unsafe { 2 } 20 | fn_var := fn (i int) int { return i } 21 | first_name, last_name := separate_name('John Doe') 22 | } 23 | 24 | --- 25 | 26 | (function opt ?string [0,3]-[0,6]) 27 | 28 | (function separate_name (string, string) [4,3]-[4,16] 29 | (variable name string [4,17]-[4,21]) 30 | (variable splitted []string [5,4]-[5,12])) 31 | 32 | (function main [9,3]-[9,7] 33 | (variable test string [10,4]-[10,8]) 34 | (variable a int [11,4]-[11,5]) 35 | (variable b int [12,4]-[12,5]) 36 | (mut variable x f32 [12,11]-[12,12]) 37 | (variable c int [16,4]-[16,5]) 38 | (variable e int [16,7]-[16,8]) 39 | (variable unsafe_var int [18,4]-[18,14]) 40 | (variable fn_var fn (i int) int [19,4]-[19,10]) 41 | (variable first_name string [20,4]-[20,14]) 42 | (variable last_name string [20,16]-[20,25]) 43 | (scope [193]-[199] 44 | (variable err IError [10,21]-[10,21])) 45 | (scope [243]-[260] 46 | (variable test2 string [14,7]-[14,12])) 47 | (scope [398]-[421] 48 | (variable i int [19,18]-[19,19]))) 49 | -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/struct_decl.test.txt: -------------------------------------------------------------------------------- 1 | struct Person { 2 | name string 3 | pub mut: 4 | age int 5 | mut: 6 | place string 7 | __global: 8 | gender byte 9 | } 10 | 11 | struct Node { 12 | child &Node 13 | } 14 | 15 | --- 16 | 17 | (struct Person [0,7]-[0,13] 18 | (field name string [1,4]-[1,8]) 19 | (pub mut field age int [3,4]-[3,7]) 20 | (mut field place string [5,4]-[5,9]) 21 | (__global field gender byte [7,4]-[7,10])) 22 | 23 | (struct Node [10,7]-[10,11] 24 | (field child &Node [11,4]-[11,9])) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/type_decl.test.txt: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | pub type Text = string 4 | type Any = string | int | []string 5 | pub type Handler = fn (a int) int 6 | pub type Logger = abc.Def 7 | 8 | --- 9 | 10 | (pub typedef Text (parent struct string) [2,9]-[2,13]) 11 | (sumtype Any [3,5]-[3,8] 12 | (struct string) 13 | (typedef int) 14 | (array []string)) 15 | (pub typedef Handler (parent function_type fn (a int) int) [4,9]-[4,16]) 16 | (pub typedef Logger (parent struct abc.Def) [5,9]-[5,15]) -------------------------------------------------------------------------------- /analyzer/test_files/symbol_registration/unsafe_expr.test.txt: -------------------------------------------------------------------------------- 1 | fn main() { 2 | a := unsafe { 'unsafe string' } 3 | b := [1, 2, 3] 4 | c := 2 5 | d := unsafe { b[1..c] } 6 | e := unsafe { a[2..4] } 7 | } 8 | 9 | --- 10 | 11 | (function main [0,3]-[0,7] 12 | (variable a string [1,2]-[1,3]) 13 | (variable b []int [2,2]-[2,3]) 14 | (variable c int [3,2]-[3,3]) 15 | (variable d []int [4,2]-[4,3]) 16 | (variable e string [5,2]-[5,3])) 17 | -------------------------------------------------------------------------------- /analyzer/text.v: -------------------------------------------------------------------------------- 1 | module analyzer 2 | 3 | pub type Runes = []rune 4 | 5 | pub fn (r Runes) at(idx int) rune { 6 | return r[idx] 7 | } 8 | 9 | pub fn (r Runes) len() int { 10 | return r.len 11 | } 12 | 13 | pub fn (r Runes) substr(start_index int, end_index int) string { 14 | mut st, mut ed := -1, -1 15 | mut offset := 0 16 | for i, v in r { 17 | if offset >= end_index { 18 | ed = i 19 | break 20 | } else if offset >= start_index && st < 0 { 21 | st = i 22 | } 23 | offset += v.length_in_bytes() 24 | } 25 | 26 | if ed < 0 { 27 | ed = r.len 28 | } 29 | 30 | return r[st..ed].string() 31 | } 32 | -------------------------------------------------------------------------------- /analyzer/tree_cursor.v: -------------------------------------------------------------------------------- 1 | module analyzer 2 | 3 | import tree_sitter 4 | import tree_sitter_v as v 5 | import ast 6 | 7 | struct TreeCursor { 8 | mut: 9 | start_line_nr u32 10 | cur_child_idx int = -1 11 | named_only bool = true 12 | child_count int [required] 13 | cursor tree_sitter.TreeCursor [required] 14 | } 15 | 16 | pub fn (mut tc TreeCursor) next() ?ast.Node { 17 | for tc.cur_child_idx < tc.child_count { 18 | if tc.cur_child_idx == -1 { 19 | tc.cursor.to_first_child() 20 | } else if !tc.cursor.next() { 21 | return none 22 | } 23 | 24 | tc.cur_child_idx++ 25 | if cur_node := tc.current_node() { 26 | if tc.named_only && cur_node.raw_node.start_point().row >= tc.start_line_nr 27 | && (cur_node.is_named() && !cur_node.is_extra()) { 28 | return cur_node 29 | } 30 | } 31 | } 32 | 33 | return none 34 | } 35 | 36 | pub fn (mut tc TreeCursor) reset() { 37 | tc.cursor.to_parent() 38 | tc.cur_child_idx = -1 39 | } 40 | 41 | pub fn (mut tc TreeCursor) to_first_child() bool { 42 | return tc.cursor.to_first_child() 43 | } 44 | 45 | pub fn (tc &TreeCursor) current_node() !ast.Node { 46 | node := tc.cursor.current_node()! 47 | return node 48 | } 49 | 50 | [unsafe] 51 | pub fn (tc &TreeCursor) free() { 52 | unsafe { 53 | tc.cursor.raw_cursor.free() 54 | tc.cur_child_idx = 0 55 | tc.child_count = 0 56 | } 57 | } 58 | 59 | [params] 60 | pub struct NewTreeCursorConfig { 61 | start_line_nr u32 62 | } 63 | 64 | pub fn new_tree_cursor(root_node ast.Node, cfg NewTreeCursorConfig) TreeCursor { 65 | return TreeCursor{ 66 | child_count: int(root_node.child_count()) 67 | cursor: root_node.tree_cursor() 68 | start_line_nr: cfg.start_line_nr 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ast/parser.v: -------------------------------------------------------------------------------- 1 | module ast 2 | 3 | import strings 4 | import tree_sitter 5 | import tree_sitter_v as v 6 | 7 | pub type Node = tree_sitter.Node 8 | pub type Tree = tree_sitter.Tree 9 | 10 | pub fn new_parser() &tree_sitter.Parser { 11 | return tree_sitter.new_parser(v.language, v.type_factory) 12 | } 13 | 14 | fn (n Node) str() string { 15 | mut cursor := n.tree_cursor() 16 | if !cursor.to_first_child() { 17 | return "" 18 | } 19 | 20 | mut builder := strings.new_builder(0) 21 | mut indent_level := 0 22 | for { 23 | current := cursor.current_node() or { break } 24 | 25 | if current.type_name != v.NodeType.unknown { 26 | for _ in 0 .. indent_level { 27 | builder.write_string(' ') 28 | } 29 | 30 | builder.write_string('${current.type_name}') 31 | builder.write_string(' *') 32 | 33 | st := current.start_point() 34 | builder.write_string('[${st.row}, ${st.column}]') 35 | 36 | builder.write_string(' - ') 37 | 38 | ed := current.end_point() 39 | builder.write_string('[${ed.row}, ${ed.column}]') 40 | 41 | builder.write_string('\n') 42 | } 43 | 44 | if cursor.to_first_child() { 45 | indent_level += 1 46 | } else if cursor.next() { 47 | // do nothing 48 | } else if cursor.to_parent() { 49 | indent_level -= 1 50 | 51 | mut ok := true 52 | for !cursor.next() { 53 | if cursor.to_parent() { 54 | indent_level -= 1 55 | } else { 56 | ok = false 57 | break 58 | } 59 | } 60 | 61 | if !ok { 62 | break 63 | } 64 | } else { 65 | break 66 | } 67 | } 68 | 69 | return builder.str() 70 | } 71 | -------------------------------------------------------------------------------- /ast/tree_walker.v: -------------------------------------------------------------------------------- 1 | module ast 2 | 3 | import tree_sitter 4 | import tree_sitter_v as v 5 | 6 | struct TreeWalker { 7 | mut: 8 | already_visited_children bool 9 | cursor tree_sitter.TreeCursor[v.NodeType] [required] 10 | } 11 | 12 | pub fn (mut tw TreeWalker) next() ?Node { 13 | if !tw.already_visited_children { 14 | if tw.cursor.to_first_child() { 15 | tw.already_visited_children = false 16 | } else if tw.cursor.next() { 17 | tw.already_visited_children = false 18 | } else { 19 | if !tw.cursor.to_parent() { 20 | return none 21 | } 22 | tw.already_visited_children = true 23 | return tw.next() 24 | } 25 | } else { 26 | if tw.cursor.next() { 27 | tw.already_visited_children = false 28 | } else { 29 | if !tw.cursor.to_parent() { 30 | return none 31 | } 32 | return tw.next() 33 | } 34 | } 35 | node := tw.cursor.current_node() or { return none } 36 | return node 37 | } 38 | 39 | pub fn new_tree_walker(root_node Node) TreeWalker { 40 | return TreeWalker{ 41 | cursor: root_node.tree_cursor() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /build.vsh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S v run 2 | 3 | import os 4 | 5 | mut vls_exec_name := 'vls' 6 | 7 | project_folder := dir(executable()) 8 | full_vls_bin_dir := real_path(join_path(project_folder, 'bin')) 9 | full_vls_exec_path := real_path(join_path(full_vls_bin_dir, vls_exec_name)) 10 | 11 | chdir(project_folder)! 12 | 13 | mkdir(full_vls_bin_dir) or {} 14 | 15 | // use system default C compiler if found 16 | mut cc := 'cc' 17 | 18 | if os.args.len >= 2 { 19 | if os.args[1] in ['cc', 'gcc', 'clang', 'msvc'] { 20 | cc = os.args[1] 21 | } else { 22 | println('> Usage error: parameter must one of cc, gcc, clang, msvc') 23 | exit(1) 24 | } 25 | } 26 | 27 | println('> Building VLS...') 28 | 29 | vls_git_hash := os.execute('git rev-parse --short HEAD') 30 | if vls_git_hash.exit_code != 0 { 31 | println('Please install git') 32 | exit(vls_git_hash.exit_code) 33 | } 34 | os.setenv('VLS_BUILD_COMMIT', vls_git_hash.output.trim_space(), true) 35 | 36 | mut buffer := ['v'] 37 | buffer << '-g' 38 | buffer << ['-o', full_vls_exec_path] 39 | buffer << ['-gc', 'boehm'] 40 | buffer << ['-cc', cc] 41 | if cc != 'msvc' { 42 | buffer << ['-d', 'use_libbacktrace'] 43 | } 44 | 45 | index_extra := os.args.index('--') 46 | if index_extra > 0 { 47 | buffer << os.args[index_extra + 1..] 48 | } 49 | 50 | buffer << 'cmd/vls' 51 | 52 | cmd := buffer.join(' ') 53 | println(cmd) 54 | ret := system(cmd) 55 | if ret != 0 { 56 | println('Failed building VLS') 57 | exit(ret) 58 | } 59 | 60 | println('> VLS built successfully!') 61 | println('Executable saved in: ${full_vls_exec_path}') 62 | -------------------------------------------------------------------------------- /cmd/vls/utils.v: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import os 4 | import server 5 | 6 | const content_length = 'Content-Length: ' 7 | 8 | fn make_lsp_payload(output string) string { 9 | return 'Content-Length: $output.len\r\n\r\n$output' 10 | } 11 | 12 | fn launch_v_tool(args ...string) !&os.Process { 13 | // using @VEXEROOT should never happen but will be used 14 | // just in case 15 | vroot_path := server.detect_vroot_path() or { @VEXEROOT } 16 | full_v_path := os.join_path(vroot_path, 'v') 17 | mut p := os.new_process(full_v_path) 18 | p.set_args(args) 19 | p.set_redirect_stdio() 20 | return p 21 | } 22 | 23 | fn new_vls_process(args ...string) &os.Process { 24 | mut p := os.new_process(os.executable()) 25 | p.set_args(args) 26 | p.set_redirect_stdio() 27 | return p 28 | } 29 | -------------------------------------------------------------------------------- /images/instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/images/instructions.png -------------------------------------------------------------------------------- /jsonrpc/jsonrpc_test.v: -------------------------------------------------------------------------------- 1 | import jsonrpc 2 | 3 | fn test_response_json_null() { 4 | resp := jsonrpc.Response{ 5 | id: '1' 6 | } 7 | assert resp.json() == '{"jsonrpc":"2.0","id":1,"result":null}' 8 | } 9 | 10 | fn test_notification_json_null() { 11 | resp := jsonrpc.NotificationMessage{ 12 | method: 'test' 13 | } 14 | assert resp.json() == '{"jsonrpc":"2.0","method":"test","params":null}' 15 | } 16 | -------------------------------------------------------------------------------- /lsp/README.md: -------------------------------------------------------------------------------- 1 | # LSP.V 2 | Type declaration module of the Language Server Protocol 3.15 spec. For use on the [V Language Server](https://github.com/vlang/vls). 3 | 4 | ## Roadmap 5 | ### General 6 | - [x] `initialize` 7 | - [x] `initialized` 8 | - [x] `shutdown` 9 | - [x] `exit` 10 | - [x] `$/cancelRequest` 11 | ### Window 12 | - [x] `showMessage` 13 | - [x] `showMessageRequest` 14 | - [x] `logMessage` 15 | ### Telemetry 16 | - [x] `event` 17 | ### Client 18 | - [x] `registerCapability` 19 | - [x] `unregisterCapability` 20 | ### Workspace 21 | - [x] `workspaceFolders` 22 | - [x] `didChangeWorkspaceFolder` 23 | - [x] `didChangeConfiguration` 24 | - [x] `configuration` 25 | - [x] `didChangeWatchedFiles` 26 | - [x] `symbol` 27 | - [x] `executeCommand` 28 | - [x] `applyEdit` 29 | ### Text Synchronization 30 | - [x] `didOpen` 31 | - [x] `didChange` 32 | - [x] `willSave` 33 | - [x] `willSaveWaitUntil` 34 | - [x] `didSave` 35 | - [x] `didClose` 36 | ### Diagnostics 37 | - [x] `publishDiagnostics` 38 | ### Language Features 39 | - [x] `completion` 40 | - [x] `completion resolve` 41 | - [x] `hover` 42 | - [x] `signatureHelp` 43 | - [x] `declaration` 44 | - [x] `definition` 45 | - [x] `typeDefinition` 46 | - [x] `implementation` 47 | - [x] `references` 48 | - [x] `documentHighlight` 49 | - [x] `documentSymbol` 50 | - [x] `codeAction` 51 | - [x] `codeLens` 52 | - [x] `codeLens resolve` 53 | - [x] `documentLink` 54 | - [x] `documentLink resolve` 55 | - [x] `documentColor` 56 | - [x] `colorPresentation` 57 | - [x] `formatting` 58 | - [x] `rangeFormatting` 59 | - [x] `onTypeFormatting` 60 | - [x] `rename` 61 | - [x] `prepareRename` 62 | - [x] `foldingRange` 63 | 64 | #### 2020-2021 Ned Palacios -------------------------------------------------------------------------------- /lsp/client.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘client/registerCapability’ 4 | // response: void 5 | pub struct RegistrationParams { 6 | registrations []Registration 7 | } 8 | 9 | pub struct Registration { 10 | id int 11 | method string 12 | register_options string [raw] 13 | } 14 | 15 | // base interface for registration register_options 16 | // pub struct TextDocumentRegistrationOptions { 17 | // document_selector []DocumentFilter [json:documentSelector] 18 | // } 19 | // method: ‘client/unregisterCapability’ 20 | // response: void 21 | pub struct UnregistrationParams { 22 | unregistrations []Unregistration 23 | } 24 | 25 | pub struct Unregistration { 26 | id int 27 | method string 28 | } 29 | -------------------------------------------------------------------------------- /lsp/code_action.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct CodeActionOptions { 4 | code_action_kinds []string [json: codeActionKinds] 5 | } 6 | 7 | // method: ‘textDocument/codeAction’ 8 | // response [](Command | CodeAction) | null 9 | pub struct CodeActionParams { 10 | text_document TextDocumentIdentifier [json: textDocument] 11 | range Range 12 | context CodeActionContext 13 | } 14 | 15 | // type CodeActionKind string 16 | pub const ( 17 | empty = '' 18 | quick_fix = 'quickfix' 19 | refactor = 'refactor' 20 | refactor_extract = 'refactor.extract' 21 | refactor_inline = 'refactor.inline' 22 | refactor_rewrite = 'refactor.rewrite' 23 | source = 'source' 24 | source_organize_imports = 'source.organizeImports' 25 | ) 26 | 27 | pub struct CodeActionContext { 28 | diagnostics []Diagnostic 29 | only []string 30 | } 31 | 32 | pub struct CodeAction { 33 | title string 34 | kind string 35 | // CodeActionKind 36 | diagnostics []Diagnostic 37 | edit WorkspaceEdit 38 | command Command 39 | } 40 | 41 | pub struct CodeActionRegistrationOptions { 42 | document_selector []DocumentFilter [json: documentSelector] 43 | code_action_kinds []string [json: codeActionKinds] 44 | } 45 | -------------------------------------------------------------------------------- /lsp/code_lens.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct CodeLensOptions { 4 | pub mut: 5 | resolve_provider bool [json: resolveProvider] 6 | } 7 | 8 | // method: ‘textDocument/codeLens’ 9 | // response: []CodeLens | none 10 | pub struct CodeLensParams { 11 | text_document TextDocumentIdentifier [json: textDocument] 12 | } 13 | 14 | pub struct CodeLens { 15 | range Range 16 | command Command 17 | data string [raw] 18 | } 19 | 20 | pub struct CodeLensRegistrationOptions { 21 | document_selector []DocumentFilter [json: documentSelector] 22 | resolve_provider bool [json: resolveProvider] 23 | } 24 | 25 | // method: ‘codeLens/resolve’ 26 | // response: CodeLens 27 | // request: CodeLens 28 | -------------------------------------------------------------------------------- /lsp/color_presentation.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // /** 4 | // * Color provider options. 5 | // */ 6 | // export interface ColorProviderOptions { 7 | // } 8 | // method: ‘textDocument/colorPresentation’ 9 | // response: []ColorPresentation 10 | pub struct ColorPresentationParams { 11 | text_document TextDocumentIdentifier [json: textDocument] 12 | color Color 13 | range Range 14 | } 15 | 16 | pub struct ColorPresentation { 17 | label string 18 | text_edit TextEdit [json: textEdit] 19 | additional_text_edits []TextEdit [json: additionalTextEdits] 20 | } 21 | -------------------------------------------------------------------------------- /lsp/declaration.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/declaration’ 4 | // response: Location | []Location | []LocationLink | none 5 | // request: TextDocumentPositionParams 6 | -------------------------------------------------------------------------------- /lsp/definition.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/definition’ 4 | // response: Location | []Location | []LocationLink | none 5 | // request: TextDocumentPositionParams 6 | // method: ‘textDocument/typeDefinition’ 7 | // response: Location | []Location | []LocationLink | none 8 | // request: TextDocumentPositionParams 9 | -------------------------------------------------------------------------------- /lsp/diagnostics.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct Diagnostic { 4 | pub mut: 5 | range Range 6 | severity DiagnosticSeverity 7 | code string 8 | source string 9 | message string 10 | related_information []DiagnosticRelatedInformation [json: relatedInformation] 11 | } 12 | 13 | [json_as_number] 14 | pub enum DiagnosticSeverity { 15 | error = 1 16 | warning = 2 17 | information = 3 18 | hint = 4 19 | } 20 | 21 | pub struct DiagnosticRelatedInformation { 22 | location Location 23 | message string 24 | } 25 | 26 | // method: ‘textDocument/publishDiagnostics’ 27 | pub struct PublishDiagnosticsParams { 28 | pub: 29 | uri DocumentUri 30 | diagnostics []Diagnostic 31 | } 32 | -------------------------------------------------------------------------------- /lsp/document_color.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/documentColor’ 4 | // response: []ColorInformation 5 | pub struct DocumentColorParams { 6 | text_document TextDocumentIdentifier [json: textDocument] 7 | } 8 | 9 | pub struct ColorInformation { 10 | range Range 11 | color Color 12 | } 13 | 14 | pub struct Color { 15 | red int 16 | green int 17 | blue int 18 | alpha int 19 | } 20 | -------------------------------------------------------------------------------- /lsp/document_highlight.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/documentHighlight’ 4 | // response: []DocumentHighlight | none 5 | // request: TextDocumentPositionParams 6 | pub struct DocumentHighlight { 7 | range Range 8 | kind int 9 | } 10 | 11 | [json_as_number] 12 | pub enum DocumentHighlightKind { 13 | text = 1 14 | read = 2 15 | write = 3 16 | } 17 | -------------------------------------------------------------------------------- /lsp/document_link.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct DocumentLinkOptions { 4 | resolve_provider bool [json: resolveProvider] 5 | } 6 | 7 | // method: ‘textDocument/documentLink’ 8 | // response: []DocumentLink | none 9 | pub struct DocumentLinkParams { 10 | text_document TextDocumentIdentifier [json: textDocument] 11 | } 12 | 13 | pub struct DocumentLink { 14 | range Range 15 | target DocumentUri 16 | data string [raw] 17 | } 18 | 19 | pub struct DocumentLinkRegistrationOptions { 20 | document_selector []DocumentFilter [json: documentSelector] 21 | resolve_provider bool [json: resolveProvider] 22 | } 23 | 24 | // method: ‘documentLink/resolve’ 25 | // response: DocumentLink 26 | // request: DocumentLink 27 | -------------------------------------------------------------------------------- /lsp/document_symbol.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/documentSymbol’ 4 | // response: []DocumentSymbol | []SymbolInformation | none 5 | pub struct DocumentSymbolParams { 6 | pub: 7 | text_document TextDocumentIdentifier [json: textDocument] 8 | } 9 | 10 | [json_as_number] 11 | pub enum SymbolKind { 12 | file = 1 13 | module_ = 2 14 | namespace = 3 15 | package = 4 16 | class = 5 17 | method = 6 18 | property = 7 19 | field = 8 20 | constructor = 9 21 | enum_ = 10 22 | interface_ = 11 23 | function = 12 24 | variable = 13 25 | constant = 14 26 | string = 15 27 | number = 16 28 | boolean = 17 29 | array = 18 30 | object = 19 31 | key = 20 32 | null = 21 33 | enum_member = 22 34 | struct_ = 23 35 | event = 24 36 | operator = 25 37 | type_parameter = 26 38 | } 39 | 40 | pub struct DocumentSymbol { 41 | pub mut: 42 | name string 43 | detail string 44 | kind SymbolKind 45 | deprecated bool 46 | range Range 47 | selection_range Range [json: selectionRange] 48 | children []DocumentSymbol 49 | } 50 | 51 | pub struct SymbolInformation { 52 | pub mut: 53 | name string 54 | kind SymbolKind 55 | deprecated bool 56 | location Location 57 | container_name string [json: containerName] 58 | } 59 | -------------------------------------------------------------------------------- /lsp/file_resource.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct CreateFileOptions { 4 | overwrite bool 5 | ignore_if_exists bool [json: ignoreIfExists] 6 | } 7 | 8 | pub struct CreateFile { 9 | kind string = 'create' 10 | uri DocumentUri 11 | options CreateFileOptions 12 | } 13 | 14 | pub struct RenameFileOptions { 15 | overwrite bool 16 | ignore_if_exists bool [json: ignoreIfExists] 17 | } 18 | 19 | pub struct RenameFile { 20 | kind string = 'rename' 21 | old_uri DocumentUri [json: oldUri] 22 | new_uri DocumentUri [json: newUri] 23 | options RenameFileOptions 24 | } 25 | 26 | pub struct DeleteFileOptions { 27 | recursive bool 28 | ignore_if_exists bool [json: ignoreIfExists] 29 | } 30 | 31 | pub struct DeleteFile { 32 | kind string = 'delete' 33 | uri DocumentUri 34 | options DeleteFileOptions 35 | } 36 | -------------------------------------------------------------------------------- /lsp/folding_range.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/foldingRange’ 4 | // response: []FoldingRange | none 5 | pub struct FoldingRangeParams { 6 | pub: 7 | text_document TextDocumentIdentifier [json: textDocument] 8 | position Position 9 | } 10 | 11 | pub const ( 12 | folding_range_kind_comment = 'comment' 13 | folding_range_kind_imports = 'imports' 14 | folding_range_kind_region = 'region' 15 | ) 16 | 17 | pub struct FoldingRange { 18 | start_line int [json: startLine] 19 | start_character int [json: startCharacter] 20 | end_line int [json: endLine] 21 | end_character int [json: endCharacter] 22 | kind string 23 | } 24 | -------------------------------------------------------------------------------- /lsp/formatting.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/formatting’ 4 | // response: []TextEdit | none 5 | pub struct DocumentFormattingParams { 6 | pub: 7 | text_document TextDocumentIdentifier [json: textDocument] 8 | options FormattingOptions 9 | } 10 | 11 | pub struct FormattingOptions { 12 | tab_size int [json: tabSize] 13 | insert_spaces bool [json: insertSpaces] 14 | // [key] bool | number | string 15 | } 16 | 17 | // method: ‘textDocument/rangeFormatting’ 18 | // response: []TextEdit | none 19 | pub struct DocumentRangeFormattingParams { 20 | text_document TextDocumentIdentifier [json: textDocument] 21 | range Range 22 | options FormattingOptions 23 | } 24 | 25 | pub struct DocumentOnTypeFormattingOptions { 26 | first_trigger_character string [json: firstTriggerCharacter] 27 | more_trigger_character []string [json: moreTriggerCharacter] 28 | } 29 | 30 | // method: ‘textDocument/onTypeFormatting’ 31 | // response: []TextEdit | none 32 | pub struct DocumentOnTypeFormattingParams { 33 | text_document TextDocumentIdentifier [json: textDocument] 34 | position Position 35 | ch string 36 | options FormattingOptions 37 | } 38 | 39 | pub struct DocumentOnTypeFormattingRegistrationOptions { 40 | document_selector []DocumentFilter [json: documentSelector] 41 | first_trigger_character string [json: firstTriggerCharacter] 42 | more_trigger_character []string [json: moreTriggerCharacter] 43 | } 44 | -------------------------------------------------------------------------------- /lsp/hover.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct HoverSettings { 4 | dynamic_registration bool [json: dynamicRegistration] 5 | content_format []string [json: contentFormat] 6 | } 7 | 8 | // method: ‘textDocument/hover’ 9 | // response: Hover | none 10 | // request: TextDocumentPositionParams 11 | pub struct HoverParams { 12 | pub: 13 | text_document TextDocumentIdentifier [json: textDocument] 14 | position Position 15 | } 16 | 17 | type HoverResponseContent = MarkedString | MarkupContent | []MarkedString | string 18 | 19 | pub struct Hover { 20 | pub: 21 | contents HoverResponseContent 22 | range Range 23 | } 24 | 25 | // pub type MarkedString = string | MarkedString 26 | pub struct MarkedString { 27 | language string 28 | value string 29 | } 30 | 31 | pub fn hover_v_marked_string(text string) HoverResponseContent { 32 | return HoverResponseContent(MarkedString{ 33 | language: 'v' 34 | value: text 35 | }) 36 | } 37 | 38 | pub fn hover_markdown_string(text string) HoverResponseContent { 39 | return HoverResponseContent(MarkupContent{ 40 | kind: markup_kind_markdown 41 | value: text 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /lsp/implementation.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/implementation’ 4 | // response: Location | []Location | []LocationLink | none 5 | // request: TextDocumentPositionParams 6 | -------------------------------------------------------------------------------- /lsp/initialize.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘initialize’ 4 | // response: InitializeResult 5 | pub struct InitializeParams { 6 | pub mut: 7 | process_id int [json: processId] = -2 8 | client_info ClientInfo [json: clientInfo] 9 | root_uri DocumentUri [json: rootUri] 10 | root_path DocumentUri [json: rootPath] 11 | initialization_options string [json: initializationOptions; skip] 12 | capabilities ClientCapabilities [skip] 13 | trace string 14 | workspace_folders []WorkspaceFolder [skip] 15 | } 16 | 17 | pub struct ClientInfo { 18 | pub mut: 19 | name string [json: name] 20 | version string [json: version] 21 | } 22 | 23 | pub struct InitializeResult { 24 | capabilities ServerCapabilities 25 | } 26 | 27 | // method: ‘initialized’ 28 | // notification 29 | // pub struct InitializedParams {} 30 | [json_as_number] 31 | pub enum InitializeErrorCode { 32 | unknown_protocol_version = 1 33 | } 34 | 35 | pub struct InitializeError { 36 | retry bool 37 | } 38 | 39 | /* 40 | * 41 | * The kind of resource operations supported by the client. 42 | */ 43 | [json_as_number] 44 | pub enum ResourceOperationKind { 45 | create 46 | rename 47 | delete 48 | } 49 | 50 | [json_as_number] 51 | pub enum FailureHandlingKind { 52 | abort 53 | transactional 54 | undo 55 | text_only_transactional 56 | } 57 | 58 | pub struct ExecuteCommandOptions { 59 | commands []string 60 | } 61 | 62 | pub struct StaticRegistrationOptions { 63 | id string 64 | } 65 | 66 | // method: ‘shutdown’ 67 | // response: none 68 | // method: ‘exit’ 69 | // response: none 70 | -------------------------------------------------------------------------------- /lsp/log/log_test.v: -------------------------------------------------------------------------------- 1 | module log 2 | 3 | import json 4 | 5 | struct TestLogItem { 6 | kind string 7 | payload string 8 | } 9 | 10 | fn test_notification_send() { 11 | mut lg := new() 12 | 13 | lg.log(kind: .send_notification, payload: '"Hello!"'.bytes()) 14 | buf := lg.buffer.str() 15 | result := json.decode(TestLogItem, buf)? 16 | 17 | assert result.kind == 'send-notification' 18 | assert result.payload == 'Hello!' 19 | } 20 | 21 | fn test_notification_receive() { 22 | mut lg := new() 23 | 24 | lg.log(kind: .recv_notification, payload: '"Received!"'.bytes()) 25 | buf := lg.buffer.str() 26 | result := json.decode(TestLogItem, buf)? 27 | 28 | assert result.kind == 'recv-notification' 29 | assert result.payload == 'Received!' 30 | } 31 | 32 | fn test_request_send() { 33 | mut lg := new() 34 | 35 | lg.log(kind: .recv_request, payload: '"Request sent."'.bytes()) 36 | buf := lg.buffer.str() 37 | result := json.decode(TestLogItem, buf)? 38 | 39 | assert result.kind == 'recv-request' 40 | assert result.payload == 'Request sent.' 41 | } 42 | 43 | fn test_request_receive() { 44 | mut lg := new() 45 | 46 | lg.log(kind: .recv_request, payload: '"Request received."'.bytes()) 47 | buf := lg.buffer.str() 48 | result := json.decode(TestLogItem, buf)? 49 | 50 | assert result.kind == 'recv-request' 51 | assert result.payload == 'Request received.' 52 | } 53 | 54 | fn test_response_send() { 55 | mut lg := new() 56 | 57 | lg.log(kind: .send_response, payload: '"Response sent."'.bytes()) 58 | buf := lg.buffer.str() 59 | result := json.decode(TestLogItem, buf)? 60 | 61 | assert result.kind == 'send-response' 62 | assert result.payload == 'Response sent.' 63 | } 64 | 65 | fn test_response_receive() { 66 | mut lg := new() 67 | 68 | lg.log(kind: .send_response, payload: '"Response received."'.bytes()) 69 | buf := lg.buffer.str() 70 | result := json.decode(TestLogItem, buf)? 71 | 72 | assert result.kind == 'send-response' 73 | assert result.payload == 'Response received.' 74 | } 75 | -------------------------------------------------------------------------------- /lsp/references.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/references’ 4 | // response: []Location | none 5 | pub struct ReferenceParams { 6 | // extend: TextDocumentPositionParams 7 | context ReferenceContext 8 | } 9 | 10 | pub struct ReferenceContext { 11 | include_declaration bool 12 | } 13 | -------------------------------------------------------------------------------- /lsp/rename.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct RenameOptions { 4 | prepare_provider bool [json: prepareProvider] 5 | } 6 | 7 | // method: ‘textDocument/rename’ 8 | // response: WorkspaceEdit | none 9 | pub struct RenameParams { 10 | text_docuent TextDocumentIdentifier [json: textDocument] 11 | position Position 12 | new_name string [json: newName] 13 | } 14 | 15 | pub struct RenameRegistrationOptions { 16 | document_selector []DocumentFilter [json: documentSelector] 17 | prepare_provider bool [json: prepareProvider] 18 | } 19 | 20 | // method: ‘textDocument/prepareRename’ 21 | // response: Range | { range: Range, placeholder: string } | none 22 | // request: TextDocumentPositionParams 23 | -------------------------------------------------------------------------------- /lsp/signature_help.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct SignatureHelpOptions { 4 | trigger_characters []string [json: triggerCharacters] 5 | retrigger_characters []string [json: retriggerCharacters] 6 | } 7 | 8 | [json_as_number] 9 | pub enum SignatureHelpTriggerKind { 10 | invoked = 1 11 | trigger_character = 2 12 | content_change = 3 13 | } 14 | 15 | // method: ‘textDocument/signatureHelp’ 16 | // response: SignatureHelp | none 17 | pub struct SignatureHelpParams { 18 | pub: 19 | // TODO: utilize struct embedding feature 20 | // for all structs that use TextDocumentPositionParams 21 | // embed: TextDocumentPositionParams 22 | text_document TextDocumentIdentifier [json: textDocument] 23 | position Position 24 | context SignatureHelpContext 25 | } 26 | 27 | pub struct SignatureHelpContext { 28 | pub: 29 | trigger_kind SignatureHelpTriggerKind [json: triggerKind] 30 | trigger_character string [json: triggerCharacter] 31 | is_retrigger bool [json: isRetrigger] 32 | active_signature_help SignatureHelp [json: activeSignatureHelp] 33 | } 34 | 35 | pub struct SignatureHelp { 36 | pub: 37 | signatures []SignatureInformation 38 | pub mut: 39 | active_parameter int [json: activeParameter] 40 | } 41 | 42 | pub struct SignatureInformation { 43 | pub mut: 44 | label string 45 | // documentation MarkupContent 46 | parameters []ParameterInformation 47 | } 48 | 49 | pub struct ParameterInformation { 50 | label string 51 | } 52 | 53 | pub struct SignatureHelpRegistrationOptions { 54 | document_selector []DocumentFilter [json: documentSelector] 55 | trigger_characters []string [json: triggerCharacters] 56 | } 57 | -------------------------------------------------------------------------------- /lsp/symbol.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘textDocument/signatureHelp’ 4 | // response: SignatureHelp | none 5 | // request: TextDocumentPositionParams 6 | // struct SymbolInformation { 7 | // } 8 | -------------------------------------------------------------------------------- /lsp/text_document.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | pub struct Position { 4 | pub: 5 | line int 6 | character int 7 | } 8 | 9 | pub struct Range { 10 | pub: 11 | start Position 12 | end Position 13 | } 14 | 15 | pub struct TextEdit { 16 | range Range 17 | new_text string [json: newText] 18 | } 19 | 20 | pub struct TextDocumentIdentifier { 21 | pub: 22 | uri DocumentUri 23 | } 24 | 25 | pub struct TextDocumentEdit { 26 | text_document VersionedTextDocumentIdentifier [json: textDocument] 27 | edits []TextEdit 28 | } 29 | 30 | pub struct TextDocumentItem { 31 | pub: 32 | uri DocumentUri 33 | language_id string [json: languageId] 34 | version int 35 | text string 36 | } 37 | 38 | pub struct VersionedTextDocumentIdentifier { 39 | pub: 40 | uri DocumentUri 41 | version int 42 | } 43 | 44 | pub struct Location { 45 | pub mut: 46 | uri DocumentUri 47 | range Range 48 | } 49 | 50 | pub struct LocationLink { 51 | pub: 52 | origin_selection_range Range [json: originSelectionRange] 53 | target_uri DocumentUri [json: targetUri] 54 | target_range Range [json: targetRange] 55 | target_selection_range Range [json: targetSelectionRange] 56 | } 57 | 58 | // pub struct TextDocumentContentChangeEvent { 59 | // range Range 60 | // text string 61 | // } 62 | pub struct TextDocumentPositionParams { 63 | pub: 64 | text_document TextDocumentIdentifier [json: textDocument] 65 | position Position 66 | } 67 | 68 | pub const ( 69 | markup_kind_plaintext = 'plaintext' 70 | markup_kind_markdown = 'markdown' 71 | ) 72 | 73 | pub struct MarkupContent { 74 | kind string 75 | // MarkupKind 76 | value string 77 | } 78 | 79 | pub struct TextDocument { 80 | uri DocumentUri 81 | language_id string 82 | version int 83 | line_count int 84 | } 85 | 86 | pub struct FullTextDocument { 87 | uri DocumentUri 88 | language_id string 89 | version int 90 | content string 91 | line_offsets []int 92 | } 93 | -------------------------------------------------------------------------------- /lsp/window.v: -------------------------------------------------------------------------------- 1 | module lsp 2 | 3 | // method: ‘window/showMessage’ 4 | // notification 5 | pub struct ShowMessageParams { 6 | @type MessageType 7 | // @type int 8 | message string 9 | } 10 | 11 | [json_as_number] 12 | pub enum MessageType { 13 | error = 1 14 | warning = 2 15 | info = 3 16 | log = 4 17 | } 18 | 19 | // method: ‘window/showMessageRequest’ 20 | // response: MessageActionItem | none / null 21 | pub struct ShowMessageRequestParams { 22 | @type MessageType 23 | message string 24 | actions []MessageActionItem 25 | } 26 | 27 | pub struct MessageActionItem { 28 | title string 29 | } 30 | 31 | // method: ‘window/logMessage’ 32 | // notification 33 | pub struct LogMessageParams { 34 | @type MessageType 35 | message string 36 | } 37 | 38 | // method: ‘telemetry/event 39 | // notification 40 | // any 41 | -------------------------------------------------------------------------------- /server/features_code_lens.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | import lsp 4 | 5 | pub fn (mut ls Vls) code_lens(params lsp.CodeLensParams, mut wr ResponseWriter) ?[]lsp.CodeLens { 6 | if Feature.code_lens !in ls.enabled_features { 7 | return none 8 | } 9 | 10 | // TODO: compute codelenses, for now return empty result 11 | return none 12 | } 13 | -------------------------------------------------------------------------------- /server/features_document_link.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | import lsp 4 | 5 | pub fn (mut ls Vls) document_link(params lsp.DocumentLinkParams, mut wr ResponseWriter) ?[]lsp.DocumentLink { 6 | if Feature.document_link !in ls.enabled_features { 7 | return none 8 | } 9 | 10 | return none 11 | } 12 | -------------------------------------------------------------------------------- /server/file.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | import ast 4 | import lsp 5 | import structures.ropes 6 | 7 | struct File { 8 | mut: 9 | uri lsp.DocumentUri 10 | source &ropes.Rope 11 | tree &ast.Tree [required] 12 | version int = 1 13 | } 14 | 15 | fn (file &File) get_offset(line int, col int) int { 16 | return compute_offset(file.source, line, col) 17 | } 18 | 19 | fn (file &File) get_position(offset int) lsp.Position { 20 | return compute_position(file.source, offset) 21 | } 22 | 23 | fn (file_map map[string]File) count(dir string) int { 24 | mut file_count := 0 25 | for k, _ in file_map { 26 | if k.starts_with(dir) { 27 | file_count++ 28 | } 29 | } 30 | return file_count 31 | } 32 | -------------------------------------------------------------------------------- /server/os_utils_default.c.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | const ( 4 | v_exec_name = 'v' 5 | path_list_sep = ':' 6 | ) 7 | 8 | fn is_proc_exists(pid int) bool { 9 | errno_ := C.kill(pid, 0) 10 | // if errno_ != C.ESRCH { 11 | if errno_ == 0 { 12 | return true 13 | } 14 | return false 15 | } 16 | -------------------------------------------------------------------------------- /server/os_utils_windows.c.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | const ( 4 | v_exec_name = 'v.exe' 5 | path_list_sep = ';' 6 | ) 7 | 8 | fn C.OpenProcess(access int, inherit_handle bool, pid int) C.HANDLE 9 | 10 | fn is_proc_exists(pid int) bool { 11 | exit_code := u32(0) 12 | got_process := C.OpenProcess(0x0400, false, pid) 13 | C.GetExitCodeProcess(got_process, voidptr(&exit_code)) 14 | if exit_code == C.STILL_ACTIVE { 15 | return true 16 | } 17 | return false 18 | } 19 | -------------------------------------------------------------------------------- /server/tests/code_lens_test.v: -------------------------------------------------------------------------------- 1 | import server 2 | import test_utils 3 | import jsonrpc.server_test_utils { new_test_client } 4 | import lsp 5 | 6 | fn test_code_lens() { 7 | mut ls := server.new() 8 | mut t := &test_utils.Tester{ 9 | test_files_dir: test_utils.get_test_files_path(@FILE) 10 | folder_name: 'code_lens' 11 | client: new_test_client(ls) 12 | } 13 | 14 | mut writer := t.client.server.writer() 15 | test_files := t.initialize()? 16 | for file in test_files { 17 | // open document 18 | doc_id := t.open_document(file) or { 19 | t.fail(file, err.msg()) 20 | continue 21 | } 22 | 23 | if _ := ls.code_lens(lsp.CodeLensParams{ 24 | text_document: doc_id 25 | }, mut writer) 26 | { 27 | t.fail(file, 'should not return a result') 28 | } else { 29 | t.is_null(file, true, err) 30 | } 31 | 32 | // Delete document 33 | t.close_document(doc_id) or { 34 | t.fail(file, err.msg()) 35 | continue 36 | } 37 | } 38 | 39 | assert t.is_ok() 40 | } 41 | -------------------------------------------------------------------------------- /server/tests/diagnostics_test.v: -------------------------------------------------------------------------------- 1 | import server 2 | import test_utils 3 | import jsonrpc.server_test_utils { new_test_client } 4 | import lsp 5 | import os 6 | 7 | const base_dir = os.join_path(os.dir(@FILE), 'test_files', 'diagnostics') 8 | 9 | const diagnostics_results = { 10 | 'simple.vv': lsp.PublishDiagnosticsParams{ 11 | uri: lsp.document_uri_from_path(os.join_path(base_dir, 'simple.vv')) 12 | diagnostics: [ 13 | lsp.Diagnostic{ 14 | message: 'unexpected eof, expecting `}`' 15 | severity: .error 16 | range: lsp.Range{ 17 | start: lsp.Position{4, 10} 18 | end: lsp.Position{4, 10} 19 | } 20 | }, 21 | lsp.Diagnostic{ 22 | message: "module 'os' is imported but never used" 23 | severity: .warning 24 | range: lsp.Range{ 25 | start: lsp.Position{2, 7} 26 | end: lsp.Position{2, 7} 27 | } 28 | }, 29 | ] 30 | } 31 | 'error_highlight.vv': lsp.PublishDiagnosticsParams{ 32 | uri: lsp.document_uri_from_path(os.join_path(base_dir, 'error_highlight.vv')) 33 | diagnostics: [ 34 | lsp.Diagnostic{ 35 | message: 'unexpected name `asfasf`' 36 | severity: .error 37 | range: lsp.Range{ 38 | start: lsp.Position{1, 1} 39 | end: lsp.Position{1, 1} 40 | } 41 | }, 42 | ] 43 | } 44 | } 45 | 46 | fn test_diagnostics() { 47 | mut t := &test_utils.Tester{ 48 | test_files_dir: test_utils.get_test_files_path(@FILE) 49 | folder_name: 'diagnostics' 50 | client: new_test_client(server.new()) 51 | } 52 | 53 | test_files := t.initialize()? 54 | for file in test_files { 55 | doc_id := t.open_document(file) or { 56 | t.fail(file, err.msg()) 57 | continue 58 | } 59 | 60 | diagnostic_params := t.diagnostics()? 61 | if diagnostic_params.uri.path() != file.file_path { 62 | t.fail(file, 'no diagnostics found') 63 | continue 64 | } 65 | 66 | expected := diagnostics_results[file.file_name] or { lsp.PublishDiagnosticsParams{} } 67 | assert diagnostic_params == expected 68 | } 69 | assert t.is_ok() 70 | } 71 | -------------------------------------------------------------------------------- /server/tests/document_link_test.v: -------------------------------------------------------------------------------- 1 | import server 2 | import test_utils 3 | import jsonrpc.server_test_utils { new_test_client } 4 | import lsp 5 | 6 | fn test_code_lens() { 7 | mut ls := server.new() 8 | mut t := &test_utils.Tester{ 9 | test_files_dir: test_utils.get_test_files_path(@FILE) 10 | folder_name: 'document_link' 11 | client: new_test_client(ls) 12 | } 13 | 14 | mut writer := t.client.server.writer() 15 | test_files := t.initialize()? 16 | for file in test_files { 17 | // open document 18 | doc_id := t.open_document(file) or { 19 | t.fail(file, err.msg()) 20 | continue 21 | } 22 | 23 | if _ := ls.document_link(lsp.DocumentLinkParams{ 24 | text_document: doc_id 25 | }, mut writer) 26 | { 27 | t.fail(file, 'should not return a result') 28 | } else { 29 | t.is_null(file, true, err) 30 | } 31 | 32 | // Delete document 33 | t.close_document(doc_id) or { 34 | t.fail(file, err.msg()) 35 | continue 36 | } 37 | } 38 | 39 | assert t.is_ok() 40 | } 41 | -------------------------------------------------------------------------------- /server/tests/regression_test.v: -------------------------------------------------------------------------------- 1 | import jsonrpc 2 | import jsonrpc.server_test_utils { new_test_client } 3 | import server 4 | import test_utils 5 | 6 | // REGRESSION TEST 7 | // NB: This is a simple implementation for now. What this test does is 8 | // to open a file from a test folder and close if no panic or any related 9 | // "stop-the-process" errors occur. 10 | // 11 | // Files are taken from the existing issues. If there is an issue related 12 | // to checker / parser that only crashes within VLS, please tag the issue 13 | // `needs-regression-test` and add the offending code here. 14 | // 15 | // This is just an extension of the existing V test suite. If the code also 16 | // applies to the V compiler, it is better to add it there instead. 17 | 18 | fn test_regression() { 19 | mut t := &test_utils.Tester{ 20 | test_files_dir: test_utils.get_test_files_path(@FILE) 21 | folder_name: 'regressions' 22 | client: new_test_client(server.new()) 23 | } 24 | 25 | test_files := t.initialize()? 26 | for file in test_files { 27 | doc_id := t.open_document(file) or { 28 | t.fail(file, err.msg()) 29 | continue 30 | } 31 | 32 | t.close_document(doc_id) or { 33 | t.fail(file, err.msg()) 34 | continue 35 | } 36 | 37 | t.ok(file) 38 | } 39 | 40 | assert t.is_ok() 41 | } 42 | -------------------------------------------------------------------------------- /server/tests/test_files/code_lens/simple.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/.do_not_import/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/server/tests/test_files/completion/.do_not_import/.gitkeep -------------------------------------------------------------------------------- /server/tests/test_files/completion/abc/abc.v: -------------------------------------------------------------------------------- 1 | module abc 2 | 3 | pub struct Point { 4 | pub: 5 | a int 6 | b int 7 | } 8 | 9 | pub fn this_is_a_function() string { 10 | return 'wee' 11 | } 12 | 13 | pub enum KeyCode { 14 | shift 15 | control 16 | } 17 | 18 | pub fn (code KeyCode) print() {} 19 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/abc/def/def.v: -------------------------------------------------------------------------------- 1 | module def 2 | 3 | pub fn hello() string { 4 | return 'hello' 5 | } 6 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/abc/def/ghi/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/server/tests/test_files/completion/abc/def/ghi/.gitkeep -------------------------------------------------------------------------------- /server/tests/test_files/completion/assign.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | two := 2 5 | mut zero := 0 6 | 7 | two = 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/binded_symbol.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import gfx 4 | 5 | fn main() { 6 | C. 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/blank.vv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/server/tests/test_files/completion/blank.vv -------------------------------------------------------------------------------- /server/tests/test_files/completion/call_args.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn add_to_four(num int) int { 4 | return num + 4 5 | } 6 | 7 | fn main() { 8 | sample_num := 2 9 | sample_num2 := 3 10 | should_not_appear := 'hey' 11 | add_to_four() 12 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/embedded_struct_field.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import abc 4 | 5 | pub struct ThreeDPoint { 6 | abc.Point 7 | z int 8 | } 9 | 10 | fn main() { 11 | point := ThreeDPoint{ 12 | Point: Point{1,2} 13 | z: 3 14 | } 15 | 16 | println(point.) 17 | } 18 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/enum_member.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import abc 4 | 5 | fn main() { 6 | println(abc.KeyCode.) 7 | } 8 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/enum_method.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import abc 4 | 5 | fn main() { 6 | println(abc.KeyCode.shift.) 7 | } 8 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/enum_val_in_struct.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | enum Breed { 4 | golden_retriever 5 | beagle 6 | chihuahua 7 | dalmatian 8 | } 9 | 10 | fn (b Breed) print() { 11 | println(b.str()) 12 | } 13 | 14 | struct Dog { 15 | breed Breed 16 | } 17 | 18 | fn main() { 19 | baz := Dog{breed: } 20 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/filtered_fields_in_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import os 4 | 5 | struct Log { 6 | pub: 7 | level Level 8 | output_label string 9 | ofile os.File 10 | output_target LogTarget 11 | pub mut: 12 | output_file_name string 13 | } 14 | 15 | fn main() { 16 | mut logger := Log{} 17 | logger. 18 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/filtered_methods_in_immutable_var.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Foo {} 4 | 5 | fn (mut f Foo) set_name(name string) { 6 | } 7 | 8 | fn (f Foo) lol() string { 9 | return f.name 10 | } 11 | 12 | fn main() { 13 | foo := Foo{'bob'} 14 | foo. 15 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/filtered_methods_in_mutable_var.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Foo {} 4 | 5 | fn (mut f Foo) set_name(name string) { 6 | } 7 | 8 | fn (f Foo) lol() string { 9 | return f.name 10 | } 11 | 12 | fn main() { 13 | mut foo := Foo{'bob'} 14 | foo. 15 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/fn_literal.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | list_exec := fn (cmd int) { 5 | gs := 'hello' 6 | 7 | } 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/gfx/gfx.v: -------------------------------------------------------------------------------- 1 | module gfx 2 | 3 | [typedef] 4 | pub struct C.Foo { 5 | bar int 6 | baz string 7 | data voidptr 8 | count int 9 | } 10 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/import_symbols.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import pg { } -------------------------------------------------------------------------------- /server/tests/test_files/completion/incomplete_call_expr_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Bee { 4 | len int 5 | } 6 | 7 | fn return_bee() Bee { 8 | return Bee{len: 1} 9 | } 10 | 11 | fn main3() string { 12 | return_bee('test'). 13 | } 14 | -------------------------------------------------------------------------------- /server/tests/test_files/completion/incomplete_enum_selector.vv: -------------------------------------------------------------------------------- 1 | struct Color { 2 | red 3 | blue 4 | yellow 5 | } 6 | 7 | fn (c Color) print() { 8 | println(c.str()) 9 | } 10 | 11 | fn main() { 12 | foo := Color.red 13 | foo. 14 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/incomplete_module.vv: -------------------------------------------------------------------------------- 1 | module -------------------------------------------------------------------------------- /server/tests/test_files/completion/incomplete_nested_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Barw { 4 | name string 5 | } 6 | 7 | fn (b Barw) theres_a_method() {} 8 | 9 | struct Foow { 10 | bar Barw 11 | } 12 | 13 | fn main() { 14 | foo := Foow{Barw{}} 15 | foo.bar. 16 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/incomplete_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Foo { 4 | name string 5 | } 6 | 7 | fn (f Foo) lol() string { 8 | return f.name 9 | } 10 | 11 | fn main() { 12 | foo := Foo{'bob'} 13 | foo. 14 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/invalid_call.vv: -------------------------------------------------------------------------------- 1 | waz() -------------------------------------------------------------------------------- /server/tests/test_files/completion/local_results.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | foo := 'Test' 5 | bar := 2 6 | 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/module_selector.vv: -------------------------------------------------------------------------------- 1 | import abc.def 2 | 3 | fn main() { 4 | 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/module_symbols_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import abc 4 | 5 | fn main() { 6 | abc. 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/self_reference_var_in_struct_field.vv: -------------------------------------------------------------------------------- 1 | struct Command { 2 | cmd &Command 3 | } 4 | 5 | fn main() { 6 | test := &Command{ 7 | cmd: 8 | } 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/struct_init.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Person { 4 | name string 5 | age int 6 | } 7 | 8 | fn main() { 9 | prs := Person{} 10 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/struct_init_string_field.vv: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | text string 3 | num int 4 | } 5 | 6 | fn main() { 7 | name := 'bob' 8 | another_name := 'lol' 9 | foo := Foo { 10 | text: 11 | num: 1 12 | } 13 | } -------------------------------------------------------------------------------- /server/tests/test_files/completion/type_decl.vv: -------------------------------------------------------------------------------- 1 | struct Foo {} 2 | struct Bar {} 3 | 4 | type Fooz = -------------------------------------------------------------------------------- /server/tests/test_files/connection/hello.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('hello world!') 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/call_arg.vv: -------------------------------------------------------------------------------- 1 | fn function_name(num int) {} 2 | 3 | fn main() { 4 | nm := 10 5 | function_name(nm) 6 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/call_expr.vv: -------------------------------------------------------------------------------- 1 | fn function_name() {} 2 | 3 | fn main() { 4 | function_name() 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/enum_val.vv: -------------------------------------------------------------------------------- 1 | enum Color { 2 | red 3 | green 4 | blue 5 | } 6 | 7 | fn main() { 8 | col := Color.blue 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/expr_in_array.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | just_a_name := 'Bob' 3 | names := [just_a_name, 'Steve'] 4 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/expr_in_map_key.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | just_a_name := 'Bob' 3 | 4 | ages := { 5 | just_a_name: 20 6 | 'Steve': 10 7 | } 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/expr_in_map_value.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | just_an_age := 39 3 | 4 | ages := { 5 | 'Bob': just_an_age 6 | 'Steve': 10 7 | } 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/fn_literal.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | list_exec := fn () { 5 | gs := 'hello' 6 | println(gs) 7 | } 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/fn_param_type.vv: -------------------------------------------------------------------------------- 1 | struct Zz { 2 | num int 3 | } 4 | 5 | fn do_what(zz Zz) {} -------------------------------------------------------------------------------- /server/tests/test_files/definition/fn_return_type.vv: -------------------------------------------------------------------------------- 1 | type Text = string 2 | 3 | fn do_nothing() Text { 4 | return 'hey' 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/index_expr.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | names := ['baz', 'boo'] 3 | iddx := 0 4 | println(names[iddx]) 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/interface_field.vv: -------------------------------------------------------------------------------- 1 | type Str = string 2 | 3 | interface Stringer { 4 | content Str 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/interface_method_skip.vv: -------------------------------------------------------------------------------- 1 | struct Bazz { 2 | bas int 3 | } 4 | 5 | interface Bazzs { 6 | check() Bazz 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/node_error.vv: -------------------------------------------------------------------------------- 1 | struct Ff { 2 | b int 3 | 4 | fn (f FF) errrr() {} -------------------------------------------------------------------------------- /server/tests/test_files/definition/selector_expr.vv: -------------------------------------------------------------------------------- 1 | struct Zz { 2 | counter int 3 | } 4 | 5 | fn main() { 6 | zz := Zz{1} 7 | zz.counter 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/stmt.vv: -------------------------------------------------------------------------------- 1 | fn this_should_not_highlight() { 2 | 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/struct_field_type.vv: -------------------------------------------------------------------------------- 1 | type Num = int 2 | 3 | struct AnotherStruct { 4 | num Num 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/struct_init.vv: -------------------------------------------------------------------------------- 1 | struct Person3 { 2 | name string 3 | } 4 | 5 | fn main() { 6 | pr := Person3{'lol'} 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/struct_init_field_name.vv: -------------------------------------------------------------------------------- 1 | struct Person { 2 | name string 3 | } 4 | 5 | fn main() { 6 | pr := Person{name: 'lol'} 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/struct_init_field_value.vv: -------------------------------------------------------------------------------- 1 | enum Kind { 2 | handsome 3 | ugly 4 | } 5 | 6 | struct Person2 { 7 | kind Kind 8 | } 9 | 10 | fn main() { 11 | pr := Person2{kind: .ugly} 12 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/var.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | nmm := 10 3 | println(nmm) 4 | } -------------------------------------------------------------------------------- /server/tests/test_files/definition/var_receiver.vv: -------------------------------------------------------------------------------- 1 | struct Pp {} 2 | 3 | fn (pp Pp) qq() { 4 | ss := pp 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/diagnostics/error_highlight.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | asfasf 3 | println('text') 4 | } 5 | -------------------------------------------------------------------------------- /server/tests/test_files/diagnostics/simple.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import os 4 | 5 | fn foo() { -------------------------------------------------------------------------------- /server/tests/test_files/document_link/simple.vv: -------------------------------------------------------------------------------- 1 | fn main() {} -------------------------------------------------------------------------------- /server/tests/test_files/document_symbols/simple.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | type Uri = string 4 | 5 | const ( 6 | text = 'helo' 7 | two = 2 8 | ) 9 | 10 | enum Color { 11 | red 12 | blue 13 | yellow 14 | } 15 | 16 | struct Person { 17 | name string 18 | } 19 | 20 | fn (p Person) say() { 21 | println('hello! $p.name') 22 | } 23 | 24 | fn main() { 25 | per := Person{} 26 | per.say() 27 | } 28 | 29 | type Recursive = []Recursive | int -------------------------------------------------------------------------------- /server/tests/test_files/folding_range/comment_skip.vv: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is a very very long comment range. 4 | 5 | Like very very very long. 6 | 7 | Magnis justo a a tincidunt curae nascetur viverra venenatis at 8 | duis a congue lorem ultricies congue porttitor quis rhoncus nam 9 | in aenean venenatis eros imperdiet eleifend convallis montes. Dis 10 | a proin vitae semper suspendisse in adipiscing a 11 | suspendisse suspendisse etiam a eros eget aptent suspendisse parturient 12 | volutpat dui a fusce arcu urna in litora cubilia. Lacus habitasse ad id 13 | massa fames curae senectus dui ullamcorper condimentum ac risus convallis 14 | enim. Erat est nam est ad ullamcorper potenti bibendum maecenas a bibendum 15 | fusce mi adipiscing eu suspendisse commodo a felis conubia vestibulum lacinia 16 | a. Suspendisse a etiam etiam maecenas a sagittis lobortis a sed nibh cubilia 17 | volutpat himenaeos potenti a tristique per sagittis vestibulum pharetra. 18 | 19 | */ -------------------------------------------------------------------------------- /server/tests/test_files/folding_range/simple_skip.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Stru { 4 | name string 5 | age int 6 | height f32 7 | } 8 | 9 | interface Speaker { 10 | speak(word string) string 11 | silent() 12 | } 13 | 14 | enum Color { 15 | red 16 | blue 17 | green 18 | } 19 | 20 | fn main() { 21 | num := 2 22 | hello := 'world' 23 | foo := 10.00 24 | } -------------------------------------------------------------------------------- /server/tests/test_files/formatting/cjk_1.out: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('test') //这是中文注释 5 | } 6 | -------------------------------------------------------------------------------- /server/tests/test_files/formatting/cjk_1.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('test') //这是中文注释 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/formatting/cjk_2.out: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('test') //这是中文注释,新内容 5 | } 6 | -------------------------------------------------------------------------------- /server/tests/test_files/formatting/cjk_2.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('test') //这是中文注释,新内容 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/formatting/empty.vv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlang/vls/dd8c00497c8de79f939e26795f7115332d2347b6/server/tests/test_files/formatting/empty.vv -------------------------------------------------------------------------------- /server/tests/test_files/formatting/simple_skip_windows.out: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Test { 4 | this_is_a_long_field int 5 | bar string 6 | } 7 | 8 | fn main() { 9 | println('hello!') 10 | } 11 | -------------------------------------------------------------------------------- /server/tests/test_files/formatting/simple_skip_windows.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Test{ 4 | this_is_a_long_field int 5 | bar string 6 | } 7 | 8 | fn main () { 9 | println ('hello!') 10 | } -------------------------------------------------------------------------------- /server/tests/test_files/formatting/with_error.vv: -------------------------------------------------------------------------------- 1 | struct Test { 2 | foo string 3 | 4 | fn main() { -------------------------------------------------------------------------------- /server/tests/test_files/hover/call_expr_method.vv: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | name string 3 | } 4 | 5 | fn (foo Foo) call() string { 6 | return foo.name 7 | } 8 | 9 | fn main() { 10 | foo := Foo{'bar'} 11 | baz := foo.call() 12 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/call_expr_simple.vv: -------------------------------------------------------------------------------- 1 | fn greet(name string) { 2 | println(name) 3 | } 4 | 5 | fn main() { 6 | greet('Ned') 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/enum.vv: -------------------------------------------------------------------------------- 1 | enum Color { 2 | red 3 | blue 4 | yellow 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/fn_literal.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | list_exec := fn (cmd int) { 5 | gs := 'hello' 6 | println(cmd) 7 | } 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/function.vv: -------------------------------------------------------------------------------- 1 | // this is docstring 2 | fn foo(param1 string, mut param2 []string) bool { 3 | return false 4 | } 5 | -------------------------------------------------------------------------------- /server/tests/test_files/hover/function_param.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn add_stuff(mut arr []string, text string) { 4 | arr << text 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/import.vv: -------------------------------------------------------------------------------- 1 | import os -------------------------------------------------------------------------------- /server/tests/test_files/hover/interface_spec.vv: -------------------------------------------------------------------------------- 1 | interface Fooer { 2 | random_num() int 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/interface_spec_params.vv: -------------------------------------------------------------------------------- 1 | interface Tester { 2 | test(num int) int 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/module.vv: -------------------------------------------------------------------------------- 1 | module foo 2 | 3 | fn main() {} -------------------------------------------------------------------------------- /server/tests/test_files/hover/node_error_skip.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Foo { 4 | a 5 | 6 | 7 | fn (f Foo) greet() {} -------------------------------------------------------------------------------- /server/tests/test_files/hover/selector_expr.vv: -------------------------------------------------------------------------------- 1 | struct Person { 2 | name string 3 | } 4 | 5 | fn main() { 6 | person := Person{'Test'} 7 | person.name 8 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/struct.vv: -------------------------------------------------------------------------------- 1 | struct Abc { 2 | def string 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/struct_field.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Foo { 4 | bar string 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/struct_init_a.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Person { 4 | name string 5 | } 6 | 7 | fn main() { 8 | person := Person{ 9 | name: 'Bob' 10 | } 11 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/struct_init_b.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | import cli 4 | 5 | fn main() { 6 | mut sub_cmd := cli.Command{ 7 | name: 'sub' 8 | usage: 'arg1 arg2' 9 | required_args: 2 10 | } 11 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/type_alias.vv: -------------------------------------------------------------------------------- 1 | type Str = string -------------------------------------------------------------------------------- /server/tests/test_files/hover/type_fn.vv: -------------------------------------------------------------------------------- 1 | type Handler = fn (test string) string -------------------------------------------------------------------------------- /server/tests/test_files/hover/type_sum.vv: -------------------------------------------------------------------------------- 1 | type Any = int | string -------------------------------------------------------------------------------- /server/tests/test_files/hover/variable.vv: -------------------------------------------------------------------------------- 1 | fn main() { 2 | num := 1 3 | num2 := num 4 | } -------------------------------------------------------------------------------- /server/tests/test_files/hover/with_call_expr_below.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | test := 1 5 | println(test) 6 | } 7 | -------------------------------------------------------------------------------- /server/tests/test_files/implementation/simple.vv: -------------------------------------------------------------------------------- 1 | interface Speaker { 2 | speak() string 3 | } 4 | 5 | interface Tester { 6 | random_num int 7 | test(num int) int 8 | } 9 | 10 | struct Foo { 11 | random_num int 12 | } 13 | 14 | fn (f Foo) speak() string { 15 | return 'jk lol' 16 | } 17 | 18 | fn (f Foo) test(f2 int) int { 19 | return num + f.random_num 20 | } 21 | -------------------------------------------------------------------------------- /server/tests/test_files/pos_compute_offset/crlf.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn crlf_test() { 4 | test := 'Hello World' 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/pos_compute_offset/lf.vv: -------------------------------------------------------------------------------- 1 | module main 2 | fn lf_test() { 3 | test := 123 4 | } -------------------------------------------------------------------------------- /server/tests/test_files/pos_to_lsp_pos/simple.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn hello() {} -------------------------------------------------------------------------------- /server/tests/test_files/pos_to_lsp_range/simple.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | pub fn should_be_one_line() { 4 | // test comment 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/pos_to_lsp_range/with_last_line.vv: -------------------------------------------------------------------------------- 1 | fn with_last_line() { 2 | test := 123 3 | name := 'hello' 4 | } -------------------------------------------------------------------------------- /server/tests/test_files/regressions/function_in_struct_decl_skip_macos.vv: -------------------------------------------------------------------------------- 1 | module lexer 2 | 3 | import benchmark 4 | 5 | pub struct Tt { 6 | benchmark benchmark.Benchmark = benchmark.new_benchmark() 7 | } -------------------------------------------------------------------------------- /server/tests/test_files/regressions/incomplete_fn.vv: -------------------------------------------------------------------------------- 1 | fn -------------------------------------------------------------------------------- /server/tests/test_files/regressions/option_interface_name.vv: -------------------------------------------------------------------------------- 1 | interface MyInterface { 2 | ?duh() string 3 | } -------------------------------------------------------------------------------- /server/tests/test_files/regressions/simple_vweb_app_skip.vv: -------------------------------------------------------------------------------- 1 | import vweb 2 | 3 | struct App { 4 | vweb.Context 5 | } 6 | 7 | fn main() { 8 | vweb.run(8080) 9 | } 10 | 11 | ['/hello/:user'] 12 | fn (mut app App) hello_user(user string) vweb.Result { 13 | return app.text('Hello $user') 14 | } -------------------------------------------------------------------------------- /server/tests/test_files/regressions/string_literal_selector.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn main() { 4 | println('hello world!') 5 | ''. 6 | } -------------------------------------------------------------------------------- /server/tests/test_files/signature_help/empty_middle_arg.vv: -------------------------------------------------------------------------------- 1 | fn foo(a int, b f32, c i64) {} 2 | 3 | foo(10,, i64(100)) -------------------------------------------------------------------------------- /server/tests/test_files/signature_help/empty_second_arg.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn return_number(a int, b int) int { 4 | return a 5 | } 6 | 7 | return_number(10, ) -------------------------------------------------------------------------------- /server/tests/test_files/signature_help/simple.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn greet(name string) bool { 4 | println(name) 5 | } 6 | 7 | fn main() { 8 | greet() 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/signature_help/with_content.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn greet(name string, age int) bool { 4 | println(name) 5 | } 6 | 7 | fn main() { 8 | greet('Bob', 12) 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/signature_help/with_content_b.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn greet(name string, age int) bool { 4 | println(name) 5 | } 6 | 7 | fn main() { 8 | greet('Bob', 12) 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/workspace_did_change/changed_be_ignored.vv: -------------------------------------------------------------------------------- 1 | module workspace_did_change 2 | 3 | const foo = 1 -------------------------------------------------------------------------------- /server/tests/test_files/workspace_did_change/should_be_deleted.vv: -------------------------------------------------------------------------------- 1 | module workspace_did_change 2 | 3 | fn hello() string { 4 | return 'world!' 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/workspace_did_change/should_be_renamed.vv: -------------------------------------------------------------------------------- 1 | module workspace_did_change 2 | 3 | fn what_does_the_fox_say() int { 4 | return 1 5 | } -------------------------------------------------------------------------------- /server/tests/test_files/workspace_symbols/file1.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | fn foo() string { 4 | return 'hello' 5 | } 6 | 7 | fn main() { 8 | // test 9 | } -------------------------------------------------------------------------------- /server/tests/test_files/workspace_symbols/file2.vv: -------------------------------------------------------------------------------- 1 | module main 2 | 3 | struct Person { 4 | name string 5 | } 6 | 7 | fn hello(name string) { 8 | println(name) 9 | } -------------------------------------------------------------------------------- /server/window.v: -------------------------------------------------------------------------------- 1 | module server 2 | 3 | import lsp 4 | 5 | // log_message sends a window/logMessage notification to the client 6 | pub fn (mut wr ResponseWriter) log_message(message string, typ lsp.MessageType) { 7 | wr.write_notify('window/logMessage', lsp.LogMessageParams{ 8 | @type: typ 9 | message: message 10 | }) 11 | } 12 | 13 | // show_message sends a window/showMessage notification to the client 14 | pub fn (mut wr ResponseWriter) show_message(message string, typ lsp.MessageType) { 15 | wr.write_notify('window/showMessage', lsp.ShowMessageParams{ 16 | @type: typ 17 | message: message 18 | }) 19 | } 20 | 21 | pub fn (mut wr ResponseWriter) show_message_request(message string, actions []lsp.MessageActionItem, typ lsp.MessageType) { 22 | wr.write_notify('window/showMessageRequest', lsp.ShowMessageRequestParams{ 23 | @type: typ 24 | message: message 25 | actions: actions 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /structures/depgraph/depgraph_test.v: -------------------------------------------------------------------------------- 1 | module depgraph 2 | 3 | fn test_depgraph() { 4 | mut course_book := Tree{} 5 | course_book.add('MAJOR-PHILOSOPHY', 'STAT-101', 'PHIL-102') 6 | course_book.add('MAJOR-MATHS', 'STAT-101', 'CALC-102') 7 | course_book.add('CALC-102', 'CALC-101') 8 | course_book.add('CALC-101', 'STAT-100') 9 | course_book.add('STAT-101', 'STAT-100') 10 | course_book.add('STAT-100') 11 | course_book.add('PHIL-102', 'PHIL-101') 12 | course_book.add('PHIL-101') 13 | 14 | assert course_book.get_available_nodes('STAT-100') == ['CALC-101', 'STAT-101', 'PHIL-101'] 15 | assert course_book.get_node('PHIL-102')?.get_all_dependencies() == ['PHIL-101'] 16 | 17 | philo := course_book.get_node('MAJOR-PHILOSOPHY')? 18 | assert philo.dependencies == ['STAT-101', 'PHIL-102'] 19 | assert philo.get_all_dependencies() == ['STAT-101', 'PHIL-102', 'STAT-100', 'PHIL-101'] 20 | assert philo.get_all_dependencies('PHIL-101', 'STAT-100') == ['STAT-101', 'PHIL-102'] 21 | assert course_book.get_node('MAJOR-MATHS')?.get_next_nodes('STAT-100') == [ 22 | 'CALC-101', 23 | 'STAT-101', 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /structures/ropes/ropes_test.v: -------------------------------------------------------------------------------- 1 | // a v port of the https://github.com/vinzmay/go-rope/blob/master/rope_test.go test file 2 | import structures.ropes 3 | 4 | fn test_rope_creation() { 5 | r := ropes.new('test') 6 | assert r.str() == 'test' 7 | assert r.len() == 4 8 | } 9 | 10 | fn test_rope_concat() { 11 | r := ropes.new('abcdef') 12 | r2 := ropes.new('ghilmno') 13 | r3 := r.concat(r2) 14 | assert r.str() == 'abcdef' 15 | assert r.len() == 6 16 | assert r2.str() == 'ghilmno' 17 | assert r2.len() == 7 18 | assert r3.str() == 'abcdefghilmno' 19 | assert r3.len() == 13 20 | } 21 | 22 | fn test_rope_split() { 23 | r := ropes.new('abcdef') 24 | r1, r2 := r.split(4) 25 | assert r.str() == 'abcdef' 26 | assert r.len() == 6 27 | assert r1.str() == 'abcd' 28 | assert r1.len() == 4 29 | assert r2.str() == 'ef' 30 | assert r2.len() == 2 31 | 32 | assert r.delete(1, 4).string() == 'af' 33 | } 34 | 35 | fn test_rope_substr() { 36 | r := ropes.new('abcdef') 37 | assert r.substr(0, 4) == 'abcd' 38 | } 39 | 40 | fn test_rope_balance() { 41 | mut r := ropes.new('abcd') 42 | 43 | r = r.insert(4, 'ef') 44 | assert r.str() == 'abcdef' 45 | assert r.is_leaf() 46 | 47 | r = r.rebalance() 48 | assert r.str() == 'abcdef' 49 | assert r.len() == 6 50 | } 51 | -------------------------------------------------------------------------------- /test_utils/test_file_parser.v: -------------------------------------------------------------------------------- 1 | module test_utils 2 | 3 | import regex 4 | 5 | // newlines_to_spaces replaces the newlines 6 | // and multiples into single space. 7 | // TODO: use single instance of regex pattern 8 | pub fn newlines_to_spaces(text string) string { 9 | mut re2 := regex.regex_opt(r'\s+') or { return text } 10 | return re2.replace(text, ' ') 11 | } 12 | 13 | // parse_test_file_content extracts and returns the source content 14 | // and the expected output from the text mostly from .test.txt files. 15 | pub fn parse_test_file_content(text string) (string, string) { 16 | triple_dash_idx := text.last_index('---') or { return '', '' } 17 | 18 | return text[..triple_dash_idx].trim_space(), text[triple_dash_idx + 3..].trim_space() 19 | } 20 | -------------------------------------------------------------------------------- /test_utils/test_file_parser_test.v: -------------------------------------------------------------------------------- 1 | module test_utils 2 | 3 | fn test_parse_test_file_content() { 4 | src, expected := parse_test_file_content('hello\n---\n(world)\n(test)\t\t\t(world)') 5 | assert src == 'hello' 6 | assert newlines_to_spaces(expected) == '(world) (test) (world)' 7 | } 8 | -------------------------------------------------------------------------------- /test_utils/test_utils_test.v: -------------------------------------------------------------------------------- 1 | module test_utils 2 | 3 | import json 4 | import jsonrpc 5 | 6 | struct Foo { 7 | hello string 8 | } 9 | 10 | fn test_send() { 11 | mut io := Testio{} 12 | io.send('request message') 13 | assert io.raw_responses[0] == 'request message' 14 | } 15 | 16 | fn test_request() { 17 | mut io := Testio{} 18 | assert io.current_req_id == 1 19 | payload := io.request('foo') 20 | assert payload == '{"jsonrpc":"2.0","id":1,"method":"foo","params":{}}' 21 | assert io.current_req_id == 2 22 | } 23 | 24 | fn test_request_with_params() { 25 | mut io := Testio{} 26 | param := { 27 | 'hello': 'world' 28 | } 29 | payload := io.request_with_params('foo', param) 30 | assert payload == '{"jsonrpc":"2.0","id":1,"method":"foo","params":{"hello":"world"}}' 31 | assert io.current_req_id == 2 32 | } 33 | 34 | fn test_result() { 35 | mut io := Testio{} 36 | result := { 37 | 'hello': 'world' 38 | } 39 | resp := jsonrpc.Response{ 40 | id: '1' 41 | result: result 42 | } 43 | io.send(json.encode(resp)) 44 | assert io.result() == json.encode(result) 45 | } 46 | 47 | fn test_notification() { 48 | mut io := Testio{} 49 | request := json.encode(jsonrpc.NotificationMessage{ 50 | method: 'log' 51 | params: 'just a log' 52 | }) 53 | io.send(request) 54 | method, params := io.notification()? 55 | assert method == 'log' 56 | assert params == '"just a log"' 57 | } 58 | 59 | fn test_response_error() { 60 | mut io := Testio{} 61 | payload := jsonrpc.Response{ 62 | error: jsonrpc.response_error(error: jsonrpc.method_not_found) 63 | } 64 | request := json.encode(payload) 65 | io.send(request) 66 | err_code, err_message := io.response_error()? 67 | assert err_code == jsonrpc.method_not_found.code() 68 | assert err_message == jsonrpc.method_not_found.msg() 69 | } 70 | -------------------------------------------------------------------------------- /tree_sitter/lib/alloc.c: -------------------------------------------------------------------------------- 1 | #include "alloc.h" 2 | #include 3 | 4 | static void *ts_malloc_default(size_t size) { 5 | void *result = malloc(size); 6 | if (size > 0 && !result) { 7 | fprintf(stderr, "tree-sitter failed to allocate %zu bytes", size); 8 | exit(1); 9 | } 10 | return result; 11 | } 12 | 13 | static void *ts_calloc_default(size_t count, size_t size) { 14 | void *result = calloc(count, size); 15 | if (count > 0 && !result) { 16 | fprintf(stderr, "tree-sitter failed to allocate %zu bytes", count * size); 17 | exit(1); 18 | } 19 | return result; 20 | } 21 | 22 | static void *ts_realloc_default(void *buffer, size_t size) { 23 | void *result = realloc(buffer, size); 24 | if (size > 0 && !result) { 25 | fprintf(stderr, "tree-sitter failed to reallocate %zu bytes", size); 26 | exit(1); 27 | } 28 | return result; 29 | } 30 | 31 | // Allow clients to override allocation functions dynamically 32 | void *(*ts_current_malloc)(size_t) = ts_malloc_default; 33 | void *(*ts_current_calloc)(size_t, size_t) = ts_calloc_default; 34 | void *(*ts_current_realloc)(void *, size_t) = ts_realloc_default; 35 | void (*ts_current_free)(void *) = free; 36 | 37 | void ts_set_allocator( 38 | void *(*new_malloc)(size_t), 39 | void *(*new_calloc)(size_t, size_t), 40 | void *(*new_realloc)(void *, size_t), 41 | void (*new_free)(void *) 42 | ) { 43 | ts_current_malloc = new_malloc ? new_malloc : ts_malloc_default; 44 | ts_current_calloc = new_calloc ? new_calloc : ts_calloc_default; 45 | ts_current_realloc = new_realloc ? new_realloc : ts_realloc_default; 46 | ts_current_free = new_free ? new_free : free; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /tree_sitter/lib/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ALLOC_H_ 2 | #define TREE_SITTER_ALLOC_H_ 3 | 4 | #include "api.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | extern void *(*ts_current_malloc)(size_t); 15 | extern void *(*ts_current_calloc)(size_t, size_t); 16 | extern void *(*ts_current_realloc)(void *, size_t); 17 | extern void (*ts_current_free)(void *); 18 | 19 | // Allow clients to override allocation functions 20 | #ifndef ts_malloc 21 | #define ts_malloc ts_current_malloc 22 | #endif 23 | #ifndef ts_calloc 24 | #define ts_calloc ts_current_calloc 25 | #endif 26 | #ifndef ts_realloc 27 | #define ts_realloc ts_current_realloc 28 | #endif 29 | #ifndef ts_free 30 | #define ts_free ts_current_free 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif // TREE_SITTER_ALLOC_H_ 38 | -------------------------------------------------------------------------------- /tree_sitter/lib/error_costs.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ERROR_COSTS_H_ 2 | #define TREE_SITTER_ERROR_COSTS_H_ 3 | 4 | #define ERROR_STATE 0 5 | #define ERROR_COST_PER_RECOVERY 500 6 | #define ERROR_COST_PER_MISSING_TREE 110 7 | #define ERROR_COST_PER_SKIPPED_TREE 100 8 | #define ERROR_COST_PER_SKIPPED_LINE 30 9 | #define ERROR_COST_PER_SKIPPED_CHAR 1 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /tree_sitter/lib/get_changed_ranges.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_GET_CHANGED_RANGES_H_ 2 | #define TREE_SITTER_GET_CHANGED_RANGES_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./tree_cursor.h" 9 | #include "./subtree.h" 10 | 11 | typedef Array(TSRange) TSRangeArray; 12 | 13 | void ts_range_array_get_changed_ranges( 14 | const TSRange *old_ranges, unsigned old_range_count, 15 | const TSRange *new_ranges, unsigned new_range_count, 16 | TSRangeArray *differences 17 | ); 18 | 19 | bool ts_range_array_intersects( 20 | const TSRangeArray *self, unsigned start_index, 21 | uint32_t start_byte, uint32_t end_byte 22 | ); 23 | 24 | unsigned ts_subtree_get_changed_ranges( 25 | const Subtree *old_tree, const Subtree *new_tree, 26 | TreeCursor *cursor1, TreeCursor *cursor2, 27 | const TSLanguage *language, 28 | const TSRangeArray *included_range_differences, 29 | TSRange **ranges 30 | ); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif // TREE_SITTER_GET_CHANGED_RANGES_H_ 37 | -------------------------------------------------------------------------------- /tree_sitter/lib/host.h: -------------------------------------------------------------------------------- 1 | 2 | // Determine endian and pointer size based on known defines. 3 | // TS_BIG_ENDIAN and TS_PTR_SIZE can be set as -D compiler arguments 4 | // to override this. 5 | 6 | #if !defined(TS_BIG_ENDIAN) 7 | #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \ 8 | || (defined( __APPLE_CC__) && (defined(__ppc__) || defined(__ppc64__))) 9 | #define TS_BIG_ENDIAN 1 10 | #else 11 | #define TS_BIG_ENDIAN 0 12 | #endif 13 | #endif 14 | 15 | #if !defined(TS_PTR_SIZE) 16 | #if UINTPTR_MAX == 0xFFFFFFFF 17 | #define TS_PTR_SIZE 32 18 | #else 19 | #define TS_PTR_SIZE 64 20 | #endif 21 | #endif 22 | -------------------------------------------------------------------------------- /tree_sitter/lib/length.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_LENGTH_H_ 2 | #define TREE_SITTER_LENGTH_H_ 3 | 4 | #include 5 | #include 6 | #include "./point.h" 7 | #include "api.h" 8 | 9 | typedef struct { 10 | uint32_t bytes; 11 | TSPoint extent; 12 | } Length; 13 | 14 | static const Length LENGTH_UNDEFINED = {0, {0, 1}}; 15 | static const Length LENGTH_MAX = {UINT32_MAX, {UINT32_MAX, UINT32_MAX}}; 16 | 17 | static inline bool length_is_undefined(Length length) { 18 | return length.bytes == 0 && length.extent.column != 0; 19 | } 20 | 21 | static inline Length length_min(Length len1, Length len2) { 22 | return (len1.bytes < len2.bytes) ? len1 : len2; 23 | } 24 | 25 | static inline Length length_add(Length len1, Length len2) { 26 | Length result; 27 | result.bytes = len1.bytes + len2.bytes; 28 | result.extent = point_add(len1.extent, len2.extent); 29 | return result; 30 | } 31 | 32 | static inline Length length_sub(Length len1, Length len2) { 33 | Length result; 34 | result.bytes = len1.bytes - len2.bytes; 35 | result.extent = point_sub(len1.extent, len2.extent); 36 | return result; 37 | } 38 | 39 | static inline Length length_zero(void) { 40 | Length result = {0, {0, 0}}; 41 | return result; 42 | } 43 | 44 | static inline Length length_saturating_sub(Length len1, Length len2) { 45 | if (len1.bytes > len2.bytes) { 46 | return length_sub(len1, len2); 47 | } else { 48 | return length_zero(); 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /tree_sitter/lib/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_LEXER_H_ 2 | #define TREE_SITTER_LEXER_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./length.h" 9 | #include "./subtree.h" 10 | #include "api.h" 11 | #include "parser.h" 12 | 13 | typedef struct { 14 | TSLexer data; 15 | Length current_position; 16 | Length token_start_position; 17 | Length token_end_position; 18 | 19 | TSRange *included_ranges; 20 | const char *chunk; 21 | TSInput input; 22 | TSLogger logger; 23 | 24 | uint32_t included_range_count; 25 | uint32_t current_included_range_index; 26 | uint32_t chunk_start; 27 | uint32_t chunk_size; 28 | uint32_t lookahead_size; 29 | bool did_get_column; 30 | 31 | char debug_buffer[TREE_SITTER_SERIALIZATION_BUFFER_SIZE]; 32 | } Lexer; 33 | 34 | void ts_lexer_init(Lexer *); 35 | void ts_lexer_delete(Lexer *); 36 | void ts_lexer_set_input(Lexer *, TSInput); 37 | void ts_lexer_reset(Lexer *, Length); 38 | void ts_lexer_start(Lexer *); 39 | void ts_lexer_finish(Lexer *, uint32_t *); 40 | void ts_lexer_advance_to_end(Lexer *); 41 | void ts_lexer_mark_end(Lexer *); 42 | bool ts_lexer_set_included_ranges(Lexer *self, const TSRange *ranges, uint32_t count); 43 | TSRange *ts_lexer_included_ranges(const Lexer *self, uint32_t *count); 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif // TREE_SITTER_LEXER_H_ 50 | -------------------------------------------------------------------------------- /tree_sitter/lib/lib.c: -------------------------------------------------------------------------------- 1 | // The Tree-sitter library can be built by compiling this one source file. 2 | // 3 | // The following directories must be added to the include path: 4 | // - include 5 | 6 | #define _POSIX_C_SOURCE 200112L 7 | 8 | #include "./alloc.c" 9 | #include "./get_changed_ranges.c" 10 | #include "./language.c" 11 | #include "./lexer.c" 12 | #include "./node.c" 13 | #include "./parser.c" 14 | #include "./query.c" 15 | #include "./stack.c" 16 | #include "./subtree.c" 17 | #include "./tree_cursor.c" 18 | #include "./tree.c" 19 | -------------------------------------------------------------------------------- /tree_sitter/lib/point.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_POINT_H_ 2 | #define TREE_SITTER_POINT_H_ 3 | 4 | #include "api.h" 5 | 6 | #define POINT_ZERO ((TSPoint) {0, 0}) 7 | #define POINT_MAX ((TSPoint) {UINT32_MAX, UINT32_MAX}) 8 | 9 | static inline TSPoint point__new(unsigned row, unsigned column) { 10 | TSPoint result = {row, column}; 11 | return result; 12 | } 13 | 14 | static inline TSPoint point_add(TSPoint a, TSPoint b) { 15 | if (b.row > 0) 16 | return point__new(a.row + b.row, b.column); 17 | else 18 | return point__new(a.row, a.column + b.column); 19 | } 20 | 21 | static inline TSPoint point_sub(TSPoint a, TSPoint b) { 22 | if (a.row > b.row) 23 | return point__new(a.row - b.row, a.column); 24 | else 25 | return point__new(0, a.column - b.column); 26 | } 27 | 28 | static inline bool point_lte(TSPoint a, TSPoint b) { 29 | return (a.row < b.row) || (a.row == b.row && a.column <= b.column); 30 | } 31 | 32 | static inline bool point_lt(TSPoint a, TSPoint b) { 33 | return (a.row < b.row) || (a.row == b.row && a.column < b.column); 34 | } 35 | 36 | static inline bool point_gt(TSPoint a, TSPoint b) { 37 | return (a.row > b.row) || (a.row == b.row && a.column > b.column); 38 | } 39 | 40 | static inline bool point_gte(TSPoint a, TSPoint b) { 41 | return (a.row > b.row) || (a.row == b.row && a.column >= b.column); 42 | } 43 | 44 | static inline bool point_eq(TSPoint a, TSPoint b) { 45 | return a.row == b.row && a.column == b.column; 46 | } 47 | 48 | static inline TSPoint point_min(TSPoint a, TSPoint b) { 49 | if (a.row < b.row || (a.row == b.row && a.column < b.column)) 50 | return a; 51 | else 52 | return b; 53 | } 54 | 55 | static inline TSPoint point_max(TSPoint a, TSPoint b) { 56 | if (a.row > b.row || (a.row == b.row && a.column > b.column)) 57 | return a; 58 | else 59 | return b; 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /tree_sitter/lib/reduce_action.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_REDUCE_ACTION_H_ 2 | #define TREE_SITTER_REDUCE_ACTION_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include "./array.h" 9 | #include "api.h" 10 | 11 | typedef struct { 12 | uint32_t count; 13 | TSSymbol symbol; 14 | int dynamic_precedence; 15 | unsigned short production_id; 16 | } ReduceAction; 17 | 18 | typedef Array(ReduceAction) ReduceActionSet; 19 | 20 | static inline void ts_reduce_action_set_add(ReduceActionSet *self, 21 | ReduceAction new_action) { 22 | for (uint32_t i = 0; i < self->size; i++) { 23 | ReduceAction action = self->contents[i]; 24 | if (action.symbol == new_action.symbol && action.count == new_action.count) 25 | return; 26 | } 27 | array_push(self, new_action); 28 | } 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif // TREE_SITTER_REDUCE_ACTION_H_ 35 | -------------------------------------------------------------------------------- /tree_sitter/lib/tree.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_TREE_H_ 2 | #define TREE_SITTER_TREE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { 9 | const Subtree *child; 10 | const Subtree *parent; 11 | Length position; 12 | TSSymbol alias_symbol; 13 | } ParentCacheEntry; 14 | 15 | struct TSTree { 16 | Subtree root; 17 | const TSLanguage *language; 18 | TSRange *included_ranges; 19 | unsigned included_range_count; 20 | }; 21 | 22 | TSTree *ts_tree_new(Subtree root, const TSLanguage *language, const TSRange *, unsigned); 23 | TSNode ts_node_new(const TSTree *, const Subtree *, Length, TSSymbol); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif // TREE_SITTER_TREE_H_ 30 | -------------------------------------------------------------------------------- /tree_sitter/lib/tree_cursor.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_TREE_CURSOR_H_ 2 | #define TREE_SITTER_TREE_CURSOR_H_ 3 | 4 | #include "./subtree.h" 5 | 6 | typedef struct { 7 | const Subtree *subtree; 8 | Length position; 9 | uint32_t child_index; 10 | uint32_t structural_child_index; 11 | } TreeCursorEntry; 12 | 13 | typedef struct { 14 | const TSTree *tree; 15 | Array(TreeCursorEntry) stack; 16 | } TreeCursor; 17 | 18 | void ts_tree_cursor_init(TreeCursor *, TSNode); 19 | void ts_tree_cursor_current_status( 20 | const TSTreeCursor *, 21 | TSFieldId *, 22 | bool *, 23 | bool *, 24 | bool *, 25 | TSSymbol *, 26 | unsigned * 27 | ); 28 | 29 | TSNode ts_tree_cursor_parent_node(const TSTreeCursor *); 30 | 31 | #endif // TREE_SITTER_TREE_CURSOR_H_ 32 | -------------------------------------------------------------------------------- /tree_sitter/lib/ts_atomic.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_ATOMIC_H_ 2 | #define TREE_SITTER_ATOMIC_H_ 3 | 4 | #include 5 | 6 | #ifdef __TINYC__ 7 | 8 | static inline size_t ts_atomic_load(const volatile size_t *p) { 9 | return *p; 10 | } 11 | 12 | static inline uint32_t ts_atomic_inc(volatile uint32_t *p) { 13 | *p += 1; 14 | return *p; 15 | } 16 | 17 | static inline uint32_t ts_atomic_dec(volatile uint32_t *p) { 18 | *p-= 1; 19 | return *p; 20 | } 21 | 22 | #elif defined(_WIN32) 23 | 24 | #include 25 | 26 | static inline size_t ts_atomic_load(const volatile size_t *p) { 27 | return *p; 28 | } 29 | 30 | static inline uint32_t ts_atomic_inc(volatile uint32_t *p) { 31 | return InterlockedIncrement((long volatile *)p); 32 | } 33 | 34 | static inline uint32_t ts_atomic_dec(volatile uint32_t *p) { 35 | return InterlockedDecrement((long volatile *)p); 36 | } 37 | 38 | #else 39 | 40 | static inline size_t ts_atomic_load(const volatile size_t *p) { 41 | #ifdef __ATOMIC_RELAXED 42 | return __atomic_load_n(p, __ATOMIC_RELAXED); 43 | #else 44 | return __sync_fetch_and_add((volatile size_t *)p, 0); 45 | #endif 46 | } 47 | 48 | static inline uint32_t ts_atomic_inc(volatile uint32_t *p) { 49 | return __sync_add_and_fetch(p, 1u); 50 | } 51 | 52 | static inline uint32_t ts_atomic_dec(volatile uint32_t *p) { 53 | return __sync_sub_and_fetch(p, 1u); 54 | } 55 | 56 | #endif 57 | 58 | #endif // TREE_SITTER_ATOMIC_H_ 59 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode.h: -------------------------------------------------------------------------------- 1 | #ifndef TREE_SITTER_UNICODE_H_ 2 | #define TREE_SITTER_UNICODE_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | #define U_EXPORT 12 | #define U_EXPORT2 13 | #include "unicode/utf8.h" 14 | #include "unicode/utf16.h" 15 | 16 | static const int32_t TS_DECODE_ERROR = U_SENTINEL; 17 | 18 | // These functions read one unicode code point from the given string, 19 | // returning the number of bytes consumed. 20 | typedef uint32_t (*UnicodeDecodeFunction)( 21 | const uint8_t *string, 22 | uint32_t length, 23 | int32_t *code_point 24 | ); 25 | 26 | static inline uint32_t ts_decode_utf8( 27 | const uint8_t *string, 28 | uint32_t length, 29 | int32_t *code_point 30 | ) { 31 | uint32_t i = 0; 32 | U8_NEXT(string, i, length, *code_point); 33 | return i; 34 | } 35 | 36 | static inline uint32_t ts_decode_utf16( 37 | const uint8_t *string, 38 | uint32_t length, 39 | int32_t *code_point 40 | ) { 41 | uint32_t i = 0; 42 | U16_NEXT(((uint16_t *)string), i, length, *code_point); 43 | return i * 2; 44 | } 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif // TREE_SITTER_UNICODE_H_ 51 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode/ICU_SHA: -------------------------------------------------------------------------------- 1 | 552b01f61127d30d6589aa4bf99468224979b661 2 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode/README.md: -------------------------------------------------------------------------------- 1 | # ICU Parts 2 | 3 | This directory contains a small subset of files from the Unicode organization's [ICU repository](https://github.com/unicode-org/icu). 4 | 5 | ### License 6 | 7 | The license for these files is contained in the `LICENSE` file within this directory. 8 | 9 | ### Contents 10 | 11 | * Source files taken from the [`icu4c/source/common/unicode`](https://github.com/unicode-org/icu/tree/552b01f61127d30d6589aa4bf99468224979b661/icu4c/source/common/unicode) directory: 12 | * `utf8.h` 13 | * `utf16.h` 14 | * `umachine.h` 15 | * Empty source files that are referenced by the above source files, but whose original contents in `libicu` are not needed: 16 | * `ptypes.h` 17 | * `urename.h` 18 | * `utf.h` 19 | * `ICU_SHA` - File containing the Git SHA of the commit in the `icu` repository from which the files were obtained. 20 | * `LICENSE` - The license file from the [`icu4c`](https://github.com/unicode-org/icu/tree/552b01f61127d30d6589aa4bf99468224979b661/icu4c) directory of the `icu` repository. 21 | * `README.md` - This text file. 22 | 23 | ### Updating ICU 24 | 25 | To incorporate changes from the upstream `icu` repository: 26 | 27 | * Update `ICU_SHA` with the new Git SHA. 28 | * Update `LICENSE` with the license text from the directory mentioned above. 29 | * Update `utf8.h`, `utf16.h`, and `umachine.h` with their new contents in the `icu` repository. 30 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode/ptypes.h: -------------------------------------------------------------------------------- 1 | // This file must exist in order for `utf8.h` and `utf16.h` to be used. 2 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode/urename.h: -------------------------------------------------------------------------------- 1 | // This file must exist in order for `utf8.h` and `utf16.h` to be used. 2 | -------------------------------------------------------------------------------- /tree_sitter/lib/unicode/utf.h: -------------------------------------------------------------------------------- 1 | // This file must exist in order for `utf8.h` and `utf16.h` to be used. 2 | -------------------------------------------------------------------------------- /tree_sitter/ts_version.json: -------------------------------------------------------------------------------- 1 | {"version": "439a4804db27988e2e3b5851f9d19ad495aabe2e"} -------------------------------------------------------------------------------- /tree_sitter_v/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: mirror 2 | on: 3 | schedule: 4 | # Trigger mirrors weekly 5 | - cron: 0 0 * * 0 6 | env: 7 | EM_VERSION: 1.39.18 8 | EM_CACHE_FOLDER: "emsdk-cache" 9 | 10 | jobs: 11 | mirror-to-repo: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Clone VLS 16 | run: git clone --depth=1 https://github.com/vlang/vls ../vls 17 | # Does not matter (for now) if the repo is updated than the one in vls. 18 | - name: Diff vls/tree_sitter_v and tree-sitter-v repo 19 | continue-on-error: true 20 | run: | 21 | diff -qr ../vls/tree_sitter_v . 22 | if (( $? == "1" )); then echo "Differences found. Pushing updates to tree-sitter-v repo..."; else exit 1 fi 23 | - name: Copy contents from vls/tree_sitter_v 24 | if: ${{ success() }} 25 | run: | 26 | git rm -rf . 27 | git clean -fxd 28 | cp -a ../vls/tree_sitter_v/. . 29 | - name: Commit changes 30 | if: ${{ success() }} 31 | uses: EndBug/add-and-commit@v7 32 | with: 33 | message: 'Updated parser from https://github.com/vlang/vls repo' 34 | add: '.' 35 | - name: Push changes 36 | if: ${{ success() }} 37 | uses: ad-m/github-push-action@master 38 | with: 39 | github_token: ${{ secrets.GH_TOKEN }} 40 | branch: ${{ github.ref }} -------------------------------------------------------------------------------- /tree_sitter_v/.gitignore: -------------------------------------------------------------------------------- 1 | # Avoid including irrelevant files 2 | node_modules/ 3 | *.log 4 | build/ 5 | .vscode 6 | package-lock.json 7 | .DS_Store 8 | 9 | # Ignore local files used for testing and development 10 | hello.v 11 | hello.vv 12 | hello2.v 13 | src/binding.v 14 | wasm/ 15 | grammar (old).js 16 | 17 | target/ 18 | Cargo.lock 19 | -------------------------------------------------------------------------------- /tree_sitter_v/.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | tools/ 3 | node_modules/ -------------------------------------------------------------------------------- /tree_sitter_v/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tree-sitter-v" 3 | description = "v grammar for the tree-sitter parsing library" 4 | version = "0.0.1" 5 | keywords = ["incremental", "parsing", "v"] 6 | categories = ["parsing", "text-editors"] 7 | repository = "https://github.com/tree-sitter/tree-sitter-javascript" 8 | edition = "2018" 9 | license = "MIT" 10 | 11 | build = "bindings/rust/build.rs" 12 | include = [ 13 | "bindings/rust/*", 14 | "grammar.js", 15 | "queries/*", 16 | "src/*", 17 | ] 18 | 19 | [lib] 20 | path = "bindings/rust/lib.rs" 21 | 22 | [dependencies] 23 | tree-sitter = "0.17" 24 | 25 | [build-dependencies] 26 | cc = "1.0" 27 | -------------------------------------------------------------------------------- /tree_sitter_v/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ned Palacios 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tree_sitter_v/README.md: -------------------------------------------------------------------------------- 1 | # tree-sitter-v 2 | V language grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter) 3 | 4 | [![build/test](https://github.com/nedpals/tree-sitter-v/actions/workflows/ci.yml/badge.svg)](https://github.com/nedpals/tree-sitter-v/actions/workflows/ci.yml) 5 | ![report-badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/nedpals/a5d2f238264b49f2c0301eaf799a0e7c/raw/report-badge-data.json) 6 | 7 | ## Existing grammars 8 | This grammar is heavily derived from the following language grammars: 9 | 10 | - [tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go) 11 | - [tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby/) 12 | - [tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c/) 13 | 14 | ## Installation 15 | ``` 16 | npm install tree-sitter-v 17 | ``` 18 | 19 | ## Usage [(node-tree-sitter)](https://github.com/tree-sitter/node-tree-sitter) 20 | ```javascript 21 | const Parser = require('tree-sitter'); 22 | const V = require('tree-sitter-v'); 23 | 24 | const parser = new Parser(); 25 | parser.setLanguage(V); 26 | ``` 27 | 28 | ## Usage with V [v-tree-sitter (soon)] 29 | ```v 30 | // TODO: 31 | import treesitter 32 | import tree_sitter_v.bindings.v 33 | 34 | fn main() { 35 | mut parser := treesitter.new_parser() 36 | parser.set_language(v.language) 37 | } 38 | ``` 39 | 40 | ## Limitations 41 | 1. It does not support all deprecated/outdated syntaxes to avoid any ambiguities and to enforce the one-way philosophy as much as possible. 42 | 2. Assembly/SQL code in ASM/SQL block nodes are loosely checked and parsed immediately regardless of the content. 43 | 3. Syntaxes specific for implementing JS and native compilation support are not and will not be implemented unless a consensus has been reached. Features from "Compiler magic" are being generalized into different nodes as much as possible. -------------------------------------------------------------------------------- /tree_sitter_v/binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "tree_sitter_v_binding", 5 | "include_dirs": [ 6 | " 3 | #include "nan.h" 4 | 5 | using namespace v8; 6 | 7 | extern "C" TSLanguage * tree_sitter_v(); 8 | 9 | namespace { 10 | 11 | NAN_METHOD(New) {} 12 | 13 | void Init(Local exports, Local module) { 14 | Local tpl = Nan::New(New); 15 | tpl->SetClassName(Nan::New("Language").ToLocalChecked()); 16 | tpl->InstanceTemplate()->SetInternalFieldCount(1); 17 | 18 | Local constructor = Nan::GetFunction(tpl).ToLocalChecked(); 19 | Local instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked(); 20 | Nan::SetInternalFieldPointer(instance, 0, tree_sitter_v()); 21 | 22 | Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("v").ToLocalChecked()); 23 | Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance); 24 | } 25 | 26 | NODE_MODULE(tree_sitter_v_binding, Init) 27 | 28 | } // namespace 29 | -------------------------------------------------------------------------------- /tree_sitter_v/bindings/node/index.js: -------------------------------------------------------------------------------- 1 | try { 2 | module.exports = require("../../build/Release/tree_sitter_v_binding"); 3 | } catch (error1) { 4 | if (error1.code !== 'MODULE_NOT_FOUND') { 5 | throw error1; 6 | } 7 | try { 8 | module.exports = require("../../build/Debug/tree_sitter_v_binding"); 9 | } catch (error2) { 10 | if (error2.code !== 'MODULE_NOT_FOUND') { 11 | throw error2; 12 | } 13 | throw error1 14 | } 15 | } 16 | 17 | try { 18 | module.exports.nodeTypeInfo = require("../../src/node-types.json"); 19 | } catch (_) {} 20 | -------------------------------------------------------------------------------- /tree_sitter_v/bindings/rust/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let src_dir = std::path::Path::new("src"); 3 | 4 | let mut c_config = cc::Build::new(); 5 | c_config.include(&src_dir); 6 | c_config 7 | .flag_if_supported("-Wno-unused-parameter") 8 | .flag_if_supported("-Wno-unused-but-set-variable") 9 | .flag_if_supported("-Wno-trigraphs"); 10 | let parser_path = src_dir.join("parser.c"); 11 | c_config.file(&parser_path); 12 | 13 | // If your language uses an external scanner written in C, 14 | // then include this block of code: 15 | 16 | /* 17 | let scanner_path = src_dir.join("scanner.c"); 18 | c_config.file(&scanner_path); 19 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 20 | */ 21 | 22 | c_config.compile("parser"); 23 | println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); 24 | 25 | // If your language uses an external scanner written in C++, 26 | // then include this block of code: 27 | 28 | /* 29 | let mut cpp_config = cc::Build::new(); 30 | cpp_config.cpp(true); 31 | cpp_config.include(&src_dir); 32 | cpp_config 33 | .flag_if_supported("-Wno-unused-parameter") 34 | .flag_if_supported("-Wno-unused-but-set-variable"); 35 | let scanner_path = src_dir.join("scanner.cc"); 36 | cpp_config.file(&scanner_path); 37 | cpp_config.compile("scanner"); 38 | println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); 39 | */ 40 | } 41 | -------------------------------------------------------------------------------- /tree_sitter_v/bindings/v/bindings.h: -------------------------------------------------------------------------------- 1 | #include "tree_sitter/parser.h" 2 | 3 | TSLanguage * tree_sitter_v(); 4 | -------------------------------------------------------------------------------- /tree_sitter_v/bindings/v/bindings.v: -------------------------------------------------------------------------------- 1 | module v 2 | 3 | import x.json2 4 | import os 5 | 6 | #flag -I @VMODROOT/src 7 | #flag @VMODROOT/src/parser.o 8 | 9 | #include "@VMODROOT/bindings/v/bindings.h" 10 | 11 | fn C.tree_sitter_v() &C.TSLanguage 12 | 13 | pub const language = unsafe { C.tree_sitter_v() } 14 | 15 | // load_node_types reads the node-types.json file for static analysis. 16 | pub fn load_node_types() ?[]json2.Any { 17 | contents := os.read_file(os.join_path(@VMODROOT, 'src', 'node-types.json'))? 18 | list := json2.raw_decode(contents)? 19 | return list.arr() 20 | } 21 | -------------------------------------------------------------------------------- /tree_sitter_v/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree-sitter-v", 3 | "version": "1.0.7", 4 | "main": "bindings/node", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/nedpals/tree-sitter-v.git" 9 | }, 10 | "scripts": { 11 | "test": "tree-sitter test", 12 | "generate-scanner": "v -shared -skip-unused -o src/scanner.c scanner/", 13 | "generate-types": "v generate_types.vsh", 14 | "generate": "tree-sitter generate", 15 | "parse": "tree-sitter parse", 16 | "parseg": "tree-sitter parse --debug-graph" 17 | }, 18 | "homepage": "https://github.com/nedpals/tree-sitter-v#readme", 19 | "dependencies": { 20 | "nan": "^2.14.0" 21 | }, 22 | "devDependencies": { 23 | "chalk": "^4.1.1", 24 | "glob": "^7.1.7", 25 | "minimist": "^1.2.5", 26 | "tree-sitter": "^0.20.0", 27 | "tree-sitter-cli": "^0.20.0" 28 | }, 29 | "tree-sitter": [ 30 | { 31 | "scope": "source.v", 32 | "file-types": [ 33 | "v", 34 | "vsh", 35 | "v.mod" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/array.txt: -------------------------------------------------------------------------------- 1 | === 2 | Array with Values 3 | === 4 | 5 | fn main() { 6 | test := ['hello', 'world!'] 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (array 20 | (interpreted_string_literal) 21 | (interpreted_string_literal))))))) 22 | 23 | === 24 | Array with no values 25 | === 26 | 27 | fn main() { 28 | an = [] 29 | } 30 | 31 | --- 32 | 33 | (source_file 34 | (function_declaration 35 | (identifier) 36 | (parameter_list) 37 | (block 38 | (assignment_statement 39 | (expression_list (identifier)) 40 | (expression_list (array)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/array_fixed.txt: -------------------------------------------------------------------------------- 1 | === 2 | Fixed Array 3 | === 4 | 5 | fn main() { 6 | fixed := [1]! 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (fixed_array (int_literal))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/as_type_cast_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | As Cast Expression 3 | === 4 | 5 | fn main() { 6 | dummy := hello as ast.Foo 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (as_type_cast_expression 20 | (identifier) 21 | (qualified_type (module_identifier) (type_identifier)))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/asm_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | ASM Statement 3 | === 4 | 5 | asm amd64 { 6 | mov rcx, 5 // loop 5 times 7 | loop_start: 8 | add j, 3 9 | loop loop_start 10 | ; +r (j) 11 | ; ; rcx 12 | } 13 | 14 | --- 15 | 16 | (source_file 17 | (asm_statement (identifier))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/assert_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Assert Statement 3 | === 4 | 5 | assert a == b 6 | 7 | --- 8 | 9 | (source_file 10 | (assert_statement 11 | (binary_expression 12 | (identifier) 13 | (identifier)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/assignment_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Assignment Statement 3 | === 4 | 5 | fn main() { 6 | a = 1 7 | a := 1 8 | a, b = 1, 2 9 | a, b := 1, 2 10 | } 11 | 12 | --- 13 | 14 | (source_file 15 | (function_declaration 16 | (identifier) 17 | (parameter_list) 18 | (block 19 | (assignment_statement 20 | (expression_list 21 | (identifier)) 22 | (expression_list 23 | (int_literal))) 24 | (short_var_declaration 25 | (expression_list 26 | (identifier)) 27 | (expression_list 28 | (int_literal))) 29 | (assignment_statement 30 | (expression_list 31 | (identifier) 32 | (identifier)) 33 | (expression_list 34 | (int_literal) 35 | (int_literal))) 36 | (short_var_declaration 37 | (expression_list 38 | (identifier) 39 | (identifier)) 40 | (expression_list 41 | (int_literal) 42 | (int_literal)))))) 43 | 44 | === 45 | Pointer Assignment 46 | === 47 | 48 | mut ap := &u64(a) 49 | *ap = size 50 | 51 | --- 52 | 53 | (source_file 54 | (short_var_declaration 55 | (expression_list 56 | (mutable_expression (identifier))) 57 | (expression_list 58 | (type_cast_expression 59 | (pointer_type (builtin_type)) 60 | (identifier)))) 61 | (assignment_statement 62 | (expression_list 63 | (unary_expression (identifier))) 64 | (expression_list (identifier)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/binary_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Binary Expression 3 | === 4 | 5 | pub fn should_bundle_module(mod string) bool { 6 | return mod in util.bundle_modules 7 | || (mod.contains('.') && mod.all_before('.') in util.bundle_modules) 8 | } 9 | 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list 17 | (parameter_declaration 18 | (identifier) 19 | (builtin_type))) 20 | (builtin_type) 21 | (block 22 | (return_statement 23 | (expression_list 24 | (binary_expression 25 | (binary_expression 26 | (identifier) 27 | (selector_expression 28 | (identifier) (identifier))) 29 | (parenthesized_expression 30 | (binary_expression 31 | (call_expression 32 | (selector_expression 33 | (identifier) (identifier)) 34 | (argument_list 35 | (interpreted_string_literal))) 36 | (binary_expression 37 | (call_expression 38 | (selector_expression 39 | (identifier) (identifier)) 40 | (argument_list 41 | (interpreted_string_literal))) 42 | (selector_expression 43 | (identifier) (identifier))))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/binary_expression_receive.txt: -------------------------------------------------------------------------------- 1 | === 2 | Binary Expression (Receive) 3 | === 4 | 5 | test = <- foo 6 | 7 | --- 8 | 9 | (source_file 10 | (assignment_statement 11 | (expression_list (identifier)) 12 | (expression_list 13 | (unary_expression (identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/bit_not.txt: -------------------------------------------------------------------------------- 1 | === 2 | Bitwise Not 3 | === 4 | 5 | assert ~4 == -5 6 | 7 | --- 8 | 9 | (source_file 10 | (assert_statement 11 | (binary_expression 12 | (unary_expression 13 | (int_literal)) 14 | (unary_expression 15 | (int_literal))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/c_fn_call.txt: -------------------------------------------------------------------------------- 1 | ============= 2 | C Function Call 3 | ============= 4 | 5 | C.abc(123) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (binded_identifier (identifier)) 12 | (argument_list (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/c_fn_decl.txt: -------------------------------------------------------------------------------- 1 | ============= 2 | C Function Definition 3 | ============= 4 | 5 | fn C.abc() 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (binded_identifier (identifier)) 12 | (parameter_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/call_expression_embed.txt: -------------------------------------------------------------------------------- 1 | === 2 | Call Expression (Embed Comptime) 3 | === 4 | 5 | const const_file = $embed_file('v.png') 6 | 7 | --- 8 | 9 | (source_file 10 | (const_declaration 11 | (const_spec 12 | (identifier) 13 | (call_expression 14 | (comptime_identifier 15 | (identifier)) 16 | (argument_list (interpreted_string_literal)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/cast_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Cast Expression 3 | === 4 | 5 | fn main() { 6 | t := &char(charp) 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_cast_expression 20 | (pointer_type (builtin_type)) 21 | (identifier))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/comptime_for_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Comptime For Statement 3 | === 4 | 5 | $for field in App.fields { 6 | println(field) 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (comptime_for_statement 13 | (for_in_operator 14 | (identifier_list (identifier)) 15 | (type_selector_expression (type_identifier) (identifier))) 16 | (block 17 | (call_expression 18 | (identifier) 19 | (argument_list (identifier)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/comptime_identifier.txt: -------------------------------------------------------------------------------- 1 | === 2 | Comptime Identifier (for Comptime Call) 3 | === 4 | 5 | t.$method(1) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (selector_expression 12 | (identifier) 13 | (comptime_identifier (identifier))) 14 | (argument_list (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/comptime_if_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Comptime If Expression 3 | === 4 | 5 | $if windows {} 6 | 7 | $if gc_boehm ? {} $else $if foo {} $else {} 8 | 9 | $if T is Foo {} 10 | 11 | --- 12 | 13 | (source_file 14 | (comptime_if_expression 15 | (identifier) (block)) 16 | (comptime_if_expression 17 | (identifier) 18 | (block) 19 | (comptime_if_expression 20 | (identifier) 21 | (block) 22 | (block))) 23 | (comptime_if_expression 24 | (is_expression 25 | (type_placeholder) (type_identifier)) 26 | (block))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/comptime_selector_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Comptime Selector Expression 3 | === 4 | 5 | println(t.$(field.name)) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (identifier) 12 | (argument_list 13 | (selector_expression 14 | (identifier) 15 | (comptime_selector_expression 16 | (selector_expression 17 | (identifier) (identifier))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/const_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Const declaration 3 | === 4 | 5 | const ( 6 | name = 'Foo' 7 | num = 100 8 | ) 9 | 10 | --- 11 | 12 | (source_file 13 | (const_declaration 14 | (const_spec (identifier) (interpreted_string_literal)) 15 | (const_spec (identifier) (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/const_declaration_pub.txt: -------------------------------------------------------------------------------- 1 | === 2 | Public const declaration 3 | === 4 | 5 | pub const ( 6 | name = 'Foo' 7 | num = 100 8 | ) 9 | 10 | --- 11 | 12 | (source_file 13 | (const_declaration 14 | (const_spec (identifier) (interpreted_string_literal)) 15 | (const_spec (identifier) (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/const_declaration_single.txt: -------------------------------------------------------------------------------- 1 | === 2 | Single-line const declaration 3 | === 4 | 5 | const name = 'Foo' 6 | 7 | --- 8 | 9 | (source_file 10 | (const_declaration 11 | (const_spec (identifier) (interpreted_string_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/const_declaration_single_multi.txt: -------------------------------------------------------------------------------- 1 | === 2 | Multiple single-line const declaration 3 | === 4 | 5 | const name = 'Foo' 6 | const num = 100 7 | 8 | --- 9 | 10 | (source_file 11 | (const_declaration 12 | (const_spec (identifier) (interpreted_string_literal))) 13 | (const_declaration 14 | (const_spec (identifier) (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/defer_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Defer Statement 3 | === 4 | 5 | fn main() { 6 | defer { 7 | function_call() 8 | } 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (defer_statement 19 | (block 20 | (call_expression 21 | (identifier) 22 | (argument_list))))))) 23 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/empty_function.txt: -------------------------------------------------------------------------------- 1 | === 2 | Empty Function 3 | === 4 | 5 | fn abc(i int) f64 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (identifier) 12 | (parameter_list 13 | (parameter_declaration 14 | (identifier) 15 | (builtin_type))) 16 | (builtin_type))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/empty_labelled_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Empty Labeled Statement 3 | === 4 | 5 | fn main() { 6 | testlabel: 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (labeled_statement (label_name))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/enum_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Enum declaration 3 | === 4 | 5 | enum Color { 6 | red = 1 7 | blue 8 | yellow 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (enum_declaration 15 | (type_identifier) 16 | (enum_member_declaration_list 17 | (enum_member (identifier) (int_literal)) 18 | (enum_member (identifier)) 19 | (enum_member (identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/enum_declaration_pub.txt: -------------------------------------------------------------------------------- 1 | === 2 | Public enum declaration 3 | === 4 | 5 | pub enum Color { 6 | blue 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (enum_declaration 13 | (type_identifier) 14 | (enum_member_declaration_list 15 | (enum_member (identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/float_literal.txt: -------------------------------------------------------------------------------- 1 | === 2 | Float Literal 3 | === 4 | 5 | const foo = 100.0 6 | 7 | --- 8 | 9 | (source_file 10 | (const_declaration 11 | (const_spec 12 | (identifier) (float_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/fn_literal.txt: -------------------------------------------------------------------------------- 1 | === 2 | Function Literal 3 | === 4 | 5 | fn main() { 6 | app.handle(fn (req &Req, res Res) ? { 7 | return 8 | }) 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (call_expression 19 | (selector_expression (identifier) (identifier)) 20 | (argument_list 21 | (fn_literal 22 | (parameter_list 23 | (parameter_declaration 24 | (identifier) 25 | (pointer_type (type_identifier))) 26 | (parameter_declaration 27 | (identifier) (type_identifier))) 28 | (option_type) 29 | (block (return_statement)))))))) 30 | 31 | === 32 | Function Literal with Closures 33 | === 34 | 35 | fn main() { 36 | app.handle(fn [foo, bar] (req &Req, res Res) ? { 37 | return 38 | }) 39 | } 40 | 41 | --- 42 | 43 | (source_file 44 | (function_declaration 45 | (identifier) 46 | (parameter_list) 47 | (block 48 | (call_expression 49 | (selector_expression (identifier) (identifier)) 50 | (argument_list 51 | (fn_literal 52 | (exposed_variables_list 53 | (expression_list 54 | (identifier) (identifier))) 55 | (parameter_list 56 | (parameter_declaration 57 | (identifier) 58 | (pointer_type (type_identifier))) 59 | (parameter_declaration 60 | (identifier) (type_identifier))) 61 | (option_type) 62 | (block (return_statement)))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/for_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | For Statement 3 | === 4 | 5 | fn main() { 6 | for true { 7 | // do something 8 | } 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (for_statement 19 | (true) 20 | (block (comment)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/for_statement_cstyle.txt: -------------------------------------------------------------------------------- 1 | === 2 | C-Style For Statement 3 | === 4 | 5 | fn main() { 6 | for i := 0; i < 10; i++ { 7 | println(i) 8 | } 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (for_statement 19 | (cstyle_for_clause 20 | (short_var_declaration 21 | (expression_list (identifier)) 22 | (expression_list (int_literal))) 23 | (binary_expression (identifier) (int_literal)) 24 | (inc_statement (identifier))) 25 | (block 26 | (call_expression 27 | (identifier) 28 | (argument_list (identifier)))))))) 29 | 30 | === 31 | C-Style For Statement without Update Statement 32 | === 33 | 34 | for i := 0; i < start_column; { 35 | if test {} else {} 36 | } 37 | 38 | --- 39 | 40 | (source_file 41 | (for_statement 42 | (cstyle_for_clause 43 | (short_var_declaration 44 | (expression_list (identifier)) 45 | (expression_list (int_literal))) 46 | (binary_expression (identifier) (identifier))) 47 | (block 48 | (if_expression (identifier) (block) (block))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/for_statement_in.txt: -------------------------------------------------------------------------------- 1 | === 2 | For-in Statement 3 | === 4 | 5 | fn main() { 6 | for v in arr {} 7 | for k, v in mp {} 8 | for i in 0 .. 10 {} 9 | } 10 | --- 11 | 12 | (source_file 13 | (function_declaration 14 | (identifier) 15 | (parameter_list) 16 | (block 17 | (for_statement 18 | (for_in_operator 19 | (identifier_list (identifier)) 20 | (identifier)) 21 | (block)) 22 | (for_statement 23 | (for_in_operator 24 | (identifier_list (identifier) (identifier)) 25 | (identifier)) 26 | (block)) 27 | (for_statement 28 | (for_in_operator 29 | (identifier_list (identifier)) 30 | (range (int_literal) (int_literal))) 31 | (block))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/function_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Function Declaration 3 | === 4 | 5 | fn hello_world(mut s []string, i int, words ...Text) ? {} 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (identifier) 12 | (parameter_list 13 | (parameter_declaration 14 | (mutable_identifier (identifier)) 15 | (array_type (builtin_type))) 16 | (parameter_declaration (identifier) (builtin_type)) 17 | (parameter_declaration 18 | (identifier) 19 | (variadic_type (type_identifier)))) 20 | (option_type) 21 | (block))) 22 | 23 | === 24 | Function Definition 25 | === 26 | 27 | fn C.PQerrorMessage(voidptr) &byte 28 | 29 | --- 30 | 31 | (source_file 32 | (function_declaration 33 | (binded_identifier (identifier)) 34 | (type_only_parameter_list 35 | (type_parameter_declaration (builtin_type))) 36 | (pointer_type (builtin_type)))) 37 | 38 | === 39 | Function Declaration with Closures 40 | === 41 | 42 | fn [foo, bar] hello_world() {} 43 | 44 | --- 45 | 46 | (source_file 47 | (function_declaration 48 | (exposed_variables_list 49 | (expression_list 50 | (identifier) (identifier))) 51 | (identifier) 52 | (parameter_list) 53 | (block))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/function_declaration_generic.txt: -------------------------------------------------------------------------------- 1 | === 2 | Generic function Declaration 3 | === 4 | 5 | fn hello_world(mut s []T, i int, words ...Text) ? {} 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (identifier) 12 | (type_parameters (type_placeholder)) 13 | (parameter_list 14 | (parameter_declaration 15 | (mutable_identifier (identifier)) 16 | (array_type (type_placeholder))) 17 | (parameter_declaration (identifier) (builtin_type)) 18 | (parameter_declaration 19 | (identifier) 20 | (variadic_type (type_identifier)))) 21 | (option_type) 22 | (block))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/function_overload.txt: -------------------------------------------------------------------------------- 1 | === 2 | Function Overload 3 | === 4 | 5 | fn (t Test) == (t Test) Test {} 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (parameter_list 12 | (parameter_declaration 13 | (identifier) (type_identifier))) 14 | (overloadable_operator) 15 | (parameter_list 16 | (parameter_declaration 17 | (identifier) (type_identifier))) 18 | (type_identifier) 19 | (block))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/function_type.txt: -------------------------------------------------------------------------------- 1 | === 2 | Function Type 3 | === 4 | 5 | type Handler = fn (req Req, res &Res) ?string 6 | 7 | fn new(key []u8, data []u8, hash_func fn ([]u8) []u8, blocksize int) []u8 {} 8 | 9 | fn test() fn(i int) ?(string, int) {} 10 | 11 | --- 12 | 13 | (source_file 14 | (type_declaration 15 | (type_identifier) 16 | (type_list 17 | (function_type 18 | (parameter_list 19 | (parameter_declaration 20 | (identifier) (type_identifier)) 21 | (parameter_declaration 22 | (identifier) 23 | (pointer_type (type_identifier)))) 24 | (option_type (builtin_type))))) 25 | (function_declaration 26 | (identifier) 27 | (parameter_list 28 | (parameter_declaration 29 | (identifier) (array_type (builtin_type))) 30 | (parameter_declaration 31 | (identifier) (array_type (builtin_type))) 32 | (parameter_declaration 33 | (identifier) 34 | (function_type 35 | (type_only_parameter_list 36 | (type_parameter_declaration 37 | (array_type (builtin_type)))) 38 | (array_type (builtin_type)))) 39 | (parameter_declaration 40 | (identifier) (builtin_type))) 41 | (array_type (builtin_type)) 42 | (block)) 43 | (function_declaration 44 | (identifier) 45 | (parameter_list) 46 | (function_type 47 | (parameter_list 48 | (parameter_declaration 49 | (identifier) (builtin_type))) 50 | (option_type 51 | (multi_return_type 52 | (builtin_type) (builtin_type)))) 53 | (block))) 54 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/global_var_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Global Variables 3 | === 4 | 5 | __global x = bool(true) 6 | __global y f32 7 | __global () 8 | __global ( 9 | spam string 10 | foo = int(5) 11 | ) 12 | __global ( 13 | a int 14 | ) 15 | 16 | --- 17 | 18 | (source_file 19 | (global_var_declaration 20 | (global_var_spec 21 | (identifier) 22 | (type_cast_expression 23 | (builtin_type) 24 | (true)))) 25 | (global_var_declaration 26 | (global_var_type_initializer 27 | (identifier) (builtin_type))) 28 | (global_var_declaration) 29 | (global_var_declaration 30 | (global_var_type_initializer 31 | (identifier) (builtin_type)) 32 | (global_var_spec 33 | (identifier) 34 | (type_cast_expression 35 | (builtin_type) 36 | (int_literal)))) 37 | (global_var_declaration 38 | (global_var_type_initializer 39 | (identifier) (builtin_type)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/go_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Go Statement 3 | === 4 | 5 | fn main() { 6 | go do_something() 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (go_statement 17 | (call_expression (identifier) (argument_list)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/goto_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Goto Statement 3 | === 4 | 5 | goto foo 6 | 7 | --- 8 | 9 | (source_file 10 | (goto_statement (label_name))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/if_expression_is.txt: -------------------------------------------------------------------------------- 1 | === 2 | If Expression is guard 3 | === 4 | 5 | fn main() { 6 | if var is string { 7 | // do something 8 | } 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (if_expression 19 | (is_expression (identifier) (builtin_type)) 20 | (block (comment)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/if_expression_var.txt: -------------------------------------------------------------------------------- 1 | === 2 | If Expression var declaration 3 | === 4 | 5 | fn main() { 6 | if foo := opt_fn() { 7 | // do something 8 | } 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (function_declaration 15 | (identifier) 16 | (parameter_list) 17 | (block 18 | (if_expression 19 | (short_var_declaration 20 | (expression_list (identifier)) 21 | (expression_list 22 | (call_expression 23 | (identifier) 24 | (argument_list)))) 25 | (block (comment)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/import_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Import declaration 3 | === 4 | 5 | import v.ast 6 | 7 | --- 8 | 9 | (source_file 10 | (import_declaration (import_path))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/import_declaration_symbols.txt: -------------------------------------------------------------------------------- 1 | === 2 | Import declaration with selected symbols 3 | === 4 | 5 | import json { decode, encode, Any } 6 | 7 | --- 8 | 9 | (source_file 10 | (import_declaration 11 | (import_path) 12 | (import_symbols 13 | (import_symbols_list 14 | (identifier) 15 | (identifier) 16 | (identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/import_declaratoin_alias.txt: -------------------------------------------------------------------------------- 1 | === 2 | Import declaration with alias 3 | === 4 | 5 | import x.json2 as json 6 | 7 | --- 8 | 9 | (source_file 10 | (import_declaration 11 | (import_path) 12 | (import_alias (module_identifier)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/index_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Index Expression 3 | === 4 | 5 | fn main() { 6 | test := hello[0] 7 | opt := hello[1]? 8 | opt2 := hello[two] or { 9 | return 10 | } 11 | } 12 | 13 | --- 14 | 15 | (source_file 16 | (function_declaration 17 | (identifier) 18 | (parameter_list) 19 | (block 20 | (short_var_declaration 21 | (expression_list (identifier)) 22 | (expression_list 23 | (index_expression (identifier) (int_literal)))) 24 | (short_var_declaration 25 | (expression_list (identifier)) 26 | (expression_list 27 | (index_expression 28 | (identifier) 29 | (int_literal) 30 | (option_propagator)))) 31 | (short_var_declaration 32 | (expression_list (identifier)) 33 | (expression_list 34 | (index_expression 35 | (identifier) 36 | (identifier) 37 | (option_propagator 38 | (or_block 39 | (block 40 | (return_statement)))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/interface_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Interface declaration 3 | === 4 | 5 | interface Speaker { 6 | speak() 7 | mut: 8 | speak_message(name string) string 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (interface_declaration 15 | (type_identifier) 16 | (interface_spec_list 17 | (interface_spec (field_identifier) (parameter_list)) 18 | (interface_field_scope) 19 | (interface_spec 20 | (field_identifier) 21 | (parameter_list 22 | (parameter_declaration (identifier) (builtin_type))) 23 | (builtin_type))))) 24 | 25 | === 26 | Generic Interface Declaration 27 | === 28 | 29 | interface Iterator { 30 | next() ?T 31 | } 32 | 33 | --- 34 | 35 | (source_file 36 | (interface_declaration 37 | (generic_type 38 | (type_identifier) 39 | (type_parameters (type_placeholder))) 40 | (interface_spec_list 41 | (interface_spec 42 | (field_identifier) 43 | (parameter_list) 44 | (option_type (type_placeholder)))))) 45 | 46 | === 47 | Interface Decl with Type-Only Param Spec 48 | === 49 | 50 | interface Handler { 51 | handle(Request) Response 52 | } 53 | 54 | --- 55 | 56 | (source_file 57 | (interface_declaration 58 | (type_identifier) 59 | (interface_spec_list 60 | (interface_spec 61 | (field_identifier) 62 | (type_only_parameter_list 63 | (type_parameter_declaration (type_identifier))) 64 | (type_identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/interface_declaration_embed.txt: -------------------------------------------------------------------------------- 1 | === 2 | Interface declaration with embed 3 | === 4 | 5 | interface Speaker { 6 | Talker 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (interface_declaration 13 | (type_identifier) 14 | (interface_spec_list 15 | (struct_field_declaration (type_identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/interface_declaration_field.txt: -------------------------------------------------------------------------------- 1 | === 2 | Interface declaration with struct field 3 | === 4 | 5 | interface Speaker { 6 | name string 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (interface_declaration 13 | (type_identifier) 14 | (interface_spec_list 15 | (struct_field_declaration (field_identifier) (builtin_type))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/interface_declaration_pub.txt: -------------------------------------------------------------------------------- 1 | === 2 | Public interface declaration 3 | === 4 | 5 | pub interface Speaker {} 6 | 7 | --- 8 | 9 | (source_file 10 | (interface_declaration 11 | (type_identifier) 12 | (interface_spec_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/interpreted_string_literal_interp.txt: -------------------------------------------------------------------------------- 1 | === 2 | Interpreted String Literal with Interpolation 3 | === 4 | 5 | const a = 'Hello $world! ${hello.hey} ${path.join('')}' 6 | 7 | --- 8 | 9 | (source_file 10 | (const_declaration 11 | (const_spec 12 | (identifier) 13 | (interpreted_string_literal 14 | (string_interpolation (identifier)) 15 | (string_interpolation 16 | (selector_expression 17 | (identifier) (identifier))) 18 | (string_interpolation 19 | (call_expression 20 | (selector_expression 21 | (identifier) (identifier)) 22 | (argument_list (interpreted_string_literal)))))))) 23 | 24 | === 25 | Interpreted String Literal with Escaped Interp Character 26 | === 27 | 28 | exec('docker container rm -f $(docker container ls -aq)') or {} 29 | 30 | --- 31 | 32 | (source_file 33 | (call_expression 34 | (identifier) 35 | (argument_list 36 | (interpreted_string_literal)) 37 | (option_propagator 38 | (or_block (block))))) 39 | 40 | === 41 | Comment inside string Literal 42 | === 43 | 44 | '//' 45 | 46 | --- 47 | 48 | (source_file 49 | (interpreted_string_literal)) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/js_fn_call.txt: -------------------------------------------------------------------------------- 1 | ============= 2 | JS Function Call 3 | ============= 4 | 5 | JS.abc(123) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (binded_identifier (identifier)) 12 | (argument_list (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/js_fn_decl.txt: -------------------------------------------------------------------------------- 1 | ============= 2 | JS Function Definition 3 | ============= 4 | 5 | fn JS.abc() 6 | 7 | --- 8 | 9 | (source_file 10 | (function_declaration 11 | (binded_identifier (identifier)) 12 | (parameter_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/labeled_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Labeled Statement 3 | === 4 | 5 | label: for {} 6 | 7 | --- 8 | 9 | (source_file 10 | (labeled_statement 11 | (label_name) 12 | (for_statement (block)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/lock.txt: -------------------------------------------------------------------------------- 1 | === 2 | Lock Statement 3 | === 4 | 5 | lock a, b { 6 | a++ 7 | b-- 8 | } 9 | 10 | lock {} 11 | 12 | --- 13 | 14 | (source_file 15 | (lock_expression 16 | (expression_list 17 | (identifier) 18 | (identifier)) 19 | (block 20 | (inc_statement 21 | (identifier)) 22 | (dec_statement 23 | (identifier)))) 24 | (lock_expression (block))) 25 | 26 | === 27 | Read Lock Statement 28 | === 29 | 30 | rlock a, b { 31 | a++ 32 | b-- 33 | } 34 | 35 | --- 36 | 37 | (source_file 38 | (lock_expression 39 | (expression_list 40 | (identifier) 41 | (identifier)) 42 | (block 43 | (inc_statement 44 | (identifier)) 45 | (dec_statement 46 | (identifier))))) 47 | 48 | === 49 | Lock Expression 50 | === 51 | 52 | x := rlock a, b { a + b } 53 | 54 | --- 55 | 56 | (source_file 57 | (short_var_declaration 58 | (expression_list 59 | (identifier)) 60 | (expression_list 61 | (lock_expression 62 | (expression_list 63 | (identifier) 64 | (identifier)) 65 | (block 66 | (binary_expression 67 | (identifier) 68 | (identifier))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/map.txt: -------------------------------------------------------------------------------- 1 | === 2 | Map Literal 3 | === 4 | 5 | { 6 | 'hello': 'world!', 7 | 1: 'one', 8 | foo: bar 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (map 15 | (keyed_element 16 | (interpreted_string_literal) 17 | (interpreted_string_literal)) 18 | (keyed_element 19 | (int_literal) (interpreted_string_literal)) 20 | (keyed_element (field_identifier) (identifier)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/match_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Match Expression 3 | === 4 | 5 | fn main() { 6 | match a { 7 | 'test', '123' {} 8 | 'xd' {} 9 | else {} 10 | } 11 | 12 | match b { 13 | int, string {} 14 | []Any {} 15 | else {} 16 | } 17 | } 18 | 19 | --- 20 | 21 | (source_file 22 | (function_declaration 23 | (identifier) 24 | (parameter_list) 25 | (block 26 | (match_expression 27 | (identifier) 28 | (expression_case 29 | (case_list 30 | (interpreted_string_literal) 31 | (interpreted_string_literal)) 32 | (block)) 33 | (expression_case 34 | (case_list 35 | (interpreted_string_literal)) 36 | (block)) 37 | (default_case (block))) 38 | (match_expression 39 | (identifier) 40 | (expression_case 41 | (case_list (builtin_type) (builtin_type)) 42 | (block)) 43 | (expression_case 44 | (case_list (array_type (type_identifier))) 45 | (block)) 46 | (default_case (block)))))) 47 | 48 | === 49 | Match with range 50 | === 51 | 52 | match b { 53 | 0 {} 54 | 32...126 {} 55 | else {} 56 | } 57 | 58 | --- 59 | 60 | (source_file 61 | (match_expression 62 | (identifier) 63 | (expression_case 64 | (case_list 65 | (int_literal)) 66 | (block)) 67 | (expression_case 68 | (case_list (range 69 | (int_literal) 70 | (int_literal))) 71 | (block)) 72 | (default_case 73 | (block)))) 74 | 75 | === 76 | Match with mixed expression and range 77 | === 78 | 79 | match b { 80 | 33, 35...39, 42 { true } 81 | else { false } 82 | } 83 | 84 | --- 85 | 86 | (source_file 87 | (match_expression 88 | (identifier) 89 | (expression_case 90 | (case_list 91 | (int_literal) 92 | (range (int_literal) (int_literal)) 93 | (int_literal)) 94 | (block (true))) 95 | (default_case (block (false))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/module_clause.txt: -------------------------------------------------------------------------------- 1 | ============= 2 | Module clause 3 | ============= 4 | 5 | [manualfree][foo] 6 | module main_123 7 | 8 | --- 9 | 10 | (source_file 11 | (module_clause 12 | (attribute_list 13 | (attribute_declaration 14 | (attribute_spec (identifier))) 15 | (attribute_declaration 16 | (attribute_spec (identifier)))) 17 | (module_identifier))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/multi_return_type.txt: -------------------------------------------------------------------------------- 1 | === 2 | Multi-return type 3 | === 4 | 5 | fn hello() (string, string) {} 6 | fn hello2() ?(int, f32) {} 7 | 8 | --- 9 | 10 | (source_file 11 | (function_declaration 12 | (identifier) 13 | (parameter_list) 14 | (multi_return_type 15 | (builtin_type) (builtin_type)) 16 | (block)) 17 | (function_declaration 18 | (identifier) 19 | (parameter_list) 20 | (option_type 21 | (multi_return_type 22 | (builtin_type) (builtin_type))) 23 | (block))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/mutable_argument.txt: -------------------------------------------------------------------------------- 1 | === 2 | Mutable function argument 3 | === 4 | 5 | block(mut d, mut &a, d.x) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (identifier) 12 | (argument_list 13 | (mutable_expression 14 | (identifier)) 15 | (mutable_expression 16 | (unary_expression 17 | (identifier))) 18 | (selector_expression 19 | (identifier) 20 | (identifier))))) 21 | 22 | === 23 | Mutable slice expression argument 24 | === 25 | 26 | binary.big_endian_put_u64(mut tmp[8..], len) 27 | 28 | 29 | --- 30 | 31 | (source_file 32 | (call_expression 33 | (selector_expression 34 | (identifier) 35 | (identifier)) 36 | (argument_list 37 | (mutable_expression 38 | (slice_expression 39 | (identifier) 40 | (int_literal))) 41 | (identifier)))) 42 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/mutable_match_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Match Expression with Mutable Identifier 3 | === 4 | 5 | fn main() { 6 | match mut a { 7 | 'test', '123' { 8 | a := 'test pass' 9 | } 10 | 'xd' {} 11 | else {} 12 | } 13 | } 14 | 15 | --- 16 | 17 | (source_file 18 | (function_declaration 19 | (identifier) 20 | (parameter_list) 21 | (block 22 | (match_expression 23 | (mutable_expression 24 | (identifier)) 25 | (expression_case 26 | (case_list 27 | (interpreted_string_literal) 28 | (interpreted_string_literal)) 29 | (block 30 | (short_var_declaration 31 | (expression_list 32 | (identifier)) 33 | (expression_list 34 | (interpreted_string_literal))))) 35 | (expression_case 36 | (case_list 37 | (interpreted_string_literal)) 38 | (block)) 39 | (default_case (block)))))) 40 | 41 | === 42 | Match expression with mutable struct field 43 | === 44 | 45 | match mut ts.info { 46 | Statement {} 47 | else {} 48 | } 49 | 50 | --- 51 | 52 | (source_file 53 | (match_expression 54 | (mutable_expression 55 | (selector_expression 56 | (identifier) 57 | (identifier))) 58 | (expression_case 59 | (case_list 60 | (type_identifier)) 61 | (block)) 62 | (default_case 63 | (block)))) 64 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/pseudo_comptime_identifier.txt: -------------------------------------------------------------------------------- 1 | === 2 | Pseudo-comptime Identifier 3 | === 4 | 5 | println(@VMOD) 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (identifier) 12 | (argument_list 13 | (pseudo_comptime_identifier (identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/qualified_type.txt: -------------------------------------------------------------------------------- 1 | === 2 | Qualified Type 3 | === 4 | 5 | const foo = time.Time{} 6 | 7 | fn main() { 8 | test := log.Logger{} 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (const_declaration 15 | (const_spec 16 | (identifier) 17 | (type_initializer 18 | (qualified_type 19 | (module_identifier) (type_identifier)) 20 | (literal_value)))) 21 | (function_declaration 22 | (identifier) 23 | (parameter_list) 24 | (block 25 | (short_var_declaration 26 | (expression_list (identifier)) 27 | (expression_list 28 | (type_initializer 29 | (qualified_type 30 | (module_identifier) (type_identifier)) 31 | (literal_value))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/relational_operator.txt: -------------------------------------------------------------------------------- 1 | === 2 | Relation Operator 3 | === 4 | 5 | foo := hello !in foo 6 | if foo in bar {} 7 | println(boo !is Foo) 8 | 9 | --- 10 | 11 | (source_file 12 | (short_var_declaration 13 | (expression_list (identifier)) 14 | (expression_list 15 | (binary_expression 16 | (identifier) (identifier)))) 17 | (if_expression 18 | (binary_expression 19 | (identifier) (identifier)) 20 | (block)) 21 | (call_expression 22 | (identifier) 23 | (argument_list 24 | (is_expression 25 | (identifier) (type_identifier))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/return_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Return Statement 3 | === 4 | 5 | fn foo() int { 6 | return 1 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (builtin_type) 16 | (block 17 | (return_statement 18 | (expression_list 19 | (int_literal)))))) 20 | 21 | === 22 | Multi-return statement 23 | === 24 | 25 | fn some_fn() ([]string, ModFileAndFolder) { 26 | return []string{}, res 27 | } 28 | 29 | --- 30 | 31 | (source_file 32 | (function_declaration 33 | (identifier) 34 | (parameter_list) 35 | (multi_return_type 36 | (array_type 37 | (builtin_type)) 38 | (type_identifier)) 39 | (block 40 | (return_statement 41 | (expression_list 42 | (type_initializer 43 | (array_type 44 | (builtin_type)) 45 | (literal_value)) 46 | (identifier)))))) 47 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/rune_literal.txt: -------------------------------------------------------------------------------- 1 | === 2 | Rune Literal 3 | === 4 | 5 | const a = `h` 6 | 7 | --- 8 | 9 | (source_file 10 | (const_declaration 11 | (const_spec 12 | (identifier) (rune_literal)))) 13 | 14 | === 15 | Unescaped quote 16 | === 17 | 18 | if !(ch == `'` || ch == `"`) { 19 | } 20 | 21 | 22 | --- 23 | 24 | (source_file 25 | (if_expression 26 | (unary_expression 27 | (parenthesized_expression 28 | (binary_expression 29 | (binary_expression 30 | (identifier) 31 | (rune_literal)) 32 | (binary_expression 33 | (identifier) 34 | (rune_literal))))) 35 | (block))) 36 | 37 | === 38 | \0 and \` rune literals 39 | === 40 | 41 | a := `\0` 42 | b := `\`` 43 | 44 | --- 45 | 46 | (source_file 47 | (short_var_declaration 48 | (expression_list 49 | (identifier)) 50 | (expression_list 51 | (rune_literal))) 52 | (short_var_declaration 53 | (expression_list 54 | (identifier)) 55 | (expression_list 56 | (rune_literal)))) 57 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/select_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Select Expression 3 | === 4 | 5 | fn main() { 6 | select { 7 | b := <-ch1 { 8 | println(b) 9 | } 10 | > 30 * time.millisecond { 11 | println('bad') 12 | } 13 | } 14 | 15 | // TODO: 16 | // for select { 17 | // b := <-ch2 { 18 | // h = 0 19 | // } 20 | // } { 21 | // println('ch2 open') 22 | // } 23 | 24 | // if select { 25 | // b := <-ch2 { 26 | // h = 0 27 | // } 28 | // else { 29 | // h = 2 30 | // } 31 | // } { 32 | // panic('channel is still open') 33 | // } else { 34 | // is_open = false 35 | // } 36 | } 37 | 38 | --- 39 | 40 | (source_file 41 | (function_declaration 42 | (identifier) 43 | (parameter_list) 44 | (block 45 | (select_expression 46 | (select_branch 47 | (short_var_declaration 48 | (expression_list (identifier)) 49 | (expression_list (unary_expression (identifier)))) 50 | (block 51 | (call_expression 52 | (identifier) 53 | (argument_list (identifier))))) 54 | (select_default_branch 55 | (binary_expression 56 | (int_literal) 57 | (selector_expression 58 | (identifier) (identifier))) 59 | (block 60 | (call_expression 61 | (identifier) 62 | (argument_list 63 | (interpreted_string_literal)))))) 64 | (comment) 65 | (comment) 66 | (comment) 67 | (comment) 68 | (comment) 69 | (comment) 70 | (comment) 71 | (comment) 72 | (comment) 73 | (comment) 74 | (comment) 75 | (comment) 76 | (comment) 77 | (comment) 78 | (comment) 79 | (comment) 80 | (comment) 81 | (comment) 82 | (comment) 83 | (comment)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/selector_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Selector Expression 3 | === 4 | 5 | fn main() { 6 | test.foo 7 | hello := world.bar 8 | } 9 | 10 | --- 11 | 12 | (source_file 13 | (function_declaration 14 | (identifier) 15 | (parameter_list) 16 | (block 17 | (selector_expression 18 | (identifier) (identifier)) 19 | (short_var_declaration 20 | (expression_list (identifier)) 21 | (expression_list 22 | (selector_expression 23 | (identifier) (identifier))))))) 24 | === 25 | Embedded Selector Expression 26 | === 27 | 28 | fn main() { 29 | test.Foo.hello() 30 | hello := world.Bar 31 | } 32 | 33 | --- 34 | 35 | (source_file 36 | (function_declaration 37 | (identifier) 38 | (parameter_list) 39 | (block 40 | (call_expression 41 | (selector_expression 42 | (selector_expression 43 | (identifier) (type_identifier)) 44 | (identifier)) 45 | (argument_list)) 46 | (short_var_declaration 47 | (expression_list (identifier)) 48 | (expression_list 49 | (selector_expression 50 | (identifier) (type_identifier))))))) 51 | 52 | === 53 | Comptime Selector Expression 54 | === 55 | 56 | { 57 | return $vweb.html() 58 | } 59 | 60 | --- 61 | 62 | (source_file 63 | (block 64 | (return_statement 65 | (expression_list 66 | (call_expression 67 | (selector_expression 68 | (comptime_identifier (identifier)) 69 | (identifier)) 70 | (argument_list)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/selector_expression_incomplete.txt: -------------------------------------------------------------------------------- 1 | === 2 | Incomplete selector expression 3 | === 4 | 5 | fn main() { 6 | incomplete.sel. 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (selector_expression 17 | (identifier) (identifier)) 18 | (ERROR)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/send_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Send Statement 3 | === 4 | 5 | ch := chan int{cap: 1} 6 | ch <- n 7 | 8 | --- 9 | 10 | (source_file 11 | (short_var_declaration 12 | (expression_list (identifier)) 13 | (expression_list 14 | (type_initializer 15 | (channel_type (builtin_type)) 16 | (literal_value 17 | (keyed_element 18 | (field_identifier) (int_literal)))))) 19 | (send_statement 20 | (identifier) (identifier))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/short_var_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Short Variable Declaration 3 | === 4 | 5 | fn main() { 6 | foo, bar := 'foo', 'bar' 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list 18 | (identifier) 19 | (identifier)) 20 | (expression_list 21 | (interpreted_string_literal) 22 | (interpreted_string_literal)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/slice_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Slice Expression 3 | === 4 | 5 | fn main() { 6 | hello[0..1] 7 | hello[..1] 8 | hello[0..] 9 | hello[wat+1..] 10 | } 11 | 12 | --- 13 | 14 | (source_file 15 | (function_declaration 16 | (identifier) 17 | (parameter_list) 18 | (block 19 | (slice_expression 20 | (identifier) 21 | (int_literal) 22 | (int_literal)) 23 | (slice_expression 24 | (identifier) (int_literal)) 25 | (slice_expression 26 | (identifier) (int_literal)) 27 | (slice_expression 28 | (identifier) 29 | (binary_expression 30 | (identifier) (int_literal)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/spawn_statement.txt: -------------------------------------------------------------------------------- 1 | === 2 | Spawn Statement 3 | === 4 | 5 | fn main() { 6 | spawn do_something() 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (spawn_statement 17 | (call_expression (identifier) (argument_list)))))) 18 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/spread_operator.txt: -------------------------------------------------------------------------------- 1 | === 2 | Spread Operator 3 | === 4 | 5 | t := Struct{ 6 | ...p 7 | foo: 1 8 | } 9 | 10 | --- 11 | 12 | (source_file 13 | (short_var_declaration 14 | (expression_list (identifier)) 15 | (expression_list 16 | (type_initializer 17 | (type_identifier) 18 | (literal_value 19 | (spread_operator (identifier)) 20 | (keyed_element 21 | (field_identifier) (int_literal))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/sql_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | SQL Expression 3 | === 4 | 5 | second_oldest := sql db { 6 | select from User order by age desc limit 1 offset offs 7 | } 8 | 9 | sql db { 10 | delete from User where age == 34 11 | } 12 | 13 | --- 14 | 15 | (source_file 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (sql_expression (identifier)))) 20 | (sql_expression (identifier))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/string_interpolation_format_specifier.txt: -------------------------------------------------------------------------------- 1 | === 2 | String Interpolation with Format Specifiers 3 | === 4 | 5 | '${10:10o}' 6 | '${a:-10}' 7 | '${b:10.3f}' 8 | '${c:010.4g}' 9 | 10 | --- 11 | 12 | (source_file 13 | (interpreted_string_literal 14 | (string_interpolation 15 | (int_literal) 16 | (format_specifier 17 | (int_literal)))) 18 | (interpreted_string_literal 19 | (string_interpolation 20 | (identifier) 21 | (format_specifier 22 | (int_literal)))) 23 | (interpreted_string_literal 24 | (string_interpolation 25 | (identifier) 26 | (format_specifier 27 | (int_literal) 28 | (int_literal)))) 29 | (interpreted_string_literal 30 | (string_interpolation 31 | (identifier) 32 | (format_specifier 33 | (int_literal) 34 | (int_literal))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/string_literal.txt: -------------------------------------------------------------------------------- 1 | === 2 | C String Literal 3 | === 4 | 5 | println(c'hello $world \r') 6 | 7 | --- 8 | 9 | (source_file 10 | (call_expression 11 | (identifier) 12 | (argument_list 13 | (c_string_literal 14 | (string_interpolation (identifier)) 15 | (escape_sequence))))) 16 | 17 | 18 | === 19 | Raw string Literal 20 | === 21 | 22 | println(r'\r\awr') 23 | 24 | --- 25 | 26 | (source_file 27 | (call_expression 28 | (identifier) 29 | (argument_list (raw_string_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration.txt: -------------------------------------------------------------------------------- 1 | ================== 2 | Struct declaration 3 | ================== 4 | 5 | struct Hello { 6 | hidden string 7 | pub: 8 | foo string [json:'foo'] = 'hey' 9 | bar int = 10 10 | pub mut: 11 | baz int 12 | __global: 13 | blu i64 14 | } 15 | 16 | --- 17 | 18 | (source_file 19 | (struct_declaration 20 | (type_identifier) 21 | (struct_field_declaration_list 22 | (struct_field_declaration 23 | (field_identifier) (builtin_type)) 24 | (struct_field_scope) 25 | (struct_field_declaration 26 | (field_identifier) 27 | (builtin_type) 28 | (attribute_declaration 29 | (attribute_spec (identifier) (interpreted_string_literal))) 30 | (interpreted_string_literal)) 31 | (struct_field_declaration 32 | (field_identifier) (builtin_type) (int_literal)) 33 | (struct_field_scope) 34 | (struct_field_declaration 35 | (field_identifier) (builtin_type)) 36 | (struct_field_scope) 37 | (struct_field_declaration 38 | (field_identifier) (builtin_type))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration_embed.txt: -------------------------------------------------------------------------------- 1 | === 2 | Struct declaration with embedded type 3 | === 4 | 5 | struct Stmt { 6 | ast.Node 7 | Foo 8 | name string 9 | } 10 | 11 | --- 12 | 13 | (source_file 14 | (struct_declaration 15 | (type_identifier) 16 | (struct_field_declaration_list 17 | (struct_field_declaration 18 | (qualified_type 19 | (module_identifier) (type_identifier))) 20 | (struct_field_declaration (type_identifier)) 21 | (struct_field_declaration 22 | (field_identifier) (builtin_type))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration_generic.txt: -------------------------------------------------------------------------------- 1 | === 2 | Generic struct declaration 3 | === 4 | 5 | struct Hello {} 6 | 7 | --- 8 | 9 | (source_file 10 | (struct_declaration 11 | (generic_type 12 | (type_identifier) 13 | (type_parameters 14 | (type_placeholder) 15 | (type_placeholder))) 16 | (struct_field_declaration_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration_pub.txt: -------------------------------------------------------------------------------- 1 | === 2 | Public struct declaration 3 | === 4 | 5 | pub struct Hello {} 6 | 7 | --- 8 | 9 | (source_file 10 | (struct_declaration 11 | (type_identifier) 12 | (struct_field_declaration_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration_typedef_c.txt: -------------------------------------------------------------------------------- 1 | === 2 | C typedef struct declaration 3 | === 4 | 5 | struct C.sqlite3 {} 6 | 7 | --- 8 | 9 | (source_file 10 | (struct_declaration 11 | (binded_type (identifier)) 12 | (struct_field_declaration_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/struct_declaration_typedef_js.txt: -------------------------------------------------------------------------------- 1 | === 2 | JS typedef struct declaration 3 | === 4 | 5 | struct JS.Document {} 6 | 7 | --- 8 | 9 | (source_file 10 | (struct_declaration 11 | (binded_type (identifier)) 12 | (struct_field_declaration_list))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_declaration.txt: -------------------------------------------------------------------------------- 1 | === 2 | Type declaration 3 | === 4 | 5 | type Text = string 6 | 7 | --- 8 | 9 | (source_file 10 | (type_declaration 11 | (type_identifier) 12 | (type_list (builtin_type)))) 13 | 14 | === 15 | Generic Type Declaration 16 | === 17 | 18 | type MyOption = Error | None | T 19 | 20 | --- 21 | 22 | (source_file 23 | (type_declaration 24 | (type_identifier) 25 | (type_parameters (type_placeholder)) 26 | (type_list 27 | (type_identifier) 28 | (type_identifier) 29 | (type_placeholder)))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_declaration_sum_type.txt: -------------------------------------------------------------------------------- 1 | === 2 | Sum type declaration 3 | === 4 | 5 | type Stmt = StructDecl | EnumDecl | ast.FnDecl 6 | 7 | --- 8 | 9 | (source_file 10 | (type_declaration 11 | (type_identifier) 12 | (type_list 13 | (type_identifier) 14 | (type_identifier) 15 | (qualified_type 16 | (module_identifier) (type_identifier))))) 17 | 18 | === 19 | Builtin type redefinition 20 | === 21 | 22 | type u8 = byte 23 | 24 | --- 25 | 26 | (source_file 27 | (type_declaration 28 | (builtin_type) 29 | (type_list 30 | (builtin_type)))) 31 | -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer.txt: -------------------------------------------------------------------------------- 1 | === 2 | Type Initializer 3 | === 4 | 5 | fn main() { 6 | t := Test{hello: 'world!'} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (type_identifier) 21 | (literal_value 22 | (keyed_element (field_identifier) (interpreted_string_literal))))))))) 23 | 24 | === 25 | Type Initializer with Embedded Field 26 | === 27 | 28 | Hello{ 29 | World: World{} 30 | } 31 | 32 | --- 33 | 34 | (source_file 35 | (type_initializer 36 | (type_identifier) 37 | (literal_value 38 | (keyed_element 39 | (type_identifier) 40 | (type_initializer 41 | (type_identifier) 42 | (literal_value)))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_array.txt: -------------------------------------------------------------------------------- 1 | === 2 | Array Initializer 3 | === 4 | 5 | fn main() { 6 | test := []int{len: 10, cap: 10, init: 1} 7 | } 8 | 9 | 10 | --- 11 | 12 | (source_file 13 | (function_declaration 14 | (identifier) 15 | (parameter_list) 16 | (block 17 | (short_var_declaration 18 | (expression_list (identifier)) 19 | (expression_list 20 | (type_initializer 21 | (array_type (builtin_type)) 22 | (literal_value 23 | (keyed_element (field_identifier) (int_literal)) 24 | (keyed_element (field_identifier) (int_literal)) 25 | (keyed_element (field_identifier) (int_literal))))))))) 26 | 27 | === 28 | Fixed Array Initializer 29 | === 30 | test := [1]int{} 31 | 32 | --- 33 | 34 | (source_file 35 | (short_var_declaration 36 | (expression_list (identifier)) 37 | (expression_list 38 | (type_initializer 39 | (fixed_array_type 40 | (int_literal) (builtin_type)) 41 | (literal_value))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_binded.txt: -------------------------------------------------------------------------------- 1 | === 2 | Binded Type Initializer 3 | === 4 | 5 | fn main() { 6 | t := C.TSPoint{1, 2} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (binded_type (identifier)) 21 | (literal_value 22 | (element (int_literal)) 23 | (element (int_literal))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_chan.txt: -------------------------------------------------------------------------------- 1 | === 2 | Channel type initializer 3 | === 4 | 5 | fn main() { 6 | t := chan f64{} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (channel_type (builtin_type)) 21 | (literal_value))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_generic.txt: -------------------------------------------------------------------------------- 1 | === 2 | Generic type initializer 3 | === 4 | 5 | fn main() { 6 | t := Test{hello: 'world!'} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (generic_type 21 | (type_identifier) 22 | (type_parameters (builtin_type))) 23 | (literal_value 24 | (keyed_element (field_identifier) (interpreted_string_literal))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_incomplete.txt: -------------------------------------------------------------------------------- 1 | === 2 | Incomplete Type Initializer 3 | === 4 | 5 | fn main() { 6 | t := Test{hello: } 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (type_identifier) 21 | (literal_value 22 | (keyed_element 23 | (field_identifier) 24 | (MISSING identifier))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_map_alt.txt: -------------------------------------------------------------------------------- 1 | === 2 | Map Initializer with alt syntax 3 | === 4 | 5 | fn main() { 6 | test := map{'hello': 'world'} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (builtin_type) 21 | (literal_value 22 | (keyed_element 23 | (interpreted_string_literal) 24 | (interpreted_string_literal))))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_initializer_map_empty.txt: -------------------------------------------------------------------------------- 1 | === 2 | Empty map Initializer 3 | === 4 | 5 | fn main() { 6 | test := map[string]int{} 7 | } 8 | 9 | --- 10 | 11 | (source_file 12 | (function_declaration 13 | (identifier) 14 | (parameter_list) 15 | (block 16 | (short_var_declaration 17 | (expression_list (identifier)) 18 | (expression_list 19 | (type_initializer 20 | (map_type (builtin_type) (builtin_type)) 21 | (literal_value))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/type_selector_expression.txt: -------------------------------------------------------------------------------- 1 | === 2 | Type Selector Expression / Enum Identifier 3 | === 4 | 5 | fn main() { 6 | do_stuff(.red) 7 | foo := Foo{value: .blue} 8 | mut color := Color.blue 9 | color = .yellow 10 | } 11 | 12 | --- 13 | 14 | (source_file 15 | (function_declaration 16 | (identifier) 17 | (parameter_list) 18 | (block 19 | (call_expression 20 | (identifier) 21 | (argument_list 22 | (type_selector_expression (identifier)))) 23 | (short_var_declaration 24 | (expression_list (identifier)) 25 | (expression_list 26 | (type_initializer 27 | (type_identifier) 28 | (literal_value 29 | (keyed_element 30 | (field_identifier) 31 | (type_selector_expression (identifier))))))) 32 | (short_var_declaration 33 | (expression_list 34 | (mutable_expression (identifier))) 35 | (expression_list 36 | (type_selector_expression 37 | (type_identifier) 38 | (identifier)))) 39 | (assignment_statement 40 | (expression_list (identifier)) 41 | (expression_list 42 | (type_selector_expression (identifier))))))) -------------------------------------------------------------------------------- /tree_sitter_v/test/corpus/vsh_mode.txt: -------------------------------------------------------------------------------- 1 | === 2 | VSH / Shell Mode Support 3 | === 4 | 5 | module main 6 | 7 | fn hello() {} 8 | 9 | mut a := 1 10 | 11 | --- 12 | 13 | (source_file 14 | (module_clause (module_identifier)) 15 | (function_declaration 16 | (identifier) 17 | (parameter_list) 18 | (block)) 19 | (short_var_declaration 20 | (expression_list (mutable_expression (identifier))) 21 | (expression_list (int_literal)))) -------------------------------------------------------------------------------- /tree_sitter_v/v.mod: -------------------------------------------------------------------------------- 1 | Module { 2 | name: 'tree-sitter-v' 3 | description: 'Tree sitter grammar for V' 4 | version: '1.0.7-pre' 5 | license: 'MIT' 6 | dependencies: [] 7 | } -------------------------------------------------------------------------------- /v.mod: -------------------------------------------------------------------------------- 1 | Module { 2 | name: 'vls' 3 | description: 'vls is a language server for the V language.' 4 | version: '0.0.1' 5 | dependencies: [] 6 | } --------------------------------------------------------------------------------