Steepコードリーディング(2日目)
前回の続き、Steep::Drivers::Check#run
のload_config
を追っていく。
Steep::Drivers::Utils::DriverHelper
Steep::Drivers::Utils::DriverHelper#load_config
プロジェクト内のSteepfileを使ってProject
インスタンスを返している。Project
インスタンスにはProject::Target
の配列を持つProject#targets
があり、これをeachしてgem_rbs_collectionのrbs_collection.lock.yaml
ファイルのチェックを行っている
def load_config(path: steepfile || Pathname("Steepfile"))
if path.file?
steep_file_path = path.absolute? ? path : Pathname.pwd + path
Project.new(steepfile_path: steep_file_path).tap do |project|
Project::DSL.parse(project, path.read, filename: path.to_s)
end
else
Steep.ui_logger.error { "Cannot find a configuration at #{path}: `steep init` to scaffold. Using current directory..." }
Project.new(steepfile_path: nil, base_dir: Pathname.pwd).tap do |project|
Project::DSL.eval(project) do
target :'.' do
check '.'
signature '.'
end
end
end
end.tap do |project|
project.targets.each do |target|
case result = target.options.load_collection_lock
when nil, RBS::Collection::Config::Lockfile
# ok
when Pathname
# File is missing
if result == target.options.collection_config_path
# Config file is missing
Steep.ui_logger.error { "rbs-collection configuration is missing: `#{result}`" }
else
# Lockfile is missing
Steep.ui_logger.error { "Run `rbs collection install` to generate missing lockfile: `#{result}`" }
end
when YAML::SyntaxError
# File is broken
Steep.ui_logger.error { "rbs-collection setup is broken:\nsyntax error #{result.inspect}" }
when RBS::Collection::Config::CollectionNotAvailable
unless disable_install_collection
install_collection(target, target.options.collection_config_path || raise)
else
Steep.ui_logger.error { "Run `rbs collection install` to set up RBS files for gems" }
end
end
end
end
end
Steep::Project
Project::DSL
Project::DSL#.parse
プロジェクト内のSteepfileのコードをinstance_evalで実行し、Project
のオプションを設定する。
def self.parse(project, code, filename: "Steepfile")
Steep.logger.tagged filename do
dsl = self.new(project: project)
dsl.instance_eval(code, filename)
project.global_options = dsl.to_library_options
end
end
Steepfileにはtarget :app do ... end
のように記述するが、それがProject::DSL#target
を呼び出すスクリプトとなる。
Project::DSL#target
Project::Target
を作成し、Project#targets
に追加する。
def target(name, &block)
dsl = TargetDSL.new(name, project: project)
Steep.logger.tagged "target=#{name}" do
dsl.instance_eval(&block) if block
end
target = Project::Target.new(
name: dsl.name,
source_pattern: dsl.source_pattern,
signature_pattern: dsl.signature_pattern,
options: dsl.library_configured? ? dsl.to_library_options : nil,
code_diagnostics_config: dsl.code_diagnostics_config,
project: project,
unreferenced: dsl.unreferenced
)
dsl.groups.each do
group = Group.new(target, _1.name, _1.source_pattern, _1.signature_pattern, _1.code_diagnostics_config || target.code_diagnostics_config)
target.groups << group
end
project.targets << target
end
SteepfileのDSLを追加したり変更したいときは、この辺りのメソッドを追加したり変更すると良さそう。
次回は Steep::Drivers::Check#run
の Server::WorkerProcess.start_typecheck_workers
を追っていく。