Skip to content

v.gen.v #

V3 source formatter

The V3 formatter formats source syntax without type checking.

String literal spelling

Non-interpolated string literals retain their original source spelling for everything except the quote delimiter: escape sequences and the r, c, or js prefix are copied byte for byte. For example, 'x=\0' stays 'x=\0' and 'x=\x00' stays 'x=\x00'. Surrounding code is still formatted normally.

The formatter uses the original literal's source span rather than decoding and re-encoding it. This avoids collapsing hex or Unicode escapes into characters and keeps a NUL followed by digits distinct from an octal escape.

The delimiter is normalized: single quotes are preferred, unless the literal contains a ' but no ". So "text" becomes 'text', while "it's" keeps its double quotes. Only the quote escaping is rewritten along with the delimiter, so "say \"hi\"" becomes 'say "hi"' and 'it\'s' becomes "it's". This is the rule that interpolated literals and the legacy formatter already follow, so plain and interpolated literals are spelled the same way. A raw literal cannot escape a quote, so its delimiter decides what it can hold and is kept as written.

Literals without a usable source spelling, such as synthesized AST nodes, still use the existing escaping fallback. That fallback emits NUL as \x00 so that following octal digits cannot change the value.

The C-backend rewrite from a string literal's .str selector to a c literal retains the literal spelling and is stable on subsequent formatting passes.

This policy does not change attribute formatting or compiler/scanner escape semantics. Interpolated strings continue to use their existing formatting path so embedded expressions can be formatted.

fn format #

fn format(a &flat.FlatAst) string

format finds every trailing .file node in a and formats them in order, separated by a blank line. Useful when a single file was parsed on its own.

fn format_file #

fn format_file(a &flat.FlatAst, file_id flat.NodeId) string

format_file parses-independent convenience: format the file whose trailing .file node id is file_id within a.

fn format_with_options #

fn format_with_options(a &flat.FlatAst, options FormatOptions) string

format_with_options formats every trailing file node in a with options.

fn Gen.new #

fn Gen.new() &Gen

Gen.new returns a fresh formatter.

struct FormatOptions #

struct FormatOptions {
pub:
	is_debug   bool
	is_new_int bool
	backend    string = 'c'
}

FormatOptions controls optional formatter output.

struct Gen #

struct Gen {
mut:
	a                &flat.FlatAst = unsafe { nil }
	out              strings.Builder
	indent           int
	on_newline       bool
	in_init          bool
	file_id          int
	source           string
	comments         []flat.Comment
	comment_i        int
	source_end       int = -1
	migrate_json2    bool
	json_qualifier   string
	json_import_id   int = -1
	skip_decls       map[int]bool
	selective_json   bool
	implied_imports  []string
	in_array_init    bool
	is_debug         bool
	is_new_int       bool
	is_translated    bool
	in_c_function    bool
	backend          string = 'c'
	formatter_types  map[string]FormatterTypeSource
	array_breaks     []bool
	array_depth      int
	in_index         bool
	in_string_interp bool
	// suppress_mut skips the `mut ` prefix on an assignment (used for C-style
	// `for` loop init clauses, whose variable the parser always marks mutable).
	suppress_mut bool
	// suppress_trailing_comments defers comments that belong after a surrounding
	// delimiter, such as the opening brace of a loop.
	suppress_trailing_comments int
	// attrs maps a declaration node id to its `@[...]` attribute strings. The parser stores
	// attributes on a separate floating `.directive` node rather than as a child, so they are
	// collected up-front in collect_attrs. attr_sources retains formatter-only source groups.
	attrs        map[int][]string
	attr_sources map[int]string
}

Gen holds the formatter state for one output buffer.

fn (Gen) reset #

fn (mut g Gen) reset()

reset clears the buffer so a Gen instance can be reused.

fn (Gen) gen_file #

fn (mut g Gen) gen_file(a &flat.FlatAst, file_id flat.NodeId) string

gen_file formats the top-level declarations of the given trailing file node.

fn (Gen) output_string #

fn (mut g Gen) output_string() string

output_string returns the generated V source code.