steep-relaxed 1.9.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,132 @@
1
+ require "rake"
2
+ require "rake/tasklib"
3
+ require "steep/cli"
4
+
5
+ module Steep
6
+ # Provides Rake tasks for running Steep commands.
7
+ #
8
+ # require "steep/rake_task"
9
+ # Steep::RakeTask.new do |t|
10
+ # t.check.severity_level = :error
11
+ # t.watch.verbose
12
+ # t.stats << "--format=table"
13
+ # end
14
+ class RakeTask < Rake::TaskLib # steep:ignore UnknownConstant
15
+ attr_accessor :name
16
+
17
+ def self.available_commands
18
+ %i(init check stats binstub project watch)
19
+ end
20
+
21
+ def initialize(name = :steep, cli_runner = default_cli_runner)
22
+ super()
23
+
24
+ @name = name
25
+
26
+ configuration = TaskConfiguration.new
27
+
28
+ yield configuration if block_given?
29
+
30
+ define_tasks(configuration, cli_runner)
31
+ end
32
+
33
+ private
34
+
35
+ # :nodoc:
36
+ class TaskConfiguration
37
+ def initialize
38
+ @commands = {}
39
+ end
40
+
41
+ def method_missing(command)
42
+ if respond_to?(command)
43
+ @commands[command] ||= CommandConfiguration.new
44
+ else
45
+ super
46
+ end
47
+ end
48
+
49
+ def respond_to_missing?(name, include_private = false)
50
+ RakeTask.available_commands.include?(name) || super
51
+ end
52
+
53
+ def options(command)
54
+ @commands[command]&.to_a || []
55
+ end
56
+ end
57
+
58
+ # :nodoc:
59
+ class CommandConfiguration
60
+ def initialize
61
+ @options = []
62
+ end
63
+
64
+ def method_missing(name, value = nil)
65
+ option = "--#{name.to_s.gsub(/_/, '-').gsub(/=/, '')}"
66
+ option << "=#{value}" if value
67
+
68
+ self << option
69
+ end
70
+
71
+ def respond_to_missing?(_name)
72
+ true
73
+ end
74
+
75
+ def <<(value)
76
+ @options << value
77
+ self
78
+ end
79
+
80
+ def to_a
81
+ @options
82
+ end
83
+ end
84
+
85
+ def default_cli_runner
86
+ lambda do |arguments|
87
+ require "steep"
88
+
89
+ cli = Steep::CLI.new(
90
+ stdout: $stdout,
91
+ stdin: $stdin,
92
+ stderr: $stderr,
93
+ argv: arguments
94
+ )
95
+
96
+ cli.run
97
+ end
98
+ end
99
+
100
+ def define_tasks(configuration, cli_runner)
101
+ namespace name do
102
+ RakeTask.available_commands.each do |command|
103
+ desc "Run steep #{command}"
104
+ task command do |_, args|
105
+ configured_options = configuration.options(command)
106
+
107
+ argv = [
108
+ command.to_s,
109
+ *configured_options,
110
+ *args.extras
111
+ ]
112
+
113
+ result = cli_runner[argv]
114
+
115
+ raise "Steep failed" if result.nonzero?
116
+ end
117
+ end
118
+
119
+ desc "Run steep help"
120
+ task "help" do
121
+ arguments = ["--help"]
122
+
123
+ cli_runner[arguments]
124
+ end
125
+ end
126
+
127
+ # Default steep task to steep:check
128
+ desc "Run steep check" unless ::Rake.application.last_description # steep:ignore UnknownConstant
129
+ task name => ["#{name}:check"]
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,29 @@
1
+ class RBS::Location
2
+ def as_lsp_range
3
+ {
4
+ start: {
5
+ line: start_line - 1,
6
+ character: start_column
7
+ },
8
+ end: {
9
+ line: end_line - 1,
10
+ character: end_column
11
+ }
12
+ }
13
+ end
14
+ end
15
+
16
+ class Parser::Source::Range
17
+ def as_lsp_range
18
+ {
19
+ start: {
20
+ line: line - 1,
21
+ character: column
22
+ },
23
+ end: {
24
+ line: last_line - 1,
25
+ character: last_column
26
+ }
27
+ }
28
+ end
29
+ end
@@ -0,0 +1,97 @@
1
+ module Steep
2
+ module Server
3
+ class BaseWorker
4
+ LSP = LanguageServer::Protocol
5
+
6
+ attr_reader :project
7
+ attr_reader :reader, :writer, :queue
8
+
9
+ ShutdownJob = _ = Struct.new(:id, keyword_init: true)
10
+
11
+ def initialize(project:, reader:, writer:)
12
+ @project = project
13
+ @reader = reader
14
+ @writer = writer
15
+ @skip_job = false
16
+ @shutdown = false
17
+ @skip_jobs_after_shutdown = false
18
+ end
19
+
20
+ def skip_jobs_after_shutdown!(flag = true)
21
+ @skip_jobs_after_shutdown = flag
22
+ end
23
+
24
+ def skip_jobs_after_shutdown?
25
+ @skip_jobs_after_shutdown
26
+ end
27
+
28
+ def skip_job?
29
+ @skip_job
30
+ end
31
+
32
+ def handle_request(request)
33
+ # process request
34
+ end
35
+
36
+ def handle_job(job)
37
+ # process async job
38
+ end
39
+
40
+ def run
41
+ tags = Steep.logger.formatter.current_tags.dup
42
+ thread = Thread.new do
43
+ Thread.current.abort_on_exception = true
44
+
45
+ Steep.logger.formatter.push_tags(*tags)
46
+ Steep.logger.tagged "background" do
47
+ while job = queue.pop
48
+ case job
49
+ when ShutdownJob
50
+ writer.write(id: job.id, result: nil)
51
+ else
52
+ if skip_job?
53
+ Steep.logger.info "Skipping job..."
54
+ else
55
+ begin
56
+ handle_job(job)
57
+ rescue => exn
58
+ Steep.log_error exn
59
+ writer.write(
60
+ {
61
+ method: "window/showMessage",
62
+ params: {
63
+ type: LSP::Constant::MessageType::ERROR,
64
+ message: "Unexpected error: #{exn.message} (#{exn.class})"
65
+ }
66
+ }
67
+ )
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ Steep.logger.tagged "frontend" do
76
+ begin
77
+ reader.read do |request|
78
+ Steep.logger.info "Received message from master: #{request[:method]}(#{request[:id]})"
79
+ case request[:method]
80
+ when "shutdown"
81
+ queue << ShutdownJob.new(id: request[:id])
82
+ @skip_job = skip_jobs_after_shutdown?
83
+ queue.close
84
+ when "exit"
85
+ break
86
+ else
87
+ handle_request(request) unless @shutdown
88
+ end
89
+ end
90
+ ensure
91
+ thread.join
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,73 @@
1
+ module Steep
2
+ module Server
3
+ module ChangeBuffer
4
+ attr_reader :mutex
5
+ attr_reader :buffered_changes
6
+
7
+ def push_buffer
8
+ mutex.synchronize do
9
+ yield buffered_changes
10
+ end
11
+ end
12
+
13
+ def pop_buffer
14
+ changes = mutex.synchronize do
15
+ copy = buffered_changes.dup
16
+ buffered_changes.clear
17
+ copy
18
+ end
19
+
20
+ if block_given?
21
+ yield changes
22
+ else
23
+ changes
24
+ end
25
+ end
26
+
27
+ def load_files(input)
28
+ Steep.logger.tagged "#load_files" do
29
+ push_buffer do |changes|
30
+ input.each do |filename, content|
31
+ if content.is_a?(Hash)
32
+ content = Base64.decode64(content[:text]).force_encoding(Encoding::UTF_8)
33
+ end
34
+ changes[Pathname(filename.to_s)] = [Services::ContentChange.new(text: content)]
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def collect_changes(request)
41
+ push_buffer do |changes|
42
+ if path = Steep::PathHelper.to_pathname(request[:params][:textDocument][:uri])
43
+ path = project.relative_path(path)
44
+ version = request[:params][:textDocument][:version]
45
+ Steep.logger.info { "Updating source: path=#{path}, version=#{version}..." }
46
+
47
+ changes[path] ||= []
48
+ request[:params][:contentChanges].each do |change|
49
+ changes.fetch(path) << Services::ContentChange.new(
50
+ range: change[:range]&.yield_self {|range|
51
+ [
52
+ range[:start].yield_self {|pos| Services::ContentChange::Position.new(line: pos[:line] + 1, column: pos[:character]) },
53
+ range[:end].yield_self {|pos| Services::ContentChange::Position.new(line: pos[:line] + 1, column: pos[:character]) }
54
+ ]
55
+ },
56
+ text: change[:text]
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def reset_change(uri:, text:)
64
+ push_buffer do |changes|
65
+ if path = Steep::PathHelper.to_pathname(uri)
66
+ path = project.relative_path(path)
67
+ changes[path] = [Services::ContentChange.new(text: text)]
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,77 @@
1
+ module Steep
2
+ module Server
3
+ module CustomMethods
4
+ module FileLoad
5
+ METHOD = "$/steep/file/load"
6
+
7
+ def self.notification(params)
8
+ { method: METHOD, params: params }
9
+ end
10
+ end
11
+
12
+ module FileReset
13
+ METHOD = "$/steep/file/reset"
14
+
15
+ def self.notification(params)
16
+ { method: METHOD, params: params }
17
+ end
18
+ end
19
+
20
+ module TypeCheck
21
+ METHOD = "$/steep/typecheck"
22
+
23
+ def self.request(id, params)
24
+ { method: METHOD, id: id, params: params }
25
+ end
26
+
27
+ def self.response(id, result)
28
+ { id: id, result: result }
29
+ end
30
+ end
31
+
32
+ module TypeCheckGroups
33
+ METHOD = "$/steep/typecheck/groups"
34
+
35
+ def self.notification(params)
36
+ { method: METHOD, params: params }
37
+ end
38
+ end
39
+
40
+ module TypeCheck__Start
41
+ METHOD = "$/steep/typecheck/start"
42
+
43
+ def self.notification(params)
44
+ { method: METHOD, params: params }
45
+ end
46
+ end
47
+
48
+ module TypeCheck__Progress
49
+ METHOD = "$/steep/typecheck/progress"
50
+
51
+ def self.notification(params)
52
+ { method: METHOD, params: params }
53
+ end
54
+ end
55
+
56
+ module Stats
57
+ METHOD = "$/steep/stats"
58
+
59
+ def self.request(id)
60
+ { method: METHOD, id: id, params: nil }
61
+ end
62
+
63
+ def self.response(id, result)
64
+ { id: id, result: result }
65
+ end
66
+ end
67
+
68
+ module Groups
69
+ METHOD = "$/steep/groups"
70
+
71
+ def self.response(id, result)
72
+ { id: id, result: result }
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,45 @@
1
+ module Steep
2
+ module Server
3
+ class DelayQueue
4
+ attr_reader :delay, :thread, :queue, :last_task
5
+
6
+ def initialize(delay:)
7
+ @delay = delay
8
+
9
+ @queue = Thread::Queue.new
10
+
11
+ @thread = Thread.new do
12
+ while (scheduled_at, proc = queue.pop)
13
+ diff = scheduled_at - Time.now
14
+ case
15
+ when diff > 0.1
16
+ sleep diff
17
+ when diff > 0
18
+ while Time.now < scheduled_at
19
+ # nop
20
+ sleep 0
21
+ end
22
+ end
23
+
24
+ if proc.equal?(last_task)
25
+ unless @cancelled
26
+ proc[]
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def cancel
34
+ @cancelled = true
35
+ queue.clear()
36
+ end
37
+
38
+ def execute(&block)
39
+ @last_task = block
40
+ scheduled_at = Time.now + delay
41
+ queue << [scheduled_at, block]
42
+ end
43
+ end
44
+ end
45
+ end