collie-lsp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.collie.yml.example +144 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +10 -0
- data/LICENSE +21 -0
- data/README.md +273 -0
- data/Rakefile +8 -0
- data/collie-lsp.gemspec +36 -0
- data/exe/collie-lsp +9 -0
- data/lib/collie_lsp/collie_wrapper.rb +97 -0
- data/lib/collie_lsp/document_store.rb +66 -0
- data/lib/collie_lsp/handlers/code_action.rb +77 -0
- data/lib/collie_lsp/handlers/completion.rb +72 -0
- data/lib/collie_lsp/handlers/definition.rb +117 -0
- data/lib/collie_lsp/handlers/diagnostics.rb +64 -0
- data/lib/collie_lsp/handlers/document_symbol.rb +185 -0
- data/lib/collie_lsp/handlers/folding_range.rb +211 -0
- data/lib/collie_lsp/handlers/formatting.rb +55 -0
- data/lib/collie_lsp/handlers/hover.rb +104 -0
- data/lib/collie_lsp/handlers/references.rb +185 -0
- data/lib/collie_lsp/handlers/rename.rb +226 -0
- data/lib/collie_lsp/handlers/semantic_tokens.rb +302 -0
- data/lib/collie_lsp/handlers/workspace_symbol.rb +161 -0
- data/lib/collie_lsp/protocol/initialize.rb +58 -0
- data/lib/collie_lsp/protocol/shutdown.rb +25 -0
- data/lib/collie_lsp/protocol/text_document.rb +81 -0
- data/lib/collie_lsp/server.rb +104 -0
- data/lib/collie_lsp/version.rb +5 -0
- data/lib/collie_lsp.rb +25 -0
- data/vscode-extension/.gitignore +3 -0
- data/vscode-extension/.vscode/launch.json +17 -0
- data/vscode-extension/.vscode/tasks.json +14 -0
- data/vscode-extension/README.md +35 -0
- data/vscode-extension/package.json +49 -0
- data/vscode-extension/src/extension.ts +48 -0
- data/vscode-extension/test-grammar.y +42 -0
- data/vscode-extension/tsconfig.json +12 -0
- metadata +98 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ec633ab14d54c5cf9447d1638970e179df88b9a86a1c39b3bfcafa1340aede55
|
|
4
|
+
data.tar.gz: c166948efe29a27db239c004941b56da587834eec902af888973f581e471c0f9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5546ee6a736111222aae47aea6d466e1835ae841f16b2861d788f8041617fa6979b1722c3cdf3bf22c7a9a62a9304f49e536012dbab118bdcbabd0c6b17cd09a
|
|
7
|
+
data.tar.gz: 88d501fa5b1e60098453a0755967b3b296b9f13c16bccfde08e343dd6e4dae1a07daf1d1c543ff7c8d60ce27851f59b6e10a4c8c7532f1d0100a5760821693de
|
data/.collie.yml.example
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Example collie-lsp configuration file
|
|
2
|
+
# Copy this file to .collie.yml and customize as needed
|
|
3
|
+
|
|
4
|
+
# Inherit configuration from another file (optional)
|
|
5
|
+
# inherit_from: .collie_base.yml
|
|
6
|
+
|
|
7
|
+
# Linter rules configuration
|
|
8
|
+
rules:
|
|
9
|
+
# Validation rules (severity: error)
|
|
10
|
+
DuplicateToken:
|
|
11
|
+
enabled: true
|
|
12
|
+
severity: error
|
|
13
|
+
|
|
14
|
+
UndefinedSymbol:
|
|
15
|
+
enabled: true
|
|
16
|
+
severity: error
|
|
17
|
+
|
|
18
|
+
UnreachableRule:
|
|
19
|
+
enabled: true
|
|
20
|
+
severity: error
|
|
21
|
+
|
|
22
|
+
CircularReference:
|
|
23
|
+
enabled: true
|
|
24
|
+
severity: error
|
|
25
|
+
|
|
26
|
+
MissingStartSymbol:
|
|
27
|
+
enabled: true
|
|
28
|
+
severity: error
|
|
29
|
+
|
|
30
|
+
# Warning rules (severity: warning)
|
|
31
|
+
UnusedNonterminal:
|
|
32
|
+
enabled: true
|
|
33
|
+
severity: warning
|
|
34
|
+
|
|
35
|
+
UnusedToken:
|
|
36
|
+
enabled: true
|
|
37
|
+
severity: warning
|
|
38
|
+
|
|
39
|
+
LeftRecursion:
|
|
40
|
+
enabled: true
|
|
41
|
+
severity: warning
|
|
42
|
+
|
|
43
|
+
RightRecursion:
|
|
44
|
+
enabled: true
|
|
45
|
+
severity: warning
|
|
46
|
+
|
|
47
|
+
AmbiguousPrecedence:
|
|
48
|
+
enabled: true
|
|
49
|
+
severity: warning
|
|
50
|
+
|
|
51
|
+
# Style rules (severity: convention)
|
|
52
|
+
TokenNaming:
|
|
53
|
+
enabled: true
|
|
54
|
+
severity: convention
|
|
55
|
+
# Tokens should be UPPER_CASE
|
|
56
|
+
pattern: '^[A-Z][A-Z0-9_]*$'
|
|
57
|
+
|
|
58
|
+
NonterminalNaming:
|
|
59
|
+
enabled: true
|
|
60
|
+
severity: convention
|
|
61
|
+
# Nonterminals should be snake_case
|
|
62
|
+
pattern: '^[a-z][a-z0-9_]*$'
|
|
63
|
+
|
|
64
|
+
ActionVariableNaming:
|
|
65
|
+
enabled: true
|
|
66
|
+
severity: convention
|
|
67
|
+
|
|
68
|
+
ConsistentTagNaming:
|
|
69
|
+
enabled: true
|
|
70
|
+
severity: convention
|
|
71
|
+
|
|
72
|
+
TrailingWhitespace:
|
|
73
|
+
enabled: true
|
|
74
|
+
severity: convention
|
|
75
|
+
|
|
76
|
+
EmptyAction:
|
|
77
|
+
enabled: false
|
|
78
|
+
severity: convention
|
|
79
|
+
|
|
80
|
+
LongRule:
|
|
81
|
+
enabled: true
|
|
82
|
+
severity: convention
|
|
83
|
+
max_alternatives: 10
|
|
84
|
+
|
|
85
|
+
# Optimization rules (severity: info)
|
|
86
|
+
FactorizableRules:
|
|
87
|
+
enabled: false
|
|
88
|
+
severity: info
|
|
89
|
+
|
|
90
|
+
RedundantEpsilon:
|
|
91
|
+
enabled: false
|
|
92
|
+
severity: info
|
|
93
|
+
|
|
94
|
+
PrecImprovement:
|
|
95
|
+
enabled: false
|
|
96
|
+
severity: info
|
|
97
|
+
|
|
98
|
+
# Formatter configuration
|
|
99
|
+
formatter:
|
|
100
|
+
# Number of spaces for indentation
|
|
101
|
+
indent_size: 4
|
|
102
|
+
|
|
103
|
+
# Align token declarations
|
|
104
|
+
align_tokens: true
|
|
105
|
+
|
|
106
|
+
# Align rule alternatives
|
|
107
|
+
align_alternatives: true
|
|
108
|
+
|
|
109
|
+
# Number of blank lines around section separators (%%)
|
|
110
|
+
blank_lines_around_sections: 2
|
|
111
|
+
|
|
112
|
+
# Maximum line length before wrapping
|
|
113
|
+
max_line_length: 120
|
|
114
|
+
|
|
115
|
+
# Preserve blank lines between rules
|
|
116
|
+
preserve_blank_lines: true
|
|
117
|
+
|
|
118
|
+
# Sort token declarations alphabetically
|
|
119
|
+
sort_tokens: false
|
|
120
|
+
|
|
121
|
+
# File patterns
|
|
122
|
+
include:
|
|
123
|
+
- '**/*.y'
|
|
124
|
+
- '**/*.yacc'
|
|
125
|
+
|
|
126
|
+
exclude:
|
|
127
|
+
- 'vendor/**/*'
|
|
128
|
+
- 'tmp/**/*'
|
|
129
|
+
- 'node_modules/**/*'
|
|
130
|
+
- '.git/**/*'
|
|
131
|
+
|
|
132
|
+
# Editor integration settings
|
|
133
|
+
editor:
|
|
134
|
+
# Show diagnostics on save only (vs. on change)
|
|
135
|
+
diagnostics_on_save: false
|
|
136
|
+
|
|
137
|
+
# Debounce delay for diagnostics (milliseconds)
|
|
138
|
+
diagnostics_delay: 300
|
|
139
|
+
|
|
140
|
+
# Enable semantic tokens
|
|
141
|
+
semantic_tokens: true
|
|
142
|
+
|
|
143
|
+
# Enable code folding
|
|
144
|
+
folding: true
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
- Initial commit
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Yudai Takada
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# collie-lsp
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/collie-lsp)
|
|
4
|
+
[](https://github.com/ydah/collie-lsp/actions)
|
|
5
|
+
|
|
6
|
+
Language Server Protocol (LSP) implementation for Lrama Style BNF grammar files (.y files).
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- Real-time diagnostics and linting
|
|
11
|
+
- Document formatting
|
|
12
|
+
- Code actions and quick fixes
|
|
13
|
+
- Hover information and auto-completion
|
|
14
|
+
- Go to definition and find references
|
|
15
|
+
- Symbol renaming and workspace search
|
|
16
|
+
- Semantic highlighting and code folding
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Add this line to your application's Gemfile:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
gem 'collie-lsp'
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
And then execute:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or install it yourself as:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
gem install collie-lsp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### Starting the Server
|
|
41
|
+
|
|
42
|
+
The LSP server can be started in stdio mode (the default for most LSP clients):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
collie-lsp --stdio
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or in socket mode:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
collie-lsp --socket=7658
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Editor Configuration
|
|
55
|
+
|
|
56
|
+
#### VS Code
|
|
57
|
+
|
|
58
|
+
Install the collie-lsp extension from the VS Code marketplace, or configure manually:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"collie-lsp.serverPath": "collie-lsp",
|
|
63
|
+
"collie-lsp.trace.server": "verbose"
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### Neovim (with nvim-lspconfig)
|
|
68
|
+
|
|
69
|
+
```lua
|
|
70
|
+
require'lspconfig'.collie_lsp.setup{
|
|
71
|
+
cmd = { "collie-lsp", "--stdio" },
|
|
72
|
+
filetypes = { "yacc" },
|
|
73
|
+
root_dir = function(fname)
|
|
74
|
+
return vim.fn.getcwd()
|
|
75
|
+
end,
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### Emacs (with lsp-mode)
|
|
80
|
+
|
|
81
|
+
```elisp
|
|
82
|
+
(add-to-list 'lsp-language-id-configuration '(yacc-mode . "yacc"))
|
|
83
|
+
|
|
84
|
+
(lsp-register-client
|
|
85
|
+
(make-lsp-client :new-connection (lsp-stdio-connection "collie-lsp")
|
|
86
|
+
:major-modes '(yacc-mode)
|
|
87
|
+
:server-id 'collie-lsp))
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Vim (with vim-lsp)
|
|
91
|
+
|
|
92
|
+
```vim
|
|
93
|
+
if executable('collie-lsp')
|
|
94
|
+
au User lsp_setup call lsp#register_server({
|
|
95
|
+
\ 'name': 'collie-lsp',
|
|
96
|
+
\ 'cmd': {server_info->['collie-lsp', '--stdio']},
|
|
97
|
+
\ 'whitelist': ['yacc'],
|
|
98
|
+
\ })
|
|
99
|
+
endif
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Configuration
|
|
103
|
+
|
|
104
|
+
Create a `.collie.yml` file in your project root:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
# Linter rules
|
|
108
|
+
rules:
|
|
109
|
+
DuplicateToken:
|
|
110
|
+
enabled: true
|
|
111
|
+
severity: error
|
|
112
|
+
|
|
113
|
+
TokenNaming:
|
|
114
|
+
enabled: true
|
|
115
|
+
severity: convention
|
|
116
|
+
pattern: '^[A-Z][A-Z0-9_]*$'
|
|
117
|
+
|
|
118
|
+
NonterminalNaming:
|
|
119
|
+
enabled: true
|
|
120
|
+
severity: convention
|
|
121
|
+
pattern: '^[a-z][a-z0-9_]*$'
|
|
122
|
+
|
|
123
|
+
# Formatter options
|
|
124
|
+
formatter:
|
|
125
|
+
indent_size: 4
|
|
126
|
+
align_tokens: true
|
|
127
|
+
align_alternatives: true
|
|
128
|
+
max_line_length: 120
|
|
129
|
+
|
|
130
|
+
# File patterns
|
|
131
|
+
include:
|
|
132
|
+
- '**/*.y'
|
|
133
|
+
exclude:
|
|
134
|
+
- 'vendor/**/*'
|
|
135
|
+
- 'tmp/**/*'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Install dependencies
|
|
144
|
+
bundle install
|
|
145
|
+
|
|
146
|
+
# Run tests
|
|
147
|
+
bundle exec rspec
|
|
148
|
+
|
|
149
|
+
# Or use rake
|
|
150
|
+
bundle exec rake
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Architecture
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
lib/collie_lsp/
|
|
157
|
+
├── server.rb # Main LSP server
|
|
158
|
+
├── document_store.rb # Document management
|
|
159
|
+
├── collie_wrapper.rb # Collie gem integration
|
|
160
|
+
├── protocol/ # LSP protocol handlers
|
|
161
|
+
│ ├── initialize.rb
|
|
162
|
+
│ ├── text_document.rb
|
|
163
|
+
│ └── shutdown.rb
|
|
164
|
+
└── handlers/ # Feature handlers
|
|
165
|
+
├── diagnostics.rb # Lint diagnostics
|
|
166
|
+
├── formatting.rb # Document formatting
|
|
167
|
+
├── code_action.rb # Quick fixes
|
|
168
|
+
├── hover.rb # Hover information
|
|
169
|
+
├── completion.rb # Auto-completion
|
|
170
|
+
├── definition.rb # Go to definition
|
|
171
|
+
├── references.rb # Find references
|
|
172
|
+
├── document_symbol.rb # Document outline
|
|
173
|
+
├── rename.rb # Symbol renaming
|
|
174
|
+
├── semantic_tokens.rb # Semantic highlighting
|
|
175
|
+
├── workspace_symbol.rb # Workspace search
|
|
176
|
+
└── folding_range.rb # Code folding
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Testing
|
|
180
|
+
|
|
181
|
+
Run the test suite:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
bundle exec rspec
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Run specific tests:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
bundle exec rspec spec/collie_lsp/handlers/hover_spec.rb
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Run with coverage:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
COVERAGE=true bundle exec rspec
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Logging
|
|
200
|
+
|
|
201
|
+
Enable logging for debugging:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
COLLIE_LSP_LOG=/tmp/collie-lsp.log collie-lsp --stdio
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Then tail the log file:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
tail -f /tmp/collie-lsp.log
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## LSP Capabilities
|
|
214
|
+
|
|
215
|
+
### textDocument/publishDiagnostics
|
|
216
|
+
Real-time linting as you type, showing errors, warnings, and style violations.
|
|
217
|
+
|
|
218
|
+
### textDocument/formatting
|
|
219
|
+
Format the entire document according to your style preferences.
|
|
220
|
+
|
|
221
|
+
### textDocument/codeAction
|
|
222
|
+
Quick fixes for autocorrectable offenses. Access via your editor's "Quick Fix" command.
|
|
223
|
+
|
|
224
|
+
### textDocument/hover
|
|
225
|
+
Hover over a symbol to see its type and documentation.
|
|
226
|
+
|
|
227
|
+
### textDocument/completion
|
|
228
|
+
Intelligent auto-completion for:
|
|
229
|
+
- Declared tokens
|
|
230
|
+
- Defined nonterminals
|
|
231
|
+
- Grammar keywords
|
|
232
|
+
|
|
233
|
+
### textDocument/definition
|
|
234
|
+
Jump to the definition of any token or nonterminal.
|
|
235
|
+
|
|
236
|
+
### textDocument/references
|
|
237
|
+
Find all references to a symbol across the file.
|
|
238
|
+
|
|
239
|
+
### textDocument/documentSymbol
|
|
240
|
+
View document outline in your editor's symbol browser.
|
|
241
|
+
|
|
242
|
+
### textDocument/rename
|
|
243
|
+
Rename symbols with validation and automatic updates throughout the file.
|
|
244
|
+
|
|
245
|
+
### textDocument/semanticTokens/full
|
|
246
|
+
Enhanced syntax highlighting for:
|
|
247
|
+
- Keywords (`%token`, `%type`, etc.)
|
|
248
|
+
- Tokens (uppercase identifiers)
|
|
249
|
+
- Nonterminals (lowercase identifiers)
|
|
250
|
+
- Comments and strings
|
|
251
|
+
|
|
252
|
+
### workspace/symbol
|
|
253
|
+
Search for symbols across all open documents.
|
|
254
|
+
|
|
255
|
+
### textDocument/foldingRange
|
|
256
|
+
Fold code sections:
|
|
257
|
+
- Grammar rules
|
|
258
|
+
- Block comments
|
|
259
|
+
- C code blocks (`%{ ... %}`)
|
|
260
|
+
- Action blocks (`{ ... }`)
|
|
261
|
+
|
|
262
|
+
## Contributing
|
|
263
|
+
|
|
264
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ydah/collie-lsp.
|
|
265
|
+
|
|
266
|
+
## License
|
|
267
|
+
|
|
268
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
269
|
+
|
|
270
|
+
## Related Projects
|
|
271
|
+
|
|
272
|
+
- [collie](https://github.com/ydah/collie) - The core linter and formatter (coming soon)
|
|
273
|
+
- [lrama](https://github.com/ruby/lrama) - LALR parser generator
|
data/Rakefile
ADDED
data/collie-lsp.gemspec
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/collie_lsp/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'collie-lsp'
|
|
7
|
+
spec.version = CollieLsp::VERSION
|
|
8
|
+
spec.authors = ['Yudai Takada']
|
|
9
|
+
spec.email = ['t.yudai92@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Language Server Protocol implementation for Lrama Style BNF grammar files'
|
|
12
|
+
spec.description = 'collie-lsp provides real-time linting, formatting, and code intelligence ' \
|
|
13
|
+
'features for .y grammar files in any LSP-compatible editor'
|
|
14
|
+
spec.homepage = 'https://github.com/ydah/collie-lsp'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
17
|
+
|
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
|
|
22
|
+
spec.metadata['documentation_uri'] = "#{spec.homepage}/blob/main/README.md"
|
|
23
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
24
|
+
|
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
|
26
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
27
|
+
(File.expand_path(f) == __FILE__) ||
|
|
28
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
spec.bindir = 'exe'
|
|
32
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
33
|
+
spec.require_paths = ['lib']
|
|
34
|
+
|
|
35
|
+
spec.add_dependency 'language_server-protocol', '~> 3.17.0'
|
|
36
|
+
end
|
data/exe/collie-lsp
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CollieLsp
|
|
4
|
+
# Wrapper around the Collie gem for LSP integration
|
|
5
|
+
class CollieWrapper
|
|
6
|
+
# Initialize wrapper
|
|
7
|
+
# @param workspace_root [String, nil] Workspace root directory for config discovery
|
|
8
|
+
def initialize(workspace_root: nil)
|
|
9
|
+
config_path = find_config(workspace_root)
|
|
10
|
+
@config = load_config(config_path)
|
|
11
|
+
load_rules
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Parse grammar source into AST
|
|
15
|
+
# @param source [String] Grammar source code
|
|
16
|
+
# @param filename [String] Filename for error messages
|
|
17
|
+
# @return [Object, Hash] AST or error hash
|
|
18
|
+
def parse(_source, filename: 'grammar.y')
|
|
19
|
+
# For now, return a mock AST structure
|
|
20
|
+
# This will be replaced with actual Collie parser when available
|
|
21
|
+
{
|
|
22
|
+
declarations: [],
|
|
23
|
+
rules: [],
|
|
24
|
+
prologue: nil,
|
|
25
|
+
epilogue: nil
|
|
26
|
+
}
|
|
27
|
+
rescue StandardError => e
|
|
28
|
+
{ error: e.message, location: { line: 1, column: 1 } }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Lint grammar source
|
|
32
|
+
# @param source [String] Grammar source code
|
|
33
|
+
# @param filename [String] Filename for error messages
|
|
34
|
+
# @return [Array<Hash>] Array of offenses
|
|
35
|
+
def lint(source, filename: 'grammar.y')
|
|
36
|
+
ast = parse(source, filename: filename)
|
|
37
|
+
return [] if ast.is_a?(Hash) && ast[:error]
|
|
38
|
+
|
|
39
|
+
# For now, return empty offenses
|
|
40
|
+
# This will be replaced with actual Collie linter when available
|
|
41
|
+
[]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Format grammar source
|
|
45
|
+
# @param source [String] Grammar source code
|
|
46
|
+
# @param filename [String] Filename for error messages
|
|
47
|
+
# @return [String, nil] Formatted source or nil on error
|
|
48
|
+
def format(source, filename: 'grammar.y')
|
|
49
|
+
ast = parse(source, filename: filename)
|
|
50
|
+
return nil if ast.is_a?(Hash) && ast[:error]
|
|
51
|
+
|
|
52
|
+
# For now, return the source as-is
|
|
53
|
+
# This will be replaced with actual Collie formatter when available
|
|
54
|
+
source
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Autocorrect offenses in grammar source
|
|
58
|
+
# @param source [String] Grammar source code
|
|
59
|
+
# @param filename [String] Filename for error messages
|
|
60
|
+
# @return [String] Corrected source
|
|
61
|
+
def autocorrect(source, filename: 'grammar.y')
|
|
62
|
+
# For now, return the source as-is
|
|
63
|
+
# This will be replaced with actual Collie autocorrect when available
|
|
64
|
+
source
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Find configuration file
|
|
70
|
+
# @param root [String, nil] Workspace root directory
|
|
71
|
+
# @return [String, nil] Config file path or nil
|
|
72
|
+
def find_config(root)
|
|
73
|
+
return nil unless root
|
|
74
|
+
|
|
75
|
+
config_file = File.join(root, '.collie.yml')
|
|
76
|
+
File.exist?(config_file) ? config_file : nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Load configuration
|
|
80
|
+
# @param config_path [String, nil] Config file path
|
|
81
|
+
# @return [Hash] Configuration hash
|
|
82
|
+
def load_config(config_path)
|
|
83
|
+
if config_path && File.exist?(config_path)
|
|
84
|
+
require 'yaml'
|
|
85
|
+
YAML.load_file(config_path)
|
|
86
|
+
else
|
|
87
|
+
{}
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Load linter rules
|
|
92
|
+
def load_rules
|
|
93
|
+
# This will be replaced with actual Collie rule loading when available
|
|
94
|
+
# Collie::Linter::Registry.load_rules
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CollieLsp
|
|
4
|
+
# Manages open documents in memory
|
|
5
|
+
class DocumentStore
|
|
6
|
+
def initialize
|
|
7
|
+
@documents = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Open a new document
|
|
11
|
+
# @param uri [String] Document URI
|
|
12
|
+
# @param text [String] Document text content
|
|
13
|
+
# @param version [Integer] Document version
|
|
14
|
+
def open(uri, text, version)
|
|
15
|
+
@documents[uri] = {
|
|
16
|
+
text: text,
|
|
17
|
+
version: version,
|
|
18
|
+
ast: nil,
|
|
19
|
+
diagnostics: []
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Update document content
|
|
24
|
+
# @param uri [String] Document URI
|
|
25
|
+
# @param text [String] New document text
|
|
26
|
+
# @param version [Integer] New document version
|
|
27
|
+
def change(uri, text, version)
|
|
28
|
+
return unless @documents[uri]
|
|
29
|
+
|
|
30
|
+
@documents[uri][:text] = text
|
|
31
|
+
@documents[uri][:version] = version
|
|
32
|
+
@documents[uri][:ast] = nil # Invalidate AST cache
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Get document data
|
|
36
|
+
# @param uri [String] Document URI
|
|
37
|
+
# @return [Hash, nil] Document data or nil if not found
|
|
38
|
+
def get(uri)
|
|
39
|
+
@documents[uri]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Close a document
|
|
43
|
+
# @param uri [String] Document URI
|
|
44
|
+
def close(uri)
|
|
45
|
+
@documents.delete(uri)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Update cached AST for a document
|
|
49
|
+
# @param uri [String] Document URI
|
|
50
|
+
# @param ast [Object] Parsed AST
|
|
51
|
+
def update_ast(uri, ast)
|
|
52
|
+
return unless @documents[uri]
|
|
53
|
+
|
|
54
|
+
@documents[uri][:ast] = ast
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Update diagnostics for a document
|
|
58
|
+
# @param uri [String] Document URI
|
|
59
|
+
# @param diagnostics [Array<Hash>] LSP diagnostics
|
|
60
|
+
def update_diagnostics(uri, diagnostics)
|
|
61
|
+
return unless @documents[uri]
|
|
62
|
+
|
|
63
|
+
@documents[uri][:diagnostics] = diagnostics
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|