class Vips::Introspect
call.
everything we know about it. This is used for doc generation as well as
Introspect a vips operation and return a large structure containing
def self.get name
def self.get name @@introspect_cache[name] ||= Introspect.new name end
def self.get_yard name
def self.get_yard name introspect = Introspect.get name introspect.add_yard_introspection name introspect end
def add_yard_introspection name
extra metadata in a separate method to keep the main path as fast as
Yard comment generation needs a little more introspection. We add this
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
def initialize name
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