rucoa 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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