mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 18:43:44 +00:00
docs(formatter,formatter_graphql,formatter_yaml): annotate own-line comment inlining as known policy violation (#26131)
This commit is contained in:
1 parent
f94b22296c
commit
b8796080d5
5 files changed
+53
-6
No files matched your search
@@ -126,6 +126,7 @@ JS-side mechanics of the shared "never cross" invariants:
|
||||
|
||||
- Line boundary: line comments are printed via `line_suffix`, and own-line comments stay own-line (they become the next node's leading comments)
|
||||
- Both are structural guarantees, keep them
|
||||
- One known violation, kept for Prettier compat: an own-line comment claimed mid-line inlines onto that line (`const // c` + break), see the NOTE in `FormatLeadingComments` (`formatter/trivia.rs`)
|
||||
- User content: e.g. Prettier relocates a comment after a trailing array hole backward across commas to the last real element — an attachment artifact, we keep the comment in place and diverge intentionally
|
||||
- Suppression: when hiding comments from a node (`limit_comments_up_to`), check `has_trailing_suppression_comment` first, or the node loses its suppression
|
||||
|
||||
|
||||
@@ -104,6 +104,20 @@ pub enum FormatLeadingComments<'a> {
|
||||
|
||||
impl<'a> Format<'a, JsFormatContext<'a>> for FormatLeadingComments<'a> {
|
||||
fn fmt(&self, f: &mut JsFormatter<'_, 'a>) {
|
||||
// NOTE: Known FORMATTER_POLICY violation ("own-line comments stay own-line"):
|
||||
// the line break BEFORE the first comment is never reproduced,
|
||||
// so an own-line comment claimed mid-line inlines onto that line
|
||||
// ```js
|
||||
// const
|
||||
// // c
|
||||
// a = 1
|
||||
//
|
||||
// // ->
|
||||
//
|
||||
// const // c
|
||||
// a = 1
|
||||
// ```
|
||||
// Kept for now: Prettier byte-compat outweighs the invariant.
|
||||
fn format_leading_comments_impl<'a>(
|
||||
comments: impl IntoIterator<Item = &'a Comment>,
|
||||
f: &mut JsFormatter<'_, 'a>,
|
||||
|
||||
@@ -44,13 +44,10 @@ This crate instead collects comment spans into a positional cursor, drained in s
|
||||
|
||||
The shared placement invariants apply: a comment stays between the source tokens it sat between, and a same-line trailing comment stays on its line.
|
||||
|
||||
Two bounded exceptions:
|
||||
Two known deviations, kept deliberately (details live on the helpers' doc comments):
|
||||
|
||||
- an own-line comment claimed right after a printed literal (`type`, `:`, `=`) inlines on that literal's line
|
||||
- `type` + break + `# c` + break + `A` prints as `type # c` + break + `A`
|
||||
- identical to Prettier and to `oxc_formatter`'s `const // c` + break + `a = 1`; keeping it own-line would need a column-conditional break the IR does not have
|
||||
- positions no printer claims fall back to an own-line trailing comment after the node, which may cross remaining in-span tokens (e.g. a type's `!`)
|
||||
- `flush_overlooked_inside_comments`
|
||||
- an own-line comment claimed right after a printed literal inlines on that literal's line (`write_leading_comments`)
|
||||
- positions no printer claims fall back to a trailing comment after the node, which may cross remaining in-span tokens (`flush_overlooked_inside_comments`)
|
||||
|
||||
Where Prettier relocates a comment across tokens instead, we diverge, see DIVERGENCES.md.
|
||||
|
||||
|
||||
@@ -39,6 +39,24 @@ fn write_gap(gap: &[u8], f: &mut GraphqlFormatter<'_, '_>) {
|
||||
|
||||
/// Emit comments that precede a node,
|
||||
/// preserving the source's vertical spacing (0/1/blank) between each comment and the next position.
|
||||
///
|
||||
/// NOTE: Known FORMATTER_POLICY violation ("own-line comments stay own-line"):
|
||||
/// the line break BEFORE the first comment is never reproduced,
|
||||
/// so an own-line comment claimed mid-line (right after `type`, `:`, `=`) inlines onto that line
|
||||
/// ```graphql
|
||||
/// type
|
||||
/// # c
|
||||
/// A { f: Int }
|
||||
///
|
||||
/// # ->
|
||||
///
|
||||
/// type # c
|
||||
/// A {
|
||||
/// f: Int
|
||||
/// }
|
||||
/// ```
|
||||
/// Kept for now: Prettier byte-compat outweighs the invariant
|
||||
/// (fixable in the existing IR: hardline before flushing at the claim points).
|
||||
fn write_leading_comments(comments: &[Span], value_start: u32, f: &mut GraphqlFormatter<'_, '_>) {
|
||||
let source = f.context().source_text();
|
||||
for (i, &span) in comments.iter().enumerate() {
|
||||
@@ -199,6 +217,9 @@ fn write_trailing_inside_comments<'a>(
|
||||
/// positions no printer claims (e.g. between a type and its `!`, or after the last argument's directives).
|
||||
/// Draining them here keeps the positional cursor monotonic,
|
||||
/// a later flush point would sit AFTER these comments in the source, making its gap range inverted (start > end).
|
||||
///
|
||||
/// The cost: the comments land after the node, possibly crossing remaining in-span tokens (e.g. a type's `!`).
|
||||
/// Known "never crosses user content" violation, accepted for monotonicity.
|
||||
pub fn flush_overlooked_inside_comments(upper_bound: u32, f: &mut GraphqlFormatter<'_, '_>) {
|
||||
let leftover = f.context().comments().take_before(upper_bound);
|
||||
write_trailing_inside_comments(leftover, None, f);
|
||||
|
||||
@@ -117,6 +117,20 @@ pub fn write_node<'a>(node: &'a Node<'a>, f: &mut YamlFormatter<'_, 'a>) {
|
||||
write_props(&node.props, is_block_collection && !has_middle_comments, f);
|
||||
|
||||
// Prettier: `[middles.len() == 1 ? "" : hardline, join(hardline, middles), hardline]`.
|
||||
//
|
||||
// NOTE: The single-middle case is a known FORMATTER_POLICY violation
|
||||
// ("own-line comments stay own-line"): an own-line `# c` inlines after the props
|
||||
// ```yaml
|
||||
// key: &a
|
||||
// # c
|
||||
// a: 1
|
||||
//
|
||||
// # ->
|
||||
//
|
||||
// key: &a # c
|
||||
// a: 1
|
||||
// ```
|
||||
// Kept for now: Prettier byte-compat outweighs the invariant.
|
||||
// A block collection's trailing suppression marker is NOT a middle comment:
|
||||
// it stays pending so the first item's check can claim it.
|
||||
let middles_bound = suppression_flush_bound(is_block_collection, content_start, f);
|
||||
|
||||
Reference in new issue
Block a user