API Documentation

Public API

JuliaFormatter.formatFunction
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_textFunction
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_fileFunction
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
JuliaFormatter.format_mdFunction
JuliaFormatter.format_md(
    text::AbstractString,
    style::AbstractStyle = DefaultStyle();
    formatting_options...
)

Normalizes the Markdown source and formats Julia code blocks.

See Formatting Options for a list of available formatting options.

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.AlignGroupType
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.ConfigurationType
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.FormattingErrorType
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.OptionsType
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._contains_returnMethod

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_rangesMethod
_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_textMethod
_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.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_markersMethod
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.binaryop_to_whereop!Method
binaryop_to_whereop(fst::FST, s::State)

Handles the case of a function def defined as:

foo(a::A)::R where A = body

In this case instead of it being parsed as (1):

Binary
 - Where
 - OP
 - RHS

It's parsed as (2):

Binary
 - Binary
  - LHS
  - OP
  - Where
   - R
   - ...
 - OP
 - RHS

(1) is preferrable since it's the same parsed result as:

foo(a::A) where A = body

This transformation converts (2) to (1).

ref https://github.com/julia-vscode/CSTParser.jl/issues/93

source
JuliaFormatter.can_transform_syntaxMethod
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.find_config_fileMethod
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.first_nonws_leaf_and_offsetFunction
first_nonws_leaf_and_offset(
    node::JuliaSyntax.GreenNode,
)::Union{Nothing,Tuple{JuliaSyntax.GreenNode,Int}

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.has_delimitersMethod
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_comeMethod
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_newlinesMethod
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_formattable_fileMethod
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_iterable_argMethod

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_2semicolonsMethod
is_newline_after_2semicolons(cst::JuliaSyntax.GreenNode, i::Int)

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.isignoredMethod
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.length_toMethod
length_to(x::FST, ntyps; start::Int = 1)

Returns the length to any node type in ntyps based off the start index.

source
JuliaFormatter.move_at_sign_to_the_endMethod
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_rangesMethod
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.p_pipe_to_callMethod
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.

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 / 3
end

to

function foo()
    a = 2 * 3
    return a / 3
end
source
JuliaFormatter.remove_line_range_markersMethod
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.source_begins_with_op_needing_parensMethod

sourcebeginswithopneeding_parens(s, cst, offset)

Check whether the first token of cst is an operator. Used in p_kw: if the value on the rhs of kwarg=value begins with an operator, then we parenthesise value to avoid ambiguity.

Note that the behaviour of this differs from unary_info(cst): for example, unary_info(cst) does not pick up expressions such as >=(1), which is interpreted as a function call, not an application of a unary operator. However, these are exactly the sort of things that we want to parenthesise in p_kw – hence this function.

source
JuliaFormatter.source_op_kind_from_offsetMethod
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.unary_infoMethod
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.walkMethod
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.Shims.is_caller_in_function_defMethod
is_caller_in_function_def(t::JuliaSyntax.GreenNode) -> Bool

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

function f(...)
    body
end

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_callMethod

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_whitespaceMethod
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