Class: Audition::Static::GraphAudit

Inherits:
Object
  • Object
show all
Defined in:
lib/audition/static/graph_audit.rb

Overview

Whole-program semantic checks backed by the rubydex graph. rubydex resolves state to its true owner, so an ivar written in the class body, in def self.x, and inside class << self, across several files, unifies into one declaration owned by the singleton class. Per-file AST visitors cannot see that.

Constant Summary collapse

CVAR_WHY =
"Class variables cannot be accessed from non-main Ractors " \
"at all; both reads and writes raise " \
"Ractor::IsolationError (\"can not access class variables " \
"from non-main Ractors\")."
CVAR_FIX =
"Replace with a deeply frozen constant, per-instance " \
"state, or Ractor-local storage (Ractor.current[:key], " \
"Ractor.store_if_absent)."
STATE_WHY =
"This instance variable lives on the class/module object, " \
"which is shared across Ractors; non-main Ractors raise " \
"Ractor::IsolationError when writing it, and when reading " \
"it while it holds a non-shareable value (verified on " \
"Ruby 4.0)."
STATE_FIX =
"Precompute and freeze the value at load time, use " \
"Ractor.store_if_absent for lazy initialization, or keep " \
"per-Ractor state in Ractor.current[:key]."

Instance Method Summary collapse

Instance Method Details

#analyze_paths(paths) ⇒ Array<Finding>

rubydex's index_all descends directories but skips bare file lists, so files are fed through index_source individually.

Parameters:

  • paths (Array<String>)

    files to index and audit

Returns:



49
50
51
52
53
54
55
56
57
# File 'lib/audition/static/graph_audit.rb', line 49

def analyze_paths(paths)
  sources = {}
  paths.each do |path|
    sources[path] = File.read(path)
  rescue SystemCallError
    next
  end
  analyze_sources(sources)
end

#analyze_sources(sources) ⇒ Array<Finding>

Parameters:

  • sources (Hash{String => String})

    path => source

Returns:



35
36
37
38
39
40
41
42
# File 'lib/audition/static/graph_audit.rb', line 35

def analyze_sources(sources)
  graph = Rubydex::Graph.new
  sources.each do |path, code|
    graph.index_source(path, code, "ruby")
  end
  @sources = sources
  audit(graph)
end