rucoa 0.4.0 → 0.6.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +12 -2
  5. data/README.md +47 -17
  6. data/data/definitions_ruby_3_1 +0 -0
  7. data/images/diagnostics.gif +0 -0
  8. data/images/document-formatting.gif +0 -0
  9. data/images/document-symbol.gif +0 -0
  10. data/images/selection-ranges.gif +0 -0
  11. data/lib/rucoa/cli.rb +3 -2
  12. data/lib/rucoa/configuration.rb +111 -32
  13. data/lib/rucoa/definition_archiver.rb +29 -0
  14. data/lib/rucoa/definition_builders/rbs_constant_definition_builder.rb +44 -0
  15. data/lib/rucoa/definition_builders/rbs_method_definition_builder.rb +106 -0
  16. data/lib/rucoa/definition_builders/yard_method_definition_builder.rb +218 -0
  17. data/lib/rucoa/definition_builders.rb +9 -0
  18. data/lib/rucoa/definition_store.rb +63 -0
  19. data/lib/rucoa/definitions/base.rb +12 -0
  20. data/lib/rucoa/definitions/constant_definition.rb +51 -0
  21. data/lib/rucoa/definitions/method_definition.rb +126 -0
  22. data/lib/rucoa/definitions/method_parameter_definition.rb +30 -0
  23. data/lib/rucoa/definitions.rb +9 -0
  24. data/lib/rucoa/handlers/base.rb +8 -0
  25. data/lib/rucoa/handlers/exit_handler.rb +11 -0
  26. data/lib/rucoa/handlers/initialize_handler.rb +13 -0
  27. data/lib/rucoa/handlers/initialized_handler.rb +10 -0
  28. data/lib/rucoa/handlers/shutdown_handler.rb +12 -0
  29. data/lib/rucoa/handlers/text_document_completion_handler.rb +216 -0
  30. data/lib/rucoa/handlers/text_document_did_change_handler.rb +1 -20
  31. data/lib/rucoa/handlers/text_document_did_open_handler.rb +11 -4
  32. data/lib/rucoa/handlers/text_document_document_symbol_handler.rb +5 -4
  33. data/lib/rucoa/handlers/text_document_hover_handler.rb +76 -0
  34. data/lib/rucoa/handlers/text_document_range_formatting_handler.rb +1 -1
  35. data/lib/rucoa/handlers/text_document_selection_range_handler.rb +3 -3
  36. data/lib/rucoa/handlers/text_document_signature_help_handler.rb +68 -0
  37. data/lib/rucoa/handlers.rb +5 -0
  38. data/lib/rucoa/node_inspector.rb +111 -0
  39. data/lib/rucoa/nodes/base.rb +30 -0
  40. data/lib/rucoa/nodes/def_node.rb +59 -0
  41. data/lib/rucoa/nodes/lvar_node.rb +25 -0
  42. data/lib/rucoa/nodes/send_node.rb +43 -0
  43. data/lib/rucoa/nodes.rb +1 -0
  44. data/lib/rucoa/parser_builder.rb +1 -0
  45. data/lib/rucoa/position.rb +14 -3
  46. data/lib/rucoa/range.rb +64 -14
  47. data/lib/rucoa/rbs_document_loader.rb +43 -0
  48. data/lib/rucoa/rubocop_autocorrector.rb +1 -1
  49. data/lib/rucoa/rubocop_investigator.rb +1 -1
  50. data/lib/rucoa/server.rb +63 -13
  51. data/lib/rucoa/source.rb +59 -4
  52. data/lib/rucoa/source_store.rb +6 -10
  53. data/lib/rucoa/types/method_type.rb +23 -0
  54. data/lib/rucoa/types.rb +7 -0
  55. data/lib/rucoa/version.rb +1 -1
  56. data/lib/rucoa/yard_glob_document_loader.rb +47 -0
  57. data/lib/rucoa/yard_string_document_loader.rb +70 -0
  58. data/lib/rucoa.rb +9 -0
  59. data/rucoa.gemspec +2 -0
  60. metadata +58 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1656b3603d72a44829a30fd9bd0d0d876ab9daa3af05cad16ad78298fa6fce7d
