API Documentation

Public API

JuliaFormatter.format — Function
JuliaFormatter.format(
    path,
    style::Union{Nothing,AbstractStyle} = nothing;
    throw_on_error::Bool = false,
    format_markdown::Union{Nothing,Bool} = nothing,
    ignore::Union{Nothing,Vector{String}} = nothing,
    overwrite::Union{Nothing,Bool} = nothing,
    verbose::Union{Nothing,Bool} = nothing,
    formatting_options...,
)::Bool

Recursively traverse path and format all Julia source files inside, or format path if it is itself a Julia source file.

Returns true if no files were modified (NOTE: when throw_on_error is false (the default), this can include the case where formatting errored, in which case files will not be modified!), and false if any files were modified.

See Formatting Options for details on the formatting options. Extra keyword arguments are the following. Note that the default values documented here are only used if they are not specified in either a configuration file or as keyword arguments to format().

  • throw_on_error: If true, errors encountered while formatting individual files will be rethrown instead of being caught and logged as warnings. Default is false.

  • format_markdown: If true, additionally formats Julia code blocks inside .md, .jmd, and .qmd files. Defaults to false.

  • ignore: A vector of glob patterns to ignore. Default is String[].

  • overwrite: If true, overwrite the original files with the formatted code. Default is true.

  • verbose: If true, print the names of files being formatted. Default is false.

Errors

By default, format() does not throw errors. It is intended for "batch" use where you just want to format a bunch of files at a go. Warnings will be issued in lieu of any errors.

Set throw_on_error = true to let errors propagate instead.

Configuration files

format() will automatically search for .JuliaFormatter.toml configuration files upwards from the directory of each file being formatted.

Options specified as keyword arguments to format() will override any options specified in configuration files. Likewise if the style positional argument is specified, it will override any style specified in configuration files.

Output

Returns a boolean indicating whether the files were already formatted (true) or not (false).

source
JuliaFormatter.format_text — Function
JuliaFormatter.format_text(
    text::AbstractString,
    style::AbstractStyle = DefaultStyle();
    lines::Union{Nothing,Vector{Tuple{Int,Int}}} = nothing,
    options...,
)::String

Formats a string containing Julia code, returning the formatted code as another string. See Formatting Options for details on available options.

Line-range formatting

Pass lines to restrict formatting to a set of line ranges, emitting everything else verbatim. lines is a Vector{Tuple{Int,Int}} of inclusive, 1-based (start, stop) line ranges, e.g. format_text(text; lines = [(1, 10), (42, 47)]). Overlapping and adjacent ranges are merged. A range that begins or ends in the middle of a multi-line expression is formatted on a best-effort basis.

This function can throw the following errors

  • If text is not valid Julia code, it will throw a JuliaSyntax.ParseError.

  • If any other error happens during the formatting, it will throw a JuliaFormatter.FormattingError.

  • If the formatted text is not valid Julia code, it will throw an JuliaFormatter.InvalidFormattedTextError.

source
JuliaFormatter.format_file — Function
JuliaFormatter.format_file(args...; kwargs...)
Deprecated

format_file is deprecated. Use format instead, which has the same behaviour but handles both files and directories.

source

Internal API

Note that these are subject to change in any version (even patches), and the docstrings are not necessarily up to date!

JuliaFormatter.AlignGroup — Type
AlignGroup

Group of FST node indices and required metadata to potentially align them.

  • node_inds. Indices of FST nodes affected by alignment.
  • nodes. FST nodes affected by alignment.
  • line_offsets. Display line offset of the character nodes may be aligned to in the source file.
  • lens. Length of the FST node prior to the alignment character. Used to calculate extra whitespace padding.
  • whitespaces. Number of whitespaces between the alignment character and the prior FST node. If this is > 1 it signifies additional whitespace was manually added by the user since the formatter would only use 0 or 1 whitespaces.
source
JuliaFormatter.Configuration — Type
Configuration

A Configuration represents a collection of both formatting options and file options.

Configurations can be constructed from:

  • default values.
  • keyword arguments passed to format();
  • a .JuliaFormatter.toml configuration file; or
  • arguments passed on the command-line to jlfmt.
