rubocop-language-server 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c853c364ec0cc7e3719baf350aad7066e178b86f69cf2df6e62cbe3e3b5027f
4
- data.tar.gz: 86ae737c1675cf0463cb4b42101392d1d0a2aeaec4488689ec46d289f201719c
3
+ metadata.gz: 0435ae728e2ef62d03b6083d4258aad99d19fec9079c259f6aedd9920b75f30f
4
+ data.tar.gz: 62e717b8af33b4e3c53f11abb60e81b51b5de406a05e1766a4edbda99f1e8a2e
5
5
  SHA512:
6
- metadata.gz: 6abc7037d1a27fe23a3b0141f3456330964fbcf339b94304794e8c58a2303ad14a6f0b021b6c2c448a370775103de51311750a9a3521627f111f38b3060a9b36
7
- data.tar.gz: 71420c7136ecb89943a524cf5e82a62cdd436594c95f3324cc8cb4968e6c931f5c516a0b4153395eced0eb9c7e0d45fa0b77d4cc55fc6dc5bbcceb772f5b628d
6
+ metadata.gz: 9006babbc5f87a95cd4ee62c6c1b2bec77c95c29938a31e78aecff62303d7c4b14a3fddd7b4c56c2ec06f81e6bd763467d155df2f19c7fbd1319427e423badb0
7
+ data.tar.gz: 0bfe2126e06f394a6e663224b643c70012cf5b0338ecf5b6d10266be16d59c2ce2fc178275a8ef99b8177cf0506e168a0ffc02eba0306b26f38f2805ca6c2b16
@@ -0,0 +1,16 @@
1
+ name: Ruby
2
+
3
+ on: [push,pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v2
10
+ - name: Set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: 3.0.1
14
+ bundler-cache: true
15
+ - name: Run the default task
16
+ run: bundle exec rake
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ SuggestExtensions: false
4
+ TargetRubyVersion: 3.0
5
+
6
+ Layout/HashAlignment:
7
+ EnforcedColonStyle: table
8
+
9
+ Metrics/AbcSize:
10
+ Enabled: false
11
+
12
+ Metrics/BlockLength:
13
+ Enabled: false
14
+
15
+ Metrics/MethodLength:
16
+ Enabled: false
17
+
18
+ Style/Documentation:
19
+ Enabled: false
20
+
21
+ Style/FrozenStringLiteralComment:
22
+ Enabled: false
23
+
24
+ Style/IfUnlessModifier:
25
+ Enabled: false
@@ -0,0 +1,4 @@
1
+ {
2
+ // "rubocop-language-server.trace.server": "verbose",
3
+ "editor.formatOnSave": true
4
+ }
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rubocop-language-server.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rubocop-language-server (0.1.6)
5
+ language_server-protocol (>= 3.16)
6
+ rubocop (>= 1.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.2)
12
+ language_server-protocol (3.16.0.1)
13
+ parallel (1.20.1)
14
+ parser (3.0.2.0)
15
+ ast (~> 2.4.1)
16
+ rainbow (3.0.0)
17
+ rake (13.0.6)
18
+ regexp_parser (2.1.1)
19
+ rexml (3.2.5)
20
+ rubocop (1.18.3)
21
+ parallel (~> 1.10)
22
+ parser (>= 3.0.0.0)
23
+ rainbow (>= 2.2.2, < 4.0)
24
+ regexp_parser (>= 1.8, < 3.0)
25
+ rexml
26
+ rubocop-ast (>= 1.7.0, < 2.0)
27
+ ruby-progressbar (~> 1.7)
28
+ unicode-display_width (>= 1.4.0, < 3.0)
29
+ rubocop-ast (1.8.0)
30
+ parser (>= 3.0.1.1)
31
+ ruby-progressbar (1.11.0)
32
+ unicode-display_width (2.0.0)
33
+
34
+ PLATFORMS
35
+ x86_64-darwin-20
36
+ x86_64-darwin-21
37
+
38
+ DEPENDENCIES
39
+ rake (~> 13.0)
40
+ rubocop-language-server!
41
+
42
+ BUNDLED WITH
43
+ 2.2.20
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Ufuk Kayserilioglu
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # RuboCop Language Server
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/rubocop/language-server`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'rubocop-language-server'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rubocop-language-server
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/withgrayce/rubocop-language-server. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/withgrayce/rubocop-language-server/blob/main/CODE_OF_CONDUCT.md).
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the Rubocop::LanguageServer project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/withgrayce/rubocop-language-server/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'rubocop-language-server'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,4 @@
1
+ #! /usr/bin/env ruby
2
+ require_relative '../lib/rubocop/language/server/cli'
3
+
4
+ Rubocop::Language::Server::Cli.start(ARGV)
@@ -0,0 +1,79 @@
1
+ require 'rubocop'
2
+ require 'language_server-protocol'
3
+
4
+ # require 'rubocop-language-server'
5
+ require_relative 'handler'
6
+
7
+ module Rubocop
8
+ module Language
9
+ module Server
10
+ module Cli
11
+ def self.start(_argv)
12
+ handler = Handler.new
13
+
14
+ handler.config do
15
+ on('initialize') do
16
+ store.clear
17
+
18
+ respond_with_capabilities
19
+ end
20
+
21
+ on('shutdown') do
22
+ store.clear
23
+
24
+ nil
25
+ end
26
+
27
+ on('textDocument/didChange') do |request|
28
+ uri = request.dig(:params, :textDocument, :uri)
29
+ text = request.dig(:params, :contentChanges, 0, :text)
30
+
31
+ collector = collect_diagnostics(uri: uri, text: text)
32
+ send_diagnostics(collector)
33
+
34
+ nil
35
+ end
36
+
37
+ on('textDocument/didOpen') do |request|
38
+ uri = request.dig(:params, :textDocument, :uri)
39
+ text = request.dig(:params, :textDocument, :text)
40
+
41
+ collector = collect_diagnostics(uri: uri, text: text)
42
+ send_diagnostics(collector)
43
+
44
+ nil
45
+ end
46
+
47
+ on('textDocument/didClose') do |request|
48
+ uri = request.dig(:params, :textDocument, :uri)
49
+
50
+ clear_diagnostics(uri: uri)
51
+
52
+ nil
53
+ end
54
+
55
+ on('textDocument/formatting') do |request|
56
+ uri = request.dig(:params, :textDocument, :uri)
57
+
58
+ collector = collect_diagnostics(uri: uri, text: store.text_for(uri))
59
+ send_text_edits(collector)
60
+ end
61
+
62
+ on('textDocument/codeAction') do |request|
63
+ uri = request.dig(:params, :textDocument, :uri)
64
+ range = request.dig(:params, :range)
65
+ start_line = range.dig(:start, :line)
66
+ end_line = range.dig(:end, :line)
67
+
68
+ line_range = Range.new(start_line, end_line)
69
+
70
+ send_code_actions(uri, line_range)
71
+ end
72
+ end
73
+
74
+ handler.start
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,48 @@
1
+ require_relative 'model/diagnostic_collection'
2
+
3
+ module Rubocop
4
+ module Language
5
+ module Server
6
+ class DiagnosticCollector < RuboCop::Runner
7
+ RUBOCOP_FLAGS = [
8
+ '--stderr', # Print any output to stderr so that our stdout does not get polluted
9
+ '--format',
10
+ 'quiet', # Supress any progress output by setting the formatter to `quiet`
11
+ '--auto-correct' # Apply the autocorrects on the supplied buffer
12
+ ].freeze
13
+
14
+ attr_reader :uri, :file, :text, :formatted_text, :diagnostics
15
+
16
+ def initialize(uri:, text:)
17
+ @uri = uri
18
+ @file = CGI.unescape(URI.parse(uri).path)
19
+ @text = text
20
+ @formatted_text = nil
21
+
22
+ super(
23
+ ::RuboCop::Options.new.parse(RUBOCOP_FLAGS).first,
24
+ ::RuboCop::ConfigStore.new
25
+ )
26
+ end
27
+
28
+ def run
29
+ # Send text via "stdin".
30
+ # RuboCop reads all of stdin into the "stdin" option, when `--stdin`
31
+ # flag is supplied
32
+ @options[:stdin] = text
33
+
34
+ # Invoke the actual run method with just this file in `paths`
35
+ super([file])
36
+
37
+ # RuboCop applies autocorrections to the "stdin" option,
38
+ # so read that into the formatted text attribute
39
+ @formatted_text = @options[:stdin]
40
+ end
41
+
42
+ def file_finished(_file, offenses)
43
+ @diagnostics = Model::DiagnosticCollection.new(uri, offenses)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,124 @@
1
+ require_relative 'state_store'
2
+ require_relative 'diagnostic_collector'
3
+
4
+ module Rubocop
5
+ module Language
6
+ module Server
7
+ class Handler
8
+ Interface = LanguageServer::Protocol::Interface
9
+ Constant = LanguageServer::Protocol::Constant
10
+
11
+ def initialize
12
+ @writer = LanguageServer::Protocol::Transport::Stdio::Writer.new
13
+ @reader = LanguageServer::Protocol::Transport::Stdio::Reader.new
14
+ @handlers = {}
15
+ @store = StateStore.new
16
+ end
17
+
18
+ def config(&blk)
19
+ instance_exec(&blk)
20
+ end
21
+
22
+ def start
23
+ reader.read do |request|
24
+ handle(request)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :writer, :reader, :store
31
+
32
+ def on(message, &blk)
33
+ @handlers[message.to_s] = blk
34
+ end
35
+
36
+ def handler_for(request)
37
+ @handlers[request[:method]]
38
+ end
39
+
40
+ def handle(request)
41
+ log("Got request method: #{request[:method]}")
42
+ handler = handler_for(request)
43
+ result = handler.call(request) if handler
44
+ writer.write(id: request[:id], result: result) if result
45
+ end
46
+
47
+ def log(msg)
48
+ warn(msg)
49
+ end
50
+
51
+ def notify(method:, params: {})
52
+ log("In notify: #{writer}")
53
+ writer.write(method: method, params: params)
54
+ end
55
+
56
+ def respond_with_capabilities
57
+ Interface::InitializeResult.new(
58
+ capabilities: Interface::ServerCapabilities.new(
59
+ text_document_sync: Interface::TextDocumentSyncOptions.new(
60
+ change: Constant::TextDocumentSyncKind::FULL,
61
+ open_close: true
62
+ ),
63
+ document_formatting_provider: true,
64
+ code_action_provider: true
65
+ )
66
+ )
67
+ end
68
+
69
+ def notify_diagnostics(uri:, diagnostics_response:)
70
+ notify(
71
+ method: 'textDocument/publishDiagnostics',
72
+ params: Interface::PublishDiagnosticsParams.new(
73
+ uri: uri,
74
+ diagnostics: diagnostics_response
75
+ )
76
+ )
77
+ end
78
+
79
+ def clear_diagnostics(uri:)
80
+ store.delete(uri)
81
+
82
+ notify_diagnostics(uri: uri, diagnostics_response: [])
83
+ end
84
+
85
+ def send_diagnostics(collector)
86
+ notify_diagnostics(
87
+ uri: collector.uri,
88
+ diagnostics_response: collector.diagnostics.response
89
+ )
90
+ end
91
+
92
+ def send_code_actions(uri, line_range)
93
+ store.code_actions_for(uri, line_range)
94
+ end
95
+
96
+ def send_text_edits(collector)
97
+ return unless collector.formatted_text
98
+
99
+ [
100
+ Interface::TextEdit.new(
101
+ range: Interface::Range.new(
102
+ start: Interface::Position.new(line: 0, character: 0),
103
+ end: Interface::Position.new(
104
+ line: collector.text.size,
105
+ character: collector.text.size
106
+ )
107
+ ),
108
+ new_text: collector.formatted_text
109
+ )
110
+ ]
111
+ end
112
+
113
+ def collect_diagnostics(uri:, text:)
114
+ collector = DiagnosticCollector.new(uri: uri, text: text)
115
+ collector.run
116
+
117
+ store.set(uri: collector.uri, text: collector.text, diagnostics: collector.diagnostics)
118
+
119
+ collector
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,94 @@
1
+ module Rubocop
2
+ module Language
3
+ module Server
4
+ module Model
5
+ class Diagnostic
6
+ attr_reader :badge, :message, :start, :end, :replacements
7
+
8
+ DOCS_URLS = {
9
+ Bundler: 'https://docs.rubocop.org/rubocop/cops_bundler.html#%{anchor}',
10
+ Gemspec: 'https://docs.rubocop.org/rubocop/cops_gemspec.html#%{anchor}',
11
+ Layout: 'https://docs.rubocop.org/rubocop/cops_layout.html#%{anchor}',
12
+ Lint: 'https://docs.rubocop.org/rubocop/cops_lint.html#%{anchor}',
13
+ Metrics: 'https://docs.rubocop.org/rubocop/cops_metrics.html#%{anchor}',
14
+ Migration: 'https://docs.rubocop.org/rubocop/cops_migration.html#%{anchor}',
15
+ Naming: 'https://docs.rubocop.org/rubocop/cops_naming.html#%{anchor}',
16
+ Security: 'https://docs.rubocop.org/rubocop/cops_security.html#%{anchor}',
17
+ Style: 'https://docs.rubocop.org/rubocop/cops_style.html#%{anchor}',
18
+ Minitest: 'https://docs.rubocop.org/rubocop-minitest/cops_minitest.html#%{anchor}',
19
+ Performance: 'https://docs.rubocop.org/rubocop-performance/cops_performance.html#%{anchor}',
20
+ Rails: 'https://docs.rubocop.org/rubocop-rails/cops_rails.html#%{anchor}',
21
+ RSpec: 'https://docs.rubocop.org/rubocop-rspec/cops_rspec.html#%{anchor}',
22
+ 'RSpec/Capybara': 'https://docs.rubocop.org/rubocop-rspec/cops_rspec/capybara.html#%{anchor}',
23
+ 'RSpec/FactoryBot': 'https://docs.rubocop.org/rubocop-rspec/cops_rspec/factorybot.html#%{anchor}',
24
+ 'RSpec/Rails': 'https://docs.rubocop.org/rubocop-rspec/cops_rspec/rails.html#%{anchor}',
25
+ Sorbet: 'https://github.com/Shopify/rubocop-sorbet/blob/master/manual/cops_sorbet.md#%{anchor}'
26
+ }.freeze
27
+
28
+ def initialize(offense)
29
+ @badge = RuboCop::Cop::Badge.parse(offense.cop_name)
30
+ @message = offense.message
31
+ @start = Interface::Position.new(line: offense.line - 1, character: offense.column)
32
+ @end = Interface::Position.new(line: offense.last_line - 1, character: offense.last_column)
33
+ @replacements = replacements_from_offense(offense)
34
+ end
35
+
36
+ def correctable?
37
+ !!@replacements
38
+ end
39
+
40
+ def cop_name
41
+ @cop_name ||= badge.to_s
42
+ end
43
+
44
+ def diagnostic_response
45
+ @diagnostic_response ||= Interface::Diagnostic.new(
46
+ message: message,
47
+ source: 'RuboCop',
48
+ code: cop_name,
49
+ code_description: Interface::CodeDescription.new(
50
+ href: doc_url
51
+ ),
52
+ severity: Constant::DiagnosticSeverity::INFORMATION,
53
+ range: Interface::Range.new(
54
+ start: start,
55
+ end: self.end
56
+ )
57
+ )
58
+ end
59
+
60
+ private
61
+
62
+ def doc_url
63
+ @doc_url ||= begin
64
+ anchor = cop_name.downcase.gsub(%r{/}, '')
65
+ docs_url_template = DOCS_URLS[badge.department]
66
+
67
+ if docs_url_template
68
+ format(docs_url_template, anchor: anchor)
69
+ end
70
+ end
71
+ end
72
+
73
+ def replacements_from_offense(offense)
74
+ return unless offense.correctable?
75
+
76
+ offense.corrector.as_replacements.map do |range, replacement|
77
+ edit_from_replacement(range, replacement)
78
+ end
79
+ end
80
+
81
+ def edit_from_replacement(range, replacement)
82
+ Interface::TextEdit.new(
83
+ range: Interface::Range.new(
84
+ start: Interface::Position.new(line: range.line - 1, character: range.column),
85
+ end: Interface::Position.new(line: range.last_line - 1, character: range.last_column)
86
+ ),
87
+ new_text: replacement
88
+ )
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,78 @@
1
+ require_relative 'diagnostic'
2
+
3
+ module Rubocop
4
+ module Language
5
+ module Server
6
+ module Model
7
+ Interface = LanguageServer::Protocol::Interface
8
+ Constant = LanguageServer::Protocol::Constant
9
+
10
+ class DiagnosticCollection
11
+ attr_reader :uri, :diagnostics
12
+
13
+ def initialize(uri, offenses)
14
+ @uri = uri
15
+ @diagnostics = offenses.map do |offense|
16
+ Diagnostic.new(offense)
17
+ end
18
+ end
19
+
20
+ def response
21
+ diagnostics.map(&:diagnostic_response)
22
+ end
23
+
24
+ def correctable_diagnostics
25
+ @correctable_diagnostics ||= diagnostics.select(&:correctable?)
26
+ end
27
+
28
+ def code_actions(line_range)
29
+ line_diagnostics = correctable_diagnostics.select do |diagnostic|
30
+ line_range.include?(diagnostic.start.line)
31
+ end
32
+
33
+ actions = line_diagnostics.map do |diagnostic|
34
+ code_action_from(
35
+ diagnostic,
36
+ title: "Autocorrect `#{diagnostic.cop_name}`",
37
+ kind: Constant::CodeActionKind::QUICK_FIX
38
+ )
39
+ end
40
+
41
+ if actions.any?
42
+ actions << code_action_from(
43
+ line_diagnostics,
44
+ title: 'Autocorrect all offenses on line',
45
+ kind: 'rubocop.fix'
46
+ )
47
+ end
48
+
49
+ actions
50
+ end
51
+
52
+ private
53
+
54
+ def code_action_from(diagnostics, title:, kind:)
55
+ diagnostics = Array(diagnostics)
56
+
57
+ Interface::CodeAction.new(
58
+ title: title,
59
+ kind: kind,
60
+ edit: Interface::WorkspaceEdit.new(
61
+ document_changes: [
62
+ Interface::TextDocumentEdit.new(
63
+ text_document: Interface::OptionalVersionedTextDocumentIdentifier.new(
64
+ uri: uri,
65
+ version: nil
66
+ ),
67
+ edits: diagnostics.flat_map(&:replacements)
68
+ )
69
+ ]
70
+ ),
71
+ is_preferred: true
72
+ )
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,19 @@
1
+ module Rubocop
2
+ module Language
3
+ module Server
4
+ class State
5
+ attr_reader :uri, :text, :diagnostics
6
+
7
+ def initialize(uri:, text:, diagnostics: [])
8
+ @uri = uri
9
+ @text = text
10
+ @diagnostics = diagnostics
11
+ end
12
+
13
+ def code_actions(line_range)
14
+ diagnostics.code_actions(line_range)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,51 @@
1
+ require_relative 'state'
2
+
3
+ module Rubocop
4
+ module Language
5
+ module Server
6
+ class StateStore
7
+ def initialize
8
+ @state_map = {}
9
+ end
10
+
11
+ def clear
12
+ @state_map = {}
13
+ end
14
+
15
+ def delete(uri)
16
+ @state_map.delete(uri)
17
+ []
18
+ end
19
+
20
+ def set(uri:, text:, diagnostics: [])
21
+ @state_map[uri] = State.new(uri: uri, text: text, diagnostics: diagnostics || [])
22
+ end
23
+
24
+ def get(uri)
25
+ @state_map[uri]
26
+ end
27
+
28
+ def text_for(uri)
29
+ state = get(uri)
30
+
31
+ return state.text if state
32
+
33
+ file = CGI.unescape(URI.parse(uri).path)
34
+ File.binread(file)
35
+ end
36
+
37
+ def code_actions_for(uri, line_range)
38
+ state = get(uri)
39
+
40
+ return [] unless state
41
+
42
+ state.code_actions(line_range)
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :state_map
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ module Rubocop
2
+ module Language
3
+ module Server
4
+ VERSION = '0.0.2'.freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ # rubocop:disable Naming/FileName
2
+ require_relative 'language/server/version'
3
+
4
+ module Rubocop
5
+ module Language
6
+ module Server
7
+ end
8
+ end
9
+ end
10
+ # rubocop:enable Naming/FileName
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/rubocop/language/server/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rubocop-language-server'
7
+ spec.version = Rubocop::Language::Server::VERSION
8
+ spec.authors = ['Grayce']
9
+ spec.email = ['aubrey@withgrayce.com']
10
+
11
+ spec.summary = 'A Language Server Provider for RuboCop'
12
+ spec.homepage = 'https://github.com/withgrayce/rubocop-language-server'
13
+ spec.license = 'MIT'
14
+ spec.required_ruby_version = '>= 2.6.0'
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = 'https://github.com/withgrayce/rubocop-language-server'
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_runtime_dependency('rubocop', '>= 1.0')
31
+ spec.add_runtime_dependency('language_server-protocol', '>= 3.16')
32
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-language-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grayce
@@ -41,10 +41,33 @@ dependencies:
41
41
  description:
