Individual switch class. Not important to the user.
Defined within Switch
are several Switch-derived classes: NoArgument
, RequiredArgument
, etc.
Raises when there is an argument for a switch which takes no argument.
Raises when a switch with mandatory argument has no argument.
Raises when the given argument does not match required format.
Raises when the given argument word can’t be completed uniquely.
DesugarCompiler
is a compiler that desugars Ruby code into a more primitive form. This is useful for consumers that want to deal with fewer node types.
A pattern is an object that wraps a Ruby pattern matching expression. The expression would normally be passed to an ‘in` clause within a `case` expression or a rightward assignment expression. For example, in the following snippet:
case node in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] end
the pattern is the ConstantPathNode[...]
expression.
The pattern gets compiled into an object that responds to call by running the compile
method. This method itself will run back through Prism
to parse the expression into a tree, then walk the tree to generate the necessary callable objects. For example, if you wanted to compile the expression above into a callable, you would:
callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile callable.call(node)
The callable object returned by compile
is guaranteed to respond to call with a single argument, which is the node to match against. It also is guaranteed to respond to ===
, which means it itself can be used in a ‘case` expression, as in:
case node when callable end
If the query given to the initializer cannot be compiled into a valid matcher (either because of a syntax error or because it is using syntax we do not yet support) then a Prism::Pattern::CompilationError
will be raised.
Gem::ConfigFile
RubyGems options and gem command options from gemrc.
gemrc is a YAML
file that uses strings to match gem command arguments and symbols to match RubyGems options.
Gem command arguments use a String
key that matches the command name and allow you to specify default arguments:
install: --no-rdoc --no-ri update: --no-rdoc --no-ri
You can use gem:
to set default arguments for all commands.
RubyGems options use symbol keys. Valid options are:
:backtrace
See backtrace
:sources
Sets Gem::sources
:verbose
See verbose
:concurrent_downloads
gemrc files may exist in various locations and are read and merged in the following order:
system wide (/etc/gemrc)
per user (~/.gemrc)
per environment (gemrc files listed in the GEMRC environment variable)
Raised when there are conflicting gem specs loaded
Example using a Gem::Package
Builds a .gem file given a Gem::Specification
. A .gem file is a tarball which contains a data.tar.gz, metadata.gz, checksums.yaml.gz and possibly signatures.
require 'rubygems' require 'rubygems/package' spec = Gem::Specification.new do |s| s.summary = "Ruby based make-like utility." s.name = 'rake' s.version = PKG_VERSION s.requirements << 'none' s.files = PKG_FILES s.description = <<-EOF Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax. EOF end Gem::Package.build spec
Reads a .gem file.
require 'rubygems' require 'rubygems/package' the_gem = Gem::Package.new(path_to_dot_gem) the_gem.contents # get the files in the gem the_gem.extract_files destination_directory # extract the gem into a directory the_gem.spec # get the spec out of the gem the_gem.verify # check the gem is OK (contains valid gem specification, contains a not corrupt contents archive)
files
are the files in the .gem tar file, not the Ruby files in the gem extract_files
and contents
automatically call verify
Create a package based upon a Gem::Specification
. Gem packages, as well as zip files and tar/gzipped packages can be produced by this task.
In addition to the Rake targets generated by Rake::PackageTask, a Gem::PackageTask
will also generate the following tasks:
Create a RubyGems package with the given name and version.
Example using a Gem::Specification
:
require 'rubygems' require 'rubygems/package_task' spec = Gem::Specification.new do |s| s.summary = "Ruby based make-like utility." s.name = 'rake' s.version = PKG_VERSION s.requirements << 'none' s.files = PKG_FILES s.description = <<-EOF Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax. EOF end Gem::PackageTask.new(spec) do |pkg| pkg.need_zip = true pkg.need_tar = true end
Subclass of StreamUI that instantiates the user interaction using $stdin, $stdout, and $stderr.
This class is useful for exploring contents before and after a block
It searches above and below the passed in block to match for whatever criteria you give it:
Example:
def dog # 1 puts "bark" # 2 puts "bark" # 3 end # 4 scan = AroundBlockScan.new( code_lines: code_lines block: CodeBlock.new(lines: code_lines[1]) ) scan.scan_while { true } puts scan.before_index # => 0 puts scan.after_index # => 3
This class is responsible for taking a code block that exists at a far indentaion and then iteratively increasing the block so that it captures everything within the same indentation block.
def dog puts "bow" puts "wow" end
block = BlockExpand.new
(code_lines: code_lines)
.call(CodeBlock.new(lines: code_lines[1]))
puts block.to_s # => puts “bow”
puts "wow"
Once a code block has captured everything at a given indentation level then it will expand to capture surrounding indentation.
block = BlockExpand.new
(code_lines: code_lines)
.call(block)
block.to_s # => def dog
puts "bow" puts "wow" end
Turns a “invalid block(s)” into useful context
There are three main phases in the algorithm:
Sanitize/format input source
Search for invalid blocks
Format invalid blocks into something meaninful
This class handles the third part.
The algorithm is very good at capturing all of a syntax error in a single block in number 2, however the results can contain ambiguities. Humans are good at pattern matching and filtering and can mentally remove extraneous data, but they can’t add extra data that’s not present.
In the case of known ambiguious cases, this class adds context back to the ambiguity so the programmer has full information.
Beyond handling these ambiguities, it also captures surrounding code context information:
puts block.to_s # => "def bark" context = CaptureCodeContext.new( blocks: block, code_lines: code_lines ) lines = context.call.map(&:original) puts lines.join # => class Dog def bark end
Searches code for a syntax error
There are three main phases in the algorithm:
Sanitize/format input source
Search for invalid blocks
Format invalid blocks into something meaninful
This class handles the part.
The bulk of the heavy lifting is done in:
- CodeFrontier (Holds information for generating blocks and determining if we can stop searching) - ParseBlocksFromLine (Creates blocks into the frontier) - BlockExpand (Expands existing blocks to search more code)
## Syntax error detection
When the frontier holds the syntax error, we can stop searching
search = CodeSearch.new(<<~EOM) def dog def lol end EOM search.call search.invalid_blocks.map(&:to_s) # => # => ["def lol\n"]