source
JuliaFormatter.FormattingError — Type
FormattingError(line, column, original_error)

Error thrown when formatting fails. The line and column fields indicate the location of the error in the source code.

source
JuliaFormatter.Metadata — Type
Metadata(; op_kind = K"None", standalone_shortcircuit = NotStandalone, ...)
Metadata(op_kind::JuliaSyntax.Kind)
Metadata(md::Metadata; kwargs...)

Extra information attached to an FST node. All fields have defaults (K"None", NotStandalone, or false), so you only need to pass the fields you care about, e.g.

Metadata(; op_kind = K"=", is_short_form_function = true)

The single-argument form Metadata(k) is short for Metadata(; op_kind = k). The form Metadata(md; kwargs...) makes a copy of md with the given fields changed, e.g.

Metadata(md; has_multiline_argument = true)

When adding a new field, give it a default value here and only update the call sites that need a non-default value.

source
JuliaFormatter.Options — Type
Options{T<:_Unset}

Struct containing all the options for formatting.

The type parameter T is used to indicate whether the option is allowed to be unset. By default, T is Union{}.

  • Options{Union{}} indicates that all options MUST be set to some value. For example,

    Options(; always_use_return=true)

    creates a set of default options but with always_use_return set to true.

  • Options{_Unset} indicates that all options are allowed to be unset. For example.

    Options{_Unset}(; always_use_return=true)

    creates a set of empty options but with always_use_return set to true.

This allows us to perform a merge on two Options objects which can be partially populated.

source
JuliaFormatter.ShortCircuitStandalone — Type
ShortCircuitStandalone

Indicates whether a node is a short-circuiting logical operator (&& or ||) whose value is not used in any way, i.e., it exists solely for its side effects.

For example, a && b is standalone in

function f()    a && b    cend

but not in x = a && b, return a && b, or (a && b).

Any node that isn't && or || is NotStandalone.

StandaloneInLongForm is for nodes that are not standalone as written, but would be if the enclosing short-form function definition were rewritten as a long-form one (without a return being added). For example, in

f() = a && b

a && b is used as the value of f(), so it is not standalone. But in

function f()    a && bend

it is a statement on its own, so it is standalone. We need to track this information at the CST stage so that it can be used later on in the nesting stage, specifically in short_to_long_function_def!. Outside of that function, StandaloneInLongForm is treated the same as NotStandalone.

source
JuliaFormatter._contains_return — Method

Recursively check whether a CST node contains a return node anywhere inside it. Used to avoid prepending return to expressions like x > 0 ? (return 1) : (return 2).

source
JuliaFormatter._format_line_ranges — Method
_format_line_ranges(
    text::AbstractString,
    style::AbstractStyle,
    lines::Vector{Tuple{Int,Int}};
    kwargs...,
) -> String

Format only the lines of text covered by lines (a vector of inclusive, 1-based (start, stop) line ranges), emitting all other lines verbatim. See the comment at the top of this file for the overall strategy.

source
JuliaFormatter._format_text — Method
_format_text(
    text::AbstractString, style::AbstractStyle, opts::Options{Union{}};
    check_output::Bool=true,
    maxiters::Int=1,
    ensure_trailing_newline::Bool=false
)

The lower-level entry point for text formatting.

check_output is a boolean flag that indicates whether the output should be checked for validity. If set to true, the function will attempt to parse the formatted text and throw an InvalidFormattedTextError if it is not valid Julia code. If false it will just return the formatted text, which may be invalid!

The maxiters keyword argument is specified in order to allow the formatting algorithm to iterate to a fixed point. This is a hack and should really not be used, but currently SciMLStyle is not idempotent and requires multiple iterations to reach a fixed point. By default maxiters is set to 1, i.e., only one pass.

If ensure_trailing_newline is set to true, the function will ensure that the formatted text ends with a single newline character. This might be either CRLF or LF depending on the line ending normalization settings. If set to false, the function will not modify the trailing newline character(s) in the formatted text. This option is useful when formatting files.

source
JuliaFormatter.absorbs_trailing_comma — Method
absorbs_trailing_comma(fst::FST)

