Class: Necropsy::ReferenceBarrier

Inherits:
Object
  • Object
show all
Defined in:
lib/necropsy/reference_barrier.rb

Constant Summary collapse

MAX_FILE_BYTES =
1_048_576
MAX_STREAM_FILE_BYTES =
16_777_216
MAX_TOTAL_SCAN_BYTES =
67_108_864
MAX_TOTAL_MATCHES =
10_000
MAX_SCAN_SECONDS =
5.0
MAX_MATCHES_PER_DEFINITION =
5
MAX_SNIPPET_BYTES =
240
SKIPPED_SAMPLE_LIMIT =
50
BINARY_EXTENSIONS =
%w[
  .7z .a .bundle .class .db .dll .dylib .eot .exe .gif .gz .ico .jar .jpeg .jpg .o .pdf .png .so .sqlite
  .tar .ttf .webp .woff .woff2 .zip
].freeze
GENERATED_PATH_PARTS =
%w[generated dist].freeze
TOOL_METADATA_BASENAMES =
%w[.necropsy.yml .necropsy_baseline.yml].freeze
GENERATED_MARKER =
/(?:@generated|automatically generated|generated file|do not edit)/i
UNSAFE_SKIP_REASONS =
%i[generated oversized unreadable scan_budget match_budget time_budget].freeze
COMMON_SHORT_NAMES =
%w[call create destroy edit index new run show update].freeze
REFERENCE_DSL_KEYS =
%w[action callback command function handler method perform task].freeze
TOKEN_PATTERN =
/[A-Za-z_][A-Za-z0-9_]*(?:[!?=](?![A-Za-z0-9_]))?/

Instance Method Summary collapse

Constructor Details

#initialize(graph:, project:, ignored_paths: [], monotonic_clock: nil) ⇒ ReferenceBarrier

Returns a new instance of ReferenceBarrier.



25
26
27
28
29
30
# File 'lib/necropsy/reference_barrier.rb', line 25

def initialize(graph:, project:, ignored_paths: [], monotonic_clock: nil)
  @graph = graph
  @project = project
  @ignored_paths = Array(ignored_paths).compact.to_set { |path| File.expand_path(path, project.root) }
  @monotonic_clock = monotonic_clock || -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }
end

Instance Method Details

#apply(findings) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/necropsy/reference_barrier.rb', line 32

def apply(findings)
  @candidates = findings.reject { |finding| finding.blockers.any? }.map(&:node).sort_by(&:graph_id)
  @candidate_index = build_candidate_index
  @non_token_index = build_non_token_index
  @non_token_pattern = build_non_token_pattern
  @matches = Hash.new { |hash, key| hash[key] = [] }
  @skipped_counts = Hash.new(0)
  @skipped_samples = []
  @unsafe_runtime_skips = []
  @files_scanned = 0
  @files_streamed = 0
  @bytes_scanned = 0
  @total_matches = 0
  @truncated_matches = 0
  @scan_deadline = monotonic_time + MAX_SCAN_SECONDS
  files = project.non_ruby_reference_files
  unless candidates.empty?
    files.each do |file|
      if time_budget_exceeded?
        record_time_budget(project.relative_path(file))
      elsif @match_budget_exceeded
        record_match_budget(project.relative_path(file))
      else
        scan_file(file)
      end
    end
  end
  add_blockers
  unsafe_blockers = add_unsafe_skip_blocker
  record_diagnostic(files)
  matches.values.sum(&:length) + unsafe_blockers
end