The PrettyPrinterVisitor is used to visit a node and pretty print it.

The main method here is visit that performs the pretty printing of a ANode.

Because some tokens like TComment are not stored in the AST, we visit the AST like traditionnal visitor and also maintain a pointer to the current_token (actually the next one to be printed).

Visited productions are in charges to move the token pointer using methods such as:

Introduced properties

private var _break_strings: Bool

nitc :: PrettyPrinterVisitor :: _break_strings

Do we break string literals that are too long?
private var _current_length: Int

nitc :: PrettyPrinterVisitor :: _current_length

Length of the current line.
private var _current_token: nullable Token

nitc :: PrettyPrinterVisitor :: _current_token

Token under cursor.
private var _indent: Int

nitc :: PrettyPrinterVisitor :: _indent

Current indent level.
private var _inline_do: Bool

nitc :: PrettyPrinterVisitor :: _inline_do

Do we force do to be on the same line as the method signature?
private var _max_size: Int

nitc :: PrettyPrinterVisitor :: _max_size

Max line size.
private var _no_inline: Bool

nitc :: PrettyPrinterVisitor :: _no_inline

Disable automatic inlining.
private var _previous_length: Int

nitc :: PrettyPrinterVisitor :: _previous_length

Length of the previous line.
private var _skip_empty: Bool

nitc :: PrettyPrinterVisitor :: _skip_empty

Do we force the deletion of empty lines?
private var _tab_size: Int

nitc :: PrettyPrinterVisitor :: _tab_size

Size of a tabulation in spaces.
private var _tpl: nullable Template

nitc :: PrettyPrinterVisitor :: _tpl

The template under construction.
private var _wait_addn: Int

nitc :: PrettyPrinterVisitor :: _wait_addn

End of line chars are stored until another char is added.
fun add(t: String)

nitc :: PrettyPrinterVisitor :: add

Add t to current template.
fun addn

nitc :: PrettyPrinterVisitor :: addn

Add a '\n'.
fun adds

nitc :: PrettyPrinterVisitor :: adds

Add a space.
fun addt

nitc :: PrettyPrinterVisitor :: addt

Add '\t' * indent.
fun break_strings: Bool

nitc :: PrettyPrinterVisitor :: break_strings

Do we break string literals that are too long?
fun break_strings=(break_strings: Bool)

nitc :: PrettyPrinterVisitor :: break_strings=

Do we break string literals that are too long?
fun can_inline(n: nullable ANode): Bool

nitc :: PrettyPrinterVisitor :: can_inline

Is the node inlinable and can fit on the line.
fun catch_up(target: nullable ANode)

nitc :: PrettyPrinterVisitor :: catch_up

Visit all tokens between current_token and target.
private fun clear

nitc :: PrettyPrinterVisitor :: clear

Prepare self for a new visit.
fun collect_comments(from: nullable ANode, to: nullable ANode): Array[TComment]

nitc :: PrettyPrinterVisitor :: collect_comments

Collect all TComment between from and to.
fun consume(token: String)

nitc :: PrettyPrinterVisitor :: consume

Visit current_token.
fun consume_comments

nitc :: PrettyPrinterVisitor :: consume_comments

Consume comments and end of lines if any
fun current_length: Int

nitc :: PrettyPrinterVisitor :: current_length

Length of the current line.
protected fun current_length=(current_length: Int)

nitc :: PrettyPrinterVisitor :: current_length=

Length of the current line.
fun current_token: nullable Token

nitc :: PrettyPrinterVisitor :: current_token

Token under cursor.
protected fun current_token=(current_token: nullable Token)

nitc :: PrettyPrinterVisitor :: current_token=

Token under cursor.
fun finish_line

nitc :: PrettyPrinterVisitor :: finish_line

Visit all tokens between current_token and the end of line.
fun forcen

nitc :: PrettyPrinterVisitor :: forcen

Perform addn even if not skip_empty.
fun indent: Int

nitc :: PrettyPrinterVisitor :: indent

Current indent level.
protected fun indent=(indent: Int)

