Types and checks
The carton command ships in the carton-tools gem, released with carton at the same version, so apps and gems built on Carton do not install it. Add it where your checks run:
# Gemfilegem 'carton'gem 'carton-tools', group: :developmentIt reads code with Prism and never runs it, so it needs no RUBY_BOX=1. Give it the app’s files or directories; it follows each import into the Cartons it reaches. Run it under bundle exec in a bundled app so named imports resolve.
RBS for imports
Section titled “RBS for imports”carton rbs main.rb writes sig/generated/carton.rbs, which tells a type checker such as Steep what each import returns:
- An exported constant, such as
export Billing, types assingleton(::Billing). The Carton declaresBillingin its own RBS, as a gem would. - A keyword export, such as
export version: '1.0', types as a record,{ version: ::String }. - A Bare Carton gets a module, such as
Carton::Namespace::Util, with a singleton method per Helper and a constant per constant. Types come from rbs-inline#:annotations, or areuntyped.
Load Carton’s own signatures and the generated file in the Steepfile, and regenerate the file whenever an import or export changes:
# Steepfiletarget :app do signature 'sig' library 'carton' check 'main.rb'endStatic checks
Section titled “Static checks”carton check main.rb prints each problem as file:line: level: message and exits non-zero on any error, so it can run in CI. Errors are certain to fail or misbehave when the code runs; warnings are things a dynamic program could still get right. --strict fails on warnings too.
It reports, among others:
- an import of a missing path, or of a file inside a Carton
- an import cycle
- a
requirethat reaches into another Carton and would load a second copy - a private constant of an exported module used from outside
- a gem a Gem Carton uses without declaring it in its gemspec
The CLI reference lists every check.
Dynamic imports
Section titled “Dynamic imports”An import whose path is computed at runtime, as in plugin discovery, cannot be followed. Mark it with # carton:dynamic, on its line or the line above, to say so and silence its warning:
Dir.glob('plugins/*/').each do |dir| import_relative dir # carton:dynamicend