From e99ba5460e5d658ce1b7fe36445364a7e91dcab8 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 24 Jun 2024 10:22:42 -0700 Subject: [PATCH] Properly generate code for parameter default value Strings. Fixes https://github.com/dart-lang/mockito/issues/756 In order to properly allow single quotes and dollar signs in parameter default values, we must not print as raw, and we must escape dollar signs ourselves, before passing to code_builder. PiperOrigin-RevId: 646140324 --- lib/src/builder.dart | 6 +++- test/builder/auto_mocks_test.dart | 47 ++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lib/src/builder.dart b/lib/src/builder.dart index 4888f2cc..9f0a5873 100644 --- a/lib/src/builder.dart +++ b/lib/src/builder.dart @@ -1822,7 +1822,11 @@ class _MockClassInfo { } else if (constant.isInt) { return literalNum(constant.intValue); } else if (constant.isString) { - return literalString(constant.stringValue, raw: true); + // code_builder writes all strings with single quotes. + // Raw single quoted strings may not contain single quotes, + // so escape dollar signs and use a non-raw string instead. + final stringValue = constant.stringValue.replaceAll('\$', '\\\$'); + return literalString(stringValue); } else if (constant.isList) { return literalConstList([ for (final element in constant.listValue) diff --git a/test/builder/auto_mocks_test.dart b/test/builder/auto_mocks_test.dart index 1e6a0f36..83631677 100644 --- a/test/builder/auto_mocks_test.dart +++ b/test/builder/auto_mocks_test.dart @@ -281,13 +281,46 @@ void main() { await expectSingleNonNullableOutput( dedent(r''' class Foo { - void m([String a = 'Hello', String b = 'Hello ' r"World"]) {} + void m([String a = 'Hello', String b = "World"]) {} } '''), _containsAllOf(dedent2(''' void m([ - String? a = r'Hello', - String? b = r'Hello World', + String? a = 'Hello', + String? b = 'World', + ]) => + ''')), + ); + }); + + test('matches string literal parameter default values with quote characters', + () async { + await expectSingleNonNullableOutput( + dedent(r''' + class Foo { + void m([String a = 'Hel"lo', String b = "Wor'ld"]) {} + } + '''), + _containsAllOf(dedent2(''' + void m([ + String? a = 'Hel"lo', + String? b = 'Wor\\'ld', + ]) => + ''')), + ); + }); + + test('matches raw string literal parameter default values', () async { + await expectSingleNonNullableOutput( + dedent(r''' + class Foo { + void m([String a = r'$Hello', String b = r"$World"]) {} + } + '''), + _containsAllOf(dedent2(''' + void m([ + String? a = '\\\$Hello', + String? b = '\\\$World', ]) => ''')), ); @@ -337,8 +370,8 @@ void main() { _containsAllOf(dedent2(''' void m( [Map? a = const { - 1: r'a', - 2: r'b', + 1: 'a', + 2: 'b', }]) => ''')), ); @@ -354,8 +387,8 @@ void main() { _containsAllOf(dedent2(''' void m( [Map? a = const { - 1: r'a', - 2: r'b', + 1: 'a', + 2: 'b', }]) => ''')), );