nitc :: PrettyPrinterVisitor :: indent=

Current indent level.
fun inline_do: Bool

nitc :: PrettyPrinterVisitor :: inline_do

Do we force do to be on the same line as the method signature?
fun inline_do=(inline_do: Bool)

nitc :: PrettyPrinterVisitor :: inline_do=

Do we force do to be on the same line as the method signature?
fun last_line_is_blank: Bool

nitc :: PrettyPrinterVisitor :: last_line_is_blank

Is the last line a blank line?
fun max_size: Int

nitc :: PrettyPrinterVisitor :: max_size

Max line size.
fun max_size=(max_size: Int)

nitc :: PrettyPrinterVisitor :: max_size=

Max line size.
fun need_catch_up(target: nullable Token): Bool

nitc :: PrettyPrinterVisitor :: need_catch_up

Is there token to visit between current_token and target?
fun no_inline: Bool

nitc :: PrettyPrinterVisitor :: no_inline

Disable automatic inlining.
fun no_inline=(no_inline: Bool)

nitc :: PrettyPrinterVisitor :: no_inline=

Disable automatic inlining.
fun pretty(n: ANode): Template

nitc :: PrettyPrinterVisitor :: pretty

Pretty print n.
fun pretty_nmodule(nmodule: AModule): Template

nitc :: PrettyPrinterVisitor :: pretty_nmodule

Pretty print the whole nmodule with comments before and after.
fun previous_length: Int

nitc :: PrettyPrinterVisitor :: previous_length

Length of the previous line.
protected fun previous_length=(previous_length: Int)

nitc :: PrettyPrinterVisitor :: previous_length=

Length of the previous line.
fun skip

nitc :: PrettyPrinterVisitor :: skip

Skip the current_token.
fun skip_empty: Bool

nitc :: PrettyPrinterVisitor :: skip_empty

Do we force the deletion of empty lines?
fun skip_empty=(skip_empty: Bool)

nitc :: PrettyPrinterVisitor :: skip_empty=

Do we force the deletion of empty lines?
fun skip_line

nitc :: PrettyPrinterVisitor :: skip_line

Skip current_token until the end of line.
fun skip_to(target: nullable Token)

nitc :: PrettyPrinterVisitor :: skip_to

Skip current_token until target is reached.
fun tab_size: Int

nitc :: PrettyPrinterVisitor :: tab_size

Size of a tabulation in spaces.
protected fun tab_size=(tab_size: Int)

nitc :: PrettyPrinterVisitor :: tab_size=

Size of a tabulation in spaces.
private fun tpl: nullable Template

nitc :: PrettyPrinterVisitor :: tpl

The template under construction.
private fun tpl=(tpl: nullable Template)

nitc :: PrettyPrinterVisitor :: tpl=

The template under construction.
fun visit(n: nullable ANode)

nitc :: PrettyPrinterVisitor :: visit

Visit n if not null.
fun visit_args(n: nullable ANodes[ANode])

nitc :: PrettyPrinterVisitor :: visit_args

Visit a list of arguments ANode with optional parentheses
fun visit_list(n: nullable ANodes[ANode])

nitc :: PrettyPrinterVisitor :: visit_list

Visit a list of ANode.
fun visit_recv(n_expr: AExpr)

nitc :: PrettyPrinterVisitor :: visit_recv

Visit explicit receiver, implicit self will be ignored.
private fun wait_addn: Int

nitc :: PrettyPrinterVisitor :: wait_addn

End of line chars are stored until another char is added.
private fun wait_addn=(wait_addn: Int)

nitc :: PrettyPrinterVisitor :: wait_addn=

End of line chars are stored until another char is added.

Redefined properties

redef type SELF: PrettyPrinterVisitor

nitc $ PrettyPrinterVisitor :: SELF

Type of this instance, automatically specialized in every class

All properties

fun !=(other: nullable Object): Bool

core :: Object :: !=

Have self and other different values?
fun ==(other: nullable Object): Bool

core :: Object :: ==

Have self and other the same value?
type CLASS: Class[SELF]

core :: Object :: CLASS

The type of the class of self.
type SELF: Object

core :: Object :: SELF

Type of this instance, automatically specialized in every class
private var _break_strings: Bool

nitc :: PrettyPrinterVisitor :: _break_strings

Do we break string literals that are too long?
private var _current_length: Int

nitc :: PrettyPrinterVisitor :: _current_length

Length of the current line.
private var _current_token: nullable Token

nitc :: PrettyPrinterVisitor :: _current_token

Token under cursor.
private var _indent: Int

nitc :: PrettyPrinterVisitor :: _indent

Current indent level.
private var _inline_do: Bool

nitc :: PrettyPrinterVisitor :: _inline_do

Do we force do to be on the same line as the method signature?
private var _max_size: Int

nitc :: PrettyPrinterVisitor :: _max_size

Max line size.
private var _no_inline: Bool

nitc :: PrettyPrinterVisitor :: _no_inline

Disable automatic inlining.
private var _previous_length: Int

nitc :: PrettyPrinterVisitor :: _previous_length

Length of the previous line.
private var _skip_empty: Bool

nitc :: PrettyPrinterVisitor :: _skip_empty

Do we force the deletion of empty lines?
private var _tab_size: Int

nitc :: PrettyPrinterVisitor :: _tab_size

Size of a tabulation in spaces.
private var _tpl: nullable Template

nitc :: PrettyPrinterVisitor :: _tpl

The template under construction.
private var _wait_addn: Int

nitc :: PrettyPrinterVisitor :: _wait_addn

End of line chars are stored until another char is added.
fun add(t: String)

nitc :: PrettyPrinterVisitor :: add

Add t to current template.
fun addn

nitc :: PrettyPrinterVisitor :: addn

Add a '\n'.
fun adds

nitc :: PrettyPrinterVisitor :: adds

Add a space.
fun addt

nitc :: PrettyPrinterVisitor :: addt

Add '\t' * indent.
fun break_strings: Bool

nitc :: PrettyPrinterVisitor :: break_strings

Do we break string literals that are too long?
fun break_strings=(break_strings: Bool)

nitc :: PrettyPrinterVisitor :: break_strings=

Do we break string literals that are too long?
fun can_inline(n: nullable ANode): Bool

nitc :: PrettyPrinterVisitor :: can_inline

Is the node inlinable and can fit on the line.
fun catch_up(target: nullable ANode)

nitc :: PrettyPrinterVisitor :: catch_up

Visit all tokens between current_token and target.
protected fun class_factory(name: String): CLASS

core :: Object :: class_factory

Implementation used by get_class to create the specific class.
fun class_name: String

core :: Object :: class_name

The class name of the object.
private fun clear

nitc :: PrettyPrinterVisitor :: clear

Prepare self for a new visit.
fun collect_comments(from: nullable ANode, to: nullable ANode): Array[TComment]

nitc :: PrettyPrinterVisitor :: collect_comments

Collect all TComment between from and to.
fun consume(token: String)

nitc :: PrettyPrinterVisitor :: consume

Visit current_token.
fun consume_comments

nitc :: PrettyPrinterVisitor :: consume_comments

Consume comments and end of lines if any
fun current_length: Int

nitc :: PrettyPrinterVisitor :: current_length

Length of the current line.
protected fun current_length=(current_length: Int)

nitc :: PrettyPrinterVisitor :: current_length=

Length of the current line.
fun current_token: nullable Token

nitc :: PrettyPrinterVisitor :: current_token

Token under cursor.
protected fun current_token=(current_token: nullable Token)

nitc :: PrettyPrinterVisitor :: current_token=

Token under cursor.
fun finish_line

nitc :: PrettyPrinterVisitor :: finish_line

Visit all tokens between current_token and the end of line.
fun forcen

nitc :: PrettyPrinterVisitor :: forcen

Perform addn even if not skip_empty.
fun get_class: CLASS

core :: Object :: get_class

The meta-object representing the dynamic type of self.
fun hash: Int

