Skip to content

Instantly share code, notes, and snippets.

@kddnewton
kddnewton / constants.rb
Created August 23, 2022 14:42
Extract constant references from files
#!/usr/bin/env ruby
# The purpose of this script is to extract all constant references from a given
# source file. It reads ARGF, which means you can either pass the content in
# through stdin or you can pass the file name as an argument. So for example,
# you can either:
#
# echo 'Foo::Bar' | ./constants
#
# or you can pass a file name, as in:
@kddnewton
kddnewton / inline.rb
Last active September 26, 2022 15:04
inlined response
# This class is responsible for publishing a post. This is basically a curried
# global function that is addressable through the PublishPost class. It can be
# easily tested, since its only dependency is the post that it accepts.
class PublishPost
attr_reader :post
def initialize(post)
@post = post
end
@kddnewton
kddnewton / test.rb
Created September 30, 2022 16:58
Minitest example
require "minitest/autorun"
class TemplatingTest < Minitest::Test
def test_positional_argument_splats
assert_templates <<~RUBY, "h1", "*args"
@_target << "<h1>" << _output(*args) << "</h1>"
RUBY
end
def test_multiple_positional_argument_splats
@kddnewton
kddnewton / pattern.rb
Created October 28, 2022 15:07
Pattern matching
# This module is a light implementation of pattern matching that allows us to
# match against hashes and arrays as we would with the new pattern matching
# syntax.
module Pattern
class ArrayPattern
attr_reader :values
def initialize(values)
@values = values
end
@kddnewton
kddnewton / pattern.rb
Created November 1, 2022 21:52
More pattern matching
# Imagine we need to switch on some kind of input and do something based on some
# attribute of that input. We can do this with a case statement, where we inline
# each of the implementations of the interface that we're defining into the case
# statement. That would look something like:
class Input
attr_reader :type, :name
def initialize(type, name)
@type = type
@kddnewton
kddnewton / latexify.rb
Last active November 7, 2022 14:45
LaTeXify Ruby methods
#!/usr/bin/env ruby
# frozen_string_literal: true
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "syntax_tree"
end
@kddnewton
kddnewton / mutation.rb
Created November 8, 2022 20:22
Mutation visitor
require "syntax_tree"
# Create a new visitor that is going to visit the parsed tree.
visitor = SyntaxTree::Visitor::MutationVisitor.new
# Define a mutation on the visitor that is going to search for the given pattern
# to find nodes that match it and then call the given block to mutate the node
# in place in the tree.
visitor.mutate("If[predicate: Assign | OpAssign]") do |node|
# Get the existing If's predicate node.
@kddnewton
kddnewton / linter.rb
Created November 9, 2022 20:17
Linting with Syntax Tree
# frozen_string_literal: true
module SyntaxTree
# This class is used to create a mutation that transforms syntax trees based
# on various linting rules.
class Linter
def mutation
SyntaxTree.mutation do |mutator|
# Lint/AssignmentInCondition
mutator.mutate("IfNode[predicate: Assign | OpAssign] | UnlessNode[predicate: Assign | OpAssign] | WhileNode[predicate: Assign | OpAssign] | UntilNode[predicate: Assign | OpAssign]") do |node|
@kddnewton
kddnewton / count.rb
Created November 28, 2022 21:50
Count the number of YARV instructions in source
def count(iseq)
iseq[12].select { _1 in [:ensure | :rescue, *] }.sum { count(_1[1]) } +
iseq[13].sum do
case _1
in Integer | Symbol
0
in [*, ["YARVInstructionSequence/SimpleDataFormat", *] => child, *]
1 + count(child)
in Array
1