Class: Steep::Drivers::Watch

Inherits:
Object
  • Object
show all
Includes:
Utils::EachSignature
Defined in:
lib/steep/drivers/watch.rb

Defined Under Namespace

Classes: Options, WatchListener

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils::EachSignature

#each_file_in_dir, #each_file_in_path

Constructor Details

#initialize(source_dirs:, signature_dirs:, stdout:, stderr:) ⇒ Watch

Returns a new instance of Watch.



23
24
25
26
27
28
29
30
# File 'lib/steep/drivers/watch.rb', line 23

def initialize(source_dirs:, signature_dirs:, stdout:, stderr:)
  @source_dirs = source_dirs
  @signature_dirs = signature_dirs
  @stdout = stdout
  @stderr = stderr
  @options = Options.new
  @queue = Thread::Queue.new
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



18
19
20
# File 'lib/steep/drivers/watch.rb', line 18

def options
  @options
end

#queueObject (readonly)

Returns the value of attribute queue.



19
20
21
# File 'lib/steep/drivers/watch.rb', line 19

def queue
  @queue
end

#signature_dirsObject (readonly)

Returns the value of attribute signature_dirs.



15
16
17
# File 'lib/steep/drivers/watch.rb', line 15

def signature_dirs
  @signature_dirs
end

#source_dirsObject (readonly)

Returns the value of attribute source_dirs.



14
15
16
# File 'lib/steep/drivers/watch.rb', line 14

def source_dirs
  @source_dirs
end

#stderrObject (readonly)

Returns the value of attribute stderr.



17
18
19
# File 'lib/steep/drivers/watch.rb', line 17

def stderr
  @stderr
end

#stdoutObject (readonly)

Returns the value of attribute stdout.



16
17
18
# File 'lib/steep/drivers/watch.rb', line 16

def stdout
  @stdout
end

Instance Method Details

#project_optionsObject



32
33
34
35
36
37
# File 'lib/steep/drivers/watch.rb', line 32

def project_options
  Project::Options.new.tap do |opt|
    opt.fallback_any_is_error = options.fallback_any_is_error
    opt.allow_missing_definitions = options.allow_missing_definitions
  end
end

#run(block: true) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/steep/drivers/watch.rb', line 156

def run(block: true)
  project = Project.new(WatchListener.new(stdout: stdout, stderr: stderr, verbose: false))

  source_dirs.each do |path|
    each_file_in_path(".rb", path) do |file_path|
      file = Project::SourceFile.new(path: file_path, options: options)
      file.content = file_path.read
      project.source_files[file_path] = file
    end
  end

  signature_dirs.each do |path|
    each_file_in_path(".rbi", path) do |file_path|
      file = Project::SignatureFile.new(path: file_path)
      file.content = file_path.read
      project.signature_files[file_path] = file
    end
  end

  project.type_check

  source_listener.start
  signature_listener.start
  t = type_check_thread(project)

  binding.pry(quiet: true) if block

  queue.close
  t.join
end

#signature_listenerObject



47
48
49
50
51
52
53
# File 'lib/steep/drivers/watch.rb', line 47

def signature_listener
  @signature_listener ||= yield_self do
    Listen.to(*signature_dirs.map(&:to_s), only: /\.rbi$/) do |modified, added, removed|
      queue << [:signature, modified, added, removed]
    end
  end
end

#source_listenerObject



39
40
41
42
43
44
45
# File 'lib/steep/drivers/watch.rb', line 39

def source_listener
  @source_listener ||= yield_self do
    Listen.to(*source_dirs.map(&:to_s), only: /\.rb$/) do |modified, added, removed|
      queue << [:source, modified, added, removed]
    end
  end
end

#type_check_thread(project) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/steep/drivers/watch.rb', line 55

def type_check_thread(project)
  Thread.new do
    until queue.closed?
      begin
        events = []
        events << queue.deq
        until queue.empty?
          events << queue.deq(nonblock: true)
        end

        events.compact.each do |name, modified, added, removed|
          case name
          when :source
            (modified + added).each do |name|
              path = Pathname(name).relative_path_from(Pathname.pwd)
              file = project.source_files[path] || Project::SourceFile.new(path: path, options: project_options)
              file.content = path.read
              project.source_files[path] = file
            end

            removed.each do |name|
              path = Pathname(name).relative_path_from(Pathname.pwd)
              project.source_files.delete(path)
            end

          when :signature
            (modified + added).each do |name|
              path = Pathname(name).relative_path_from(Pathname.pwd)
              file = project.signature_files[path] || Project::SignatureFile.new(path: path)
              file.content = path.read
              project.signature_files[path] = file
            end

            removed.each do |name|
              path = Pathname(name).relative_path_from(Pathname.pwd)
              project.signature_files.delete(path)
            end
          end
        end

        begin
          project.type_check
        rescue Racc::ParseError => exn
          stderr.puts exn.message
          project.clear
        end
      end
    end
  rescue ClosedQueueError
    # nop
  end
end