Skip to content

Reflow API

This section is for rule authors who produce whitespace or layout fixes.

Many SQLFluff rules involve spacing and layout — enforcing a particular whitespace style or adding/removing code while respecting the layout configuration. The sqlfluff.utils.reflow module provides centralised utilities so that all layout rules behave consistently.

Rules should use ReflowSequence rather than constructing LintFix objects manually; it returns ready-to-use fix lists and respects the user's layout configuration automatically.

Source: sqlfluff/utils/reflow/

ReflowSequence

Class for keeping track of elements in a reflow operation.

This acts as the primary route into using the reflow routines. It acts in a way that plays nicely within a rule context in that it accepts segments and configuration, while allowing access to modified segments and a series of LintFix objects, which can be returned by the calling rule.

Sequences are made up of alternating ReflowBlock and ReflowPoint objects (even if some points have no segments). This is validated on construction.

Most operations also return ReflowSequence objects such that operations can be chained, and then the resultant fixes accessed at the last stage, for example:

python fixes = ( ReflowSequence.from_around_target( context.segment, root_segment=context.parent_stack[0], config=context.config, ) .rebreak() .get_fixes() )

Parameters:

ParameterTypeDefaultDescription
elementslist[ReflowBlock | ReflowPoint]
root_segmentBaseSegment
reflow_configReflowConfig
depth_mapDepthMap
lint_resultslist[LintResult] | NoneNone

Methods

break_long_lines

python
break_long_lines() → ReflowSequence

Rebreak any remaining long lines in a sequence.

This assumes that reindent() has already been applied.

Returns:

ReflowSequence — See return type.

from_around_target

python
from_around_target(
    target_segment,
    root_segment,
    config,
    sides="both"
) → ReflowSequence

Generate a sequence around a target.

Parameters:

ParameterTypeDefaultDescription
target_segmentBaseSegmentThe segment to center around when considering the sequence to construct.
root_segmentBaseSegmentThe relevant root segment (usually the base FileSegment).
configFluffConfigA config object from which to load the spacing behaviours of different segments.
sidesstr"both"Limit the reflow sequence to just one side of the target. Default is two sided ("both"), but set to "before" or "after" to limit to either side. NOTE: We don't just expand to the first block around the target but to the first code element, which means we may swallow several comment blocks in the process. To evaluate reflow around a specific target, we need need to generate a sequence which goes for the preceding raw to the following raw. i.e. at least: block - point - block - point - block (where the central block is the target).

Returns:

ReflowSequence — See return type.

from_raw_segments

python
from_raw_segments(
    segments,
    root_segment,
    config,
    depth_map=None
) → ReflowSequence

Construct a ReflowSequence from a sequence of raw segments.

This is intended as a base constructor, which others can use. In particular, if no depth_map argument is provided, this method will generate one in a potentially inefficient way. If the calling method has access to a better way of inferring a depth map (for example because it has access to a common root segment for all the content), it should do that instead and pass it in.

Parameters:

ParameterTypeDefaultDescription
segmentscollections.abc.Sequence[RawSegment]
root_segmentBaseSegment
configFluffConfig
depth_mapDepthMap | NoneNone

Returns:

ReflowSequence — See return type.

from_root

python
from_root(
    root_segment,
    config
) → ReflowSequence

Generate a sequence from a root segment.

Parameters:

ParameterTypeDefaultDescription
root_segmentBaseSegmentThe relevant root segment (usually the base FileSegment).
configFluffConfigA config object from which to load the spacing behaviours of different segments.

Returns:

ReflowSequence — See return type.

get_fixes

python
get_fixes() → list[LintFix]

Get the current fix buffer.

We're hydrating them here directly from the LintResult objects, so for more accurate results, consider using .get_results(). This method is particularly useful when consolidating multiple results into one.

Returns:

list[LintFix] — See return type.

get_raw

python
get_raw() → str

Get the current raw representation.

Returns:

str — See return type.

get_results

python
get_results() → list[LintResult]

Return the current result buffer.

Returns:

list[LintResult] — See return type.

insert

python
insert(
    insertion,
    target,
    pos="before"
) → ReflowSequence