core :: Object :: hash

The hash code of the object.
fun indent: Int

nitc :: PrettyPrinterVisitor :: indent

Current indent level.
protected fun indent=(indent: Int)

nitc :: PrettyPrinterVisitor :: indent=

Current indent level.
init init

core :: Object :: init

fun inline_do: Bool

nitc :: PrettyPrinterVisitor :: inline_do

Do we force do to be on the same line as the method signature?
fun inline_do=(inline_do: Bool)

nitc :: PrettyPrinterVisitor :: inline_do=

Do we force do to be on the same line as the method signature?
fun inspect: String

core :: Object :: inspect

Developer readable representation of self.
protected fun inspect_head: String

core :: Object :: inspect_head

Return "CLASSNAME:#OBJECTID".
intern fun is_same_instance(other: nullable Object): Bool

core :: Object :: is_same_instance

Return true if self and other are the same instance (i.e. same identity).
fun is_same_serialized(other: nullable Object): Bool

core :: Object :: is_same_serialized

Is self the same as other in a serialization context?
intern fun is_same_type(other: Object): Bool

core :: Object :: is_same_type

Return true if self and other have the same dynamic type.
fun last_line_is_blank: Bool

nitc :: PrettyPrinterVisitor :: last_line_is_blank

Is the last line a blank line?
fun max_size: Int

nitc :: PrettyPrinterVisitor :: max_size

Max line size.
fun max_size=(max_size: Int)

nitc :: PrettyPrinterVisitor :: max_size=

Max line size.
private intern fun native_class_name: CString

core :: Object :: native_class_name

The class name of the object in CString format.
fun need_catch_up(target: nullable Token): Bool

nitc :: PrettyPrinterVisitor :: need_catch_up

Is there token to visit between current_token and target?
fun no_inline: Bool

nitc :: PrettyPrinterVisitor :: no_inline

Disable automatic inlining.
fun no_inline=(no_inline: Bool)

nitc :: PrettyPrinterVisitor :: no_inline=

Disable automatic inlining.
intern fun object_id: Int

core :: Object :: object_id

An internal hash code for the object based on its identity.
fun output

core :: Object :: output

Display self on stdout (debug only).
intern fun output_class_name

core :: Object :: output_class_name

Display class name on stdout (debug only).
fun pretty(n: ANode): Template

nitc :: PrettyPrinterVisitor :: pretty

Pretty print n.
fun pretty_nmodule(nmodule: AModule): Template

nitc :: PrettyPrinterVisitor :: pretty_nmodule

Pretty print the whole nmodule with comments before and after.
fun previous_length: Int

nitc :: PrettyPrinterVisitor :: previous_length

Length of the previous line.
protected fun previous_length=(previous_length: Int)

nitc :: PrettyPrinterVisitor :: previous_length=

Length of the previous line.
fun serialization_hash: Int

core :: Object :: serialization_hash

Hash value use for serialization
fun skip

nitc :: PrettyPrinterVisitor :: skip

Skip the current_token.
fun skip_empty: Bool

nitc :: PrettyPrinterVisitor :: skip_empty

Do we force the deletion of empty lines?
fun skip_empty=(skip_empty: Bool)

nitc :: PrettyPrinterVisitor :: skip_empty=

Do we force the deletion of empty lines?
fun skip_line

nitc :: PrettyPrinterVisitor :: skip_line

Skip current_token until the end of line.
fun skip_to(target: nullable Token)

nitc :: PrettyPrinterVisitor :: skip_to

Skip current_token until target is reached.
intern fun sys: Sys

core :: Object :: sys

Return the global sys object, the only instance of the Sys class.
fun tab_size: Int

nitc :: PrettyPrinterVisitor :: tab_size

Size of a tabulation in spaces.
protected fun tab_size=(tab_size: Int)

nitc :: PrettyPrinterVisitor :: tab_size=

Size of a tabulation in spaces.
abstract fun to_jvalue(env: JniEnv): JValue

core :: Object :: to_jvalue

fun to_s: String

