Class: Lock::Gemfile::Rewriter

Inherits:
Parser::TreeRewriter
  • Object
show all
Defined in:
lib/lock/gemfile/rewriter.rb

Overview

The Lock::Gemfile::Rewriter class is a subclass of Parser::TreeRewriter that rewrites a Gemfile’s Abstract Syntax Tree (AST) to include locked gem versions from a corresponding Gemfile.lock file.

The rewriter traverses the AST and looks for ‘gem` method calls. For each `gem` call found, it checks if a version specifier is already present. If not, it retrieves the locked version from the provided lockfile hash and inserts a version specifier string after the gem name.

The version specifier can be either pessimistic or exact, depending on the value of the ‘pessimistic` attribute. If `pessimistic` is true (default), the version specifier will be prefixed with “~>”, otherwise it will be an exact version.

Example usage:

parser = Parser::Ruby31.new ast = parser.parse(buffer)

rewriter = Lock::Gemfile::Rewriter.new rewriter.lockfile = {
  "rails" => "6.1.0", "puma" => "5.0.4"
} rewriter.pessimistic = true

modified_ast = rewriter.rewrite(buffer, ast)

Attributes:

lockfile (Hash): A hash containing gem names as keys and their
locked versions as values.  pessimistic (Boolean): Determines
whether to use pessimistic version specifiers. Default is true.

Methods:

on_send(node): Called when a `:send` node is encountered in the
AST. Checks if the node represents a `gem` method call
               and inserts the locked version specifier if
               applicable.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#lockfileObject

Returns the value of attribute lockfile.



44
45
46
# File 'lib/lock/gemfile/rewriter.rb', line 44

def lockfile
  @lockfile
end

#pessimisticObject

Returns the value of attribute pessimistic.



44
45
46
# File 'lib/lock/gemfile/rewriter.rb', line 44

def pessimistic
  @pessimistic
end

Instance Method Details

#on_send(node) ⇒ Object

Handles ‘:send` nodes in the AST, which represent method calls.

If the node is a ‘gem` method call and doesn’t already have a version specifier, retrieves the locked version from the ‘lockfile` hash and inserts a version specifier string.

The version specifier can be either pessimistic or exact, depending on the value of ‘pessimistic`.

Arguments:

node (Parser::AST::Node): The `:send` node being processed.


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/lock/gemfile/rewriter.rb', line 59

def on_send(node)
  return unless node.type == :send && node.children[1] == :gem

  gem_name = node.children[2].children[0]

  old_version_specifier = node.children[3]
  already_has_version_specifier = old_version_specifier && old_version_specifier.type == :str

  return if already_has_version_specifier

  lockfile_gem_details = lockfile[gem_name]
  new_version_specifier = lockfile_gem_details&.to_s
  prefix = if pessimistic
             "~> "
           else
             ""
           end

  return unless new_version_specifier

  insert_after(node.children[2].location.end, ", '#{prefix}#{new_version_specifier}'")
end