From 6d1de52a24efafa8bf33faea09eb5f92b3672b84 Mon Sep 17 00:00:00 2001 From: eggnstone Date: Sun, 21 Jul 2024 13:57:01 +0200 Subject: [PATCH] Added PropertyAccessFormatter. --- TODO.txt | 15 ++++---- lib/src/FormatVisitor.dart | 4 ++- .../Formatters/ClassDeclarationFormatter.dart | 8 ++--- .../Formatters/ImportDirectiveFormatter.dart | 8 ++--- .../Formatters/MethodInvocationFormatter.dart | 12 ++++--- .../Formatters/PropertyAccessFormatter.dart | 36 +++++++++++++++++++ .../PropertyAccessFormatter_test.dart | 33 +++++++++++++++++ ...bleDeclarationFormatter_test.disabled.dart | 7 ++-- 8 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 lib/src/Formatters/PropertyAccessFormatter.dart create mode 100644 test/Formatters/PropertyAccessFormatter_test.dart diff --git a/TODO.txt b/TODO.txt index cb557d0..6234ac2 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,25 +6,26 @@ TODO -- e.g. . -- e.g. offset < lastConsumedPosition - favicon.ico does not work when called from plugin. -- integration tests for indentation=-1 -- integration tests for maxEmptyLines +- Integration tests for indentation=-1 +- Integration tests for maxEmptyLines - maxEmptyLines can only work when removeLeadingWhitespace does not already remove all empty lines. -- tests for FormalParameterListFormatter, ... (test preservation/removal of trailing comma) +- Tests for FormalParameterListFormatter, ... (test preservation/removal of trailing comma) - Block comments: keep indentation - Own lint rule: don't return Futures in a try-catch block. - Own lint rule: don't call unawaited stuff in a try-catch block. - Own lint rule: don't return Futures. -- ensure DEBUG is off when publishing -- safety: don't accept result if length is 0 or very short, e.g. when throwing UnimplementedError in StringTools. +- Ensure DEBUG is off when publishing +- Safety: don't accept result if length is 0 or very short, e.g. when throwing UnimplementedError in StringTools. - No blank lines between {{ and }} - No blank line after { and before } - Investigate line endings. Keep existing style, but also offer option to convert. +- No more than maxEmptyLines blank lines at file end. DONE (I think) ============== - Method params: indent when multiline with "(" and "({" - WebService: Shut down if calling process dies. -- quit doesn't work anymore -- simplify TestAstVisitor +- Quit doesn't work anymore +- Simplify TestAstVisitor - Don't add line break between "}" and ";" - Don't add line break between "}" and "," diff --git a/lib/src/FormatVisitor.dart b/lib/src/FormatVisitor.dart index 61f2949..0d9b5e8 100644 --- a/lib/src/FormatVisitor.dart +++ b/lib/src/FormatVisitor.dart @@ -54,6 +54,7 @@ import 'Formatters/PartDirectiveFormatter.dart'; import 'Formatters/PartOfDirectiveFormatter.dart'; import 'Formatters/PatternVariableDeclarationStatementFormatter.dart'; import 'Formatters/PrefixedIdentifierFormatter.dart'; +import 'Formatters/PropertyAccessFormatter.dart'; import 'Formatters/RecordLiteralFormatter.dart'; import 'Formatters/RecordPatternFormatter.dart'; import 'Formatters/RecordTypeAnnotationFormatter.dart'; @@ -130,6 +131,7 @@ class FormatVisitor extends AstVisitor late final PartOfDirectiveFormatter _partOfDirectiveFormatter = PartOfDirectiveFormatter(config, this, _formatState); late final PatternVariableDeclarationStatementFormatter _patternVariableDeclarationStatementFormatter = PatternVariableDeclarationStatementFormatter(config, this, _formatState); late final PrefixedIdentifierFormatter _prefixedIdentifierFormatter = PrefixedIdentifierFormatter(config, this, _formatState); + late final PropertyAccessFormatter _propertyAccessFormatter = PropertyAccessFormatter(config, this, _formatState); late final RecordLiteralFormatter _recordLiteralFormatter = RecordLiteralFormatter(config, this, _formatState); late final RecordPatternFormatter _recordPatternFormatter = RecordPatternFormatter(config, this, _formatState); late final RecordTypeAnnotationFormatter _recordTypeAnnotationFormatter = RecordTypeAnnotationFormatter(config, this, _formatState); @@ -647,7 +649,7 @@ class FormatVisitor extends AstVisitor @override void visitPropertyAccess(PropertyAccess node) - => _defaultFormatter.format(node); + => _propertyAccessFormatter.format(node); @override void visitRecordLiteral(RecordLiteral node) diff --git a/lib/src/Formatters/ClassDeclarationFormatter.dart b/lib/src/Formatters/ClassDeclarationFormatter.dart index 7f2fe03..b283a9b 100644 --- a/lib/src/Formatters/ClassDeclarationFormatter.dart +++ b/lib/src/Formatters/ClassDeclarationFormatter.dart @@ -25,8 +25,8 @@ class ClassDeclarationFormatter extends IFormatter if (node is! ClassDeclaration) throw FormatException('Not a ClassDeclaration: ${node.runtimeType}'); - final String textWithPossibleLineBreak = formatState.getText(node.classKeyword.offset, node.leftBracket.offset); - final bool pushLevel = textWithPossibleLineBreak.contains('\n'); + //final String textWithPossibleLineBreak = formatState.getText(node.classKeyword.offset, node.leftBracket.offset); + //final bool pushLevel = true;//textWithPossibleLineBreak.contains('\n'); formatState.acceptList(node.sortedCommentAndAnnotations, astVisitor, '$methodName/node.sortedCommentAndAnnotations'); formatState.copyEntity(node.sealedKeyword, astVisitor, '$methodName/node.abstractKeyword'); @@ -37,7 +37,7 @@ class ClassDeclarationFormatter extends IFormatter formatState.copyEntity(node.finalKeyword, astVisitor, '$methodName/node.finalKeyword'); formatState.copyEntity(node.classKeyword, astVisitor, '$methodName/node.classKeyword'); - if (pushLevel) + //if (pushLevel) formatState.pushLevel('$methodName/node.classKeyword/after'); formatState.copyEntity(node.name, astVisitor, '$methodName/node.name'); @@ -46,7 +46,7 @@ class ClassDeclarationFormatter extends IFormatter formatState.copyEntity(node.withClause, astVisitor, '$methodName/node.withClause'); formatState.copyEntity(node.implementsClause, astVisitor, '$methodName/node.implementsClause'); - if (pushLevel) + //if (pushLevel) formatState.popLevelAndIndent(); formatState.copyOpeningBraceAndPushLevel(node.leftBracket, config, '$methodName/node.leftBracket'); diff --git a/lib/src/Formatters/ImportDirectiveFormatter.dart b/lib/src/Formatters/ImportDirectiveFormatter.dart index f1908c2..66be558 100644 --- a/lib/src/Formatters/ImportDirectiveFormatter.dart +++ b/lib/src/Formatters/ImportDirectiveFormatter.dart @@ -25,13 +25,13 @@ class ImportDirectiveFormatter extends IFormatter if (node is! ImportDirective) throw FormatException('Not an ImportDirective: ${node.runtimeType}'); - final String textWithPossibleLineBreak = formatState.getText(node.importKeyword.offset, node.semicolon.offset); - final bool pushLevel = textWithPossibleLineBreak.contains('\n'); + //final String textWithPossibleLineBreak = formatState.getText(node.importKeyword.offset, node.semicolon.offset); + //final bool pushLevel = true;//final bool pushLevel = textWithPossibleLineBreak.contains('\n'); formatState.acceptList(node.sortedCommentAndAnnotations, astVisitor, '$methodName/node.sortedCommentAndAnnotations'); formatState.copyEntity(node.importKeyword, astVisitor, '$methodName/node.importKeyword'); - if (pushLevel) + //if (pushLevel) formatState.pushLevel('$methodName/node.classKeyword/after'); formatState.copyEntity(node.uri, astVisitor, '$methodName/node.uri'); @@ -42,7 +42,7 @@ class ImportDirectiveFormatter extends IFormatter formatState.acceptList(node.combinators, astVisitor, '$methodName/node.combinators'); formatState.copySemicolon(node.semicolon, config, '$methodName/node.semicolon'); - if (pushLevel) + //if (pushLevel) formatState.popLevelAndIndent(); if (Constants.DEBUG_I_FORMATTER) log('END $methodName(${StringTools.toDisplayString(node, Constants.MAX_DEBUG_LENGTH)})', --formatState.logIndent); diff --git a/lib/src/Formatters/MethodInvocationFormatter.dart b/lib/src/Formatters/MethodInvocationFormatter.dart index 4d2fd8e..aa51316 100644 --- a/lib/src/Formatters/MethodInvocationFormatter.dart +++ b/lib/src/Formatters/MethodInvocationFormatter.dart @@ -26,26 +26,28 @@ class MethodInvocationFormatter extends IFormatter if (node is! MethodInvocation) throw FormatException('Not a MethodInvocation: ${node.runtimeType}'); - bool pushLevel = false; + /*bool pushLevel = false; if (node.target != null && node.operator != null && node.operator!.type == TokenType.PERIOD) { final String textWithPossibleLineBreak = formatState.getText(node.target!.end, node.operator!.offset); - pushLevel = textWithPossibleLineBreak.contains('\n'); + pushLevel = true;//pushLevel = textWithPossibleLineBreak.contains('\n'); } + pushLevel = true;*/ formatState.copyEntity(node.target, astVisitor, '$methodName/node.target'); - if (pushLevel) + //if (pushLevel) formatState.pushLevel('$methodName/node.target/after'); formatState.copyEntity(node.operator, astVisitor, '$methodName/node.operator'); formatState.copyEntity(node.methodName, astVisitor, '$methodName/node.methodName'); formatState.copyEntity(node.typeArguments, astVisitor, '$methodName/node.typeArguments'); - formatState.copyEntity(node.argumentList, astVisitor, '$methodName/node.argumentList'); - if (pushLevel) + //if (pushLevel) formatState.popLevelAndIndent(); + formatState.copyEntity(node.argumentList, astVisitor, '$methodName/node.argumentList'); + if (Constants.DEBUG_I_FORMATTER) log('END $methodName(${StringTools.toDisplayString(node, Constants.MAX_DEBUG_LENGTH)})', --formatState.logIndent); } } diff --git a/lib/src/Formatters/PropertyAccessFormatter.dart b/lib/src/Formatters/PropertyAccessFormatter.dart new file mode 100644 index 0000000..575851c --- /dev/null +++ b/lib/src/Formatters/PropertyAccessFormatter.dart @@ -0,0 +1,36 @@ +// ignore_for_file: always_put_control_body_on_new_line + +import 'package:analyzer/dart/ast/ast.dart'; + +import '../Constants/Constants.dart'; +import '../Data/Config.dart'; +import '../FormatState.dart'; +import '../Tools/StringTools.dart'; +import 'IFormatter.dart'; + +class PropertyAccessFormatter extends IFormatter +{ + final AstVisitor astVisitor; + final Config config; + final FormatState formatState; + + PropertyAccessFormatter(this.config, this.astVisitor, this.formatState); + + @override + void format(AstNode node) + { + const String methodName = 'PropertyAccessFormatter.format'; + if (Constants.DEBUG_I_FORMATTER) log('START $methodName(${StringTools.toDisplayString(node, Constants.MAX_DEBUG_LENGTH)})', formatState.logIndent++); + + if (node is! PropertyAccess) + throw FormatException('Not a PropertyAccess: ${node.runtimeType}'); + + formatState.copyEntity(node.target, astVisitor, '$methodName/node.target'); + formatState.pushLevel('$methodName/node.target/after'); + formatState.copyEntity(node.operator, astVisitor, '$methodName/node.operator'); + formatState.copyEntity(node.propertyName, astVisitor, '$methodName/node.propertyName'); + formatState.popLevelAndIndent(); + + if (Constants.DEBUG_I_FORMATTER) log('END $methodName(${StringTools.toDisplayString(node, Constants.MAX_DEBUG_LENGTH)})', --formatState.logIndent); + } +} diff --git a/test/Formatters/PropertyAccessFormatter_test.dart b/test/Formatters/PropertyAccessFormatter_test.dart new file mode 100644 index 0000000..a5b37a5 --- /dev/null +++ b/test/Formatters/PropertyAccessFormatter_test.dart @@ -0,0 +1,33 @@ +import 'package:analyzer/dart/ast/ast.dart'; +import 'package:dart_format/src/Formatters/PropertyAccessFormatter.dart'; + +import '../TestTools/AstCreator.dart'; +import '../TestTools/TestConfig.dart'; +import '../TestTools/TestGroupConfig.dart'; +import '../TestTools/TestTools.dart'; +import '../TestTools/Visitors/TestVisitor.dart'; + +void main() +{ + TestTools.init(); + + final List testGroupConfigs = [ + TestGroupConfig( + inputNodeCreator: AstCreator.createInitializerInTopLevelVariable, + inputLeading: 'int i=', + inputMiddle: 'f\n.a\n.b', + inputTrailing: ';', + name: r'PropertyAccess / f\n.a\n.b', + astVisitors: >[ + TestVisitor(6, 'f\n.a'), + TestVisitor(12, 'b') + ], + testConfigs: [ + TestConfig.none(), + TestConfig('f\n.a\n .b') + ] + ) + ]; + + TestTools.runTestGroupsForFormatter(testGroupConfigs, 'PropertyAccessFormatter', PropertyAccessFormatter.new, StackTrace.current); +} diff --git a/test/Formatters/VariableDeclarationFormatter_test.disabled.dart b/test/Formatters/VariableDeclarationFormatter_test.disabled.dart index 953f357..04f051c 100644 --- a/test/Formatters/VariableDeclarationFormatter_test.disabled.dart +++ b/test/Formatters/VariableDeclarationFormatter_test.disabled.dart @@ -1,7 +1,6 @@ /* import 'package:analyzer/dart/ast/ast.dart'; import 'package:dart_format/src/Formatters/VariableDeclarationFormatter.dart'; -import 'package:dart_format/src/Formatters/VariableDeclarationListFormatter.dart'; import '../TestTools/AstCreator.dart'; import '../TestTools/TestGroupConfig.dart'; @@ -15,12 +14,12 @@ void main() final List testGroupConfigs = [ TestGroupConfig( inputNodeCreator: AstCreator.createVariableDeclarationInTopLevelVariableDeclaration, - inputLeading: 'bool ', - inputMiddle: 'b = true\n&& false', + inputLeading: 'int ', + inputMiddle: 'i=f\n.a\n.b', inputTrailing: ';', name: 'Multiline VariableDeclaration', astVisitors: >[ - TestVisitor(9, 'true\n&& false') + TestVisitor(6, 'f\n.a\n.b') ] ) ];