DecodeSourceDecodeCommentTags

class Tags

Represents a collection of documentation tags and their parsing logic.

Definitions

def self.build

Build a tags parser with directive mappings.

Signature

yields {|directives| directives['directive'] = Class}
parameter directives Hash(String, _Directive)

The directive mappings hash to configure.

returns Tags

A new tags parser with the configured directives.

rbs

() (Hash[String, Class]) -> void -> Tags

Implementation

def self.build
	directives = Hash.new
	
	yield directives
	
	return self.new(directives)
end

def initialize(directives)

Initialize a new tags parser.

Signature

parameter directives Hash(String, _Directive)

The directive mappings.

Implementation

def initialize(directives)
	@directives = directives
end

def valid_indentation?(line, level)

Check if a line has valid indentation for the given level.

Signature

parameter line String

The line to check.

parameter level Integer

The expected indentation level.

Implementation

def valid_indentation?(line, level)
	line.start_with?("  " * level) || line.start_with?("\t" * level)
end

PATTERN = /\A\s*@(?<directive>.*?)(\s+(?<remainder>.*?))?\Z/

Signature

constant

Pattern for matching tag directives in comment lines.

def parse(lines, level = 0, &block)

Parse documentation tags from lines.

Signature

parameter lines Array(String)

The lines to parse.

parameter level Integer

The indentation level.

yields {|node| process parsed node}
parameter node Node | Text

The parsed node (either a structured tag or plain text).

returns void

Parses tags from lines and yields them to the block.

rbs

(Array[String] lines, ?Integer level) (Node | Text) -> void -> void

Implementation

def parse(lines, level = 0, &block)
	while line = lines.first
		# Is it at the right indentation level:
		return unless valid_indentation?(line, level)
		
		# We are going to consume the line:
		lines.shift
		
		# Match it against a tag:
		if match = PATTERN.match(line)
			directive = match[:directive] #: String
			remainder = match[:remainder] #: String
			
			# @type var klass: _Directive?
			if klass = @directives[directive]
				yield klass.parse(
					directive, remainder,
					lines, self, level
				)
			else
				# Ignore unknown directive.
			end
			
		# Or it's just text:
		else
			yield Text.new(line)
		end
	end
end

def ignore(lines, level = 0)

Ignore lines at the specified indentation level.

Signature

parameter lines Array(String)

The lines to ignore.

parameter level Integer

The indentation level.

Implementation

def ignore(lines, level = 0)
	if line = lines.first
		# Is it at the right indentation level:
		return unless valid_indentation?(line, level)
		
		lines.shift
	end
end