steep 0.45.0 → 0.46.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/.github/workflows/ruby.yml +1 -0
  3. data/CHANGELOG.md +17 -2
  4. data/Gemfile.lock +2 -2
  5. data/lib/steep/cli.rb +7 -1
  6. data/lib/steep/diagnostic/lsp_formatter.rb +59 -6
  7. data/lib/steep/diagnostic/ruby.rb +51 -0
  8. data/lib/steep/drivers/check.rb +3 -0
  9. data/lib/steep/drivers/init.rb +10 -3
  10. data/lib/steep/drivers/utils/driver_helper.rb +15 -0
  11. data/lib/steep/drivers/validate.rb +1 -1
  12. data/lib/steep/drivers/watch.rb +3 -0
  13. data/lib/steep/project/dsl.rb +105 -33
  14. data/lib/steep/project/options.rb +12 -53
  15. data/lib/steep/project/target.rb +21 -8
  16. data/lib/steep/server/type_check_worker.rb +6 -9
  17. data/lib/steep/services/hover_content.rb +2 -2
  18. data/lib/steep/version.rb +1 -1
  19. data/sample/Steepfile +10 -3
  20. data/smoke/alias/Steepfile +2 -1
  21. data/smoke/and/Steepfile +2 -1
  22. data/smoke/array/Steepfile +2 -1
  23. data/smoke/block/Steepfile +2 -2
  24. data/smoke/case/Steepfile +2 -1
  25. data/smoke/class/Steepfile +2 -1
  26. data/smoke/const/Steepfile +2 -1
  27. data/smoke/diagnostics/Steepfile +2 -1
  28. data/smoke/diagnostics-rbs/Steepfile +1 -1
  29. data/smoke/diagnostics-rbs-duplicated/Steepfile +2 -1
  30. data/smoke/diagnostics-ruby-unsat/Steepfile +2 -1
  31. data/smoke/dstr/Steepfile +2 -1
  32. data/smoke/ensure/Steepfile +2 -1
  33. data/smoke/enumerator/Steepfile +2 -1
  34. data/smoke/extension/Steepfile +2 -1
  35. data/smoke/hash/Steepfile +2 -1
  36. data/smoke/hello/Steepfile +2 -1
  37. data/smoke/if/Steepfile +2 -1
  38. data/smoke/implements/Steepfile +2 -1
  39. data/smoke/initialize/Steepfile +2 -1
  40. data/smoke/integer/Steepfile +2 -1
  41. data/smoke/interface/Steepfile +2 -1
  42. data/smoke/kwbegin/Steepfile +2 -1
  43. data/smoke/lambda/Steepfile +2 -1
  44. data/smoke/literal/Steepfile +2 -1
  45. data/smoke/map/Steepfile +2 -1
  46. data/smoke/method/Steepfile +2 -1
  47. data/smoke/module/Steepfile +2 -1
  48. data/smoke/regexp/Steepfile +2 -1
  49. data/smoke/regression/Steepfile +2 -1
  50. data/smoke/rescue/Steepfile +2 -1
  51. data/smoke/self/Steepfile +2 -1
  52. data/smoke/skip/Steepfile +2 -1
  53. data/smoke/stdout/Steepfile +2 -1
  54. data/smoke/super/Steepfile +2 -1
  55. data/smoke/toplevel/Steepfile +2 -1
  56. data/smoke/tsort/Steepfile +4 -5
  57. data/smoke/type_case/Steepfile +2 -1
  58. data/smoke/unexpected/Steepfile +2 -1
  59. data/smoke/yield/Steepfile +2 -1
  60. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '080cf1692f90640baacc712908524e2daf36039ea992eb3424de7094c49f6778'
4
- data.tar.gz: dd9f8837ec50e625ce9a0814fcbef03191bf484debd33034f9d00819115fef81
3
+ metadata.gz: e43c16938ef0238a9b3e44934a3e183ec663722b4c1161f9bd016dfcd2442b9b
4
+ data.tar.gz: 20168ebc69417b83c9eff010d44aac53ac43f47c572c8acc99d52d08ec11866d
5
5
  SHA512:
6
- metadata.gz: 67d26f6197f5b4fe53195c2202cdbbf556e2496fda4498151646c6d93a8455de0b75af66c35b16f32375fc239574600e33cc5f8caf92cc8f96a659ca0588b4da
7
- data.tar.gz: 718c99448377245e8e0871af93c445d037aef4dbc727185bfd658f49672c08a11e8acc3807c7cb2a55814ffd32fb87642c9b37fc9f17143d4474a2810e2e4f3e
6
+ metadata.gz: 33c2bd116ea87f549ffb29fbc2382e7c000405a74280fcc4a1a8553ae52e6b7af3d5611a150c828d494fe50f37e120e58e45f286bd374bbd35958ee0c760c872
7
+ data.tar.gz: 0466f3f59d18bf0ba34ce522bc6a1cceed85c1f6ca4df66b6647a557bec165c64dd9d594f673833dc24a0b5a9d0eb04795bff37dc391e22cf560b566c6f08319
@@ -15,6 +15,7 @@ jobs:
15
15
  - "2.6"
