Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions .devcontainer/dotfiles/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,30 @@ vim.api.nvim_create_autocmd("FileType", {
pattern = "proto",
callback = function()
local bin = vim.fn.getcwd() .. "/target/debug/protols"
if vim.fn.executable(bin) == 1 then
vim.lsp.start({
name = "protols-dev",
cmd = { bin },
root_dir = vim.fn.getcwd(),
init_options = { include_paths = { vim.fn.getcwd() } },
on_init = function(client)
client.notify("$/setTrace", { value = "verbose" })
end,
})
local debug_port = os.getenv("LSP_DEBUG_PORT")

local lsp_config = {
name = "protols-dev",
root_dir = vim.fn.getcwd(),
init_options = { include_paths = { vim.fn.getcwd() } },
on_init = function(client)
client.notify("$/setTrace", { value = "verbose" })
end,
}

if debug_port and debug_port ~= "" then
lsp_config.cmd = vim.lsp.rpc.connect("127.0.0.1", tonumber(debug_port))
vim.notify("protols-dev: connecting to port " .. debug_port, vim.log.levels.INFO)
else
vim.notify("protols-dev: binary not found. Run 'cargo build' first!", 3)
if vim.fn.executable(bin) == 1 then
lsp_config.cmd = { bin }
else
vim.notify("protols-dev: binary not found. Run 'cargo build' first!", vim.log.levels.ERROR)
return
end
end

vim.lsp.start(lsp_config)
end,
})

Expand Down
27 changes: 27 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug protols via TCP",
"program": "${workspaceFolder}/target/debug/protols",
"args": [
"--port",
"${config:protols.debugPort}"
],
"cwd": "${workspaceFolder}",
"sourceLanguages": [
"rust"
],
"terminal": "console",
"presentation": {
"hidden": false,
"group": "lsp-debug",
"order": 1
},
"preLaunchTask": "Neovim (TCP Debug Mode)",
"expressions": "native"
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"protols.debugPort": "7301"
}
104 changes: 104 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"version": "2.0.0",
"tasks": [
{
"icon": {
"id": "package"
},
"type": "cargo",
"command": "build",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
},
"label": "Rust: cargo build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
}
},
{
"icon": {
"id": "check-all"
},
"type": "cargo",
"command": "clippy",
"problemMatcher": [
"$rustc"
],
"group": "none",
"label": "Rust: cargo clippy",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
}
},
{
"icon": {
"id": "beaker"
},
"type": "cargo",
"command": "test",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "test",
"isDefault": true
},
"label": "Rust: cargo test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
}
},
{
"label": "Neovim (TCP Debug Mode)",
"icon": {
"id": "debug-console"
},
"type": "process",
"command": "nvim",
"isBackground": true,
"problemMatcher": {
"pattern": {
"regexp": "."
},
"background": {
"activeOnStart": true,
"beginsPattern": ".",
"endsPattern": "."
}
},
"options": {
"env": {
"LSP_DEBUG_PORT": "${config:protols.debugPort}"
}
},
"group": "none",
"presentation": {
"reveal": "always",
"panel": "dedicated",
"group": "lsp-debug",
"focus": true,
"close": false,
"clear": true,
}
}
]
}
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "protols"
description = "Language server for proto3 files"
description = "Language server for Protocol Buffers files"
version = "0.13.4"
edition = "2024"
license = "MIT"
Expand Down
65 changes: 59 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- [For Neovim](#for-neovim)
- [Setting Include Paths in Neovim](#setting-include-paths-in-neovim)
- [Command Line Options](#command-line-options)
- [Examples](#examples)
- [For Visual Studio Code](#for-visual-studio-code)
- [Configuration](#%EF%B8%8Fconfiguration)
- [Sample `protols.toml`](#sample-protolstoml)
Expand All @@ -45,6 +46,9 @@
- [Packaging](#-packaging)
- [Contributing](#-contributing)
- [Setting Up Locally](#setting-up-locally)
- [Option 1: Using Dev Containers (Easiest)](#option-1-using-dev-containers-easiest)
- [Option 2: Manual Setup](#option-2-manual-setup)
- [Debugging](#-debugging)
- [License](#-license)

---
Expand Down Expand Up @@ -87,19 +91,62 @@ require'lspconfig'.protols.setup{

Protols supports various command line options to customize its behavior:

```
protols [OPTIONS]
```text
Usage: protols [OPTIONS]

Options:
-i, --include-paths <INCLUDE_PATHS> Include paths for proto files, comma-separated
-V, --version Print version information
-h, --help Print help information
-i, --include-paths <INCLUDE_PATHS> Include paths for proto files, comma-separated (can be used multiple times)
-h, --help Print help
-V, --version Print version

Transport:
--stdio Use stdin/stdout for communication (default)
--socket <ADDR> Use TCP communication with a specific address and port. Examples: "192.168.1.10:5005" or "0.0.0.0:5005"
--port <PORT> Use TCP communication on localhost with a specific port. Example: "5005"
--pipe <PATH> Use Unix domain socket (Linux/macOS) or Named Pipe (Windows). Examples: "/tmp/protols.sock" or "protols-pipe" (Windows)
```

For example, to specify include paths when starting the language server:
#### Examples

##### Specify include paths

You can provide include paths using a comma-separated list or by repeating the
flag:

```bash
protols --include-paths=/path/to/protos,/another/path/to/protos
# or
protols -i /path/to/protos -i /another/path/to/protos
```

##### Communication via TCP
TCP transport is useful when the language server and the IDE run in different
environments.

- **Localhost only**: Connect within the same machine.
```bash
protols --port 7301
```
- **Container/Docker mode**: Listen on all interfaces to allow access from the
host machine to the container.
```bash
protols --socket 0.0.0.0:7301
```
- **Specific interface**: Listen on a specific network IP.
```bash
protols --socket 192.168.1.10:7301
```

##### Communication via Unix Domain Socket
On Linux or macOS, you can use a socket file for communication:
```bash
protols --pipe /tmp/protols.sock
```

##### Communication via Named Pipes (Windows)
On Windows, you can specify a pipe name. `protols` handles the `\\.\pipe\` prefix automatically:
```bash
protols --pipe protols-pipe
```

### For Visual Studio Code
Expand Down Expand Up @@ -265,6 +312,12 @@ testing.
cargo test
```

### 🐞 Debugging

If you want to contribute or debug the server logic, please refer to the
[Debugging Guide](docs/debugging.md) for instructions on setting up a TCP-based
debug session with VS Code and Neovim.

---

## 📄 License
Expand Down
54 changes: 54 additions & 0 deletions docs/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Debugging protols

Since `protols` is a language server, debugging it directly via standard I/O can
be challenging. Furthermore, attaching a debugger to a running process inside a
Dev Container is often restricted by security policies.

The recommended way to debug is to start the server in TCP mode and connect to
it with your LSP client.

## Debugging with VS Code and Neovim

The project includes a pre-configured `launch.json` for VS Code that automates
the debugging setup.

### 1. Start the Debug Session

In VS Code, go to the **Run and Debug** view and select **"Debug protols via
TCP"**.

This will:
- Build the project in debug mode.
- Start the server listening on a TCP port (default: `7301`).
- Automatically open a new terminal with **Neovim** inside the Dev Container.

### 2. Connect Neovim

The Neovim instance in the Dev Container is pre-configured to detect the
`LSP_DEBUG_PORT` environment variable.

1. Wait for the message in the VS Code Debug Console: `LSP server listening on TCP: 127.0.0.1:7301`.
2. In the opened Neovim terminal, open any `.proto` file (e.g., `:e sample/simple.proto`).
3. Neovim will automatically connect to the debugged server instance via the specified port.

### 3. Verify Connection
To ensure the debugger is working and the server is responding:
1. Set a breakpoint in the Rust code (e.g., in `src/parser/docsymbol.rs`).
2. In Neovim, trigger an LSP request, such as fetching document symbols:
```vim
:lua vim.lsp.buf.document_symbol()
```
3. The debugger should hit your breakpoint in VS Code.

## Manual Debugging

If you prefer to run the components manually:

1. **Start the server:**
```bash
cargo run -- --port 7301
```
2. **Start Neovim:**
```bash
LSP_DEBUG_PORT=7301 nvim your_file.proto
```
Loading