ruby_syntax_lsp 0.0.1 → 0.0.3
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 +4 -4
- data/exe/ruby_syntax_lsp +1 -5
- data/lib/ruby_syntax_lsp/cli.rb +31 -0
- data/lib/ruby_syntax_lsp/core.rb +110 -0
- data/lib/ruby_syntax_lsp/version.rb +5 -0
- data/lib/ruby_syntax_lsp.rb +4 -106
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd63477afde1ec0fdfc9656110ca5a10831c1c4f099d605a4d7d3e3d30ef172b
|
4
|
+
data.tar.gz: 9fdea095c4577242d338f7297687a029f70c2778dc585f8bc86b89ae202640da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f7b203defc5b27a654b022fee00d48832004d259ac28f423ad0f54511a9407e433f20374b47e6908e43715f49c7edd86a9bf19b159f495a6808c615515b1b9d
|
7
|
+
data.tar.gz: 20b535acf85bb150b1f44fb914129957bc054d935335c645ea833fc5224d068e923d943d757656b11ca1793ba8e80cee77d781760952960127fbcdb0bf173ce0
|
data/exe/ruby_syntax_lsp
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require_relative "core"
|
5
|
+
require_relative "version"
|
6
|
+
|
7
|
+
class RubySyntaxLsp
|
8
|
+
def self.cli
|
9
|
+
options = {
|
10
|
+
log_level: :info,
|
11
|
+
}
|
12
|
+
opts = OptionParser.new("Usage: ruby_syntax_lsp [options]")
|
13
|
+
|
14
|
+
opts.on("--log LEVEL", "Set log level (debug, info, warn, error, fatal)") do |v|
|
15
|
+
options[:log_level] = level.to_sym
|
16
|
+
end
|
17
|
+
|
18
|
+
opts.on("--verbose", "Set log level to debug") do
|
19
|
+
options[:log_level] = :debug
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.version = RubySyntaxLsp::VERSION
|
23
|
+
|
24
|
+
opts.parse!
|
25
|
+
|
26
|
+
reader = LSP::Transport::Stdio::Reader.new
|
27
|
+
writer = LSP::Transport::Stdio::Writer.new
|
28
|
+
|
29
|
+
RubySyntaxLsp.new(writer, reader, options[:log_level]).start
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "language_server-protocol"
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
LSP = LanguageServer::Protocol
|
7
|
+
|
8
|
+
class RubySyntaxLsp
|
9
|
+
def initialize(writer, reader, level)
|
10
|
+
@writer = writer
|
11
|
+
@reader = reader
|
12
|
+
@logger = Logger.new(STDERR, level: level)
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
@logger.info "Started Ruby Syntax LSP server..."
|
17
|
+
@reader.read do |request|
|
18
|
+
break if request[:method] == "shutdown"
|
19
|
+
method_name = ("request_" + request[:method].gsub(/[A-Z]/) { |m| "_#{m.downcase}" }.gsub("/", "_")).to_sym
|
20
|
+
if respond_to?(method_name)
|
21
|
+
@logger.debug "Received supported method: #{method_name}"
|
22
|
+
begin
|
23
|
+
send(method_name, request[:id], request[:params])
|
24
|
+
rescue => e
|
25
|
+
@logger.error "Error: #{e.full_message}"
|
26
|
+
@writer.write(
|
27
|
+
code: -32603,
|
28
|
+
message: e.message,
|
29
|
+
)
|
30
|
+
end
|
31
|
+
elsif request[:method].start_with?("$/")
|
32
|
+
@logger.debug "Received unsupported method: #{request[:method]}"
|
33
|
+
else
|
34
|
+
@writer.write(
|
35
|
+
code: -32601,
|
36
|
+
message: "Method not implemented: #{request[:method]}",
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def request_initialize(id, params)
|
43
|
+
@writer.write(
|
44
|
+
id: id,
|
45
|
+
result: LSP::Interface::InitializeResult.new(
|
46
|
+
capabilities: LSP::Interface::ServerCapabilities.new(
|
47
|
+
text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
|
48
|
+
change: LSP::Constant::TextDocumentSyncKind::FULL,
|
49
|
+
),
|
50
|
+
),
|
51
|
+
),
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
def request_initialized(id, params)
|
56
|
+
# none
|
57
|
+
end
|
58
|
+
|
59
|
+
def request_text_document_did_change(id, params)
|
60
|
+
@writer.write(
|
61
|
+
method: "textDocument/publishDiagnostics",
|
62
|
+
params: {
|
63
|
+
uri: params[:textDocument][:uri],
|
64
|
+
diagnostics: params[:contentChanges].filter_map do |change|
|
65
|
+
text = change[:text]
|
66
|
+
begin
|
67
|
+
RubyVM::InstructionSequence.compile(text)
|
68
|
+
rescue SyntaxError => e
|
69
|
+
@logger.info("SyntaxError detected:\n#{e.message}")
|
70
|
+
lines = text.lines
|
71
|
+
e.message.split(/^<compiled>:(?=\d+: )/m)[1..].map do |error|
|
72
|
+
@logger.info("Parsing this error message:\n#{error}")
|
73
|
+
lineno_s, message = error.split(": ", 2)
|
74
|
+
lineno = lineno_s.strip.to_i
|
75
|
+
@logger.info("Line number: #{lineno}")
|
76
|
+
range = if message.lines.length > 1 # Message has `^`
|
77
|
+
pos_start = message.lines[2].delete_prefix("...").index("^")
|
78
|
+
if message.lines[1].start_with?("...")
|
79
|
+
pos_start += lines[lineno - 1].index(message.lines[1].delete_prefix("...").delete_suffix("..."))
|
80
|
+
end
|
81
|
+
pos_end = pos_start + message.lines[2].count("~") + 1
|
82
|
+
|
83
|
+
@logger.info("line: #{lineno}, position: #{pos_start}-#{pos_end}")
|
84
|
+
LSP::Interface::Range.new(
|
85
|
+
start: LSP::Interface::Position.new(line: lineno - 1, character: pos_start),
|
86
|
+
end: LSP::Interface::Position.new(line: lineno - 1, character: pos_end),
|
87
|
+
)
|
88
|
+
else
|
89
|
+
@logger.info("line: #{lineno}, no position")
|
90
|
+
LSP::Interface::Range.new(
|
91
|
+
start: LSP::Interface::Position.new(line: lineno - 1, character: 0),
|
92
|
+
end: LSP::Interface::Position.new(line: lineno - 1, character: lines[lineno - 1].length - 1),
|
93
|
+
)
|
94
|
+
end
|
95
|
+
LSP::Interface::Diagnostic.new(
|
96
|
+
range: range,
|
97
|
+
severity: LSP::Constant::DiagnosticSeverity::ERROR,
|
98
|
+
message: message.lines[0].strip.sub(/^syntax error, /, ""),
|
99
|
+
source: "Ruby Syntax LSP",
|
100
|
+
)
|
101
|
+
end
|
102
|
+
else
|
103
|
+
@logger.info("No SyntaxError")
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end.flatten,
|
107
|
+
},
|
108
|
+
)
|
109
|
+
end
|
110
|
+
end
|
data/lib/ruby_syntax_lsp.rb
CHANGED
@@ -1,107 +1,5 @@
|
|
1
|
-
|
2
|
-
require "Logger"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
class Server
|
8
|
-
def initialize(writer, reader)
|
9
|
-
@writer = writer
|
10
|
-
@reader = reader
|
11
|
-
end
|
12
|
-
|
13
|
-
def start
|
14
|
-
$logger.info "Started Ruby Syntax LSP server..."
|
15
|
-
@reader.read do |request|
|
16
|
-
break if request[:method] == "shutdown"
|
17
|
-
method_name = ("request_" + request[:method].gsub(/[A-Z]/) { |m| "_#{m.downcase}" }.gsub("/", "_")).to_sym
|
18
|
-
if respond_to?(method_name)
|
19
|
-
$logger.debug "Received supported method: #{method_name}"
|
20
|
-
begin
|
21
|
-
send(method_name, request[:id], request[:params])
|
22
|
-
rescue => e
|
23
|
-
$logger.error "Error: #{e.full_message}"
|
24
|
-
@writer.write(
|
25
|
-
code: -32603,
|
26
|
-
message: e.message,
|
27
|
-
)
|
28
|
-
end
|
29
|
-
elsif request[:method].start_with?("$/")
|
30
|
-
$logger.debug "Received unsupported method: #{request[:method]}"
|
31
|
-
else
|
32
|
-
@writer.write(
|
33
|
-
code: -32601,
|
34
|
-
message: "Method not implemented: #{request[:method]}",
|
35
|
-
)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def request_initialize(id, params)
|
41
|
-
@writer.write(
|
42
|
-
id: id,
|
43
|
-
result: LSP::Interface::InitializeResult.new(
|
44
|
-
capabilities: LSP::Interface::ServerCapabilities.new(
|
45
|
-
text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
|
46
|
-
change: LSP::Constant::TextDocumentSyncKind::FULL,
|
47
|
-
),
|
48
|
-
),
|
49
|
-
),
|
50
|
-
)
|
51
|
-
end
|
52
|
-
|
53
|
-
def request_initialized(id, params)
|
54
|
-
# none
|
55
|
-
end
|
56
|
-
|
57
|
-
def request_text_document_did_change(id, params)
|
58
|
-
@writer.write(
|
59
|
-
method: "textDocument/publishDiagnostics",
|
60
|
-
params: {
|
61
|
-
uri: params[:textDocument][:uri],
|
62
|
-
diagnostics: params[:contentChanges].filter_map do |change|
|
63
|
-
text = change[:text]
|
64
|
-
begin
|
65
|
-
RubyVM::InstructionSequence.compile(text)
|
66
|
-
rescue SyntaxError => e
|
67
|
-
$logger.info("SyntaxError detected:\n#{e.message}")
|
68
|
-
lines = text.lines
|
69
|
-
e.message.split(/^<compiled>:(?=\d+: )/m)[1..].map do |error|
|
70
|
-
$logger.info("Parsing this error message:\n#{error}")
|
71
|
-
lineno_s, message = error.split(": ", 2)
|
72
|
-
lineno = lineno_s.to_i
|
73
|
-
range = if message.lines.length > 1 # Message has `^`
|
74
|
-
pos_start = message.lines[2].index("^")
|
75
|
-
if message.lines[1].start_with?("...")
|
76
|
-
pos_start += lines[lineno - 1].index(message.lines[1].delete_prefix("...").delete_suffix("...")) - 3
|
77
|
-
end
|
78
|
-
pos_end = pos_start + message.lines[2].count("~") + 1
|
79
|
-
|
80
|
-
$logger.info("line: #{lineno}, position: #{pos_start}-#{pos_end}")
|
81
|
-
LSP::Interface::Range.new(
|
82
|
-
start: LSP::Interface::Position.new(line: lineno - 1, character: pos_start),
|
83
|
-
end: LSP::Interface::Position.new(line: lineno - 1, character: pos_end),
|
84
|
-
)
|
85
|
-
else
|
86
|
-
$logger.info("line: #{lineno}, no position")
|
87
|
-
LSP::Interface::Range.new(
|
88
|
-
start: LSP::Interface::Position.new(line: lineno - 1, character: 0),
|
89
|
-
end: LSP::Interface::Position.new(line: lineno - 1, character: lines[lineno - 1].length - 1),
|
90
|
-
)
|
91
|
-
end
|
92
|
-
LSP::Interface::Diagnostic.new(
|
93
|
-
range: range,
|
94
|
-
severity: LSP::Constant::DiagnosticSeverity::ERROR,
|
95
|
-
message: message.lines[0].strip.sub(/^syntax error, /, ""),
|
96
|
-
source: "Ruby Syntax LSP",
|
97
|
-
)
|
98
|
-
end
|
99
|
-
else
|
100
|
-
$logger.info("No SyntaxError")
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
end.flatten,
|
104
|
-
},
|
105
|
-
)
|
106
|
-
end
|
107
|
-
end
|
3
|
+
require_relative "ruby_syntax_lsp/cli"
|
4
|
+
require_relative "ruby_syntax_lsp/core"
|
5
|
+
require_relative "ruby_syntax_lsp/version"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_syntax_lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sevenc-nanashi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -34,6 +34,9 @@ extra_rdoc_files: []
|
|
34
34
|
files:
|
35
35
|
- exe/ruby_syntax_lsp
|
36
36
|
- lib/ruby_syntax_lsp.rb
|
37
|
+
- lib/ruby_syntax_lsp/cli.rb
|
38
|
+
- lib/ruby_syntax_lsp/core.rb
|
39
|
+
- lib/ruby_syntax_lsp/version.rb
|
37
40
|
homepage: https://github.com/sevenc-nanashi/ruby_syntax_lsp
|
38
41
|
licenses:
|
39
42
|
- MIT
|
@@ -57,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
60
|
- !ruby/object:Gem::Version
|
58
61
|
version: '0'
|
59
62
|
requirements: []
|
60
|
-
rubygems_version: 3.
|
63
|
+
rubygems_version: 3.4.1
|
61
64
|
signing_key:
|
62
65
|
specification_version: 4
|
63
66
|
summary: A Ruby Language Server that checks syntax
|