4
- data.tar.gz: ff2fffdb7e90ed0f23cf782bc5c25db77dabb327c3e5b1d0a92aad8d2a5dc201
3
+ metadata.gz: f31a0a81d1013267e3bfc0358911e1306e22f0b34f40249604050914da18d8f4
4
+ data.tar.gz: b999e9fe78ee1dbb0b11662756c84399b474fb8522476429c90becb454fb0fd1
5
5
  SHA512:
6
- metadata.gz: 49421faba6f35b3cf0bd33c12ae521cf55125fc8c8b044f5a4d353b4ee9413150b0ca4082884e786329b1cefa3cb5eb5ab513b9723e638cb9786ab768d2f8dd0
7
- data.tar.gz: 8ef7dfaf46a49d70eb9404558191aadb3e1778f761a4642c432b53c9e3b1f208ff57f64a5b43ec7aef527dc4b573baaed10f4d859043574e86452b0af60aecb4
6
+ metadata.gz: 1af0f2fed0d7d7930f69768234263e77707f1f22d80e93392ae126c0cfa72d11b3356de6ba5c6f3476ff7b3f27239c1667ac1c2442e9e12301bdadb0a25fec47
7
+ data.tar.gz: bdd44ba9cb0284a16589798ec20ee7d9e9bf01989e054108859f3f8286a3f6382a45d84be056dd7a755de8b14d4cf9e28610652489e8e57f9c009b1f81c7f432
data/.rubocop.yml CHANGED
@@ -29,6 +29,9 @@ RSpec/MultipleMemoizedHelpers:
29
29
  RSpec/NamedSubject:
30
30
  Enabled: false
31
31
 
32
+ Security/MarshalLoad:
33
+ Enabled: false
34
+
32
35
  Sevencop/HashLiteralOrder:
33
36
  Enabled: true
34
37
 
data/Gemfile CHANGED
@@ -11,3 +11,4 @@ gem 'rubocop-performance'
11
11
  gem 'rubocop-rake'
12
12
  gem 'rubocop-rspec'
13
13
  gem 'sevencop'
14
+ gem 'yardspec'
data/Gemfile.lock CHANGED
@@ -1,9 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rucoa (0.4.0)
4
+ rucoa (0.6.0)
5
5
  parser
6
+ rbs
6
7
  rubocop
8
+ yard
7
9
 
8
10
  GEM
9
11
  remote: https://rubygems.org/
@@ -16,6 +18,7 @@ GEM
16
18
  ast (~> 2.4.1)
17
19
  rainbow (3.1.1)
18
20
  rake (13.0.6)
21
+ rbs (2.6.0)
19
22
  regexp_parser (2.5.0)
20
23
  rexml (3.2.5)
21
24
  rspec (3.11.0)
@@ -51,9 +54,15 @@ GEM
51
54
  rubocop-rspec (2.12.1)
52
55
  rubocop (~> 1.31)
53
56
  ruby-progressbar (1.11.0)
54
- sevencop (0.9.3)
57
+ sevencop (0.10.0)
55
58
  rubocop
56
59
  unicode-display_width (2.2.0)
60
+ webrick (1.7.0)
61
+ yard (0.9.28)
62
+ webrick (~> 1.7.0)
63
+ yardspec (0.2.0)
64
+ rspec
65
+ yard
57
66
 
58
67
  PLATFORMS
59
68
  x86_64-linux
@@ -67,6 +76,7 @@ DEPENDENCIES
67
76
  rubocop-rspec
68
77
  rucoa!
69
78
  sevencop
79
+ yardspec
70
80
 
71
81
  BUNDLED WITH
72
82
  2.3.21
data/README.md CHANGED
@@ -15,15 +15,6 @@ To install rucoa gem, if your project is managed by bundler, add to your Gemfile
15
15
  gem 'rucoa'
16
16
  ```
17
17
 
18
- or in Rails application, we'll recommend you to do like this:
19
-
20
- ```ruby
21
- # Gemfile
22
- group :development do
23
- gem 'rucoa', require: false
24
- end
25
- ```
26
-
27
18
  If bundler is not being used to manage dependencies, simply install the gem:
28
19
 
29
20
  ```bash
@@ -32,16 +23,55 @@ gem install rucoa
32
23
 
33
24
  ## Features
34
25
 