core :: Object :: to_s

User readable representation of self.
private fun tpl: nullable Template

nitc :: PrettyPrinterVisitor :: tpl

The template under construction.
private fun tpl=(tpl: nullable Template)

nitc :: PrettyPrinterVisitor :: tpl=

The template under construction.
fun visit(n: nullable ANode)

nitc :: PrettyPrinterVisitor :: visit

Visit n if not null.
fun visit_args(n: nullable ANodes[ANode])

nitc :: PrettyPrinterVisitor :: visit_args

Visit a list of arguments ANode with optional parentheses
fun visit_list(n: nullable ANodes[ANode])

nitc :: PrettyPrinterVisitor :: visit_list

Visit a list of ANode.
fun visit_recv(n_expr: AExpr)

nitc :: PrettyPrinterVisitor :: visit_recv

Visit explicit receiver, implicit self will be ignored.
private fun wait_addn: Int

nitc :: PrettyPrinterVisitor :: wait_addn

End of line chars are stored until another char is added.
private fun wait_addn=(wait_addn: Int)

nitc :: PrettyPrinterVisitor :: wait_addn=

End of line chars are stored until another char is added.
package_diagram nitc::PrettyPrinterVisitor PrettyPrinterVisitor core::Object Object nitc::PrettyPrinterVisitor->core::Object

Parents

interface Object

core :: Object

The root of the class hierarchy.

Class definitions