Returns a new ReflowSequence with the new element inserted.

Insertion is always relative to an existing element. Either before or after it as specified by pos. This generates appropriate creation LintFix objects to direct the linter to insert those elements.

Parameters:

ParameterTypeDefaultDescription
insertionRawSegment
targetRawSegment
posstr"before"

Returns:

ReflowSequence — See return type.

INFO

This method is currently excluded from test coverage because it is not actively used by any rule. It was previously utilized by rule AL01, but that rule now uses an alternative implementation. The method is retained for potential future reuse or reference.

rebreak

python
rebreak(
    rebreak_type="lines"
) → ReflowSequence

Returns a new ReflowSequence corrected line breaks.

This intentionally does not handle indentation, as the existing indents are assumed to be correct.

INFO

Currently this only moves existing segments around line breaks (e.g. for operators and commas), but eventually this method will also handle line length considerations too.

Parameters:

ParameterTypeDefaultDescription
rebreak_typeLiteral['lines', 'keywords']"lines"

Returns:

ReflowSequence — See return type.

reindent

python
reindent() → ReflowSequence

Reindent lines within a sequence.

Returns:

ReflowSequence — See return type.

replace

python
replace(
    target,
    edit
) → ReflowSequence

Returns a new ReflowSequence with edit elements replaced.

This generates appropriate replacement LintFix objects to direct the linter to modify those elements.

Parameters:

ParameterTypeDefaultDescription
targetBaseSegment
editcollections.abc.Sequence[BaseSegment]

Returns:

ReflowSequence — See return type.

respace

python
respace(
    strip_newlines=False,
    filter="all"
) → ReflowSequence

Returns a new ReflowSequence with points respaced.

Parameters:

ParameterTypeDefaultDescription
strip_newlinesboolFalseOptionally strip newlines before respacing. This is primarily used on focused sequences to coerce objects onto a single line. This does not apply any prioritisation to which line breaks to remove and so is not a substitute for the full reindent or reflow methods.
filterstr"all"Optionally filter which reflow points to respace. Default configuration is all. Other options are newline which only respaces points containing a newline or followed by an end_of_file marker, or inline which is the inverse of newline. This is most useful for filtering between trailing whitespace and fixes between content on a line. NOTE this method relies on the embodied results being correct so that we can build on them.

Returns:

ReflowSequence — See return type.

without

python
without(
    target
) → ReflowSequence

Returns a new ReflowSequence without the specified segment.

This generates appropriate deletion LintFix objects to direct the linter to remove those elements.

Parameters:

ParameterTypeDefaultDescription
targetRawSegment

Returns:

ReflowSequence — See return type.

INFO

This method is currently excluded from test coverage because it is not actively used by any rule. It was previously utilized by rule AL01, but that rule now uses an alternative implementation. The method is retained for potential future reuse or reference.

ReflowPoint

Class for keeping track of editable elements in reflow.

This class, and its sibling ReflowBlock, should not normally be manipulated directly by rules, but instead should be manipulated using ReflowSequence.

It holds segments which can be changed during a reflow operation such as whitespace and newlines.It may also contain Indent and Dedent elements.

It holds no configuration and is influenced by the blocks on either side, so that any operations on it usually have that configuration passed in as required.

Parameters:

ParameterTypeDefaultDescription
segmentstuple[RawSegment, ...]

Methods

get_indent

python
get_indent() → str | None

Get the current indent (if there).

Returns:

str | None — See return type.

get_indent_impulse

python
get_indent_impulse() → IndentStats

Get the change in intended indent balance from this point.

Returns:

IndentStats — See return type.

get_indent_segment_vals

python
get_indent_segment_vals(
    exclude_block_indents=False
) → list[int]

Iterate through any indent segments and extract their values.

Parameters:

ParameterTypeDefaultDescription
exclude_block_indentsFalse

Returns:

list[int] — See return type.

indent_to

python
indent_to(
    desired_indent,
    after=None,
    before=None,
    description=None,
    source=None
) → tuple[list[LintResult], ReflowPoint]

Coerce a point to have a particular indent.