35
- - Diagnostics
36
- - Formatting
37
- - Quick Fix
38
- - Selection Range
39
- - Symbol
26
+ ### Diagnostics
27
+
28
+ Displays RuboCop offenses and provides Quick Fix action for autocorrection.
29
+
30
+ ![demo](images/diagnostics.gif)
31
+
32
+ ### Formatting
33
+
34
+ Run "Format Document" command or enable "Format On Save" in the settings to autocorrect RuboCop offenses.
35
+
36
+ ![demo](images/document-formatting.gif)
37
+
38
+ ### Selection
39
+
40
+ Run "Expand Selection" command to select appropriate ranges.
41
+
42
+ ![demo](images/selection-ranges.gif)
43
+
44
+ ### Symbol
45
+
46
+ See Outline section in the explorer panel to see document symbols in the current file, or run "Go to Symbol" command to search for symbols.
47
+
48
+ This extension supports the folowiing types of symbols:
49
+
50
+ - class
51
+ - module
52
+ - constant
53
+ - instance method
54
+ - singleton method (a.k.a. class method)
55
+ - attribute (attr_accessor, attr_reader, and attr_writer)
56
+
57
+ ![demo](images/document-symbol.gif)
58
+
59
+ ## Experimental features
60
+
61
+ ### Completion
62
+
63
+ Provides completion items for constant names and method names.
64
+
65
+ ### Hover
66
+
67
+ Shows documentation for the symbol under the cursor.
68
+
69
+ ### Signature help
70
+
71
+ Shows method signature help when you start to type method arguments like `"100".to_i(`.
40
72
 
41
- ### Coming soon
73
+ ## Coming soon
42
74
 
43
- - Completion
44
- - Documentation
45
75
  - Go to Definition
46
76
  - Highlight
47
77
  - Semantic Tokens
Binary file
Binary file
Binary file
Binary file
Binary file
data/lib/rucoa/cli.rb CHANGED
@@ -16,8 +16,9 @@ module Rucoa
16
16
  # @return [void]
17
17
  def call
18
18
  Server.new(
19
- input: $stdin,
20
- output: $stdout
19
+ io_in: $stdin,
20
+ io_log: $stderr,
21
+ io_out: $stdout
21
22
  ).start
22
23
  end
23
24
  end
@@ -2,57 +2,114 @@
2
2
 
3
3
  module Rucoa
4
4
  class Configuration
5
- DEFAULT_SETTINGS = {
6
- 'base' => {
7
- 'enable' => 'auto',
8
- 'useBundler' => 'auto'
9
- },
10
- 'feature' => {
11
- 'codeAction' => {
12
- 'enable' => true
13
- },
14
- 'diagnostics' => {
15
- 'enable' => true
16
- },
17
- 'documentSymbol' => {
18
- 'enable' => true
19
- },
20
- 'formatting' => {
21
- 'enable' => true
22
- },
23
- 'selectionRange' => {
24
- 'enable' => true
25
- }
26
- }
27
- }.freeze
28
-
29
5
  def initialize
30
- reset
6
+ @settings = {}
7
+ end
8
+
9
+ # @return [void]
10
+ def disable_code_action
11
+ disable_feature('codeAction')
12
+ end
13
+
14
+ # @return [void]
15
+ def disable_completion
16
+ disable_feature('completion')
17
+ end
18
+
19
+ # @return [void]
20
+ def disable_diagnostics
21
+ disable_feature('diagnostics')
22
+ end
23
+
24
+ # @return [void]
25
+ def disable_document_symbol
26
+ disable_feature('documentSymbol')
27
+ end
28
+
29
+ # @return [void]
30
+ def disable_formatting
31
+ disable_feature('formatting')
32
+ end
33
+
34
+ # @return [void]
35
+ def disable_hover
36
+ disable_feature('hover')
37
+ end
38
+
39
+ # @return [void]
40
+ def disable_selection_range
41
+ disable_feature('selectionRange')
42
+ end
43
+
44
+ # @return [void]
45
+ def disable_signature_help
46
+ disable_feature('signatureHelp')
47
+ end
48
+
49
+ # @return [void]
50
+ def enable_debug
51
+ @settings ||= {}
52
+ @settings['base'] ||= {}
53
+ @settings['base']['debug'] = true
31
54
  end
32
55
 
33
56
  # @return [Boolean]