Whether fst ends with a construct that would read a comma placed straight after it as part of itself, instead of as a separator in the surrounding list.

As an example, in

g(    global x,)

the comma after x is read as part of the global statement rather than a separator in the argument list of g. (This actually causes the code above to fail to parse.) So, absorbs_trailing_comma returns true for such nodes, and inside materialise_trailing_comma! we check for that and don't insert a comma after it.

This function has to recursively check the last node of fst because it could be something like

g(    x -> global x,)

which has the same problem.

This is applicable to various constructs such as

@macro fooarg = @macro fooarg => @macro foo() -> global x = truereturn xx -> return yc ? a : local b

Anything that ends with a closing bracket or end (e.g. (return x) or begin return x end) is fine, because the last node is then that closing token, which is a leaf, so we stop there.

source
JuliaFormatter.add_hasheq_comment! — Method

Add a #= =# comment node to the FST. Returns false if n is not a HASHEQCOMMENT.

When force_join is true, the comment is always joined to the previous node (used by contexts like hcat where the nesting phase manages line breaks). When false (the default), a comment that appears on its own line in the source is placed on a new line instead of being merged onto the previous statement.

source
JuliaFormatter.add_line_range_markers — Method
add_line_range_markers(text::AbstractString, ranges::Vector{UnitRange{Int}}) -> String

Return a copy of text with LINE_RANGE_MARKER_BEGIN / LINE_RANGE_MARKER_END comment lines inserted just before and just after each range in ranges (a normalized vector of UnitRange{Int}). Throws an ArgumentError if a range is out of bounds.

source
JuliaFormatter.add_node! — Method
add_node!(
    t::FST,
    n::FST,
    s::State;
    join_lines::Bool = false,
    max_padding::Int = -1,
    override_join_lines_based_on_source::Bool = false,
)

Appends n to t.

  • join_lines: if true, n is placed on the same line as the previous node. If false (the default), a NEWLINE is inserted before n so it appears on the next line.

  • max_padding: controls how n's length contributes to t.len, if n is not the first node being added.

    • When negative (the default), n's length is added: t.len += length(n). This is appropriate for nodes that continue the current line (e.g. an argument in a call).

    • When non-negative, we calculate npad = length(n) + max_padding (i.e., the horizontal extent of n plus some specified padding) and set t.len = max(t.len, npad). For example, in p_if, when adding the if/elseif/else keywords, we use max_padding = 0. This means that that t.len extends only up to the end of the keyword. That's because the keyword starts a new line and we don't want it to inflate the length of the parent.

    For the first node that's added, it always contributes its full length to t.len regardless of the value of max_padding.

  • override_join_lines_based_on_source: when the join_lines_based_on_source option is true, this flag overrides it so that n is added as if join_lines_based_on_source were false.

source
JuliaFormatter.align_binaryopcalls! — Method
align_binaryopcalls!(fst::FST, op_inds::Vector{Int})

Aligns binary operator expressions.

Additionally handles the case where a keyword such as const is used prior to the binary op call.

source
JuliaFormatter.block_arg_forces_nest — Method
block_arg_forces_nest(arg::JuliaSyntax.GreenNode, offset::Integer, s::State, style, ctx)::Bool

Whether arg – the sole argument of a bracketed construct such as (BLOCK) or [BLOCK for x in y], starting at byte offset of the source – is a block that will be expanded onto multiple lines, in which case the brackets must always nest. With preserve_single_line_blocks, a block that is kept on a single line does not force nesting.

source
JuliaFormatter.block_has_statements — Method
block_has_statements(cst) -> Bool

Whether the block node cst contains any statements.

Semicolons don't count. They are only statement separators and are dropped when the block is printed (see p_block), so function f(); end is just as empty as function f() end and both are printed the same way. Counting the ; as a statement would instead give function f()\nend on the first pass, which the empty-block handling then collapses to function f() end on the second — i.e. not idempotent.

source
JuliaFormatter.boundary_token_text — Method
boundary_token_text(s::State, child::JuliaSyntax.GreenNode, child_offset::Integer, rightmost::Bool)

