Class: Keiyaku::Emitter

Inherits:
Object
  • Object
show all
Defined in:
lib/keiyaku/emitter.rb,
lib/keiyaku/emitter/rbs.rb,
lib/keiyaku/emitter/security.rb

Overview

Turns an OpenAPI document into three files: value types, a client, and RBS.

The guiding rule is that anything it cannot translate faithfully becomes a loud refusal rather than plausible-looking code.

Defined Under Namespace

Classes: Model, RBS, Refusal, Security

Constant Summary collapse

HEADER =

Stamped on every file it writes: which generator, and which version of the runtime contract the code was written against.

"# Generated by keiyaku #{VERSION}. Edits will be overwritten."
LIB =

Where the runtime is, for the process that reads the generated files back. Whether it is also an installed gem is not something to depend on.

File.expand_path("..", __dir__)
SCALARS =
{
  %w[string date-time] => "Time",
  %w[string date] => "Date",
  %w[string binary] => "String",
  %w[string] => "String",
  %w[integer] => "Integer",
  %w[number] => "Float",
  %w[boolean] => ":bool"
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, namespace:) ⇒ Emitter

Returns a new instance of Emitter.



46
47
48
49
50
51
52
53
54
55
56
# File 'lib/keiyaku/emitter.rb', line 46

def initialize(path, namespace:)
  @spec = path.end_with?(".json") ? JSON.parse(File.read(path)) : YAML.load_file(path)
  @namespace = Names.namespace(namespace)
  @models = {}      # constant name => args for Keiyaku.model(...), or union source
  @unions = {}      # union source => its RBS expansion, e.g. "Dog | Cat"
  @deps = {}        # constant name => referenced constant names
  @poisoned = {}    # constant name => why nothing may be typed as it
  @refusals = []
  @notes = []
  @rbs = RBS.new(namespace: @namespace, models: @models, unions: @unions)
end

Instance Attribute Details

#brokenObject (readonly)

The generated files, and whether Ruby could read them back. Anything already written stays on disk: reading the file the generator could not load is how its remaining mistakes get found.



61
62
63
# File 'lib/keiyaku/emitter.rb', line 61

def broken
  @broken
end

#notesObject (readonly)

Returns the value of attribute notes.



44
45
46
# File 'lib/keiyaku/emitter.rb', line 44

def notes
  @notes
end

#refusalsObject (readonly)

Returns the value of attribute refusals.



44
45
46
# File 'lib/keiyaku/emitter.rb', line 44

def refusals
  @refusals
end

Class Method Details

.comment(text) ⇒ Object

Prose for a generated comment. A refusal quotes the document, and a document's string can hold a newline: interpolated into a # comment it would end the comment, and whatever came after it would be read as Ruby. A comment is one line, so this is what a comment can hold.



77
# File 'lib/keiyaku/emitter.rb', line 77

def self.comment(text) = text.to_s.gsub(/\s+/, " ").strip

Instance Method Details

#emit(dir, verify: true) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/keiyaku/emitter.rb', line 63

def emit(dir, verify: true)
  collect_models
  operations = collect_operations
  File.write(File.join(dir, "types.rb"), types_source)
  File.write(File.join(dir, "client.rb"), client_source(operations))
  File.write(File.join(dir, "#{Keiyaku.snake(@namespace)}.rbs"), @rbs.source(sorted_models, operations))
  @broken = verify ? load_check(dir) : nil
  operations
end