57
+ # @example returns false if the configuration is empty
58
+ # configuration = Rucoa::Configuration.new
59
+ # expect(configuration).not_to be_enables_debug
60
+ # @example returns true if the configuration enables debug
61
+ # configuration = Rucoa::Configuration.new
62
+ # configuration.update('base' => { 'debug' => true })
63
+ # expect(configuration).to be_enables_debug
64
+ def enables_debug?
65
+ fetch('base', 'debug', default: false)
66
+ end
67
+
68
+ # @return [Boolean]
69
+ # @example returns true if the configuration is empty
70
+ # configuration = Rucoa::Configuration.new
71
+ # expect(configuration).to be_enables_code_action
72
+ # @example returns false if the configuration disables code action
73
+ # configuration = Rucoa::Configuration.new
74
+ # configuration.disable_code_action
75
+ # expect(configuration).not_to be_enables_code_action
34
76
  def enables_code_action?
35
- @settings.dig('feature', 'codeAction', 'enable')
77
+ enables_feature?('codeAction')
78
+ end
79
+
80
+ # @return [Boolean]
81
+ def enables_completion?
82
+ enables_feature?('completion')
36
83
  end
37
84
 
38
85
  # @return [Boolean]
39
86
  def enables_diagnostics?
40
- @settings.dig('feature', 'diagnostics', 'enable')
87
+ enables_feature?('diagnostics')
41
88
  end
42
89
 
43
90
  # @return [Boolean]
44
91
  def enables_document_symbol?
45
- @settings.dig('feature', 'documentSymbol', 'enable')
92
+ enables_feature?('documentSymbol')
46
93
  end
47
94
 
48
95
  # @return [Boolean]
49
96
  def enables_formatting?
50
- @settings.dig('feature', 'formatting', 'enable')
97
+ enables_feature?('formatting')
98
+ end
99
+
100
+ # @return [Boolean]
101
+ def enables_hover?
102
+ enables_feature?('hover')
51
103
  end
52
104
 
53
105
  # @return [Boolean]
54
106
  def enables_selection_range?
55
- @settings.dig('feature', 'selectionRange', 'enable')
107
+ enables_feature?('selectionRange')
108
+ end
109
+
110
+ # @return [Boolean]
111
+ def enables_signature_help?
112
+ enables_feature?('signatureHelp')
56
113
  end
57
114
 
58
115
  # @param settings [Hash]
@@ -63,9 +120,31 @@ module Rucoa
63
120
 
64
121
  private
65
122
 
123
+ # @param feature [String]
66
124
  # @return [void]
67
- def reset
68
- @settings = DEFAULT_SETTINGS.dup
125
+ def disable_feature(feature)
126
+ @settings ||= {}
127
+ @settings['feature'] ||= {}
128
+ @settings['feature'][feature] ||= {}
129
+ @settings['feature'][feature]['enable'] = false
130
+ end
131
+
132
+ # @param feature [String]
133
+ # @return [Boolean]
134
+ def enables_feature?(feature)
135
+ fetch('feature', feature, 'enable', default: true)
136
+ end
137
+
138
+ # @param keys [Array<String>]
139
+ # @param default [Object]
140
+ # @return [Object]
141
+ def fetch(*keys, default:)
142
+ value = @settings.dig(*keys)
143
+ if value.nil?
144
+ default
145
+ else
146
+ value
147
+ end
69
148
  end
70
149
  end
