Skip to content

Instantly share code, notes, and snippets.

@sinsoku
Created January 12, 2024 11:43
Show Gist options
  • Save sinsoku/99d8ff83765b1d0b7efbd95af0ede883 to your computer and use it in GitHub Desktop.
Save sinsoku/99d8ff83765b1d0b7efbd95af0ede883 to your computer and use it in GitHub Desktop.
Experimental implementation for orthoses-cli
#!/usr/bin/env ruby
# frozen_string_literal: true
# Phase to load libraries
require_relative "../config/application"
require 'orthoses/rails'
require 'orthoses/yard'
# You can choose logger level
Orthoses.logger.level = :warn
def build_orthoses(rmtree: true, if: nil)
# DSL for Orthoses.
Orthoses::Builder.new do
use(Orthoses::CreateFileByName,
to: 'sig/orthoses', # Write to this dir. (require)
rmtree:, # Remove all `to` dir before generation. (default: false)
if:)
# Complement missing const name.
use Orthoses::MissingName
# You can use other publicly available middleware.
# `Orthoses::YARD` is available at https://github.com/ksss/orthoses-yard.
# By using this middleware, you can add the capability
# to generate type information from YARD documentation.
use Orthoses::YARD,
parse: ['app/models/**/*.rb']
# You can load hand written RBS.
# use Orthoses::LoadRBS,
# paths: Dir.glob(Rails.root / "sig/hand-written/**/*.rbs")
# Middleware package for rails application.
use Orthoses::Rails::Application
if Rails.application.initialized?
run -> {
Rails.application.reloader.reload!
Rails.application.eager_load!
}
else
# Application code loaded here is the target of the analysis.
run Orthoses::Rails::Application::Loader.new
end
end
end
find_const_names = -> (ast, parent = nil) {
return [] unless ast.is_a?(RubyVM::AbstractSyntaxTree::Node)
names = []
if %i[CLASS MODULE].include?(ast.type)
klass = ast.children[0].children[1].to_s
names << [parent, klass].compact.join("::")
end
names + ast.children.flat_map { |child| find_const_names.call(child, names[0] || parent) }
}
# TODO:
# - Orthoses の出力するrbsのメソッド順序が変わる
# - 全てのファイルを解析するのは筋が悪そう
# tmp/pids/orthoses.pid を残しておき、多重起動を防ぐ仕組みが欲しい
if ARGV[0] == 'watch'
require 'listen'
listener = Listen.to('app', only: %r{.rb$}) do |modified, added, removed|
puts("start")
puts(modified: modified, added: added, removed: removed)
#=> {:modified=>["/Users/sinsoku/tmp/app_rbs/app/models/user.rb"], :added=>[], :removed=>[]}
names = (added + modified).uniq.flat_map do |f|
ast = RubyVM::AbstractSyntaxTree.parse_file(f)
find_const_names.call(ast)
end
pp names
#=> ["User"]
build_orthoses(
rmtree: false,
if: -> (name, _content) { names.include?(name) }
).call
puts("finished")
end
listener.start
sleep
else
build_orthoses.call
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment