Module: Referral

Defined in:
lib/referral.rb,
lib/referral/cli.rb,
lib/referral/error.rb,
lib/referral/runner.rb,
lib/referral/version.rb,
lib/referral/git_store.rb,
lib/referral/file_store.rb,
lib/referral/token_types.rb,
lib/referral/value/token.rb,
lib/referral/scans_tokens.rb,
lib/referral/sorts_tokens.rb,
lib/referral/value/result.rb,
lib/referral/value/options.rb,
lib/referral/filters_tokens.rb,
lib/referral/parses_options.rb,
lib/referral/prints_results.rb,
lib/referral/value/node_type.rb,
lib/referral/expands_directories.rb,
lib/referral/matches_token_names.rb,
lib/referral/ensures_working_ruby.rb,
lib/referral/tokenizes_identifiers.rb,
lib/referral/translates_node_to_token.rb

Defined Under Namespace

Modules: Value Classes: Cli, EnsuresWorkingRuby, Error, ExpandsDirectories, FileStore, FiltersTokens, GitStore, MatchesTokenNames, ParsesOptions, PrintsResults, Runner, ScansTokens, SortsTokens, TokenizesIdentifiers, TranslatesNodeToToken

Constant Summary collapse

VERSION =
"0.0.5"
JOIN_SEPARATORS =
{
  double_colon: "::",
  dot: ".",
  hash: "#",
  tilde: "~",
}
TOKEN_TYPES =
{
  module: Value::NodeType.new(
    name: :module,
    ast_type: :MODULE,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: true,
    name_finder: ->(node) { nil }
  ),
  class: Value::NodeType.new(
    name: :class,
    ast_type: :CLASS,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: true,
    name_finder: ->(node) { nil }
  ),
  constant_def: Value::NodeType.new(
    name: :constant_declaration,
    ast_type: :CDECL,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: true,
    name_finder: ->(node) {
      possible_name = node.children[0]
      possible_name.is_a?(Symbol) ? possible_name : nil
    }
  ),
  class_method: Value::NodeType.new(
    name: :class_method,
    ast_type: :DEFS,
    join_separator: JOIN_SEPARATORS[:dot],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: true,
    name_finder: ->(node) { node.children[1] }
  ),
  instance_method: Value::NodeType.new(
    name: :instance_method,
    ast_type: :DEFN,
    join_separator: JOIN_SEPARATORS[:hash],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: true,
    name_finder: ->(node) { node.children[0] }
  ),
  local_var_assign: Value::NodeType.new(
    name: :local_var_assign,
    ast_type: :LASGN,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  instance_var_assign: Value::NodeType.new(
    name: :instance_var_assign,
    ast_type: :IASGN,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  class_var_assign: Value::NodeType.new(
    name: :class_var_assign,
    ast_type: :CVASGN,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  global_var_assign: Value::NodeType.new(
    name: :global_var_assign,
    ast_type: :GASGN,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  attr_assign: Value::NodeType.new(
    name: :attr_assign,
    ast_type: :ATTRASGN,
    join_separator: JOIN_SEPARATORS[:dot],
    token_type: :definition,
    reverse_identifiers: false,
    good_parent: false,
    name_finder: ->(node) { node.children[1] }
  ),
  call: Value::NodeType.new(
    name: :call,
    ast_type: :CALL,
    join_separator: JOIN_SEPARATORS[:dot],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: true,
    name_finder: ->(node) { node.children[1] },
    arity_finder: ->(node) { node.children.last&.children&.compact&.count || 0 }
  ),
  function_call: Value::NodeType.new(
    name: :function_call,
    ast_type: :FCALL,
    join_separator: JOIN_SEPARATORS[:dot],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] },
    arity_finder: ->(node) { node.children.last&.children&.compact&.count || 0 }
  ),
  local_var: Value::NodeType.new(
    name: :local_var,
    ast_type: :LVAR,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  instance_var: Value::NodeType.new(
    name: :instance_var,
    ast_type: :IVAR,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  class_var: Value::NodeType.new(
    name: :class_var,
    ast_type: :CVAR,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  global_var: Value::NodeType.new(
    name: :global_var,
    ast_type: :GVAR,
    join_separator: JOIN_SEPARATORS[:tilde],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  constant_ref: Value::NodeType.new(
    name: :constant,
    ast_type: :CONST,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
  double_colon: Value::NodeType.new(
    name: :constant,
    ast_type: :COLON2,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[1] }
  ),
  triple_colon: Value::NodeType.new(
    name: :constant,
    ast_type: :COLON3,
    join_separator: JOIN_SEPARATORS[:double_colon],
    token_type: :reference,
    reverse_identifiers: true,
    good_parent: false,
    name_finder: ->(node) { node.children[0] }
  ),
}
SORT_FUNCTIONS =
{
  file: ->(tokens) {
    tokens.sort_by { |token|
      [token.file, token.line, token.column, token.id]
    }
  },
  scope: ->(tokens) {
    max_length = tokens.map { |t| t.scope_and_names.size }.max
    tokens.sort_by { |token|
      names = token.scope_and_names.map { |fq| fq.name.to_s }
      [
        *names.fill("", names.size...max_length),
        token.file, token.line, token.column, token.id,
      ]
    }
  },
  least_recent_commit: ->(tokens) {
    tokens.sort_by do |token|
      [
        GitStore.time(token.file, token.line).to_i,
        token.file, token.line, token.column, token.id,
      ]
    end
  },
  most_recent_commit: ->(tokens) {
    tokens.sort_by { |token|
      [
        -1 * GitStore.time(token.file, token.line).to_i,
        token.file, token.line, token.column, token.id,
      ]
    }
  },
}
FILTER_FUNCTIONS =
{
  name: ->(token, names) {
    names.any? { |name| token.full_name.include?(name) }
  },
  exact_name: ->(token, exact_names) {
    exact_names.any? { |query|
      MatchesTokenNames.subset(token.full_name_tokens, query)
    }
  },
  full_name: ->(token, full_names) {
    full_names.any? { |query|
      MatchesTokenNames.entirely(token.full_name_tokens, query)
    }
  },
  scope: ->(token, scope_names) {
    scope_names.any? { |query|
      MatchesTokenNames.subset(token.scope_tokens, query)
    }
  },
  pattern: ->(token, regex) {
    regex.match(token.full_name) || regex.match(FileStore.read_line(token.file, token.line))
  },
  type: ->(token, types) {
    types.include?(token.node_type.name.to_s)
  },
  include_unnamed: ->(token, opt_val) {
    if !opt_val
      /\w/ =~ token.full_name
    else
      true
    end
  },
  arity: ->(token, arity) {
    if token.arity.nil?
      false
    elsif arity.end_with? "+"
      token.arity.to_i >= arity.to_i
    elsif arity.end_with? "-"
      token.arity.to_i <= arity.to_i
    else
      token.arity.to_i == arity.to_i
    end
  },
}
COLUMN_FUNCTIONS =
{
  id: ->(token) {
    token.id
  },
  location: ->(token) {
    "#{token.file}:#{token.line}:#{token.column}:"
  },
  file: ->(token) {
    token.file
  },
  line: ->(token) {
    token.line
  },
  column: ->(token) {
    token.column
  },
  type: ->(token) {
    token.type_name
  },
  scope: ->(token) {
    token.scope
  },
  name: ->(token) {
    token.literal_name
  },
  full_name: ->(token) {
    token.full_name
  },
  source: ->(token) {
    FileStore.read_line(token.file, token.line)
  },
  git_sha: ->(token) {
    GitStore.sha(token.file, token.line)
  },
  git_author: ->(token) {
    GitStore.author(token.file, token.line)
  },
  git_commit_at: ->(token) {
    GitStore.time(token.file, token.line)&.utc&.iso8601
  },
  arity: ->(token) {
    token.arity
  },

}

Class Method Summary collapse

Class Method Details

.run(*args, **kwargs, &blk) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/referral.rb', line 5

def self.run(*args, **kwargs, &blk)
  require "referral/ensures_working_ruby"
  Referral::EnsuresWorkingRuby.new.call

  require "referral/runner"
  Runner.new.call(*args, **kwargs, &blk)
end