nitc $ PrettyPrinterVisitor
# The `PrettyPrinterVisitor` is used to visit a node and pretty print it.
#
# The main method here is `visit` that performs the pretty printing of a `ANode`.
#
# Because some tokens like `TComment` are not stored in the AST,
# we visit the AST like traditionnal visitor and also maintain a
# pointer to the `current_token` (actually the next one to be printed).
#
# Visited productions are in charges to move the token pointer using methods such as:
#
# * `consume`: print `current_token` and move to the next one
# * `skip`: move to the next token without printing the current one
# * `skip_to`: move to a specified token skipping all the tokens before
# * `catch_up`: consume all the tokens between `current_token` and a specified token
# * `finish_line`: consume all the tokens between `current_token` and the end of line
class PrettyPrinterVisitor
	# Pretty print `n`.
	fun pretty(n: ANode): Template do
		clear
		n.parentize_tokens

		if n isa Prod then
			current_token = n.first_token
			visit n
		else if n isa Token then
			var p = n.parent

			while p != null and not p isa Prod do
				p = p.parent
			end

			current_token = p.first_token
			visit p
		end

		return tpl.as(not null)
	end

	# Pretty print the whole `nmodule` with comments before and after.
	fun pretty_nmodule(nmodule: AModule): Template do
		clear
		nmodule.parentize_tokens
		current_token = nmodule.location.file.first_token
		visit nmodule
		catch_up nmodule.location.file.last_token
		if skip_empty then tpl.add "\n"
		return tpl.as(not null)
	end

	# Prepare `self` for a new visit.
	private fun clear do
		tpl = new Template
		current_token = null
		indent = 0
		current_length = 0
		previous_length = 0
		wait_addn = 0
	end

	# Visit `n` if not null.
	fun visit(n: nullable ANode) do
		if n == null then return
		n.accept_pretty_printer self
	end

	# Visit a list of arguments `ANode` with optional parentheses
	fun visit_args(n: nullable ANodes[ANode]) do
		if n == null or n.is_empty then return
		if current_token isa TOpar then
			consume "("
		else
			adds
		end

		visit_list n
		if current_token isa TCpar then consume ")"
	end

	# Visit a list of `ANode`.
	fun visit_list(n: nullable ANodes[ANode]) do
		if n == null then return
		n.accept_pretty_printer self
	end

	# Is the node inlinable and can fit on the line.
	fun can_inline(n: nullable ANode): Bool do
		if n == null then return true
		if no_inline and n.location.line_start != n.location.line_end then return false
		if n.must_be_inline then return true
		if n.must_be_block then return false
		# check length
		if max_size > 0 and n.collect_length + current_length > max_size then return false
		# check block is inlinable
		return n.is_inlinable
	end

	# Collect all `TComment` between `from` and `to`.
	fun collect_comments(from: nullable ANode, to: nullable ANode): Array[TComment] do
		var res = new Array[TComment]
		if from isa Prod then from = from.first_token
		if to isa Prod then to = to.first_token
		if from == null or to == null then return res

		while from != to do
			if from isa TComment then res.add from
			from = from.as(Token).next_token
		end

		return res
	end

	# Token under cursor.
	#
	# This is the next token to visit.
	var current_token: nullable Token = null

	# Skip the `current_token`.
	fun skip do current_token = current_token.next_token

	# Skip `current_token` until the end of line.
	fun skip_line do current_token = current_token.last_real_token_in_line

	# Skip `current_token` until `target` is reached.
	fun skip_to(target: nullable Token) do
		if target == null then return
		while current_token != null and current_token != target do skip
		if current_token == null then
			target.debug("Looked for, but not found :(")
			abort
		end
	end

	# Consume comments and end of lines if any
	fun consume_comments do
		while current_token isa TEol or current_token isa TComment do visit current_token
	end

	# Visit `current_token`.
	fun consume(token: String) do
		consume_comments
		if current_token.text == token then else current_token.debug("Got `{current_token.text}`; expected `{token}`.")
		visit current_token
	end

	# Is there token to visit between `current_token` and `target`?
	fun need_catch_up(target: nullable Token): Bool do
		if target == null then return false
		return current_token != target
	end

	# Visit all tokens between `current_token` and `target`.
	fun catch_up(target: nullable ANode) do
		if target == null then return
		if current_token == null then return
		var token: Token
		if target isa Token then
			token = target
		else if target isa Prod then
			token = target.first_token.as(not null)
		else
			abort
		end
		if current_token.location > token.location then return
		while current_token != token do visit current_token
	end

	# Visit all tokens between `current_token` and the end of line.
	fun finish_line do
		if current_token isa TComment then
			adds
			visit current_token
		end

		while current_token isa TEol do visit(current_token)
	end

	# The template under construction.
	private var tpl: nullable Template = null

	# Current indent level.
	var indent = 0

	# Size of a tabulation in spaces.
	var tab_size = 8

	# Max line size.
	# 0 (or negative) to disable.
	var max_size = 80 is writable

	# Length of the current line.
	var current_length = 0

	# Length of the previous line.
	var previous_length = 0

	# Is the last line a blank line?
	fun last_line_is_blank: Bool do return previous_length == 0

	# Add `t` to current template.
	fun add(t: String) do
		if t.is_empty then return
		while wait_addn > 0 do
			tpl.add "\n"
			wait_addn -= 1
		end
		tpl.add t
		current_length += t.length
	end

	# Add a `'\n'`.
	fun addn do
		if current_length == 0 and last_line_is_blank then return
		previous_length = current_length
		current_length = 0
		if skip_empty then wait_addn += 1
	end

	# Perform `addn` even if not `skip_empty`.
	fun forcen do
		if current_length == 0 and last_line_is_blank then return
		previous_length = current_length
		current_length = 0
		wait_addn += 1
	end

	# End of line chars are stored until another char is added.
	# This avoid empty files with only a '`\n`'.
	private var wait_addn = 0

	# Add `'\t' * indent`.
	fun addt do add "\t" * indent

	# Add a space.
	fun adds do add " "

	# Visit explicit receiver, implicit self will be ignored.
	fun visit_recv(n_expr: AExpr) do
		if not n_expr isa AImplicitSelfExpr then
			visit n_expr
			consume "."
		end
	end

	# Do we break string literals that are too long?
	var break_strings = false is public writable

	# Do we force `do` to be on the same line as the method signature?
	var inline_do = false is public writable

	# Do we force the deletion of empty lines?
	var skip_empty = false is public writable

	# Disable automatic inlining.
	var no_inline = false is writable
end
src/pretty.nit:37,1--291,3