From 7a901dfa3312feb93d2ce6bc5aa8aec50e75eecf Mon Sep 17 00:00:00 2001 From: Denis Bezrukov <6227442+denbezrukov@users.noreply.github.com> Date: Fri, 30 Jun 2023 16:48:55 +0300 Subject: [PATCH] feat(rome_js_formatter): Implement the decorator formatting #4608 (#4627) --- crates/rome_js_formatter/src/comments.rs | 24 +- .../src/js/bindings/formal_parameter.rs | 9 +- .../src/js/bindings/parameters.rs | 10 +- .../src/js/lists/decorator_list.rs | 58 ++- .../src/ts/bindings/property_parameter.rs | 24 +- .../src/utils/format_modifiers.rs | 2 +- crates/rome_js_formatter/tests/language.rs | 6 +- crates/rome_js_formatter/tests/quick_test.rs | 18 +- .../argument-list-preserve-line.ts.snap | 116 ----- .../typescript/decorators/decorators.ts.snap | 377 --------------- .../decorators/inline-decorators.ts.snap | 207 --------- .../tests/specs/ts/decoartors.ts | 212 +++++++++ .../tests/specs/ts/decoartors.ts.snap | 430 +++++++++++++++++- crates/rome_js_syntax/src/parameter_ext.rs | 127 +++++- crates/rome_rowan/src/ast/batch.rs | 5 +- 15 files changed, 863 insertions(+), 762 deletions(-) delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/argument-list-preserve-line.ts.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap delete mode 100644 crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap diff --git a/crates/rome_js_formatter/src/comments.rs b/crates/rome_js_formatter/src/comments.rs index e258b304f34..41e9f0bb980 100644 --- a/crates/rome_js_formatter/src/comments.rs +++ b/crates/rome_js_formatter/src/comments.rs @@ -1035,8 +1035,28 @@ fn handle_parameter_comment(comment: DecoratedComment) -> CommentPla // ) // ``` match comment.enclosing_node().kind() { - JsSyntaxKind::JS_FORMAL_PARAMETER if comment.text_position().is_own_line() => { - return CommentPlacement::leading(comment.enclosing_node().clone(), comment) + JsSyntaxKind::JS_FORMAL_PARAMETER | JsSyntaxKind::TS_PROPERTY_PARAMETER => { + // Keep decorator comments near the decorator + // Attach leading parameter comments to the last decorator + // ```javascript + // class Foo { + // method( + // //leading own line + // /*leading same line*/ @Decorator /*trailing*/ + // //leading own line between + // /*leading same line between*/ @dec //trailing + // /*leading parameter*/ + // parameter + // ) {} + // } + // ``` + if let Some(preceding_node) = comment.preceding_node() { + if comment.following_node().kind() != Some(JsSyntaxKind::JS_DECORATOR) { + return CommentPlacement::trailing(preceding_node.clone(), comment); + } + } else if comment.text_position().is_own_line() { + return CommentPlacement::leading(comment.enclosing_node().clone(), comment); + } } JsSyntaxKind::JS_INITIALIZER_CLAUSE => { if let Some(parameter) = comment diff --git a/crates/rome_js_formatter/src/js/bindings/formal_parameter.rs b/crates/rome_js_formatter/src/js/bindings/formal_parameter.rs index ced6256aecf..c1c246dfc19 100644 --- a/crates/rome_js_formatter/src/js/bindings/formal_parameter.rs +++ b/crates/rome_js_formatter/src/js/bindings/formal_parameter.rs @@ -24,7 +24,6 @@ impl FormatNodeRule for FormatJsFormalParameter { write![ f, [ - decorators.format(), binding.format(), question_mark_token.format(), type_annotation.format() @@ -40,10 +39,12 @@ impl FormatNodeRule for FormatJsFormalParameter { should_hug_function_parameters(¶meters, f.comments()).unwrap_or(false) }); - if is_hug_parameter { - write![f, [content]]?; + if is_hug_parameter && decorators.is_empty() { + write![f, [decorators.format(), content]]?; + } else if decorators.is_empty() { + write![f, [decorators.format(), group(&content)]]?; } else { - write![f, [group(&content)]]?; + write![f, [group(&decorators.format()), group(&content)]]?; } write![f, [FormatInitializerClause::new(initializer.as_ref())]] diff --git a/crates/rome_js_formatter/src/js/bindings/parameters.rs b/crates/rome_js_formatter/src/js/bindings/parameters.rs index 3f2413bd6d4..7cb79ebdc88 100644 --- a/crates/rome_js_formatter/src/js/bindings/parameters.rs +++ b/crates/rome_js_formatter/src/js/bindings/parameters.rs @@ -32,15 +32,7 @@ impl Format for FormatAnyJsParameters { fn fmt(&self, f: &mut Formatter) -> FormatResult<()> { let list = self.list(); - let has_any_decorated_parameter = list.iter().any(|node| match node { - Ok(node) => node.syntax().first_token().map_or(false, |token| { - token - .leading_trivia() - .pieces() - .any(|piece| piece.is_skipped()) - }), - Err(_) => false, - }); + let has_any_decorated_parameter = list.has_any_decorated_parameter(); let can_hug = should_hug_function_parameters(self, f.context().comments())? && !has_any_decorated_parameter; diff --git a/crates/rome_js_formatter/src/js/lists/decorator_list.rs b/crates/rome_js_formatter/src/js/lists/decorator_list.rs index e477f4a0419..5ea0bc31b87 100644 --- a/crates/rome_js_formatter/src/js/lists/decorator_list.rs +++ b/crates/rome_js_formatter/src/js/lists/decorator_list.rs @@ -1,10 +1,14 @@ use crate::prelude::*; +use crate::utils::format_modifiers::should_expand_decorators; use rome_formatter::write; -use rome_js_syntax::JsSyntaxKind::JS_CLASS_EXPRESSION; +use rome_js_syntax::JsSyntaxKind::{ + JS_CLASS_EXPRESSION, JS_FORMAL_PARAMETER, JS_REST_PARAMETER, TS_PROPERTY_PARAMETER, +}; use rome_js_syntax::{ AnyJsDeclarationClause, AnyJsExportClause, AnyJsExportDefaultDeclaration, JsDecoratorList, JsExport, }; +use rome_rowan::SyntaxNodeOptionExt; #[derive(Debug, Clone, Default)] pub(crate) struct FormatJsDecoratorList; @@ -54,10 +58,7 @@ impl FormatRule for FormatJsDecoratorList { join.finish()?; write!(f, [hard_line_break()]) - } else if matches!( - node.syntax().parent().map(|parent| parent.kind()), - Some(JS_CLASS_EXPRESSION) - ) { + } else if matches!(node.syntax().parent().kind(), Some(JS_CLASS_EXPRESSION)) { write!(f, [expand_parent()])?; f.join_with(&soft_line_break_or_space()) .entries(node.iter().formatted()) @@ -65,26 +66,39 @@ impl FormatRule for FormatJsDecoratorList { write!(f, [soft_line_break_or_space()]) } else { - // If the parent node is an export declaration and the decorator - // was written before the export, the export will be responsible - // for printing the decorators. - let export = node.syntax().grand_parent().and_then(|grand_parent| { - JsExport::cast_ref(&grand_parent) - .or_else(|| grand_parent.parent().and_then(JsExport::cast)) - }); - let is_export = export.is_some(); - - let has_decorators_before_export = - export.map_or(false, |export| !export.decorators().is_empty()); + let is_parameter_decorators = matches!( + node.syntax().parent().kind(), + Some(JS_FORMAL_PARAMETER | JS_REST_PARAMETER | TS_PROPERTY_PARAMETER) + ); - if has_decorators_before_export { - return Ok(()); - } + if is_parameter_decorators { + let should_expand = should_expand_decorators(node); - if is_export { - write!(f, [hard_line_break()])?; + if should_expand { + write!(f, [expand_parent()])?; + } } else { - write!(f, [expand_parent()])?; + // If the parent node is an export declaration and the decorator + // was written before the export, the export will be responsible + // for printing the decorators. + let export = node.syntax().grand_parent().and_then(|grand_parent| { + JsExport::cast_ref(&grand_parent) + .or_else(|| grand_parent.parent().and_then(JsExport::cast)) + }); + let is_export = export.is_some(); + + let has_decorators_before_export = + export.map_or(false, |export| !export.decorators().is_empty()); + + if has_decorators_before_export { + return Ok(()); + } + + if is_export { + write!(f, [hard_line_break()])?; + } else { + write!(f, [expand_parent()])?; + } } f.join_with(&soft_line_break_or_space()) diff --git a/crates/rome_js_formatter/src/ts/bindings/property_parameter.rs b/crates/rome_js_formatter/src/ts/bindings/property_parameter.rs index 5d19ff86461..a70b76b6657 100644 --- a/crates/rome_js_formatter/src/ts/bindings/property_parameter.rs +++ b/crates/rome_js_formatter/src/ts/bindings/property_parameter.rs @@ -14,14 +14,22 @@ impl FormatNodeRule for FormatTsPropertyParameter { formal_parameter, } = node.as_fields(); - write![ - f, - [ - decorators.format(), - modifiers.format(), - space(), - formal_parameter.format() + let content = format_with(|f| { + write![ + f, + [ + decorators.format(), + modifiers.format(), + space(), + formal_parameter.format() + ] ] - ] + }); + + if decorators.is_empty() { + write![f, [content]] + } else { + write![f, [group(&content)]] + } } } diff --git a/crates/rome_js_formatter/src/utils/format_modifiers.rs b/crates/rome_js_formatter/src/utils/format_modifiers.rs index d8a965875d3..a48aa4057a3 100644 --- a/crates/rome_js_formatter/src/utils/format_modifiers.rs +++ b/crates/rome_js_formatter/src/utils/format_modifiers.rs @@ -62,7 +62,7 @@ where } /// This function expands decorators enclosing a group if there is a newline between decorators or after the last decorator. -fn should_expand_decorators(list: &List) -> bool +pub(crate) fn should_expand_decorators(list: &List) -> bool where Node: AstNode, List: AstNodeList, diff --git a/crates/rome_js_formatter/tests/language.rs b/crates/rome_js_formatter/tests/language.rs index d7529ce2df7..d3b0a3fa4e8 100644 --- a/crates/rome_js_formatter/tests/language.rs +++ b/crates/rome_js_formatter/tests/language.rs @@ -29,7 +29,11 @@ impl TestFormatLanguage for JsTestFormatLanguage { type FormatLanguage = JsFormatLanguage; fn parse(&self, text: &str) -> AnyParse { - let parse = parse(text, self.source_type, JsParserOptions::default()); + let parse = parse( + text, + self.source_type, + JsParserOptions::default().with_parse_class_parameter_decorators(), + ); AnyParse::new( parse.syntax().as_send().unwrap(), diff --git a/crates/rome_js_formatter/tests/quick_test.rs b/crates/rome_js_formatter/tests/quick_test.rs index 08886ec3daf..534245dadb1 100644 --- a/crates/rome_js_formatter/tests/quick_test.rs +++ b/crates/rome_js_formatter/tests/quick_test.rs @@ -13,12 +13,22 @@ mod language { // use this test check if your snippet prints as you wish, without using a snapshot fn quick_test() { let src = r#" - class A { constructor(private x, protected y, public z) {} } - class B { constructor(readonly w, private readonly x, protected readonly y, public readonly z) {} } - class C { constructor(private x: string, readonly y?, z = "default", ...rest) {} } +class Foo { + constructor( + @dec + /*leading parameter*/ private parameter + ) { } + } + + "#; let syntax = JsFileSource::tsx(); - let tree = parse(src, syntax, JsParserOptions::default()); + let tree = parse( + src, + syntax, + JsParserOptions::default().with_parse_class_parameter_decorators(), + ); + dbg!(tree.syntax()); let options = JsFormatOptions::new(syntax) .with_semicolons(Semicolons::AsNeeded) .with_quote_style(QuoteStyle::Double) diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/argument-list-preserve-line.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/argument-list-preserve-line.ts.snap deleted file mode 100644 index d1befc3d1eb..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/argument-list-preserve-line.ts.snap +++ /dev/null @@ -1,116 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: typescript/decorators/argument-list-preserve-line.ts ---- - -# Input - -```ts -class Foo { - constructor( - @inject(Bar) - private readonly bar: IBar, - - @inject(MyProcessor) - private readonly myProcessor: IMyProcessor, - - @inject(InjectionTypes.AnotherThing) - - private readonly anotherThing: IAnotherThing | undefined, - ) { } -} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,12 +1,13 @@ - class Foo { - constructor( -- @inject(Bar) -- private readonly bar: IBar, -+ @inject(Bar) -+ private readonly bar: IBar, - -- @inject(MyProcessor) -- private readonly myProcessor: IMyProcessor, -+ @inject(MyProcessor) -+ private readonly myProcessor: IMyProcessor, - -- @inject(InjectionTypes.AnotherThing) -- private readonly anotherThing: IAnotherThing | undefined, -- ) {} -+ @inject(InjectionTypes.AnotherThing) -+ -+ private readonly anotherThing: IAnotherThing | undefined, -+ ) { } - } -``` - -# Output - -```ts -class Foo { - constructor( - @inject(Bar) - private readonly bar: IBar, - - @inject(MyProcessor) - private readonly myProcessor: IMyProcessor, - - @inject(InjectionTypes.AnotherThing) - - private readonly anotherThing: IAnotherThing | undefined, - ) { } -} -``` - -# Errors -``` -argument-list-preserve-line.ts:3:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 1 │ class Foo { - 2 │ constructor( - > 3 │ @inject(Bar) - │ ^^^^^^^^^^^^ - 4 │ private readonly bar: IBar, - 5 │ - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -argument-list-preserve-line.ts:6:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 4 │ private readonly bar: IBar, - 5 │ - > 6 │ @inject(MyProcessor) - │ ^^^^^^^^^^^^^^^^^^^^ - 7 │ private readonly myProcessor: IMyProcessor, - 8 │ - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -argument-list-preserve-line.ts:9:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 7 │ private readonly myProcessor: IMyProcessor, - 8 │ - > 9 │ @inject(InjectionTypes.AnotherThing) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 10 │ - 11 │ private readonly anotherThing: IAnotherThing | undefined, - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - - -``` - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap deleted file mode 100644 index b1bf9f78fb6..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/decorators.ts.snap +++ /dev/null @@ -1,377 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: typescript/decorators/decorators.ts ---- - -# Input - -```ts -export class TestTextFileService { - constructor( - @ILifecycleService lifecycleService, - ) { - } -} - -@commonEditorContribution -export class TabCompletionController { -} - -@Component({ - selector: 'angular-component', -}) -class AngularComponent { - @Input() myInput: string; -} - -class Class { - method( - @Decorator - { prop1, prop2 }: Type - ) { - doSomething(); - } -} - -class Class2 { - method( - @Decorator1 - @Decorator2 - { prop1, prop2 }: Type - ) { - doSomething(); - } -} - -class Class3 { - method( - @Decorator - { prop1_1, prop1_2 }: Type, - { prop2_1, prop2_2 }: Type - ) { - doSomething(); - } -} - -class Class4 { - method( - param1, - @Decorator - { prop1, prop2 }: Type - ) {} -} - -class Class5 { - method( - @Decorator { prop1 }: Type - ) {} -} - -class Class6 { - method( - @Decorator({}) { prop1 }: Type - ) {} - method( - @Decorator( - {}) { prop1 }: Type - ) {} - method( - @Decorator([]) { prop1 }: Type - ) {} - method( - @Decorator( - []) { prop1 }: Type - ) {} -} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -1,5 +1,8 @@ - export class TestTextFileService { -- constructor(@ILifecycleService lifecycleService) {} -+ constructor( -+ @ILifecycleService lifecycleService, -+ ) { -+ } - } - - @commonEditorContribution -@@ -15,7 +18,7 @@ - class Class { - method( - @Decorator -- { prop1, prop2 }: Type, -+ { prop1, prop2 }: Type - ) { - doSomething(); - } -@@ -25,7 +28,7 @@ - method( - @Decorator1 - @Decorator2 -- { prop1, prop2 }: Type, -+ { prop1, prop2 }: Type - ) { - doSomething(); - } -@@ -50,12 +53,24 @@ - } - - class Class5 { -- method(@Decorator { prop1 }: Type) {} -+ method( -+ @Decorator { prop1 }: Type -+ ) {} - } - - class Class6 { -- method(@Decorator({}) { prop1 }: Type) {} -- method(@Decorator({}) { prop1 }: Type) {} -- method(@Decorator([]) { prop1 }: Type) {} -- method(@Decorator([]) { prop1 }: Type) {} -+ method( -+ @Decorator({}) { prop1 }: Type -+ ) {} -+ method( -+ @Decorator( -+ {}) { prop1 }: Type -+ ) {} -+ method( -+ @Decorator([]) { prop1 }: Type -+ ) {} -+ method( -+ @Decorator( -+ []) { prop1 }: Type -+ ) {} - } -``` - -# Output - -```ts -export class TestTextFileService { - constructor( - @ILifecycleService lifecycleService, - ) { - } -} - -@commonEditorContribution -export class TabCompletionController {} - -@Component({ - selector: "angular-component", -}) -class AngularComponent { - @Input() myInput: string; -} - -class Class { - method( - @Decorator - { prop1, prop2 }: Type - ) { - doSomething(); - } -} - -class Class2 { - method( - @Decorator1 - @Decorator2 - { prop1, prop2 }: Type - ) { - doSomething(); - } -} - -class Class3 { - method( - @Decorator - { prop1_1, prop1_2 }: Type, - { prop2_1, prop2_2 }: Type, - ) { - doSomething(); - } -} - -class Class4 { - method( - param1, - @Decorator - { prop1, prop2 }: Type, - ) {} -} - -class Class5 { - method( - @Decorator { prop1 }: Type - ) {} -} - -class Class6 { - method( - @Decorator({}) { prop1 }: Type - ) {} - method( - @Decorator( - {}) { prop1 }: Type - ) {} - method( - @Decorator([]) { prop1 }: Type - ) {} - method( - @Decorator( - []) { prop1 }: Type - ) {} -} -``` - -# Errors -``` -decorators.ts:3:3 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 1 │ export class TestTextFileService { - 2 │ constructor( - > 3 │ @ILifecycleService lifecycleService, - │ ^^^^^^^^^^^^^^^^^^ - 4 │ ) { - 5 │ } - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:21:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 19 │ class Class { - 20 │ method( - > 21 │ @Decorator - │ ^^^^^^^^^^ - 22 │ { prop1, prop2 }: Type - 23 │ ) { - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:30:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 28 │ class Class2 { - 29 │ method( - > 30 │ @Decorator1 - │ ^^^^^^^^^^^ - > 31 │ @Decorator2 - │ ^^^^^^^^^^^ - 32 │ { prop1, prop2 }: Type - 33 │ ) { - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:40:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 38 │ class Class3 { - 39 │ method( - > 40 │ @Decorator - │ ^^^^^^^^^^ - 41 │ { prop1_1, prop1_2 }: Type, - 42 │ { prop2_1, prop2_2 }: Type - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:51:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 49 │ method( - 50 │ param1, - > 51 │ @Decorator - │ ^^^^^^^^^^ - 52 │ { prop1, prop2 }: Type - 53 │ ) {} - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:58:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 56 │ class Class5 { - 57 │ method( - > 58 │ @Decorator { prop1 }: Type - │ ^^^^^^^^^^ - 59 │ ) {} - 60 │ } - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:64:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 62 │ class Class6 { - 63 │ method( - > 64 │ @Decorator({}) { prop1 }: Type - │ ^^^^^^^^^^^^^^ - 65 │ ) {} - 66 │ method( - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:67:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 65 │ ) {} - 66 │ method( - > 67 │ @Decorator( - │ ^^^^^^^^^^^ - > 68 │ {}) { prop1 }: Type - │ ^^^ - 69 │ ) {} - 70 │ method( - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:71:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 69 │ ) {} - 70 │ method( - > 71 │ @Decorator([]) { prop1 }: Type - │ ^^^^^^^^^^^^^^ - 72 │ ) {} - 73 │ method( - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -decorators.ts:74:5 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 72 │ ) {} - 73 │ method( - > 74 │ @Decorator( - │ ^^^^^^^^^^^ - > 75 │ []) { prop1 }: Type - │ ^^^ - 76 │ ) {} - 77 │ } - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - - -``` - - diff --git a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap b/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap deleted file mode 100644 index c968149bbb4..00000000000 --- a/crates/rome_js_formatter/tests/specs/prettier/typescript/decorators/inline-decorators.ts.snap +++ /dev/null @@ -1,207 +0,0 @@ ---- -source: crates/rome_formatter_test/src/snapshot_builder.rs -info: typescript/decorators/inline-decorators.ts ---- - -# Input - -```ts - -@d1 -@d2(foo) -@d3.bar -@d4.baz() -class Class1 {} - -class Class2 { - @d1 - @d2(foo) - @d3.bar - @d4.baz() - method1() {} - - @d1 - method2() {} - - @d2(foo) - method3() {} - - @d3.bar - method4() {} -} - -class Class3 { - @d1 fieldA; - @d2(foo) fieldB; - @d3.bar fieldC; - @d4.baz() fieldD; - - constructor ( - @d1 private x: number, - @d2(foo) private y: number, - @d3('foo') private z: number, - @d4({ - x: string - }) private a: string, - ) {} -} - -@decorated class Foo {} - -class Bar { - @decorated method() {} -} - -class MyContainerComponent { - @ContentChildren(MyComponent) components: QueryListSomeBigName; -} - -``` - - -# Prettier differences - -```diff ---- Prettier -+++ Rome -@@ -27,15 +27,14 @@ - @d3.bar fieldC; - @d4.baz() fieldD; - -- constructor( -- @d1 private x: number, -- @d2(foo) private y: number, -- @d3("foo") private z: number, -- @d4({ -- x: string, -- }) -- private a: string, -- ) {} -+ constructor ( -+ @d1 private x: number, -+ @d2(foo) private y: number, -+ @d3('foo') private z: number, -+ @d4({ -+ x: string -+ }) private a: string, -+ ) {} - } - - @decorated -``` - -# Output - -```ts -@d1 -@d2(foo) -@d3.bar -@d4.baz() -class Class1 {} - -class Class2 { - @d1 - @d2(foo) - @d3.bar - @d4.baz() - method1() {} - - @d1 - method2() {} - - @d2(foo) - method3() {} - - @d3.bar - method4() {} -} - -class Class3 { - @d1 fieldA; - @d2(foo) fieldB; - @d3.bar fieldC; - @d4.baz() fieldD; - - constructor ( - @d1 private x: number, - @d2(foo) private y: number, - @d3('foo') private z: number, - @d4({ - x: string - }) private a: string, - ) {} -} - -@decorated -class Foo {} - -class Bar { - @decorated method() {} -} - -class MyContainerComponent { - @ContentChildren(MyComponent) - components: QueryListSomeBigName; -} -``` - -# Errors -``` -inline-decorators.ts:32:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 31 │ constructor ( - > 32 │ @d1 private x: number, - │ ^^^ - 33 │ @d2(foo) private y: number, - 34 │ @d3('foo') private z: number, - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -inline-decorators.ts:33:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 31 │ constructor ( - 32 │ @d1 private x: number, - > 33 │ @d2(foo) private y: number, - │ ^^^^^^^^ - 34 │ @d3('foo') private z: number, - 35 │ @d4({ - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -inline-decorators.ts:34:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 32 │ @d1 private x: number, - 33 │ @d2(foo) private y: number, - > 34 │ @d3('foo') private z: number, - │ ^^^^^^^^^^ - 35 │ @d4({ - 36 │ x: string - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - -inline-decorators.ts:35:9 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - × Decorators are not valid here. - - 33 │ @d2(foo) private y: number, - 34 │ @d3('foo') private z: number, - > 35 │ @d4({ - │ ^^^^^ - > 36 │ x: string - > 37 │ }) private a: string, - │ ^^ - 38 │ ) {} - 39 │ } - - i You can enable parameter decorators by setting the `unsafeParameterDecoratorsEnabled` option to `true` in your configuration file. - - -``` - - diff --git a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts index 740968e53a4..00fa44e18ab 100644 --- a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts +++ b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts @@ -44,3 +44,215 @@ class Test2 { } +class Foo { + constructor( + @inject(Bar) + private readonly bar: IBar, + + @inject(MyProcessor) + private readonly myProcessor: IMyProcessor, + + @inject(InjectionTypes.AnotherThing) + + private readonly anotherThing: IAnotherThing | undefined, + ) { } +} + +export class TestTextFileService { + constructor( + @ILifecycleService lifecycleService, + ) { + } +} + +@commonEditorContribution +export class TabCompletionController { +} + +@Component({ + selector: 'angular-component', +}) +class AngularComponent { + @Input() myInput: string; +} + +class Class { + method( + @Decorator + { prop1, prop2 }: Type + ) { + doSomething(); + } +} + +class Class2 { + method( + @Decorator1 + @Decorator2 + { prop1, prop2 }: Type + ) { + doSomething(); + } +} + +class Class3 { + method( + @Decorator + { prop1_1, prop1_2 }: Type, + { prop2_1, prop2_2 }: Type + ) { + doSomething(); + } +} + +class Class4 { + method( + param1, + @Decorator + { prop1, prop2 }: Type + ) {} +} + +class Class5 { + method( + @Decorator { prop1 }: Type + ) {} +} + +class Class6 { + method( + @Decorator({}) { prop1 }: Type + ) {} + method( + @Decorator( + {}) { prop1 }: Type + ) {} + method( + @Decorator([]) { prop1 }: Type + ) {} + method( + @Decorator( + []) { prop1 }: Type + ) {} +} + + +@d1 +@d2(foo) +@d3.bar +@d4.baz() +class Class1 {} + +class Class2 { + @d1 + @d2(foo) + @d3.bar + @d4.baz() + method1() {} + + @d1 + method2() {} + + @d2(foo) + method3() {} + + @d3.bar + method4() {} +} + +class Class3 { + @d1 fieldA; + @d2(foo) fieldB; + @d3.bar fieldC; + @d4.baz() fieldD; + + constructor ( + @d1 private x: number, + @d2(foo) private y: number, + @d3('foo') private z: number, + @d4({ + x: string + }) private a: string, + ) {} +} + +@decorated class Foo {} + +class Bar { + @decorated method() {} +} + +class MyContainerComponent { + @ContentChildren(MyComponent) components: QueryListSomeBigName; +} + +@sealed +class Test { + @readonly + prop: string; + + constructor(@param test, @readonly private other, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last) {} + + method(@param a) {} + + get getter() {} + + set setter(@param param) {} +} + +class Class4 { + method( + @Decorator + { prop1_1, prop1_2 }: Type = {}, + { prop2_1, prop2_2 }: Type + ) { + doSomething(); + } +} + +class Class { + method(@aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) { + + } +} + + +class Class2 { + constructor(@param test, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) {} + + method(@aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) { + + } +} + +class Class3 { + constructor ( + private aaaaaaaaaaaaaaaaa: {aaaaaaaaaaaaa: number; bbbbbbbbbbb: string; cccccccccccc: Type}, + @d1 private readonly x: number, + @d2(foo) private y: number, + @d3('foo') private z: number, + + ) {} + +} + +// comments +class Foo { + constructor( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter: number + ) {} + + method( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter + ) {} +} diff --git a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap index 08b036fe391..986a2e91535 100644 --- a/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap +++ b/crates/rome_js_formatter/tests/specs/ts/decoartors.ts.snap @@ -52,6 +52,218 @@ class Test2 { } +class Foo { + constructor( + @inject(Bar) + private readonly bar: IBar, + + @inject(MyProcessor) + private readonly myProcessor: IMyProcessor, + + @inject(InjectionTypes.AnotherThing) + + private readonly anotherThing: IAnotherThing | undefined, + ) { } +} + +export class TestTextFileService { + constructor( + @ILifecycleService lifecycleService, + ) { + } +} + +@commonEditorContribution +export class TabCompletionController { +} + +@Component({ + selector: 'angular-component', +}) +class AngularComponent { + @Input() myInput: string; +} + +class Class { + method( + @Decorator + { prop1, prop2 }: Type + ) { + doSomething(); + } +} + +class Class2 { + method( + @Decorator1 + @Decorator2 + { prop1, prop2 }: Type + ) { + doSomething(); + } +} + +class Class3 { + method( + @Decorator + { prop1_1, prop1_2 }: Type, + { prop2_1, prop2_2 }: Type + ) { + doSomething(); + } +} + +class Class4 { + method( + param1, + @Decorator + { prop1, prop2 }: Type + ) {} +} + +class Class5 { + method( + @Decorator { prop1 }: Type + ) {} +} + +class Class6 { + method( + @Decorator({}) { prop1 }: Type + ) {} + method( + @Decorator( + {}) { prop1 }: Type + ) {} + method( + @Decorator([]) { prop1 }: Type + ) {} + method( + @Decorator( + []) { prop1 }: Type + ) {} +} + + +@d1 +@d2(foo) +@d3.bar +@d4.baz() +class Class1 {} + +class Class2 { + @d1 + @d2(foo) + @d3.bar + @d4.baz() + method1() {} + + @d1 + method2() {} + + @d2(foo) + method3() {} + + @d3.bar + method4() {} +} + +class Class3 { + @d1 fieldA; + @d2(foo) fieldB; + @d3.bar fieldC; + @d4.baz() fieldD; + + constructor ( + @d1 private x: number, + @d2(foo) private y: number, + @d3('foo') private z: number, + @d4({ + x: string + }) private a: string, + ) {} +} + +@decorated class Foo {} + +class Bar { + @decorated method() {} +} + +class MyContainerComponent { + @ContentChildren(MyComponent) components: QueryListSomeBigName; +} + +@sealed +class Test { + @readonly + prop: string; + + constructor(@param test, @readonly private other, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last) {} + + method(@param a) {} + + get getter() {} + + set setter(@param param) {} +} + +class Class4 { + method( + @Decorator + { prop1_1, prop1_2 }: Type = {}, + { prop2_1, prop2_2 }: Type + ) { + doSomething(); + } +} + +class Class { + method(@aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) { + + } +} + + +class Class2 { + constructor(@param test, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) {} + + method(@aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, @d2(foo) y: number,) { + + } +} + +class Class3 { + constructor ( + private aaaaaaaaaaaaaaaaa: {aaaaaaaaaaaaa: number; bbbbbbbbbbb: string; cccccccccccc: Type}, + @d1 private readonly x: number, + @d2(foo) private y: number, + @d3('foo') private z: number, + + ) {} + +} + +// comments +class Foo { + constructor( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter: number + ) {} + + method( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter + ) {} +} ``` @@ -78,7 +290,11 @@ class Test { @readonly prop: string; - constructor(@param test, @readonly private other, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last) {} + constructor( + @param test, + @readonly private other, + @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, + ) {} method(@param a) {} @@ -107,11 +323,215 @@ class Test2 { // leading comment prop: string; } -``` -# Lines exceeding max width of 80 characters -``` - 6: constructor(@param test, @readonly private other, @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last) {} +class Foo { + constructor( + @inject(Bar) + private readonly bar: IBar, + + @inject(MyProcessor) + private readonly myProcessor: IMyProcessor, + + @inject(InjectionTypes.AnotherThing) + private readonly anotherThing: IAnotherThing | undefined, + ) {} +} + +export class TestTextFileService { + constructor(@ILifecycleService lifecycleService) {} +} + +@commonEditorContribution +export class TabCompletionController {} + +@Component({ + selector: "angular-component", +}) +class AngularComponent { + @Input() myInput: string; +} + +class Class { + method( + @Decorator + { prop1, prop2 }: Type, + ) { + doSomething(); + } +} + +class Class2 { + method( + @Decorator1 + @Decorator2 + { prop1, prop2 }: Type, + ) { + doSomething(); + } +} + +class Class3 { + method( + @Decorator + { prop1_1, prop1_2 }: Type, + { prop2_1, prop2_2 }: Type, + ) { + doSomething(); + } +} + +class Class4 { + method( + param1, + @Decorator + { prop1, prop2 }: Type, + ) {} +} + +class Class5 { + method(@Decorator { prop1 }: Type) {} +} + +class Class6 { + method(@Decorator({}) { prop1 }: Type) {} + method(@Decorator({}) { prop1 }: Type) {} + method(@Decorator([]) { prop1 }: Type) {} + method(@Decorator([]) { prop1 }: Type) {} +} + +@d1 +@d2(foo) +@d3.bar +@d4.baz() +class Class1 {} + +class Class2 { + @d1 + @d2(foo) + @d3.bar + @d4.baz() + method1() {} + + @d1 + method2() {} + + @d2(foo) + method3() {} + + @d3.bar + method4() {} +} + +class Class3 { + @d1 fieldA; + @d2(foo) fieldB; + @d3.bar fieldC; + @d4.baz() fieldD; + + constructor( + @d1 private x: number, + @d2(foo) private y: number, + @d3("foo") private z: number, + @d4({ + x: string, + }) + private a: string, + ) {} +} + +@decorated +class Foo {} + +class Bar { + @decorated method() {} +} + +class MyContainerComponent { + @ContentChildren(MyComponent) + components: QueryListSomeBigName; +} + +@sealed +class Test { + @readonly + prop: string; + + constructor( + @param test, + @readonly private other, + @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, + ) {} + + method(@param a) {} + + get getter() {} + + set setter(@param param) {} +} + +class Class4 { + method( + @Decorator + { prop1_1, prop1_2 }: Type = {}, + { prop2_1, prop2_2 }: Type, + ) { + doSomething(); + } +} + +class Class { + method( + @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, + @d2(foo) y: number, + ) {} +} + +class Class2 { + constructor( + @param test, + @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, + @d2(foo) y: number, + ) {} + + method( + @aVeryLongDecoratorNameLetsSeeWhatHappensWithIt last, + @d2(foo) y: number, + ) {} +} + +class Class3 { + constructor( + private aaaaaaaaaaaaaaaaa: { + aaaaaaaaaaaaa: number; + bbbbbbbbbbb: string; + cccccccccccc: Type; + }, + @d1 private readonly x: number, + @d2(foo) private y: number, + @d3("foo") private z: number, + ) {} +} + +// comments +class Foo { + constructor( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter: number, + ) {} + + method( + //leading own line + /*leading same line*/ @Decorator /*trailing*/ + //leading own line between + /*leading same line between*/ @dec //trailing + /*leading parameter*/ + parameter, + ) {} +} ``` diff --git a/crates/rome_js_syntax/src/parameter_ext.rs b/crates/rome_js_syntax/src/parameter_ext.rs index d343b28ea83..93a659f5203 100644 --- a/crates/rome_js_syntax/src/parameter_ext.rs +++ b/crates/rome_js_syntax/src/parameter_ext.rs @@ -1,9 +1,10 @@ use crate::{ - AnyJsBindingPattern, AnyJsConstructorParameter, AnyJsParameter, JsConstructorParameterList, - JsConstructorParameters, JsLanguage, JsParameterList, JsParameters, + AnyJsBindingPattern, AnyJsConstructorParameter, AnyJsFormalParameter, AnyJsParameter, + JsConstructorParameterList, JsConstructorParameters, JsDecoratorList, JsLanguage, + JsParameterList, JsParameters, }; use rome_rowan::{ - declare_node_union, AstSeparatedList, AstSeparatedListNodesIterator, SyntaxResult, + declare_node_union, AstNodeList, AstSeparatedList, AstSeparatedListNodesIterator, SyntaxResult, }; /// An enumeration representing different types of JavaScript/TypeScript parameter lists. @@ -342,6 +343,80 @@ impl AnyJsParameterList { } }) } + + /// + /// This method checks if any parameters in the given list are decorated. + /// + /// # Examples + /// + /// ``` + /// use rome_js_factory::make; + /// use rome_js_syntax::parameter_ext::{AnyJsParameterList, AnyParameter}; + /// use rome_js_syntax::{ + /// AnyJsBinding, AnyJsBindingPattern, AnyJsConstructorParameter, AnyJsDecorator, + /// AnyJsFormalParameter, AnyJsParameter, T, + /// }; + /// use rome_rowan::SyntaxResult; + /// + /// let parameter_list = make::js_parameter_list( + /// Some(AnyJsParameter::AnyJsFormalParameter( + /// AnyJsFormalParameter::JsFormalParameter( + /// make::js_formal_parameter( + /// make::js_decorator_list(std::iter::empty()), + /// AnyJsBindingPattern::AnyJsBinding(AnyJsBinding::JsIdentifierBinding( + /// make::js_identifier_binding(make::ident("param1")), + /// )), + /// ) + /// .build(), + /// ), + /// )), + /// None, + /// ); + /// + /// let params = AnyJsParameterList::JsParameterList(parameter_list); + /// let has_any_decorated_parameter = params.has_any_decorated_parameter(); + /// assert_eq!(has_any_decorated_parameter, false); + /// + /// let decorator = make::js_decorator( + /// make::token(T![@]), + /// AnyJsDecorator::JsIdentifierExpression(make::js_identifier_expression( + /// make::js_reference_identifier(make::ident("decorator")), + /// )), + /// ); + /// let parameter_list = make::js_parameter_list( + /// Some(AnyJsParameter::AnyJsFormalParameter( + /// AnyJsFormalParameter::JsFormalParameter( + /// make::js_formal_parameter( + /// make::js_decorator_list(Some(decorator)), + /// AnyJsBindingPattern::AnyJsBinding(AnyJsBinding::JsIdentifierBinding( + /// make::js_identifier_binding(make::ident("param1")), + /// )), + /// ) + /// .build(), + /// ), + /// )), + /// None, + /// ); + /// + /// let params = AnyJsParameterList::JsParameterList(parameter_list); + /// let has_any_decorated_parameter = params.has_any_decorated_parameter(); + /// assert_eq!(has_any_decorated_parameter, true); + /// ``` + /// + /// # Returns + /// + /// Returns `true` if the list contains any decorated parameters. + /// + pub fn has_any_decorated_parameter(&self) -> bool { + self.iter().any(|parameter| { + parameter.map_or(false, |parameter| match parameter { + AnyParameter::AnyJsConstructorParameter(parameter) => { + parameter.has_any_decorated_parameter() + } + AnyParameter::AnyJsParameter(parameter) => parameter.has_any_decorated_parameter(), + }) + }) + } } /// An iterator over the parameters in an `AnyJsParameterList`. @@ -410,3 +485,49 @@ declare_node_union! { /// function could accept either type of parameters. pub AnyJsParameters = JsParameters | JsConstructorParameters } + +impl AnyJsConstructorParameter { + /// This method returns a list of decorators for a parameter if it exists. + pub fn decorators(&self) -> Option { + match self { + AnyJsConstructorParameter::AnyJsFormalParameter(parameter) => parameter.decorators(), + AnyJsConstructorParameter::JsRestParameter(parameter) => Some(parameter.decorators()), + AnyJsConstructorParameter::TsPropertyParameter(parameter) => { + Some(parameter.decorators()) + } + } + } + + /// This method checks if any parameters in the given list are decorated. + pub fn has_any_decorated_parameter(&self) -> bool { + self.decorators() + .map_or(false, |decorators| !decorators.is_empty()) + } +} + +impl AnyJsParameter { + /// This method returns a list of decorators for a parameter if it exists. + pub fn decorators(&self) -> Option { + match self { + AnyJsParameter::AnyJsFormalParameter(parameter) => parameter.decorators(), + AnyJsParameter::JsRestParameter(parameter) => Some(parameter.decorators()), + AnyJsParameter::TsThisParameter(_) => None, + } + } + + /// This method checks if any parameters in the given list are decorated. + pub fn has_any_decorated_parameter(&self) -> bool { + self.decorators() + .map_or(false, |decorators| !decorators.is_empty()) + } +} + +impl AnyJsFormalParameter { + /// This method returns a list of decorators for a parameter if it exists. + pub fn decorators(&self) -> Option { + match self { + AnyJsFormalParameter::JsBogusParameter(_) => None, + AnyJsFormalParameter::JsFormalParameter(parameter) => Some(parameter.decorators()), + } + } +} diff --git a/crates/rome_rowan/src/ast/batch.rs b/crates/rome_rowan/src/ast/batch.rs index 08303b82d60..e8280c74f75 100644 --- a/crates/rome_rowan/src/ast/batch.rs +++ b/crates/rome_rowan/src/ast/batch.rs @@ -9,7 +9,6 @@ use std::{ collections::BinaryHeap, iter::{empty, once}, }; -use tracing::debug; pub trait BatchMutationExt: AstNode where @@ -291,7 +290,7 @@ where }); let parent_depth = parent.as_ref().map(|p| p.ancestors().count()).unwrap_or(0); - debug!("pushing change..."); + tracing::debug!("pushing change..."); self.changes.push(CommitChange { parent_depth, parent, @@ -307,7 +306,7 @@ where pub fn as_text_edits(&self) -> Option<(TextRange, TextEdit)> { let mut range = None; - debug!(" changes {:?}", &self.changes); + tracing::debug!(" changes {:?}", &self.changes); for change in &self.changes { let parent = change.parent.as_ref().unwrap_or(&self.root);