16
16
  - "2.7"
17
17
  - "3.0"
18
+ - "master-nightly-focal"
18
19
  task:
19
20
  - test
20
21
  - test:output
data/CHANGELOG.md CHANGED
@@ -2,17 +2,32 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.46.0 (2021-08-30)
6
+
7
+ This release updates Steepfile DSL syntax, introducing `stdlib_path` and `configure_code_diagnostics` syntax (methods).
8
+
9
+ * `stdlib_path` allows configuring core/stdlib RBS file locations.
10
+ * `configure_code_diagnostics` allows configuring _severity_ of each type errors.
11
+
12
+ See the PRs for the explanation of these methods.
13
+ You can try `steep init` to generate updated `Steepfile` template.
14
+
15
+ * Flexible diagnostics configuration ([\#422](https://github.com/soutaro/steep/pull/422), [\#423](https://github.com/soutaro/steep/pull/423))
16
+ * Revise Steepfile _path_ DSL ([\#421](https://github.com/soutaro/steep/pull/421))
17
+ * Avoid to stop process by invalid jobs_count ([\#419](https://github.com/soutaro/steep/pull/419))
18
+ * Fix `Steep::Typing::UnknownNodeError` when hover method with numblock ([\#415](https://github.com/soutaro/steep/pull/415))
19
+
5
20
  ## 0.45.0 (2021-08-22)
6
21
 
7
22
  * Fix error reporting on `RBS::MixinClassError` ([\#411](https://github.com/soutaro/steep/pull/411))
8
23
  * Compact error reporting for method body type mismatch ([\#414](https://github.com/soutaro/steep/pull/414))
9
24
  * Fix NoMethodError with csend/numblock ([\#412](https://github.com/soutaro/steep/pull/412))
10
- * LSP completion for RBS files ([\#404](https://github.com/soutaro/steep/pull/404))
25
+ * LSP completion for RBS files ([\#404](https://github.com/soutaro/steep/pull/404))
11
26
  * Allow break without value from bot methods ([\#398](https://github.com/soutaro/steep/pull/398))
12
27
  * Type check on lvar assignments ([\#390](https://github.com/soutaro/steep/pull/390))
13
28
  * Assign different error code to break without value ([\#387](https://github.com/soutaro/steep/pull/387))
14
29
  * Support Ruby3 Keyword Arguments ([\#386](https://github.com/soutaro/steep/pull/386))
15
- * LSP hover for RBS files ([\#385](https://github.com/soutaro/steep/pull/385), [\#397](https://github.com/soutaro/steep/pull/397))
30
+ * LSP hover for RBS files ([\#385](https://github.com/soutaro/steep/pull/385), [\#397](https://github.com/soutaro/steep/pull/397))
16
31
  * Fix FileLoader to skip files not matching to the given pattern ([\#382](https://github.com/soutaro/steep/pull/382))
17
32
  * Ruby3 support for numbered block parameters and end-less def ([\#381](https://github.com/soutaro/steep/pull/381))
18
33
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (0.45.0)
4
+ steep (0.46.0)
5
5
  activesupport (>= 5.1)
6
6
  language_server-protocol (>= 3.15, < 4.0)
7
7
  listen (~> 3.0)
@@ -35,7 +35,7 @@ GEM
35
35
  ffi (1.15.3)
36
36
  i18n (1.8.10)
37
37
  concurrent-ruby (~> 1.0)
38
- language_server-protocol (3.16.0.1)
38
+ language_server-protocol (3.16.0.2)
39
39
  listen (3.7.0)
40
40
  rb-fsevent (~> 0.10, >= 0.10.3)
41
41
  rb-inotify (~> 0.9, >= 0.9.10)
data/lib/steep/cli.rb CHANGED
@@ -70,7 +70,7 @@ module Steep
70
70
  default = physical_processor_count + modifier
71
71
  command.jobs_count = default
72
72
  opts.on("-j N", "--jobs=N", "Specify the number of type check workers (defaults: #{default})") do |count|
73
- command.jobs_count = Integer(count)
73
+ command.jobs_count = Integer(count) if Integer(count) > 0
74
74
  end
75
75
  end
76
76
 
@@ -99,6 +99,9 @@ module Steep
99
99
  opts.on("--save-expectations[=PATH]", "Save expectations with current type check result to PATH (or steep_expectations.yml)") do |path|
100
100
  check.save_expectations_path = Pathname(path || "steep_expectations.yml")
101
101
  end
102
+ opts.on("--severity-level=LEVEL", /^error|warning|information|hint$/, "Specify the minimum diagnostic severity to be recognized as an error (defaults: warning): error, warning, information, or hint") do |level|
103
+ check.severity_level = level.to_sym
104
+ end
102
105
  handle_jobs_option check, opts
103
106
  handle_logging_options opts
104
107
  end.parse!(argv)
@@ -155,6 +158,9 @@ module Steep
155
158
  Drivers::Watch.new(stdout: stdout, stderr: stderr).tap do |command|
156
159
  OptionParser.new do |opts|
157
160
  opts.banner = "Usage: steep watch [options] [dirs]"
161
+ opts.on("--severity-level=LEVEL", /^error|warning|information|hint$/, "Specify the minimum diagnostic severity to be recognized as an error (defaults: warning): error, warning, information, or hint") do |level|
162
+ command.severity_level = level.to_sym
163
+ end
158
164
  handle_jobs_option command, opts
159
165
  handle_logging_options opts
160
166
  end.parse!(argv)
@@ -3,13 +3,66 @@ module Steep
3
3
  class LSPFormatter
4
4
  LSP = LanguageServer::Protocol
5
5
 
6
+ attr_reader :config
7
+ attr_reader :default_severity
8
+
9
+ ERROR = :error
10
+ WARNING = :warning
11
+ INFORMATION = :information
12
+ HINT = :hint
13
+
14
+ def initialize(config = {}, default_severity: ERROR)
15
+ @config = config
16
+ @default_severity = default_severity
17
+
18
+ config.each do |klass, severity|
19
+ validate_severity(klass, severity)
20
+ validate_class(klass)
21
+ end
22
+ validate_severity(:default, default_severity)
23
+ end
24
+
25
+ def validate_class(klass)
26
+ unless klass < Diagnostic::Ruby::Base
27
+ raise "Unexpected diagnostics class `#{klass}` given"
28
+ end
29
+ end
30
+
31
+ def validate_severity(klass, severity)
32
+ case severity
33
+ when ERROR, WARNING, INFORMATION, HINT, nil
34
+ # ok
35
+ else
36
+ raise "Unexpected severity `#{severity}` is specified for #{klass}"
37
+ end
38
+ end
39
+
6
40
  def format(diagnostic)
7
- LSP::Interface::Diagnostic.new(
8
- message: diagnostic.full_message,
9
- code: diagnostic.diagnostic_code,
10
- severity: LSP::Constant::DiagnosticSeverity::ERROR,
11
- range: diagnostic.location.as_lsp_range
12
- ).to_hash
41
+ severity = severity_for(diagnostic)
42
+
43
+ if severity
44
+ LSP::Interface::Diagnostic.new(
45
+ message: diagnostic.full_message,
46
+ code: diagnostic.diagnostic_code,
47
+ severity: severity,
48
+ range: diagnostic.location.as_lsp_range
49
+ ).to_hash
50
+ end
51
+ end
52
+
53
+ def severity_for(diagnostic)
54
+ case config.fetch(diagnostic.class, default_severity)
55
+ when ERROR
56
+ LSP::Constant::DiagnosticSeverity::ERROR
57
+ when WARNING
58
+ LSP::Constant::DiagnosticSeverity::WARNING
59
+ when INFORMATION
60
+ LSP::Constant::DiagnosticSeverity::INFORMATION
61
+ when HINT
62
+ LSP::Constant::DiagnosticSeverity::HINT
63
+ when nil
64
+ nil
65
+ end
13
66
  end
14
67
  end
15
68
  end
@@ -700,6 +700,57 @@ module Steep
700
700
  "SyntaxError: #{message}"
701
701
  end
702
702
  end
703
+
704
+ ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
705
+ if klass < Base
706
+ array << klass
707
+ end
708
+ end
709
+
710
+ def self.all_error
711
+ @all_error ||= ALL.each.with_object({}) do |klass, hash|
712
+ hash[klass] = LSPFormatter::ERROR
713
+ end.freeze
714
+ end
715
+
716
+ def self.default
717
+ @default ||= all_error.merge(
718
+ {
719
+ ImplicitBreakValueMismatch => :warning,
720
+ FallbackAny => :information,
721
+ ElseOnExhaustiveCase => :warning,
722
+ UnknownConstantAssigned => :warning,
723
+ MethodDefinitionMissing => :information
724
+ }
725
+ ).freeze
726
+ end
727
+
728
+ def self.strict
729
+ @strict ||= all_error.merge(
730
+ {
731
+ NoMethod => nil,
732
+ ImplicitBreakValueMismatch => nil,
733
+ FallbackAny => nil,
734
+ ElseOnExhaustiveCase => nil,
735
+ UnknownConstantAssigned => nil,
736
+ MethodDefinitionMissing => nil
737
+ }
738
+ ).freeze
739
+ end
740
+
741
+ def self.lenient
742
+ @lenient ||= all_error.merge(
743
+ {
744
+ NoMethod => nil,
745
+ ImplicitBreakValueMismatch => nil,
746
+ FallbackAny => nil,
747
+ ElseOnExhaustiveCase => nil,
748
+ UnknownConstantAssigned => nil,
749
+ MethodDefinitionMissing => nil,
750
+ UnexpectedJump => nil
751
+ }
752
+ ).freeze
753
+ end
703
754
  end
704
755
  end
705
756
  end
@@ -8,6 +8,7 @@ module Steep
8
8
  attr_reader :command_line_patterns
9
9
  attr_accessor :with_expectations_path
10
10
  attr_accessor :save_expectations_path
11
+ attr_accessor :severity_level
11
12
 
12
13
  include Utils::DriverHelper
13
14
  include Utils::JobsCount
@@ -16,6 +17,7 @@ module Steep
16
17
  @stdout = stdout
17
18
  @stderr = stderr
18
19
  @command_line_patterns = []
20
+ @severity_level = :warning
19
21
  end
20
22
 
21
23
  def run
@@ -70,6 +72,7 @@ module Steep
70
72
  case
71
73
  when response[:method] == "textDocument/publishDiagnostics"
72
74
  ds = response[:params][:diagnostics]
75
+ ds.select! {|d| keep_diagnostic?(d) }
73
76
  if ds.empty?
74
77
  stdout.print "."
75
78
  else
@@ -8,6 +8,8 @@ module Steep
8
8
  include Utils::DriverHelper
9
9
 
10
10
  TEMPLATE = <<~EOF
11
+ # D = Steep::Diagnostic
12
+ #
11
13
  # target :lib do
12
14
  # signature "sig"
13
15
  #
@@ -18,15 +20,20 @@ module Steep
18
20
  #
19
21
  # # library "pathname", "set" # Standard libraries
20
22
  # # library "strong_json" # Gems
23
+ #
24
+ # # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
25
+ # # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
26
+ # # configure_code_diagnostics do |hash| # You can setup everything yourself
27
+ # # hash[D::Ruby::NoMethod] = :information
28
+ # # end
21
29
  # end
22
30
 
23
- # target :spec do
31
+ # target :test do
24
32
  # signature "sig", "sig-private"
25
33
  #
26
- # check "spec"
34
+ # check "test"
27
35
  #
28
36
  # # library "pathname", "set" # Standard libraries
29
- # # library "rspec"
30
37
  # end
31
38
  EOF
32
39
 
@@ -55,6 +55,21 @@ module Steep
55
55
  end
56
56
  end
57
57
  end
58
+
59
+ def keep_diagnostic?(diagnostic)
60
+ severity = diagnostic[:severity]
61
+
62
+ case self.severity_level
63
+ when nil, :hint
64
+ true
65
+ when :error
66
+ severity <= LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR
67
+ when :warning
68
+ severity <= LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING
69
+ when :information
70
+ severity <= LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION
71
+ end
72
+ end
58
73
  end
59
74
  end
60
75
  end
@@ -36,7 +36,7 @@ module Steep
36
36
 
37
37
  any_error ||= !errors.empty?
38
38
 
39
- formatter = Diagnostic::LSPFormatter.new
39
+ formatter = Diagnostic::LSPFormatter.new({})
40
40
  diagnostics = errors.group_by {|e| e.location.buffer }.transform_values do |errors|
41
41
  errors.map {|error| formatter.format(error) }
42
42
  end
@@ -5,6 +5,7 @@ module Steep
5
5
  attr_reader :stdout
6
6
  attr_reader :stderr
7
7
  attr_reader :queue
8
+ attr_accessor :severity_level
8
9
 
9
10
  include Utils::DriverHelper
10
11
  include Utils::JobsCount
@@ -16,6 +17,7 @@ module Steep
16
17
  @stdout = stdout
17
18
  @stderr = stderr
18
19
  @queue = Thread::Queue.new
20
+ @severity_level = :warning
19
21
  end
20
22
 
21
23
  def watching?(changed_path, files:, dirs:)
@@ -126,6 +128,7 @@ module Steep
126
128
  printer = DiagnosticPrinter.new(stdout: stdout, buffer: buffer)
127
129
 
128
130
  diagnostics = response[:params][:diagnostics]
131
+ diagnostics.filter! {|d| keep_diagnostic?(d) }
129
132
 
130
133
  unless diagnostics.empty?
131
134
  diagnostics.each do |diagnostic|
@@ -7,21 +7,21 @@ module Steep
7
7
  attr_reader :libraries
8
8
  attr_reader :signatures
9
9
  attr_reader :ignored_sources
10
- attr_reader :vendor_dir
11
- attr_reader :strictness_level
12
- attr_reader :typing_option_hash
10
+ attr_reader :stdlib_root
11
+ attr_reader :core_root
13
12
  attr_reader :repo_paths
13
+ attr_reader :code_diagnostics_config
14
14
 
15
- def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [], repo_paths: [])
15
+ def initialize(name, sources: [], libraries: [], signatures: [], ignored_sources: [], repo_paths: [], code_diagnostics_config: {})
16
16
  @name = name
17
17
  @sources = sources
18
18
  @libraries = libraries
19
19
  @signatures = signatures
20
20
  @ignored_sources = ignored_sources
21
- @vendor_dir = nil
22
- @strictness_level = :default
23
- @typing_option_hash = {}
21
+ @core_root = nil
22
+ @stdlib_root = nil
24
23
  @repo_paths = []
24
+ @code_diagnostics_config = code_diagnostics_config
25
25
  end
26
26
 
27
27
  def initialize_copy(other)
@@ -30,10 +30,10 @@ module Steep
30
30
  @libraries = other.libraries.dup
31
31
  @signatures = other.signatures.dup
32
32
  @ignored_sources = other.ignored_sources.dup
33
- @vendor_dir = other.vendor_dir
34
- @strictness_level = other.strictness_level
35
- @typing_option_hash = other.typing_option_hash
36
33
  @repo_paths = other.repo_paths.dup
34
+ @core_root = other.core_root
35
+ @stdlib_root = other.stdlib_root
36
+ @code_diagnostics_config = other.code_diagnostics_config.dup
37
37
  end
38
38
 
39
39
  def check(*args)
@@ -48,9 +48,52 @@ module Steep
48
48
  libraries.push(*args)
49
49
  end
50
50
 
51
- def typing_options(level = @strictness_level, **hash)
52
- @strictness_level = level
53
- @typing_option_hash = hash
51
+ def typing_options(level = nil, **hash)
52
+ Steep.logger.error "#typing_options is deprecated and has no effect as of version 0.46.0. Update your Steepfile as follows for (almost) equivalent setting:"
53
+
54
+ messages = []
55
+
56
+ messages << "# D = Steep::Diagnostic # Define a constant to shorten namespace"
57
+
58
+ case level
59
+ when :strict
60
+ messages << "configure_code_diagnostics(D::Ruby.strict) # :strict"
61
+ when :default
62
+ messages << "configure_code_diagnostics(D::Ruby.default) # :default"
63
+ when :lenient
64
+ messages << "configure_code_diagnostics(D::Ruby.lenient) # :lenient"
65
+ end
66
+
67
+ messages.each do |msg|
68
+ Steep.logger.error " #{msg}"
69
+ end
70
+
71
+ config = []
72
+
73
+ if hash[:allow_missing_definitions]
74
+ config << "hash[D::Ruby::MethodDefinitionMissing] = nil # allow_missing_definitions"
75
+ end
76
+
77
+ if hash[:allow_fallback_any]
78
+ config << "hash[D::Ruby::FallbackAny] = nil # allow_fallback_any"
79
+ end
80
+
81
+ if hash[:allow_unknown_constant_assignment]
82
+ config << "hash[D::Ruby::UnknownConstantAssigned] = nil # allow_unknown_constant_assignment"
83
+ end
84
+
85
+ if hash[:allow_unknown_method_calls]
86
+ config << "hash[D::Ruby::NoMethod] = nil # allow_unknown_method_calls"
87
+ end
88
+
89
+ unless config.empty?
90
+ Steep.logger.error " configure_code_diagnostics do |hash|"
91
+ config.each do |c|
92
+ Steep.logger.error " #{c}"
93
+ end
94
+ Steep.logger.error " end"
95
+ end
96
+
54
97
  end
55
98
 
56
99
  def signature(*args)
@@ -68,20 +111,50 @@ module Steep
68
111
  end
69
112
 
70
113
  def no_builtin!(value = true)
71
- Steep.logger.error "`no_builtin!` in Steepfile is deprecated and ignored. Use `vendor` instead."
114
+ Steep.logger.error "`#no_builtin!` in Steepfile is deprecated and ignored. Use `#stdlib_path` instead."
72
115
  end
73
116
 
74
117
  def vendor(dir = "vendor/sigs", stdlib: nil, gems: nil)
75
- if stdlib || gems
76
- Steep.logger.warn { "#vendor with stdlib: or gems: keyword is deprecated." }
77
- end
118
+ Steep.logger.error "`#vendor` in Steepfile is deprecated and ignored. Use `#stdlib_path` instead."
119
+ end
78
120
 
79
- @vendor_dir = Pathname(dir)
121
+ def stdlib_path(core_root:, stdlib_root:)
122
+ @core_root = core_root ? Pathname(core_root) : core_root
123
+ @stdlib_root = stdlib_root ? Pathname(stdlib_root) : stdlib_root
80
124
  end
81
125
 
82
126
  def repo_path(*paths)
83
127
  @repo_paths.push(*paths.map {|s| Pathname(s) })
84
128
  end
129
+
130
+ # Configure the code diagnostics printing setup.
131
+ #
132
+ # Yields a hash, and the update the hash in the block.
133
+ #
134
+ # ```rb
135
+ # D = Steep::Diagnostic
136
+ #
137
+ # configure_code_diagnostics do |hash|
138
+ # # Assign one of :error, :warning, :information, :hint or :nil to error classes.
139
+ # hash[D::Ruby::UnexpectedPositionalArgument] = :error
140
+ # end
141
+ # ```
142
+ #
143
+ # Passing a hash is also allowed.
144
+ #
145
+ # ```rb
146
+ # D = Steep::Diagnostic
147
+ #
148
+ # configure_code_diagnostics(D::Ruby.lenient)
149
+ # ```
150
+ #
151
+ def configure_code_diagnostics(hash = nil)
152
+ if hash
153
+ code_diagnostics_config.merge!(hash)
154
+ end
155
+
156
+ yield code_diagnostics_config if block_given?
157
+ end
85
158
  end
86
159
 
87
160
  attr_reader :project
@@ -107,7 +180,9 @@ module Steep
107
180
  end
108
181
 
109
182
  def self.parse(project, code, filename: "Steepfile")
110
- self.new(project: project).instance_eval(code, filename)
183
+ Steep.logger.tagged filename do
184
+ self.new(project: project).instance_eval(code, filename)
185
+ end
111
186
  end
112
187
 
113
188
  def target(name, template: nil, &block)
@@ -115,10 +190,12 @@ module Steep
115
190
  self.class.templates[template]&.dup&.update(name: name) or
116
191
  raise "Unknown template: #{template}, available templates: #{@@templates.keys.join(", ")}"
117
192
  else
118
- TargetDSL.new(name)
193
+ TargetDSL.new(name, code_diagnostics_config: Diagnostic::Ruby.default.dup)
119
194
  end
120
195
 
121
- target.instance_eval(&block) if block_given?
196
+ Steep.logger.tagged "target=#{name}" do
197
+ target.instance_eval(&block) if block_given?
198
+ end
122
199
 
123
200
  source_pattern = Pattern.new(patterns: target.sources, ignores: target.ignored_sources, ext: ".rb")
124
201
  signature_pattern = Pattern.new(patterns: target.signatures, ext: ".rbs")
@@ -129,18 +206,13 @@ module Steep
129
206
  signature_pattern: signature_pattern,
130
207
  options: Options.new.tap do |options|
131
208
  options.libraries.push(*target.libraries)
132
- options.repository_paths.push(*target.repo_paths)
133
- options.vendor_path = target.vendor_dir
134
-
135
- case target.strictness_level
136
- when :strict
137
- options.apply_strict_typing_options!
138
- when :lenient
139
- options.apply_lenient_typing_options!
140
- end
141
-
142
- options.merge!(target.typing_option_hash)
143
- end
209
+ options.paths = Options::PathOptions.new(
210
+ core_root: target.core_root,
211
+ stdlib_root: target.stdlib_root,
212
+ repo_paths: target.repo_paths
213
+ )
214
+ end,
215
+ code_diagnostics_config: target.code_diagnostics_config
144
216
  ).tap do |target|
145
217
  project.targets << target
146
218
  end
@@ -1,63 +1,22 @@
1
1
  module Steep
2
2
  class Project
3
3
  class Options
4
- attr_accessor :allow_fallback_any
5
- attr_accessor :allow_missing_definitions
6
- attr_accessor :allow_unknown_constant_assignment
7
- attr_accessor :allow_unknown_method_calls
8
- attr_accessor :vendor_path
9
- attr_reader :libraries
10
- attr_reader :repository_paths
11
-
12
- def initialize
13
- apply_default_typing_options!
14
- self.vendor_path = nil
15
-
16
- @libraries = []
17
- @repository_paths = []
18
- end
19
-
20
- def apply_default_typing_options!
21
- self.allow_fallback_any = true
22
- self.allow_missing_definitions = true
23
- self.allow_unknown_constant_assignment = false
24
- self.allow_unknown_method_calls = false
25
- end
26
-
27
- def apply_strict_typing_options!
28
- self.allow_fallback_any = false
29
- self.allow_missing_definitions = false
30
- self.allow_unknown_constant_assignment = false
31
- self.allow_unknown_method_calls = false
32
- end
33
-
34
- def apply_lenient_typing_options!
35
- self.allow_fallback_any = true
36
- self.allow_missing_definitions = true
37
- self.allow_unknown_constant_assignment = true
38
- self.allow_unknown_method_calls = true
39
- end
4
+ PathOptions = Struct.new(:core_root, :stdlib_root, :repo_paths, keyword_init: true) do
5
+ def customized_stdlib?
6
+ stdlib_root != nil
7
+ end
40
8
 
41
- def error_to_report?(error)
42
- case
43
- when error.is_a?(Diagnostic::Ruby::FallbackAny)
44
- !allow_fallback_any
45
- when error.is_a?(Diagnostic::Ruby::MethodDefinitionMissing)
46
- !allow_missing_definitions
47
- when error.is_a?(Diagnostic::Ruby::NoMethod)
48
- !allow_unknown_method_calls
49
- when error.is_a?(Diagnostic::Ruby::UnknownConstantAssigned)
50
- !allow_unknown_constant_assignment
51
- else
52
- true
9
+ def customized_core?
10
+ core_root != nil
53
11
  end
54
12
  end
55
13
 
56
- def merge!(hash)
57
- self.allow_fallback_any = hash[:allow_fallback_any] if hash.key?(:allow_fallback_any)
58
- self.allow_missing_definitions = hash[:allow_missing_definitions] if hash.key?(:allow_missing_definitions)
59
- self.allow_unknown_constant_assignment = hash[:allow_unknown_constant_assignment] if hash.key?(:allow_unknown_constant_assignment)
60
- self.allow_unknown_method_calls = hash[:allow_unknown_method_calls] if hash.key?(:allow_unknown_method_calls)
14
+ attr_reader :libraries
15
+ attr_accessor :paths
16
+
17
+ def initialize
18
+ @paths = PathOptions.new(repo_paths: [])
19
+ @libraries = []
61
20
  end
62
21
  end
63
22
  end
@@ -6,12 +6,14 @@ module Steep
6
6
 
7
7
  attr_reader :source_pattern
8
8
  attr_reader :signature_pattern
9
+ attr_reader :code_diagnostics_config
9
10
 
10
- def initialize(name:, options:, source_pattern:, signature_pattern:)
11
+ def initialize(name:, options:, source_pattern:, signature_pattern:, code_diagnostics_config:)
11
12
  @name = name
12
13
  @options = options
13
14
  @source_pattern = source_pattern
14
15
  @signature_pattern = signature_pattern
16
+ @code_diagnostics_config = code_diagnostics_config
15
17
 
16
18
  @source_files = {}
17
19
  @signature_files = {}
@@ -30,16 +32,27 @@ module Steep
30
32
  end
31
33
 
32
34
  def self.construct_env_loader(options:, project:)
33
- repo = RBS::Repository.new(no_stdlib: options.vendor_path)
34
- options.repository_paths.each do |path|
35
+ repo = RBS::Repository.new(no_stdlib: options.paths.customized_stdlib?)
36
+
37
+ if options.paths.stdlib_root
38
+ repo.add(project.absolute_path(options.paths.stdlib_root))
39
+ end
40
+
41
+ options.paths.repo_paths.each do |path|
35
42
  repo.add(project.absolute_path(path))
36
43
  end
37
44
 
38
- loader = RBS::EnvironmentLoader.new(
39
- core_root: options.vendor_path ? nil : RBS::EnvironmentLoader::DEFAULT_CORE_ROOT,
40
- repository: repo
41
- )
42
- loader.add(path: options.vendor_path) if options.vendor_path
45
+ core_root_path =
46
+ if options.paths.customized_core?
47
+ if options.paths.core_root
48
+ project.absolute_path(options.paths.core_root)
49
+ end
50
+ else
51
+ RBS::EnvironmentLoader::DEFAULT_CORE_ROOT
52
+ end
53
+
54
+ loader = RBS::EnvironmentLoader.new(core_root: core_root_path, repository: repo)
55
+
43
56
  options.libraries.each do |lib|
44
57
  name, version = lib.split(/:/, 2)
45
58
  loader.add(library: name, version: version)
@@ -144,7 +144,7 @@ module Steep
144
144
  if job.guid == current_type_check_guid
145
145
  Steep.logger.info { "Processing ValidateAppSignature for guid=#{job.guid}, path=#{job.path}" }
146
146
  service.validate_signature(path: project.relative_path(job.path)) do |path, diagnostics|
147
- formatter = Diagnostic::LSPFormatter.new()
147
+ formatter = Diagnostic::LSPFormatter.new({})
148
148
 
149
149
  writer.write(
150
150
  method: :"textDocument/publishDiagnostics",
@@ -162,13 +162,13 @@ module Steep
162
162
  if job.guid == current_type_check_guid
163
163
  Steep.logger.info { "Processing ValidateLibrarySignature for guid=#{job.guid}, path=#{job.path}" }
164
164
  service.validate_signature(path: job.path) do |path, diagnostics|
165
- formatter = Diagnostic::LSPFormatter.new()
165
+ formatter = Diagnostic::LSPFormatter.new({})
166
166
 
167
167
  writer.write(
168
168
  method: :"textDocument/publishDiagnostics",
169
169
  params: LSP::Interface::PublishDiagnosticsParams.new(
170
170
  uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
171
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
171
+ diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
172
172
  )
173
173
  )
174
174
  end
@@ -180,17 +180,14 @@ module Steep
180
180
  if job.guid == current_type_check_guid
181
181
  Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}" }
182
182
  service.typecheck_source(path: project.relative_path(job.path)) do |path, diagnostics|
183
- if target = project.target_for_source_path(path)
184
- diagnostics = diagnostics.select {|diagnostic| target.options.error_to_report?(diagnostic) }
185
- end
186
-
187
- formatter = Diagnostic::LSPFormatter.new()
183
+ target = project.target_for_source_path(path)
184
+ formatter = Diagnostic::LSPFormatter.new(target&.code_diagnostics_config || {})
188
185
 
189
186
  writer.write(
190
187
  method: :"textDocument/publishDiagnostics",
191
188
  params: LSP::Interface::PublishDiagnosticsParams.new(
192
189
  uri: URI.parse(job.path.to_s).tap {|uri| uri.scheme = "file"},
193
- diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
190
+ diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
194
191
  )
195
192
  )
196
193
  end
@@ -128,8 +128,8 @@ module Steep
128
128
  when :send
129
129
  receiver, method_name, *_ = node.children
130
130
 
131
-
132
- result_node = if parents[0]&.type == :block
131
+ result_node = case parents[0]&.type
132
+ when :block, :numblock
133
133
  parents[0]
134
134
  else
135
135
  node
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "0.45.0"
2
+ VERSION = "0.46.0"
3
3
  end
data/sample/Steepfile CHANGED
@@ -1,6 +1,13 @@
1
- target :app do
2
- check "lib"
1
+ D = Steep::Diagnostic
2
+
3
+ target :lib do
3
4
  signature "sig"
4
5
 
5
- library "set", "pathname"
6
+ check "lib" # Directory name
7
+
8
+ # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
9
+ # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
10
+ # configure_code_diagnostics do |hash| # You can setup everything yourself
11
+ # hash[D::Ruby::NoMethod] = :information
12
+ # end
6
13
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/and/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,6 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
5
- end
6
4
 
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
6
+ end
data/smoke/case/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -2,7 +2,7 @@ all_sigs = Pathname.glob("*.rbs")
2
2
 
3
3
  all_sigs.each do |path|
4
4
  target path.basename(".rbs").to_s.to_sym do
5
- typing_options :strict
6
5
  signature path.to_s
6
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
7
7
  end
8
8
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/dstr/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/hash/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/if/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/map/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,6 +1,7 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
5
4
  library "set"
5
+
6
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
6
7
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/self/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
data/smoke/skip/Steepfile CHANGED
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,8 +1,7 @@
1
1
  target :test do
2
- signature "."
3
- check "."
4
-
5
- typing_options :strict
6
-
2
+ check "*.rb"
3
+ signature "*.rbs"
7
4
  library "tsort"
5
+
6
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
8
7
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
@@ -1,5 +1,6 @@
1
1
  target :test do
2
- typing_options :strict
3
2
  check "*.rb"
4
3
  signature "*.rbs"
4
+
5
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.all_error)
5
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.45.0
4
+ version: 0.46.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-22 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser