Class: Hone::Scanner

Inherits:
Object
  • Object
show all
Defined in:
lib/hone/scanner.rb

Overview

Scans Ruby files for optimization patterns using Prism AST analysis. Coordinates multiple pattern matchers and collects their findings.

Constant Summary collapse

DEFAULT_RUBY_GLOB =

Default glob pattern for finding Ruby files

"**/*.rb"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(patterns: Patterns.registered, rails: false) ⇒ Scanner

Returns a new instance of Scanner.



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/hone/scanner.rb', line 12

def initialize(patterns: Patterns.registered, rails: false)
  @rails = rails
  @patterns = patterns.select do |pattern|
    # Skip abstract base classes (no pattern_id)
    next false if pattern.pattern_id.nil?

    if @rails
      true
    else
      pattern.scope.nil? || pattern.scope == :ruby
    end
  end
end

Class Method Details

.group_by_file(findings) ⇒ Object

Group findings by file



61
62
63
# File 'lib/hone/scanner.rb', line 61

def self.group_by_file(findings)
  findings.group_by(&:file)
end

.group_by_optimization_type(findings) ⇒ Object

Group findings by optimization type (:cpu, :allocation, :jit)



71
72
73
# File 'lib/hone/scanner.rb', line 71

def self.group_by_optimization_type(findings)
  findings.group_by(&:optimization_type)
end

.group_by_pattern(findings) ⇒ Object

Group findings by pattern type



66
67
68
# File 'lib/hone/scanner.rb', line 66

def self.group_by_pattern(findings)
  findings.group_by(&:pattern_id)
end

Instance Method Details

#scan_directory(path, pattern: DEFAULT_RUBY_GLOB) ⇒ Object

Scan all Ruby files in a directory Returns an array of findings from all files



46
47
48
49
50
51
52
# File 'lib/hone/scanner.rb', line 46

def scan_directory(path, pattern: DEFAULT_RUBY_GLOB)
  files = Dir.glob(File.join(path, pattern))

  files.flat_map do |file|
    scan_file(file)
  end
end

#scan_file(path) ⇒ Object

Scan a single file with all patterns Returns an array of findings from all pattern matchers



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/hone/scanner.rb', line 28

def scan_file(path)
  result = Prism.parse_file(path)

  if result.errors.any?
    warn "Parse errors in #{path}:"
    result.errors.each { |e| warn "  #{e.message}" }
    return []
  end

  @patterns.flat_map do |pattern_class|
    matcher = pattern_class.new(path)
    result.value.accept(matcher)
    matcher.findings
  end
end

#scan_files(paths) ⇒ Object

Scan multiple files Returns an array of findings from all files



56
57
58
# File 'lib/hone/scanner.rb', line 56

def scan_files(paths)
  paths.flat_map { |path| scan_file(path) }
end