Return the text that will be emitted for the token of child that sits directly next to a binary operator: the last non-whitespace leaf of the left operand (rightmost = true) or the first non-whitespace leaf of the right operand (rightmost = false). This text is fed to gluing_changes_tokenization to decide whether the whitespace around the operator can be removed.

source
JuliaFormatter.can_transform_syntax — Method
can_transform_syntax(s::State, allow_in_macros::Bool)

Check whether according to the current state we are allowed to perform a syntax transformation. The allow_in_macros argument indicates whether the syntax transformation should be allowed inside macros when s.opts.transform_syntax_in_macros is true. Some syntax transformations are simply not safe to perform inside macros so are disabled even if s.opts.transform_syntax_in_macros is true.

source
JuliaFormatter.chain_continuation_indent — Method
chain_continuation_indent(fst::FST, s::State)

Indentation used for the continuation lines of operator chains, comparisons and binary operator calls.

By default these are aligned to the column at which the expression starts:

x = (aaa |>     bbb |>     ccc)

When the indent_binary_continuations option is enabled they instead receive one indent level relative to the indentation of the expression itself (see #592):

x = (aaa |>    bbb |>    ccc)
source
JuliaFormatter.default_parens_allow_nesting — Method
default_parens_allow_nesting(arg::JuliaSyntax.GreenNode, s::State, ctx::PrettyContext)

Whether DefaultStyle's p_parens puts placeholders just inside a pair of parentheses containing arg, i.e. whether the formatter may put a line break after ( and before ). For example, (a + b) may be nested as

(    a + b)

but (f(a, b)) may not, because f(a, b) can nest itself. Instead it would become

(f(    a,    b,))
source
JuliaFormatter.find_config_file — Method
find_config_file(path::AbstractString)::Union{Nothing,AbstractString}

Search for a .JuliaFormatter.toml configuration file in the directory of path and its ancestors. Returns the path to the configuration file if found, or nothing if not found.

source
JuliaFormatter.find_trailing_juxtapose — Function
find_trailing_juxtapose(node::JuliaSyntax.GreenNode)

If node is suffixed by a juxtapose node, return that juxtapose node and its offset from the beginning of node. Otherwise, return nothing.

Only juxtapose nodes at the very end of node count. For example, in 2e*y the juxtapose 2e is not at the end (y is), so this returns nothing; in y*2e it returns 2e.

source
JuliaFormatter.first_nonws_leaf_and_offset — Function
first_nonws_leaf_and_offset(
    node::JuliaSyntax.GreenNode,
)::Union{Nothing,Tuple{JuliaSyntax.GreenNode,Integer}

Return the first non-whitespace leaf node in node plus its offset from the beginning of node, or nothing if there are no non-whitespace leaves.

source
JuliaFormatter.gluing_changes_tokenization — Method
gluing_changes_tokenization(left, op, right)::Bool

For a binary operator op, check whether emitting left, op, and right with no spaces in between produces a different token stream than emitting them separated by spaces.

left and right are the text of the tokens immediately adjacent to the operator. Note that this is not necessarily equal to the text of the full left and right operands (we only take the extreme tokens).

left and/or right may be nothing, meaning that the token on that side cannot lexically merge with an operator (see boundary_token_text). Such a side is stood in for by the neutral identifier x. Using the actual text of such tokens would produce false positives. For example, if the binary expression was "a" * "b", then naively passing the extreme tokens would lead to "*".

source
JuliaFormatter.has_delimiters — Method
has_delimiters(cst::JuliaSyntax.GreenNode)

cst is assumed to be a single child node. Returns true if the node is of the syntactic form {...}, [...], or (...).

source
JuliaFormatter.has_more_args_to_come — Method
has_more_args_to_come

Searches childs[start_index:end] for the first non-whitespace node and returns whether it is not of kind stop_kind.

If the first non-whitespace node is of kind stop_kind, that implies that there are no more arguments to process in the current argument list / indexing expression / etc.

source
JuliaFormatter.hcat_allow_boundary_newlines — Method
hcat_allow_boundary_newlines(style::AbstractStyle)

Determine whether newlines are allowed immediately after the opening [ and immediately before the closing ] of an hcat node.

Most styles allow this, but YAS doesn't (and SciML too, since it dispatches to YAS).

In principle this can be generalised to vcat and ncat as well; I just haven't done so.

source
JuliaFormatter.is_column_aligned — Method
is_column_aligned(fst::FST)

Whether YASStyle lays out the continuation lines of fst relative to the column at which fst itself starts, rather than relative to the start of the line it appears on.

Iterables are column-aligned, because their arguments line up with the bracket that opens them, as is where, whose type parameters line up with the {:

f(aaaaaaaaaaaaaaaaaaaaaa,  bbbbbbbbbbbbbbbbbbbbbb)Foo{A} where {Aaaaaaaaaaaaaaa<:Xxxxxxxxxxxx,              Bbbbbbbbbbbbbbb<:Yyyyyyyyyyyy}

Block-like constructs are not, because their bodies are indented by one level from the start of the line, regardless of where function f() starts:

function f()    bodyend

For nested constructs we might need to inspect their children. For example in

@mymacro [aaaaaaaaaaaaaaaaaaaa,          bbbbbbbbbbbbbbbbbbbb]

the second line is indented according to the [ iff the last argument of the macro is column-aligned.

A binary call is column-aligned unless its operator is one of those that indents the RHS from the start of the line instead (see is_indent_nest).

Chain, Comparison and Conditional are column-aligned in YASStyle too, but they are deliberately not listed here because the only caller (n_binaryopcall!) accounts for their full width before it will consider undoing a nesting, so it never has to move one of them that has already been split over several lines.

source
JuliaFormatter.is_formattable_file — Method
is_formattable_file(filename) -> Bool

Check whether filename is a file that JuliaFormatter can format, based on its extension or the presence of a Julia shebang line (e.g. #!/usr/bin/env julia).

source
JuliaFormatter.is_indent_nest — Method
is_indent_nest(fst::FST)

Whether nesting the binary call fst at its operator indents the RHS by one level from the start of the line:

aaaaaaaaaaaa =>    rhs

as opposed to bringing it back to the column the LHS starts at, which is what every other operator does:

aaaaaaaaaaaa inrhs

True for assignments, =>, -> and standalone short-circuits.

source
JuliaFormatter.is_iterable_arg — Method

Returns whether fst can be an iterable argument. For example in the case of a function call, which is of type Call:

(a, b, c; k1=v1)

This would return true for a, b, c and k1=v1 and false for all other nodes.

source
JuliaFormatter.is_newline_after_2semicolons — Method
is_newline_after_2semicolons(cst::JuliaSyntax.GreenNode, i::Integer)

Detect if child node i of cst is a newline that follows two semicolons. For example, this will detect the newline in constructs such as

[a b;; c d]
source
JuliaFormatter.is_opaque_string — Method
is_opaque_string(fst::FST)::Bool

Whether fst is a StringN node built from a non-triple-quoted multiline literal, whose interior lines must be emitted verbatim (see the is_opaque_string field of Metadata).

source
JuliaFormatter.isignored — Method
isignored(path::AbstractString, config::Configuration)::Bool

Determine if the given path should be ignored based on the ignore patterns in the config. Returns true if the path matches any of the ignore patterns.

source
JuliaFormatter.keep_single_line — Method
keep_single_line(cst::JuliaSyntax.GreenNode, s::State, ctx::PrettyContext; offset = s.offset)::Bool

Whether the block construct cst, which starts at byte offset of the source, is written entirely on a single source line and should therefore be kept on a single line (see the preserve_single_line_blocks option).

A construct containing a docstring ("doc" x) is never kept on one line, since the docstring is always emitted on its own line. The elseif/else/catch/finally sub-nodes of an if/try don't decide for themselves but follow the enclosing construct (via ctx.parent_keep_single_line), since their own span covers neither the start of the construct nor its end.

IMPORTANT: unless offset is given explicitly, this must be called when s.offset is still positioned at the start of cst (i.e. before any of its children have been prettified), since it compares the source line of the first and last byte of cst.

source
JuliaFormatter.kw_value_needs_parens — Method
kw_value_needs_parens(fst::FST)

Used in p_kw when whitespace_in_kwargs=false. Check whether fst, which is the formatted value on the RHS of kwarg=value, needs to be parenthesised so that it isn't merged with the preceding = sign.

For example, (; a = >=(1)) cannot be formatted as (; a=>=(1)), because => would be read as a single token (the pair operator). It has to become (; a=(>=(1))) instead. Likewise, (; a = ==(1)) would become (; a===(1)) where === is a single token.

On the other hand, (; a = +x) can safely be formatted as (; a=+x) because =+ is not a token, so the lexer will still read = followed by +. Same for things like (; o=⊆).

To check this, we put = in front of the first leaf of fst and lex it: if the first token is just the = sign, then no parentheses are needed.

Note that we check the formatted FST rather than the source code, because the two do not always begin with the same token. For example, with pipe_to_function_call=true, (; a = x |> >(1)) is formatted as (; a=(>(1)(x))): the source begins with x, but the formatted value begins with >.

source
JuliaFormatter.last_nonws_leaf_and_offset — Function
last_nonws_leaf_and_offset(
    node::JuliaSyntax.GreenNode,
)::Union{Nothing,Tuple{JuliaSyntax.GreenNode,Integer}

Return the last non-whitespace leaf node in node plus its offset from the beginning of node, or nothing if there are no non-whitespace leaves. This is the mirror image of first_nonws_leaf_and_offset.

source
JuliaFormatter.materialise_trailing_comma! — Method
materialise_trailing_comma!(fst::FST, i::Int)

Turns the trailing comma node fst[i] into an actual ,, unless the node before it would read the comma as part of itself (see absorbs_trailing_comma).

This check is done here, when nesting, rather than when the FST is built, because nesting can change what the previous node ends with. For example, in BlueStyle,

g(c ? a : return b)

has its ternary turned into an if ... end block if it's too long. A ternary that ends with return b can't be followed by a comma, but an if ... end block can. Checking at this point means we see the if ... end block, which is also what the next formatting pass sees.

source
JuliaFormatter.move_at_sign_to_the_end — Method
move_at_sign_to_the_end(fst::FST, s::State)

NOTE: Assumes fst is the caller name of a macrocall such as @macro or Module.@macro.

Moves @ to the last identifier.

Example:

@Module.macro

to

Module.@macro
source
JuliaFormatter.nest_if_over_margin! — Method
nest_if_over_margin!(
    style,
    fst::FST,
    s::State,
    idx::Int;
    stop_idx::Union{Int,Nothing} = nothing,
)::Bool

Converts the node at idx to a NEWLINE if the current margin plus the additional margin from fst[idx:stop_idx-1] is greater than the allowed margin.

If stop_idx == nothing the range is fst[idx:end].

Returns whether nesting occurred.

source
JuliaFormatter.normalize_line_ranges — Method
normalize_line_ranges(lines::Vector{Tuple{Int,Int}}) -> Vector{UnitRange{Int}}

Convert the user-supplied lines (inclusive, 1-based (start, stop) line ranges) into a sorted vector of non-overlapping, non-adjacent UnitRange{Int}s.

Overlapping and adjacent ranges are merged rather than rejected: this keeps the core API robust for callers such as LSP rangesFormatting, which may legitimately hand us touching or overlapping ranges. Bounds against the actual file length are checked later, in add_line_range_markers.

source
JuliaFormatter.normalize_number_literal — Method
normalize_number_literal(k::JuliaSyntax.Kind, val::AbstractString, trailing_zero::Bool)

Add leading zeroes, and trailing zeros if trailing_zero is true, to float literals.

              trailing_zero = true     trailing_zero = false`1.`     -->   `1.0`                    `1.``.5`     -->   `0.5`                    `0.5`

Other literals are unchanged.

source
JuliaFormatter.p_binaryopcall — Method
p_binaryopcall

Note that this function contains a substantial amount of logic for formatting binary operators. Consequently, if you want to introduce custom behaviour for a specific style, you should not create an overload of this function for that style as you will have to reproduce a lot of this logic, and it's very easy to make a mistake! Instead you should define smaller helper functions which dispatch on the style and call those functions from inside this one.

source
JuliaFormatter.p_pipe_to_call — Method
p_pipe_to_call

Take a CST of the form x |> y or x .|> y, but return a FST with the equivalent function call y(x) or y.(x) instead.

Note that this function is only called for certain pipe-applications. See the call site in p_binaryopcall for details.

source
JuliaFormatter.prepend_return_fst! — Method
prepend_return_fst!(fst::FST, s::State)

Prepends return to the last expression of a block if applicable. Returns true if a return was added, and false otherwise.

Note: This function is only called when a short-form function definition is converted to a long-form one, AND always_use_return is true. For ordinary, pre-existing long-form function definitions, the implementation of always_use_return is in p_block in default/pretty.jl. This is done to avoid post-FST passes which tend to cause idempotence issues.

function foo()    a = 2 * 3    a / 3end

to

function foo()    a = 2 * 3    return a / 3end
source
JuliaFormatter.remove_line_range_markers — Method
remove_line_range_markers(marked_src::AbstractString, formatted::AbstractString) -> String

Splice the formatted in-range blocks back into the original source. marked_src is the marker-annotated source produced by add_line_range_markers and formatted is the result of formatting it. The two streams are walked line by line in lockstep:

  • outside a marker pair we keep the (verbatim) marked_src line,
  • inside a marker pair we keep the formatted line,
  • marker lines themselves are dropped.

Both streams contain the same markers in the same order, so the begin/end markers act as synchronization points between them.

source
JuliaFormatter.separate_kwargs_with_semicolon! — Method
separate_kwargs_with_semicolon!(fst::FST)

Ensures keyword arguments are separated by a ";".

Examples

Replace "," with ";".

a = f(x, y = 3)->a = f(x; y = 3)

Move ";" to the prior to the first positional argument.

a = f(x = 1; y = 2)->a = f(; x = 1, y = 2)
source
JuliaFormatter.slice_source — Method
slice_source(code::AbstractString, r::UnitRange)

Return the text of code in the byte range r.

JuliaSyntax stores and gives us byte ranges, so last(r) is the last byte of the final character. However, this doesn't align with Julia's own string slicing rules, which require that the end index be the first byte of the last character – otherwise it throws. So, if the last character is multibyte (e.g. α or ∈), last(r) is not a valid string index and code[r] throws.

To avoid this, we first move last(r) back to the start of its character using thisind (here, from 6 to 5). Note that a string range includes the whole character that starts at its last index, so this still returns the entire final character.

source
JuliaFormatter.source_op_kind_from_offset — Method
source_op_kind_from_offset(s, cst, offset)::Union{Nothing,JuliaSyntax.Kind}

Return the operator kind of cst, using the source text at offset if necessary to help determine this. If cst is not an operator, returns nothing.

Note that this function may still return a K"Identifier"! This is because Julia allows some weird postfix operators. See the comments in the function for more info.

The check against the source is needed because JuliaSyntax v1 can encode source operators as Identifier leaves in call forms. For example:

julia> JuliaSyntax.parseall(JuliaSyntax.GreenNode, "+y")     1:2      │[toplevel]     1:2      │  [call]     1:1      │    Identifier           ✔     2:2      │    Identifier           ✔

See https://github.com/JuliaLang/JuliaSyntax.jl/issues/548 for more information.

source
JuliaFormatter.starts_with_semicolon — Method
starts_with_semicolon(fst::FST)::Bool

Whether the first leaf of fst is a semicolon. Used when joining a single-line block onto the line of its parent construct: in try; isfile(x); catch; false end the body block starts with a ;, and no space should be inserted between the try keyword and the ; (try; isfile(x) rather than try ; isfile(x)).

source
JuliaFormatter.unary_info — Method
unary_info(x::JuliaSyntax.GreenNode)::Union{Bool,Nothing}

Returns:

  • true if x is a prefix unary operator application, such as +x or <:x

  • false if x is a postfix unary operator application, such as x' or x...;

  • nothing if x is not an application of a unary operator.

source
JuliaFormatter.use_long_form_standalone_shortcircuit! — Method
use_long_form_standalone_shortcircuit!(fst::FST, ::State)

If fst is marked as StandaloneInLongForm, marks it as Standalone instead. This is called when the enclosing short-form function definition is rewritten as a long-form one. See short_to_long_function_def! for more details.

source
JuliaFormatter.walk — Method
walk(f, fst::FST, s::State)

Walks fst calling f on each node.

In situations where descending further into a subtree is not desirable f should return a value other than nothing.

Note

This function mutates the State's (s) line_offset. If this is not desired you should save the value before calling this function and restore it after.

source
JuliaFormatter.wrap_in_parens — Method
wrap_in_parens(style, n::FST, arg::JuliaSyntax.GreenNode, s::State, ctx::PrettyContext)

Wrap the FST n (formatted from the CST node arg) in a pair of parentheses that are not in the source. For example, with whitespace_in_kwargs = false, p_kw turns f(a = $g(x)) into f(a=($g(x))).

The resulting Brackets node must be the same as what p_parens would produce when formatting the output a second time, where the parentheses are in the source. Otherwise the two passes may nest the code differently and formatting is not idempotent. In particular, the placeholders inside the parentheses must only be added when p_parens would add them.

open_paren_line is the source line that the ( is treated as being on. Usually this is the line n starts on, but it must be earlier if n begins with a comment that should go inside the parentheses. For example, BlueStyle turns

a ? b :# commentc && d ? e : f

into an if/elseif chain where the comment ends up inside the parentheses:

elseif (    # comment    c && d)

If the ( were placed on the line of c && d, the comment would be printed before it.

source
JuliaFormatter.Shims.is_caller_in_function_def — Method
is_caller_in_function_def(t::JuliaSyntax.GreenNode) -> Bool

Identify the caller in a function definition, i.e., the f(...) part in

function f(...)    bodyend

This may be more complicated than just is_function_call, because the caller may be f(...)::T, f(...) where T, or (f(...)) (or combinations thereof).

source
JuliaFormatter.Shims.is_function_call — Method

Determine if a CST represents a function call, i.e., F(X1, X2, ...) syntactically.

This covers, for example:

  • f(x) -> K"call"
  • f.(x) -> K"dotcall"
  • <=(x) -> K"call"
  • .<=(x) -> K"call" (with a dotted caller)
  • <:(x) -> K"<:", caught by istypeoperator
  • .<:(x) -> K"call" (with a dotted caller)

<: and >: are special-cased by JuliaSyntax to return K"<:" and K">:" nodes rather than K"call", but from a syntax perspective we want to treat them the same as any other function.

We then need to exclude a few things:

  • applications of unary operators, for example, +x, -x, and <:x. These are still parsed as K"call" but these can be identified by the fact that JuliaSyntax.is_prefix_op_call returns true for these. BUT, we don't want to exclude the parenthesised versions +(x), -(x) since these do look like function calls (and we only care about the syntax, not the semantics)! So need some custom logic to identify these...

  • bare operators, easily identified by is_leaf.

  • infix operators, for which JuliaSyntax.is_infix_op_call USUALLY returns true (but not for a <: b — hence why we instead do a check for K"(").

Note: JuliaSyntax.is_prefix_call sounds like the right thing to check, but for some reason this returns true for tons of things we don't care about. For example:

julia> JS.is_prefix_call(JS.parseall(JS.GreenNode, "1")[1])true
source
JuliaFormatter.Shims.is_really_whitespace — Method
is_really_whitespace(cst::JS.GreenNode) -> Bool

Check whether a CST node is really whitespace, i.e., either K"Whitespace" or K"NewlineWs". Note that JuliaSyntax.is_whitespace returns true for K"Comment" as well, which we don't want here.

source
JuliaFormatter.Shims.kind_from_string — Method
kind_from_string(s::AbstractString) -> Union{Nothing,JuliaSyntax.Kind}

Look up the Kind whose name is s, e.g. kind_from_string("+") gives K"+". Return nothing if there is no such Kind, e.g. for kind_from_string("foo").

This does the same thing as JuliaSyntax.Kind(s), except that JuliaSyntax.Kind(s) throws an error for unknown names. Throwing and catching an error is very slow (tens of microseconds each time), and this lookup happens for many nodes (e.g. for every keyword argument name in BlueStyle), so we read JuliaSyntax's internal lookup table directly instead.

source