This represents a location in the source.
This represents a magic comment that was encountered during parsing.
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.
TruffleRuby >= 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY
in defaults/truffleruby. However, TruffleRuby < 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY
directly in its copy of lib/rubygems/platform.rb, so it is not defined if RubyGems is updated (gem update –system). Instead, we define it here in that case, similar to bundler/lib/bundler/rubygems_ext.rb. We must define it here and not in platform.rb because platform.rb is loaded before defaults/truffleruby.
Available list of platforms for targeting Gem installations.
See ‘gem help platform` for information on platform matching.
BasicSpecification
is an abstract class which implements some common code used by both Specification and StubSpecification.
Base class for all Gem commands. When creating a new gem command, define initialize, execute
, arguments
, defaults_str
, description
and usage
(as appropriate). See the above mentioned methods for details.
A very good example to look at is Gem::Commands::ContentsCommand
Potentially raised when a specification is validated.
Raised by Gem::Validator
when something is not right in a gem.
Raised by Gem::WebauthnListener when an error occurs during security device verification.
Raised by Resolver when a dependency requests a gem for which there is no spec.
Gem::PathSupport
facilitates the GEM_HOME and GEM_PATH environment settings to the rest of RubyGems.
The Specification
class contains the information for a gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:
Gem::Specification.new do |s| s.name = 'example' s.version = '0.1.0' s.licenses = ['MIT'] s.summary = "This is an example!" s.description = "Much longer explanation of the example!" s.authors = ["Ruby Coder"] s.email = 'rubycoder@example.com' s.files = ["lib/example.rb"] s.homepage = 'https://rubygems.org/gems/example' s.metadata = { "source_code_uri" => "https://github.com/example/example" } end
Starting in RubyGems 2.0, a Specification
can hold arbitrary metadata. See metadata
for restrictions on the format and size of metadata items you may add to a specification.
Gem::StubSpecification
reads the stub: line from the gemspec. This prevents us having to eval the entire gemspec in order to find out certain information.
Validator
performs various gem file and gem database validation
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"]