Re: [PATCH 1/2] dt-check-style: Handle indented fragments in indent-unit-dts

From: Krzysztof Kozlowski

Date: Tue Sep 01 2026 - 04:26:58 EST


On Sun, Aug 30, 2026 at 08:24:54PM +0200, Sven Peter wrote:
> The multi-die Apple SoCs contain most of their nodes in a file that is
> included to instantiate the same nodes across both dies. These included
> fragments all have a tabs-only prefix that is correct in the final
> composed file. dt-check-style however finds the first line starting with
> two (or more) tabs and then indent-unit-dts rejects those correctly
> indented files.
>
> Fix that by detecing a tabs-only prefix shared by rootless files and
> treat that as a constant offset. Also add fixtures to test this.
>
> Signed-off-by: Sven Peter <sven@xxxxxxxxxx>
> ---
> scripts/dtc/dt-check-style | 69 +++++++++++++++++-----
> .../bad/dts-fragment-missing-prefix.dtsi | 6 ++
> .../bad/dts-indented-ref-node.dtsi | 6 ++
> .../expected/dts-fragment-missing-prefix.dtsi.txt | 2 +
> .../expected/dts-indented-ref-node.dtsi.txt | 2 +
> 5 files changed, 70 insertions(+), 15 deletions(-)
>
> diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style
> index 96deffc0d8a7..2afc05fa6602 100755
> --- a/scripts/dtc/dt-check-style
> +++ b/scripts/dtc/dt-check-style
> @@ -380,12 +380,43 @@ def check_mixed_indent_chars(ctx):
> yield (cont.lineno, 'mixed tabs and spaces in indent')
>

I did not expect simultaneous work, so I did some renaming and moving
which unfortunately will cause you conflicts.

My patches got merged and they add _ to detect_indent_unit(), so please
follow. Also other functions go to a bit different place after sorting.

>
> +def detect_fragment_offset(ctx):
> + """Return the indentation inherited from an include context.
> +
> + A fragment has neither a root nor top-level reference nodes and all

What is a DTS fragment?

> + its top-level lines share the same tabs-only indentation.

I don't think you are fixing right problem or at least not completely.
The Apple DTS is incorrect, because - I assume we talk about
t600x-dieX.dtsi - this should not be indented with a tab in the first
place. Apple does not get separate coding style, although I am working
on supression tags to avoid certain warnings.




> + """
> + if ctx.file_type != 'dts':
> + return ''
> + offset = None
> + for dl in ctx.lines:
> + if dl.depth != 0:
> + continue
> + if dl.linetype not in (LineType.NODE_OPEN, LineType.NODE_CLOSE,
> + LineType.PROPERTY):
> + continue
> + if dl.linetype == LineType.NODE_OPEN and \
> + (dl.node_name == '/' or dl.ref_name is not None):
> + return ''
> + if offset is None:
> + offset = dl.indent_str
> + elif dl.indent_str != offset:
> + return ''
> + if not offset:
> + return ''
> + if any(char != '\t' for char in offset):
> + return ''
> + return offset
> +
> +
> def detect_indent_unit(ctx):
> """Find the indent unit used at depth 1 in this block.
>
> Returns tuple of string (one of: ' ' (2 spaces), ' ' (4 spaces),
> - '\\t' (tab), or None if depth-1 is empty or ambiguous) and line number when
> - detection was made)."""
> + '\\t' (tab), or None if depth-1 is empty or ambiguous), line number when
> + detection was made, and whether the detected fragment prefix is valid.
> + """
> + prefix = detect_fragment_offset(ctx)
> for dl in ctx.lines:
> if dl.depth != 1:
> continue
> @@ -395,20 +426,25 @@ def detect_indent_unit(ctx):
> continue
> if not dl.indent_str:
> continue
> - if dl.indent_str == '\t':
> - return ('\t', dl.lineno)
> - if dl.indent_str == ' ':
> - return (' ', dl.lineno)
> - if dl.indent_str == ' ':
> - return (' ', dl.lineno)
> + indent = dl.indent_str
> + if prefix and not indent.startswith(prefix):
> + return (indent, dl.lineno, False)
> + if prefix:
> + indent = indent[len(prefix):]
> + if indent == '\t':
> + return ('\t', dl.lineno, True)
> + if indent == ' ':
> + return (' ', dl.lineno, True)
> + if indent == ' ':
> + return (' ', dl.lineno, True)
> # Anything else at depth 1 is non-canonical; flag elsewhere.
> - return (dl.indent_str, dl.lineno)
> - return (None, None)
> + return (indent, dl.lineno, True)
> + return (None, None, True)
>
>
> def check_indent_unit_relaxed(ctx):
> """YAML examples: 2 or 4 spaces. Never tabs or other widths."""
> - (unit, lineno) = detect_indent_unit(ctx)
> + (unit, lineno, _) = detect_indent_unit(ctx)
> if unit is None:
> return
> if unit not in (' ', ' '):
> @@ -417,7 +453,10 @@ def check_indent_unit_relaxed(ctx):
>
> def check_indent_unit_dts(ctx):
> """DTS files: 1 tab per level. Always required."""
> - (unit, lineno) = detect_indent_unit(ctx)
> + (unit, lineno, prefix_valid) = detect_indent_unit(ctx)
> + if not prefix_valid:
> + yield (lineno, 'indent does not start with fragment offset')
> + return
> if unit is None:
> return
> if unit != '\t':
> @@ -426,7 +465,7 @@ def check_indent_unit_dts(ctx):
>
> def check_indent_unit_strict(ctx):
> """YAML: must be exactly 4 spaces. DTS: 1 tab (same as relaxed)."""
> - (unit, lineno) = detect_indent_unit(ctx)
> + (unit, lineno, _) = detect_indent_unit(ctx)
> if unit is None:
> return
> if ctx.file_type == 'yaml':
> @@ -437,8 +476,8 @@ def check_indent_unit_strict(ctx):
>
> def check_indent_consistent(ctx):
> """All indented lines must be a multiple of the detected unit."""
> - (unit, lineno) = detect_indent_unit(ctx)
> - if unit is None:
> + (unit, lineno, prefix_valid) = detect_indent_unit(ctx)
> + if unit is None or not prefix_valid:
> return
> if ctx.file_type == 'yaml':
> if unit not in (' ', ' '):
> diff --git a/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi b/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi
> new file mode 100644
> index 000000000000..a72735e0884b
> --- /dev/null
> +++ b/scripts/dtc/dt-style-selftest/bad/dts-fragment-missing-prefix.dtsi
> @@ -0,0 +1,6 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +/* Include fragment whose child does not contain the inherited indentation. */
> +
> + bus@10000 {
> + compatible = "simple-bus";
> + };
> diff --git a/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi b/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi
> new file mode 100644
> index 000000000000..cabe4ee96d10
> --- /dev/null
> +++ b/scripts/dtc/dt-style-selftest/bad/dts-indented-ref-node.dtsi
> @@ -0,0 +1,6 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +/* Reference nodes must remain at column zero. */
> +
> + &example {
> + status = "okay";
> + };

A good example would be useful and probably made the discussion easier -
we would see that "good" example is actually not desired/correct style.

Best regards,
Krzysztof