SusSourceSusIdentity

class Identity

Represents a unique identity for a test or context, used for identification and location tracking.

Definitions

def self.file(parent, path, name = path, **options)

Create an identity for a file.

Signature

parameter parent Identity, nil

The parent identity.

parameter path String

The file path.

parameter name String

The name (defaults to path).

parameter options Hash

Additional options.

returns Identity

A new Identity instance.

Implementation

def self.file(parent, path, name = path, **options)
	self.new(path, name, nil, nil, **options)
end

def self.nested(parent, name, location = nil, **options)

Create a nested identity.

Signature

parameter parent Identity, nil

The parent identity.

parameter name String

The name of this identity.

parameter location Thread::Backtrace::Location, nil

Optional location (defaults to caller location).

parameter options Hash

Additional options.

returns Identity

A new Identity instance.

Implementation

def self.nested(parent, name, location = nil, **options)
	location ||= caller_locations(3...4).first
	
	self.new(location.path, name, location.lineno, parent, **options)
end

def self.current

Create an identity for the current location.

Signature

returns Identity

A new Identity instance for the current caller location.

Implementation

def self.current
	self.nested(nil, nil, caller_locations(1...2).first)
end

def initialize(path, name = nil, line = nil, parent = nil, unique: true)

Initialize a new Identity.

Signature

parameter path String

The file path.

parameter name String, nil

Optional name.

parameter line Integer, nil

Optional line number.

parameter parent Identity, nil

Optional parent identity.

parameter unique Boolean, Symbol

Whether this identity is unique or needs a unique key/line number suffix.

Implementation

def initialize(path, name = nil, line = nil, parent = nil, unique: true)
	@path = path
	@name = name
	@line = line
	@parent = parent
	@unique = unique
	
	@key = nil
end

def with_line(line)

Create a new identity with a different line number.

Signature

parameter line Integer

The line number.

returns Identity

A new Identity instance.

Implementation

def with_line(line)
	self.class.new(@path, @name, line, @parent, unique: @unique)
end

attr :path

Signature

attribute String

The file path.

attr :name

Signature

attribute String, nil

The name.

attr :line

Signature

attribute Integer, nil

The line number.

attr :parent

Signature

attribute Identity, nil

The parent identity.

attr :unique

Signature

attribute Boolean, Symbol

Whether this identity is unique.

def to_s

Signature

returns String

A string representation of this identity (the key).

Implementation

def to_s
	self.key
end

def to_location

Signature

returns Hash

A hash containing the path and line number.

Implementation

def to_location
	{
		path: ::File.expand_path(@path),
		line: @line,
	}
end

def inspect

Signature

returns String

An inspect representation of this identity.

Implementation

def inspect
	"\#<#{self.class} #{self.to_s}>"
end

def match?(other)

Check if this identity matches another.

Signature

parameter other Identity

The identity to match against.

returns Boolean

Whether the identities match.

Implementation

def match?(other)
	if path = other.path
		return false unless path === @path
	end
	
	if name = other.name
		return false unless name === @name
	end
	
	if line = other.line
		return false unless line === @line
	end
end

def each(&block)

Iterate over this identity and all its parents.

Signature

yields {|identity| ...}

Each identity in the chain.

Implementation

def each(&block)
	@parent&.each(&block)
	
	yield self
end

def key

Signature

returns String

A unique key for this identity.

Implementation

def key
	unless @key
		key = Array.new
		
		# For a specific leaf node, the last part is not unique, i.e. it must be identified explicitly.
		append_unique_key(key, @unique == true ? false : @unique)
		
		@key = key.join(":")
	end
	
	return @key
end

def scoped(locations = nil)

Given a set of locations, find the first one which matches this identity and return a new identity with the updated line number. This can be used to extract a location from a backtrace.

Signature

parameter locations Array(Thread::Backtrace::Location), nil

Optional locations to search (defaults to caller locations).

returns Identity

A new identity with updated line number if a match is found, otherwise returns self.

Implementation

def scoped(locations = nil)
	if locations
		# This code path is normally taken if we've got an exception with a backtrace:
		locations.each do |location|
			if location.path == @path
				return self.with_line(location.lineno)
			end
		end
	else
		# In theory this should be a bit faster:
		Thread.each_caller_location do |location|
			if location.path == @path
				return self.with_line(location.lineno)
			end
		end
	end
	
	return self
end