class Bake::Recipe

Structured access to an instance method in a bakefile.

def <=> other

Sort by location in source file.
def <=> other
	(self.source_location || []) <=> (other.source_location || [])
end

def arity

The method's arity, the required number of positional arguments.
def arity
	if @arity.nil?
		@arity = method.parameters.count{|type, name| type == :req}
	end
	
	return @arity
end

def call(*arguments, **options, &block)

If the recipe does not accept options, they will be ignored.
Call the recipe with the specified arguments and options.
def call(*arguments, **options, &block)
	if options.any? and self.options?
		@instance.send(@name, *arguments, **options, &block)
	else
		# Ignore options...
		@instance.send(@name, *arguments, &block)
	end
end

def command

The command name for this recipe.
def command
	@command ||= compute_command
end

def comments

@returns [Array(String)] The comment lines.
Any comments associated with the source code which defined the method.
def comments
	@comments ||= read_comments
end

def compute_command

def compute_command
	path = @instance.path
	
	if path.empty?
		@name.to_s
	elsif path.last.to_sym == @name
		path.join(":")
	else
		(path + [@name]).join(":")
	end
end

def documentation

@returns [Documentation]
The documentation object which provides structured access to the {comments}.
def documentation
	@documentation ||= Documentation.new(self.comments)
end

def initialize(instance, name, method = nil)

@parameter method [Method | Nil] The method if already known.
@parameter name [String] The method name.
@parameter instance [Base] The instance this recipe is attached to.

Initialize the recipe.
def initialize(instance, name, method = nil)
	@instance = instance
	@name = name
	@command = nil
	@comments = nil
	@signature = nil
	@documentation = nil
	
	@method = method
	@arity = nil
end

def method

The method implementation.
def method
	@method ||= @instance.method(@name)
end

def options?

@returns [Boolean]
Whether this recipe has optional arguments.
def options?
	if parameters = self.parameters
		parameters.any? do |type, name|
			type == :keyrest || type == :keyreq || type == :key
		end
	end
end

def parameters

@returns [Array | Nil]
The recipe's formal parameters, if any.
def parameters
	parameters = method.parameters
	
	unless parameters.empty?
		return parameters
	end
end

def parse(name, value, arguments, types)

def parse(name, value, arguments, types)
	if count = arguments.index(";")
		value = arguments.shift(count)
		arguments.shift
	end
	
	if type = types[name]
		value = type.parse(value)
	end
	
	return value
end

def prepare(arguments, last_result = nil)

@returns options [Hash]
@returns ordered [Array]
@parameter arguments [Array(String)] The command line arguments
Process command line arguments into the ordered and optional arguments.
def prepare(arguments, last_result = nil)
	Arguments.extract(self, arguments, input: last_result)
end

def read_comments

def read_comments
	unless source_location = self.method&.source_location
		# Bail early if we don't have a source location (there are some inconsequential cases on JRuby):
		return []
	end
	
	file, line_number = source_location
	
	lines = File.readlines(file)
	line_index = line_number - 1
	
	description = []
	line_index -= 1
	
	# Extract comment preceeding method:
	while line = lines[line_index]
		# \Z matches a trailing newline:
		if match = line.match(COMMENT)
			description.unshift(match[1])
		else
			break
		end
		
		line_index -= 1
	end
	
	return description
end

def read_signature

def read_signature
	types = {}
	
	self.documentation.parameters do |parameter|
		types[parameter[:name].to_sym] = Type.parse(parameter[:type])
	end
	
	return types
end

def required_options

def required_options
	if parameters = self.parameters
		parameters.map do |(type, name)|
			if type == :keyreq
				name
			end
		end.compact
	end
end

def signature

@returns [Array] An array of {Type} instances.
The documented type signature of the recipe.
def signature
	@signature ||= read_signature
end

def source_location

The source location of this recipe.
def source_location
	self.method.source_location
end

def to_s

def to_s
	self.command
end