class Vips::Introspect

Introspect a vips operation and return a large structure containing everything we know about it. This is used for doc generation as well as call.

Attributes

args[R]
description[R]
destructive[R]
doc_optional_input[R]
doc_optional_output[R]
flags[R]
member_x[R]
method_args[R]
name[R]
optional_input[R]
optional_output[R]
required_input[R]
required_output[R]
vips_name[R]

Public Class Methods

get(name) click to toggle source
# File lib/vips/operation.rb, line 183
def self.get name
  @@introspect_cache[name] ||= Introspect.new name
end
get_yard(name) click to toggle source
# File lib/vips/operation.rb, line 187
def self.get_yard name
  introspect = Introspect.get name
  introspect.add_yard_introspection name
  introspect
end
new(name) click to toggle source
# File lib/vips/operation.rb, line 56
def initialize name
  # if there's a trailing "!", this is a destructive version of an
  # operation
  if name[-1] == "!"
    @destructive = true
    # strip the trailing "!"
    @vips_name = name[0...-1]
  else
    @destructive = false
    @vips_name = name
  end

  @op = Operation.new @vips_name
  @args = []
  @required_input = []
  @optional_input = {}
  @required_output = []
  @optional_output = {}

  # find all the arguments the operator can take
  @op.argument_map do |pspec, argument_class, _argument_instance|
    flags = argument_class[:flags]
    if (flags & ARGUMENT_CONSTRUCT) != 0
      # names can include - as punctuation, but we always use _ in
      # Ruby
      arg_name = pspec[:name].tr("-", "_")
      @args << {
        arg_name: arg_name,
        flags: flags,
        gtype: pspec[:value_type]
      }
    end

    nil
  end

  @args.each do |details|
    arg_name = details[:arg_name]
    flags = details[:flags]

    if (flags & ARGUMENT_INPUT) != 0
      if (flags & ARGUMENT_REQUIRED) != 0 &&
          (flags & ARGUMENT_DEPRECATED) == 0
        @required_input << details
      else
        # we allow deprecated optional args
        @optional_input[arg_name] = details
      end

      # MODIFY INPUT args count as OUTPUT as well in non-destructive mode
      if (flags & ARGUMENT_MODIFY) != 0 &&
          !@destructive
        if (flags & ARGUMENT_REQUIRED) != 0 &&
            (flags & ARGUMENT_DEPRECATED) == 0
          @required_output << details
        else
          @optional_output[arg_name] = details
        end
      end
    elsif (flags & ARGUMENT_OUTPUT) != 0
      if (flags & ARGUMENT_REQUIRED) != 0 &&
          (flags & ARGUMENT_DEPRECATED) == 0
        @required_output << details
      else
        # again, allow deprecated optional args
        @optional_output[arg_name] = details
      end
    end
  end

  # in destructive mode, the first required input arg must be MODIFY and
  # must be an image
  if @destructive
    if @required_input.length < 1 ||
        @required_input[0][:flags] & ARGUMENT_MODIFY == 0 ||
        @required_input[0][:gtype] != IMAGE_TYPE
      raise Vips::Error, "operation #{@vips_name} is not destructive"
    end
  end
end

Public Instance Methods

add_yard_introspection(name) click to toggle source

Yard comment generation needs a little more introspection. We add this extra metadata in a separate method to keep the main path as fast as we can.

# File lib/vips/operation.rb, line 140
def add_yard_introspection name
  @name = name
  @description = Vips.vips_object_get_description @op
  @flags = Vips.vips_operation_get_flags @op
  @member_x = nil
  @method_args = []
  @doc_optional_input = {}
  @doc_optional_output = {}

  @args.each do |details|
    arg_name = details[:arg_name]
    flags = details[:flags]
    gtype = details[:gtype]

    details[:yard_name] = arg_name == "in" ? "im" : arg_name
    pspec = @op.get_pspec arg_name
    details[:blurb] = GObject.g_param_spec_get_blurb pspec

    if (flags & ARGUMENT_INPUT) != 0 &&
        (flags & ARGUMENT_REQUIRED) != 0 &&
        (flags & ARGUMENT_DEPRECATED) == 0
      # the first required input image is the thing we will be a method
      # of
      if @member_x.nil? && gtype == IMAGE_TYPE
        @member_x = details
      else
        @method_args << details
      end
    end
  end

  # and make the arg sets to document by filtering out deprecated args
  @optional_input.each do |arg_name, details|
    next if (details[:flags] & ARGUMENT_DEPRECATED) != 0
    @doc_optional_input[details[:arg_name]] = details
  end

  @optional_output.each do |arg_name, details|
    next if (details[:flags] & ARGUMENT_DEPRECATED) != 0
    @doc_optional_output[details[:arg_name]] = details
  end
end