71
150
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module Rucoa
6
+ class DefinitionArchiver
7
+ RUBY_DEFINITIONS_DUMP_PATH = ::File.expand_path('../../data/definitions_ruby_3_1', __dir__).freeze
8
+ private_constant :RUBY_DEFINITIONS_DUMP_PATH
9
+
10
+ class << self
11
+ # @param definitions [Array<Rucoa::Definition::Base>]
12
+ # @return [void]
13
+ def dump(definitions)
14
+ pathname = ::Pathname.new(RUBY_DEFINITIONS_DUMP_PATH)
15
+ pathname.parent.mkpath
16
+ pathname.write(
17
+ ::Marshal.dump(definitions)
18
+ )
19
+ end
20
+
21
+ # @return [Array<Rucoa::Definition::Base>]
22
+ def load
23
+ ::Marshal.load(
24
+ ::File.binread(RUBY_DEFINITIONS_DUMP_PATH)
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rucoa
4
+ module DefinitionBuilders
5
+ # Build Rucoa contant definition from RBS constant declaration.
6
+ class RbsConstantDefinitionBuilder
7
+ class << self
8
+ # @param declaration [RBS::AST::Declarations::Constant]
9
+ # @return [Rucoa::Definitions::ConstantDefinition]
10
+ def call(declaration:)
11
+ new(
12
+ declaration: declaration
13
+ ).call
14
+ end
15
+ end
16
+
17
+ # @param declaration [RBS::AST::Declarations::Constant]
18
+ # @return [Rucoa::Definitions::ConstantDefinition]
19
+ def initialize(declaration:)
20
+ @declaration = declaration
21
+ end
22
+
23
+ # @return [Rucoa::Definitions::ConstantDefinition]
24
+ def call
25
+ ::Rucoa::Definitions::ConstantDefinition.new(
26
+ full_qualified_name: full_qualified_name,
27
+ source_path: source_path
28
+ )
29
+ end
30
+
31
+ private
32
+
33
+ # @return [String]
34
+ def full_qualified_name
35
+ @declaration.name.to_s.delete_prefix('::')
36
+ end
37
+
38
+ # @return [String]
39
+ def source_path
40
+ @declaration.location.name
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rbs'
4
+
5
+ module Rucoa
6
+ module DefinitionBuilders
7
+ # Build Rucoa method definition from RBS method definition.
8
+ class RbsMethodDefinitionBuilder
9
+ class << self
10
+ # @param declaration [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
11
+ # @param method_definition [RBS::AST::Members::MethodDefinition]
12
+ # @return [Rucoa::Definitions::MethodDefinition]
13
+ def call(declaration:, method_definition:)
14
+ new(
15
+ declaration: declaration,
16
+ method_definition: method_definition
17
+ ).call
18
+ end
19
+ end
20
+
21
+ # @param declaration [RBS::AST::Declarations::Class, RBS::AST::Declarations::Module]
22
+ # @param method_definition [RBS::AST::Members::MethodDefinition]
23
+ def initialize(declaration:, method_definition:)
24
+ @declaration = declaration
25
+ @method_definition = method_definition
26
+ end
27
+
28
+ # @return [Rucoa::Definitions::MethodDefinition]
29
+ def call
30
+ Definitions::MethodDefinition.new(
31
+ description: description,
32
+ kind: kind,
33
+ method_name: method_name,
34
+ namespace: namespace,
35
+ source_path: source_path,
36
+ types: types
37
+ )
38
+ end
39
+
40
+ private
41
+
42
+ # @return [Array<Rucoa::Types::MethodType>]
43
+ def types
44
+ @method_definition.types.map do |method_type|
45
+ RbsMethodTypeToRucoaMethodTypeMapper.call(
46
+ method_type: method_type
47
+ )
48
+ end
49
+ end
50
+
51
+ # @return [String, nil]
52
+ def description
53
+ @method_definition.comment&.string&.sub(/\A\s*<!--.*-->\s*/m, '')
54
+ end
55
+
56
+ # @return [String]
57
+ def namespace
58
+ @declaration.name.to_s.delete_prefix('::')
59
+ end
60
+
61
+ # @return [String]
62
+ def method_name
63
+ @method_definition.name.to_s
64
+ end
65
+
66
+ # @return [Symbol]
67
+ def kind
68
+ @method_definition.kind
69
+ end
70
+
71
+ # @return [String]
72
+ def source_path
73
+ @declaration.location.name
74
+ end
75
+
76
+ class RbsMethodTypeToRucoaMethodTypeMapper
77
+ class << self
78
+ # @param method_type [RBS::Types::MethodType]
79
+ # @return [Rucoa::Types::MethodType]
80
+ def call(method_type:)
81
+ new(method_type: method_type).call
82
+ end
83
+
84
+ # @param type [RBS::Types::Base]
85
+ # @return [String]
86
+ def stringify(type)
87
+ type.to_s.delete_prefix('::')
88
+ end
89
+ end
90
+
91
+ # @param method_type [RBS::Types::MethodType]
92
+ def initialize(method_type:)
93
+ @method_type = method_type
94
+ end
95
+
96
+ # @return [Rucoa::Types::MethodType]
97
+ def call
98
+ Types::MethodType.new(
99
+ parameters_string: @method_type.type.param_to_s,
100
+ return_type: self.class.stringify(@method_type.type.return_type)
101
+ )
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end