If the point currently contains no newlines, one will be introduced and any trailing whitespace will be effectively removed.

More specifically, the newline is inserted before the existing whitespace, with the new indent being a replacement for that same whitespace.

For placeholder newlines or indents we generate appropriate source fixes.

Parameters:

ParameterTypeDefaultDescription
desired_indentstr
afterBaseSegment | NoneNone
beforeBaseSegment | NoneNone
descriptionstr | NoneNone
sourcestr | NoneNone

Returns:

tuple[list[LintResult], ReflowPoint] — See return type.

is_all_unrendered

python
is_all_unrendered() → bool

Return whether this element is all unrendered.

Returns True if contains only whitespace, indents, template loops or placeholders.

Returns:

bool — See return type.

INFO

  • ReflowBlocks will contain the placeholders and loops
  • ReflowPoints will contain whitespace, indents and newlines.

num_newlines

python
num_newlines() → int

Return the number of newlines in this element.

These newlines are either newline segments or contained within consumed sections of whitespace. This counts both.

Returns:

int — See return type.

respace_point

python
respace_point(
    prev_block,
    next_block,
    root_segment,
    lint_results,
    strip_newlines=False,
    anchor_on="before",
    indent_unit="space",
    tab_space_size=4
) → tuple[list[LintResult], ReflowPoint]

Respace a point based on given constraints.

NB: This effectively includes trailing whitespace fixes.

Deletion and edit fixes are generated immediately, but creations are paused to the end and done in bulk so as not to generate conflicts.

Note that the strip_newlines functionality exists here as a slight exception to pure respacing, but as a very simple case of positioning line breaks. The default operation of respace does not enable it, however it exists as a convenience for rules which wish to use it.

Parameters:

ParameterTypeDefaultDescription
prev_blockReflowBlock | None
next_blockReflowBlock | None
root_segmentBaseSegment
lint_resultslist[LintResult]
strip_newlinesboolFalse
anchor_onstr"before"
indent_unitstr"space"
tab_space_sizeint4

Returns:

tuple[list[LintResult], ReflowPoint] — See return type.

ReflowBlock

Class for keeping track of elements to reflow.

This class, and its sibling ReflowPoint, should not normally be manipulated directly by rules, but instead should be manipulated using ReflowSequence.

It holds segments to reflow and also exposes configuration regarding how they are expected to reflow around others. Typically it holds only a single element, which is usually code or a templated element. Because reflow operations control spacing, it would be very unusual for this object to be modified; as such it exposes relatively few methods.

The attributes exposed are designed to be "post configuration" i.e. they should reflect configuration appropriately.

Parameters:

ParameterTypeDefaultDescription
segmentstuple[RawSegment, ...]
spacing_beforestr
spacing_afterstr
line_positionstr | None
depth_infoDepthInfo
stack_spacing_configsdict[int, str]
line_position_configsdict[int, str]
keyword_line_positionstr | None
keyword_line_position_configsdict[int, str]
keyword_line_position_exclusionsstr | list[str] | None
keyword_line_position_exclusions_configsdict[int, str | list[str]]

Methods

from_config

python
from_config(
    segments,
    config,
    depth_info
) → ReflowBlock

Construct a ReflowBlock while extracting relevant configuration.

This is the primary route to construct a ReflowBlock, as is allows all of the inference of the spacing and position configuration from the segments it contains and the appropriate config objects.

Parameters:

ParameterTypeDefaultDescription
segmentstuple[RawSegment, ...]
configReflowConfig
depth_infoDepthInfo

Returns:

ReflowBlock — See return type.

is_all_unrendered

python
is_all_unrendered() → bool

Return whether this element is all unrendered.

Returns True if contains only whitespace, indents, template loops or placeholders.

Returns:

bool — See return type.

INFO

  • ReflowBlocks will contain the placeholders and loops
  • ReflowPoints will contain whitespace, indents and newlines.

num_newlines

python
num_newlines() → int

Return the number of newlines in this element.

These newlines are either newline segments or contained within consumed sections of whitespace. This counts both.

Returns:

int — See return type.

Released under the MIT License.