42
42
  email:
43
43
  - aubrey@withgrayce.com
44
- executables: []
44
+ executables:
45
+ - rubocop-language-server
45
46
  extensions: []
46
47
  extra_rdoc_files: []
47
- files: []
48
+ files:
49
+ - ".github/workflows/main.yml"
50
+ - ".gitignore"
51
+ - ".rubocop.yml"
52
+ - ".vscode/settings.json"
53
+ - Gemfile
54
+ - Gemfile.lock
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - bin/console
59
+ - bin/setup
60
+ - exe/rubocop-language-server
61
+ - lib/rubocop-language-server.rb
62
+ - lib/rubocop/language/server/cli.rb
63
+ - lib/rubocop/language/server/diagnostic_collector.rb
64
+ - lib/rubocop/language/server/handler.rb
65
+ - lib/rubocop/language/server/model/diagnostic.rb
66
+ - lib/rubocop/language/server/model/diagnostic_collection.rb
67
+ - lib/rubocop/language/server/state.rb
68
+ - lib/rubocop/language/server/state_store.rb
69
+ - lib/rubocop/language/server/version.rb
70
+ - rubocop-language-server.gemspec
48
71
  homepage: https://github.com/withgrayce/rubocop-language-server
49
72
  licenses:
50
73
  - MIT