class Aws::Api::Documenter

def apply

def apply
  document_service
  document_client
  document_errors
end

def client_constructor_docstring

def client_constructor_docstring
  <<-DOCS.strip
ucts an API client.
nt_constructor_options}
n [#{@client_class.name}] Returns an API client.
  DOCS
end

def client_constructor_options

def client_constructor_options
  options = {}
  @client_class.plugins.each do |plugin|
    if p = YARD::Registry[plugin.name]
      p.tags.each do |tag|
        if tag.tag_name == 'seahorse_client_option'
          option_name = tag.text.match(/.+(:\w+)/)[1]
          option_text = "@option options " + tag.text.split("\n").join("\n  ")
          options[option_name] = option_text +
            "  See {#{plugin.name}} for more details."
        end
      end
    end
  end
  options.sort_by { |k,v| k }.map(&:last).join("\n")
end

def client_docstring

def client_docstring
  path = "doc-src/services/#{@svc_name}/client.md"
  path = 'doc-src/services/default/client.md' unless File.exists?(path)
  render(path)
end

def document_client

def document_client
  yard_class = YARD::CodeObjects::ClassObject.new(@namespace, 'Client')
  yard_class.superclass = YARD::Registry['Seahorse::Client::Base']
  yard_class.docstring = client_docstring
  document_client_constructor(yard_class)
  document_client_operations(yard_class)
  document_client_waiters(yard_class)
end

def document_client_constructor(namespace)

def document_client_constructor(namespace)
  constructor = YARD::CodeObjects::MethodObject.new(namespace, :initialize)
  constructor.group = 'Constructor'
  constructor.scope = :instance
  constructor.parameters << ['options', '{}']
  constructor.docstring = client_constructor_docstring
end

def document_client_operation(namespace, method_name, operation)

def document_client_operation(namespace, method_name, operation)
  m = YARD::CodeObjects::MethodObject.new(namespace, method_name)
  m.group = 'Service Operations'
  m.scope = :instance
  m.parameters << ['params', '{}']
  m.docstring = operation_docstring(method_name, operation)
end

def document_client_operations(namespace)

def document_client_operations(namespace)
  @api.operations.each do |method_name, operation|
    document_client_operation(namespace, method_name, operation)
  end
end

def document_client_waiters(yard_class)

def document_client_waiters(yard_class)
  m = YARD::CodeObjects::MethodObject.new(yard_class, :wait_until)
  m.scope = :instance
  m.parameters << ['waiter_name', nil]
  m.parameters << ['params', '{}']
  m.docstring = YARD::Registry['Aws::ClientWaiters#wait_until'].docstring
  waiters = @client_class.waiters.waiter_names.sort.inject('') do |w,name|
    waiter = @client_class.waiters.waiter(name)
    operation = waiter.poller.operation_name
    w << "<tr><td><tt>:#{name}</tt></td><td>{##{operation}}</td><td>#{waiter.delay}</td><td>#{waiter.max_attempts}</td></tr>"
  end
  docstring = <<-DOCSTRING
s the list of supported waiters. The following table lists the supported
s and the client method they call:
>
>
h>Waiter Name</th><th>Client Method</th><th>Delay</th><th>Max Attempts</th></tr>
d>
>
ers}
y>
e>
n [Array<Symbol>] the list of supported waiters.
  DOCSTRING
  m = YARD::CodeObjects::MethodObject.new(yard_class, :waiter_names)
  m.scope = :instance
  m.docstring = docstring
end

def document_errors

def document_errors
  yard_mod = YARD::CodeObjects::ModuleObject.new(@namespace, 'Errors')
  yard_mod.docstring = errors_docstring
  base_error = YARD::CodeObjects::ClassObject.new(yard_mod, 'ServiceError')
  base_error.docstring = "Base class for all Aws::#{@svc_name} errors."
  base_error.superclass = YARD::Registry['Aws::Errors::ServiceError']
  @error_names.each do |error_name|
    error_klass = YARD::CodeObjects::ClassObject.new(yard_mod, error_name)
    error_klass.superclass = base_error
  end
end

def document_service

def document_service
  yard_mod = YARD::CodeObjects::ModuleObject.new(@namespace, @svc_name)
  yard_mod.docstring = service_docstring
  yard_mod.docstring.add_tag(YARD::Tags::Tag.new(:service, @svc_name))
  @namespace = yard_mod
end

def errors_docstring

def errors_docstring
  path = "doc-src/services/#{@svc_name}/errors.md"
  path = 'doc-src/services/default/errors.md' unless File.exists?(path)
  template = read(path)
  svc_name = @svc_name
  api = @api
  full_name = @full_name
  known_errors = @error_names
  ERB.new(template).result(binding)
end

def initialize(svc_module, docs_path)

def initialize(svc_module, docs_path)
  @svc_module = svc_module
  @svc_name = svc_module.name.split('::').last
  @client_class = svc_module.const_get(:Client)
  Aws::Api::Docstrings.apply(@client_class, docs_path)
  @api = @client_class.api
  @full_name = @api.metadata('serviceFullName')
  @error_names = @api.operations.map {|_,o| o.errors.map(&:name) }
  @error_names = @error_names.flatten.uniq.sort
  @namespace = YARD::Registry['Aws']
end

def operation_docstring(method_name, operation)

def operation_docstring(method_name, operation)
  documentor = OperationDocumenter.new(
    svc_var_name: @svc_name.downcase,
    method_name: method_name,
    operation: operation)
  tabs = Tabulator.new.tap do |t|
    t.tab(method_name, 'Formatting Example') do
      "<pre><code>#{documentor.example}</code></pre>"
    end
    t.tab(method_name, 'Request Parameters') do
      documentor.input
    end
    t.tab(method_name, 'Response Structure') do
      documentor.output
    end
  end
  errors = (operation.errors || []).map { |shape| shape.name }
  errors = errors.map { |e| "@raise [Errors::#{e}]" }.join("\n")
  docstring = <<-DOCSTRING.strip
ls the #{operation.name} operation.<p>
mentor.api_ref(operation)}
}
 [Hash] params ({})
n [PageableResponse]
rs}
  DOCSTRING
end

def read(path)

def read(path)
  File.open(path, 'r', encoding: 'UTF-8') { |f| f.read }
end

def render(path)

def render(path)
  svc_name = @svc_name
  api = @api
  full_name = @full_name
  ERB.new(File.read(path)).result(binding)
end

def service_docstring

def service_docstring
  path = "doc-src/services/#{@svc_name}/service.md"
  path = 'doc-src/services/default/service.md' unless File.exists?(path)
  template = read(path)
  svc_name = @svc_name
  api = @api
  full_name = @full_name
  ERB.new(template).result(binding)
end