class

Detector::Ruby::Cli

Inherits Detector < Reference < Object

Detects Ruby command-line applications: programs that parse argv via the stdlib OptionParser, a < Thor subclass, or a CLI gem (gli, slop, tty-option, commander, optimist, clamp, dry-cli), or that index ARGV directly. Gates the Ruby CLI analyzer. Intentionally import/usage-anchored: bare ENV[...] or a plain ARGV reference (without an index) is too common in web apps to qualify.

Constants

ARGV_INDEX = /\bARGV\s*\[\s*\d+\s*\]/
CLAMP_SUBCLASS = /<\s*Clamp::Command\b/
CLI_GEMS = ["thor", "gli", "slop", "tty-option", "commander", "optimist", "clamp", "dry-cli"]
CLI_MARKER = Regex.union(REQUIRE_OPTPARSE, OPTION_PARSER, THOR_SUBCLASS, "require \"thor\"", "require 'thor'", GLI_APP, SLOP_USE, TTY_OPTION, COMMANDER_USE, ARGV_INDEX, OPTIMIST_USE, CLAMP_SUBCLASS, DRY_CLI_SUBCLASS)

Single-pass union of every source marker above (the two thor require forms were bare includes? probes; Regex.union escapes string arguments literally). The previous chain scanned the whole file up to 11 times on non-CLI Ruby sources — the common case.

COMMANDER_USE = /\binclude\s+Commander::Methods\b/
DRY_CLI_SUBCLASS = /<\s*Dry::CLI::Command\b/
GLI_APP = /\binclude\s+GLI::App\b/
OPTIMIST_USE = /\bOptimist(?:::|\.)options\b/
OPTION_PARSER = /\bOptionParser\.new\b/
REQUIRE_OPTPARSE = /\brequire\s+["']optparse["']/
SLOP_USE = /\bSlop\.(?:parse|new)\b/
THOR_SUBCLASS = /<\s*Thor\b/
TTY_OPTION = /\binclude\s+TTY::Option\b/

Class methods

tech_name

The tech name without needing an instance, so the registry can be read off the classes themselves rather than from a parallel list.

Source

Instance methods

applicable?(filename : String) : Bool

Cheap filename-only filter the detector pass uses to skip detect on files the detector cannot possibly match. The default true preserves prior behavior (every detector runs on every file). Override with the same predicate the body of detect starts with — e.g., filename.ends_with?(".py") for a Python framework detector — so the detector loop avoids the detect dispatch on files outside the detector's language.

On large codebases (saleor's 4255 .py files) this lifts ~100 virtual detect calls per file out of the hot loop because most detectors' inner first-line is exactly this kind of cheap filename check.

Source
detect(filename : String, file_contents : String) : Bool
Source
set_name
Source