From 4c1e63a3c04f2ca427beaadffd760518bc1b7b91 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 2 Jul 2024 20:21:00 +0000 Subject: [PATCH 1/4] Augment. Report DUPLICATE_DEFINITION for enum/extension. Change-Id: I54dfd33a9d0c630d868b05e9d5403e02cd7cff34 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/374180 Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../lsp/code_lens/augmentations_test.dart | 2 +- .../error/duplicate_definition_verifier.dart | 182 ++---- .../duplicate_definition_test.dart | 572 ++++++++++++++++-- 3 files changed, 599 insertions(+), 157 deletions(-) diff --git a/pkg/analysis_server/test/lsp/code_lens/augmentations_test.dart b/pkg/analysis_server/test/lsp/code_lens/augmentations_test.dart index 1853251efd59..6f230e933d7e 100644 --- a/pkg/analysis_server/test/lsp/code_lens/augmentations_test.dart +++ b/pkg/analysis_server/test/lsp/code_lens/augmentations_test.dart @@ -204,7 +204,7 @@ enum [!A!] { '''); setAugmentationContent(r''' augment enum [!A!] { - one, + two, } '''); diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart index 8db67d78363a..da22f4ccbd40 100644 --- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart +++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart @@ -59,64 +59,25 @@ class DuplicateDefinitionVerifier { /// Check that there are no members with the same name. void checkEnum(EnumDeclaration node) { var fragment = node.declaredElement!; - var augmented = fragment.augmented; - var declarationElement = augmented.declaration; + var declarationElement = fragment.augmented.declaration; var declarationName = declarationElement.name; - var constructorNames = {}; - var instanceGetters = {}; - var instanceSetters = {}; - var staticGetters = {}; - var staticSetters = {}; + var elementContext = _getElementContext(declarationElement); + var staticGetters = elementContext.staticGetters; for (EnumConstantDeclaration constant in node.constants) { + if (constant.name.lexeme == declarationName) { + _errorReporter.atToken( + constant.name, + CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING, + ); + } _checkDuplicateIdentifier(staticGetters, constant.name, element: constant.declaredElement!); _checkValuesDeclarationInEnum(constant.name); } - for (var member in node.members) { - if (member is ConstructorDeclaration) { - if (member.returnType.name == declarationElement.name) { - var name = member.declaredElement!.name; - if (!constructorNames.add(name)) { - if (name.isEmpty) { - _errorReporter.reportErrorForName( - CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT, - member, - ); - } else { - _errorReporter.reportErrorForName( - CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME, - member, - arguments: [name], - ); - } - } - } - } else if (member is FieldDeclaration) { - for (var field in member.fields.variables) { - var identifier = field.name; - _checkDuplicateIdentifier( - member.isStatic ? staticGetters : instanceGetters, - identifier, - element: field.declaredElement!, - setterScope: member.isStatic ? staticSetters : instanceSetters, - ); - _checkValuesDeclarationInEnum(identifier); - } - } else if (member is MethodDeclaration) { - _checkDuplicateIdentifier( - member.isStatic ? staticGetters : instanceGetters, - member.name, - element: member.declaredElement!, - setterScope: member.isStatic ? staticSetters : instanceSetters, - ); - if (!(member.isStatic && member.isSetter)) { - _checkValuesDeclarationInEnum2(member.name); - } - } - } + _checkClassMembers(fragment, node.members); if (declarationName == 'values') { _errorReporter.atToken( @@ -125,21 +86,6 @@ class DuplicateDefinitionVerifier { ); } - for (var constant in node.constants) { - if (constant.name.lexeme == declarationName) { - _errorReporter.atToken( - constant.name, - CompileTimeErrorCode.ENUM_CONSTANT_SAME_NAME_AS_ENCLOSING, - ); - } - } - - _checkConflictingConstructorAndStatic( - interfaceElement: declarationElement, - staticGetters: staticGetters, - staticSetters: staticSetters, - ); - for (var accessor in fragment.accessors) { var baseName = accessor.displayName; if (accessor.isStatic) { @@ -200,31 +146,14 @@ class DuplicateDefinitionVerifier { /// Check that there are no members with the same name. void checkExtension(ExtensionDeclaration node) { - var instanceGetters = {}; - var instanceSetters = {}; - var staticGetters = {}; - var staticSetters = {}; + var fragment = node.declaredElement!; + var declarationElement = fragment.augmented.declaration; - for (var member in node.members) { - if (member is FieldDeclaration) { - for (var field in member.fields.variables) { - var identifier = field.name; - _checkDuplicateIdentifier( - member.isStatic ? staticGetters : instanceGetters, - identifier, - element: field.declaredElement!, - setterScope: member.isStatic ? staticSetters : instanceSetters, - ); - } - } else if (member is MethodDeclaration) { - _checkDuplicateIdentifier( - member.isStatic ? staticGetters : instanceGetters, - member.name, - element: member.declaredElement!, - setterScope: member.isStatic ? staticSetters : instanceSetters, - ); - } - } + var elementContext = _getElementContext(declarationElement); + var instanceGetters = elementContext.instanceGetters; + var instanceSetters = elementContext.instanceSetters; + + _checkClassMembers(fragment, node.members); // Check for local static members conflicting with local instance members. for (var member in node.members) { @@ -404,8 +333,12 @@ class DuplicateDefinitionVerifier { } /// Check that there are no members with the same name. - void _checkClassMembers(InterfaceElement element, List members) { - var declarationElement = element.augmented.declaration; + void _checkClassMembers( + InstanceElement fragment, + List members, + ) { + var declarationElement = fragment.augmented.declaration; + var elementContext = _getElementContext(declarationElement); var constructorNames = elementContext.constructorNames; var instanceGetters = elementContext.instanceGetters; @@ -446,6 +379,9 @@ class DuplicateDefinitionVerifier { element: field.declaredElement!, setterScope: member.isStatic ? staticSetters : instanceSetters, ); + if (fragment is EnumElement) { + _checkValuesDeclarationInEnum(field.name); + } } case MethodDeclaration(): _checkDuplicateIdentifier( @@ -454,14 +390,21 @@ class DuplicateDefinitionVerifier { element: member.declaredElement!, setterScope: member.isStatic ? staticSetters : instanceSetters, ); + if (fragment is EnumElement) { + if (!(member.isStatic && member.isSetter)) { + _checkValuesDeclarationInEnum(member.name); + } + } } } - _checkConflictingConstructorAndStatic( - interfaceElement: declarationElement, - staticGetters: staticGetters, - staticSetters: staticSetters, - ); + if (declarationElement is InterfaceElement) { + _checkConflictingConstructorAndStatic( + interfaceElement: declarationElement, + staticGetters: staticGetters, + staticSetters: staticSetters, + ); + } // Check for local static members conflicting with local instance members. // TODO(scheglov): This code is duplicated for enums. But for classes it is @@ -474,12 +417,14 @@ class DuplicateDefinitionVerifier { String name = identifier.lexeme; if (instanceGetters.containsKey(name) || instanceSetters.containsKey(name)) { - String className = declarationElement.displayName; - _errorReporter.atToken( - identifier, - CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, - arguments: [className, name, className], - ); + if (declarationElement is InterfaceElement) { + String className = declarationElement.name; + _errorReporter.atToken( + identifier, + CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, + arguments: [className, name, className], + ); + } } } } @@ -489,12 +434,14 @@ class DuplicateDefinitionVerifier { String name = identifier.lexeme; if (instanceGetters.containsKey(name) || instanceSetters.containsKey(name)) { - String className = declarationElement.name; - _errorReporter.atToken( - identifier, - CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, - arguments: [className, name, className], - ); + if (declarationElement is InterfaceElement) { + String className = declarationElement.name; + _errorReporter.atToken( + identifier, + CompileTimeErrorCode.CONFLICTING_STATIC_AND_INSTANCE, + arguments: [className, name, className], + ); + } } } } @@ -625,18 +572,9 @@ class DuplicateDefinitionVerifier { } } - void _checkValuesDeclarationInEnum2(Token name) { - if (name.lexeme == 'values') { - _errorReporter.atToken( - name, - CompileTimeErrorCode.VALUES_DECLARATION_IN_ENUM, - ); - } - } - - _InterfaceElementContext _getElementContext(InterfaceElement element) { - return context._interfaceElementContexts[element] ??= - _InterfaceElementContext(); + _InstanceElementContext _getElementContext(InstanceElement element) { + return context._instanceElementContexts[element] ??= + _InstanceElementContext(); } ExecutableElement? _getInheritedMember( @@ -677,12 +615,12 @@ class DuplicateDefinitionVerifier { /// Information to pass from declarations to augmentations. class DuplicationDefinitionContext { - final Map - _interfaceElementContexts = {}; + final Map _instanceElementContexts = + {}; } /// Information accumulated for a single declaration and its augmentations. -class _InterfaceElementContext { +class _InstanceElementContext { final Set constructorNames = {}; final Map instanceGetters = {}; final Map instanceSetters = {}; diff --git a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart index f64ddf9272b4..c0d3c2bb8861 100644 --- a/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart +++ b/pkg/analyzer/test/src/diagnostics/duplicate_definition_test.dart @@ -158,6 +158,33 @@ class C { ]); } + test_instance_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +class C { + int get foo => 0; +} + +augment class C { + augment int get foo => 0; +} +'''); + } + + test_instance_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +class C { + int get foo => 0; +} + +augment class C { + int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 61, 3, + contextMessages: [message(testFile, 20, 3)]), + ]); + } + test_instance_getter_method() async { await assertErrorsInCode(r''' class C { @@ -204,53 +231,29 @@ class C { } test_instance_method_method_augment() async { - var a = newFile('$testPackageLibPath/a.dart', r''' -augment library 'test.dart'; + await assertNoErrorsInCode(r''' +class A { + void foo() {} +} augment class A { augment void foo() {} } '''); - - newFile(testFile.path, r''' -import augment 'a.dart'; - -class A { - void foo() {} -} -'''); - - await resolveTestFile(); - assertNoErrorsInResult(); - - await resolveFile2(a); - assertNoErrorsInResult(); } test_instance_method_method_inAugmentation() async { - var a = newFile('$testPackageLibPath/a.dart', r''' -augment library 'test.dart'; - -augment class A { + await assertErrorsInCode(r''' +class A { void foo() {} } -'''); - newFile(testFile.path, r''' -import augment 'a.dart'; - -class A { +augment class A { void foo() {} } -'''); - - await resolveTestFile(); - assertNoErrorsInResult(); - - await resolveFile2(a); - assertErrorsInResult([ - error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 55, 3, - contextMessages: [message(testFile, 43, 3)]), +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 54, 3, + contextMessages: [message(testFile, 17, 3)]), ]); } @@ -266,6 +269,48 @@ class C { ]); } + test_instance_method_setter_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + void foo() {} +} + +augment class A { + set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 53, 3, + contextMessages: [message(testFile, 17, 3)]), + ]); + } + + test_instance_operator_operator_augment() async { + await assertNoErrorsInCode(r''' +class A { + int operator +(int _) => 0; +} + +augment class A { + augment int operator +(int _) => 0; +} +'''); + } + + test_instance_operator_operator_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + int operator +(int _) => 0; +} + +augment class A { + int operator +(int _) => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 76, 1, + contextMessages: [message(testFile, 25, 1)]), + ]); + } + test_instance_setter_getter() async { await assertNoErrorsInCode(r''' class C { @@ -287,6 +332,21 @@ class C { ]); } + test_instance_setter_method_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + set foo(_) {} +} + +augment class A { + void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 54, 3, + contextMessages: [message(testFile, 16, 3)]), + ]); + } + test_instance_setter_setter() async { await assertErrorsInCode(r''' class C { @@ -299,6 +359,33 @@ class C { ]); } + test_instance_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +class C { + void set foo(_) {} +} + +augment class C { + augment void set foo(_) {} +} +'''); + } + + test_instance_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +class C { + void set foo(_) {} +} + +augment class C { + void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 63, 3, + contextMessages: [message(testFile, 21, 3)]), + ]); + } + test_static_field_field() async { await assertErrorsInCode(r''' class C { @@ -368,6 +455,33 @@ class C { ]); } + test_static_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +class A { + static int get foo => 0; +} + +augment class A { + augment static int get foo => 0; +} +'''); + } + + test_static_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + static int get foo => 0; +} + +augment class A { + static int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 75, 3, + contextMessages: [message(testFile, 27, 3)]), + ]); + } + test_static_getter_method() async { await assertErrorsInCode(r''' class C { @@ -413,6 +527,33 @@ class C { ]); } + test_static_method_method_augment() async { + await assertNoErrorsInCode(r''' +class A { + static void foo() {} +} + +augment class A { + augment static void foo() {} +} +'''); + } + + test_static_method_method_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + static void foo() {} +} + +augment class A { + static void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 68, 3, + contextMessages: [message(testFile, 24, 3)]), + ]); + } + test_static_method_setter() async { await assertErrorsInCode(r''' class C { @@ -458,6 +599,33 @@ class C { ]); } + test_static_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +class A { + static void set foo(_) {} +} + +augment class A { + augment static void set foo(_) {} +} +'''); + } + + test_static_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +class A { + static void set foo(_) {} +} + +augment class A { + static void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 77, 3, + contextMessages: [message(testFile, 28, 3)]), + ]); + } + test_topLevel_syntheticParameters() async { await assertErrorsInCode(r''' f(,[]) {} @@ -556,6 +724,35 @@ enum E { ]); } + test_instance_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + int get foo => 0; +} + +augment enum E {; + augment int get foo => 0; +} +'''); + } + + test_instance_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + int get foo => 0; +} + +augment enum E {; + int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 65, 3, + contextMessages: [message(testFile, 24, 3)]), + ]); + } + test_instance_getter_method() async { await assertErrorsInCode(r''' enum E { @@ -605,6 +802,35 @@ enum E { ]); } + test_instance_method_method_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + void foo() {} +} + +augment enum E {; + augment void foo() {} +} +'''); + } + + test_instance_method_method_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + void foo() {} +} + +augment enum E {; + void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 58, 3, + contextMessages: [message(testFile, 21, 3)]), + ]); + } + test_instance_method_setter() async { await assertErrorsInCode(r''' enum E { @@ -654,6 +880,35 @@ enum E { ]); } + test_instance_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + void set foo(_) {} +} + +augment enum E {; + augment void set foo(_) {} +} +'''); + } + + test_instance_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + void set foo(_) {} +} + +augment enum E {; + void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 67, 3, + contextMessages: [message(testFile, 25, 3)]), + ]); + } + test_static_constant_field() async { await assertErrorsInCode(r''' enum E { @@ -774,6 +1029,35 @@ enum E { ]); } + test_static_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + static int get foo => 0; +} + +augment enum E {; + augment static int get foo => 0; +} +'''); + } + + test_static_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + static int get foo => 0; +} + +augment enum E {; + static int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 79, 3, + contextMessages: [message(testFile, 31, 3)]), + ]); + } + test_static_getter_method() async { await assertErrorsInCode(r''' enum E { @@ -823,6 +1107,35 @@ enum E { ]); } + test_static_method_method_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + static void foo() {} +} + +augment enum E {; + augment static void foo() {} +} +'''); + } + + test_static_method_method_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + static void foo() {} +} + +augment enum E {; + static void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 72, 3, + contextMessages: [message(testFile, 28, 3)]), + ]); + } + test_static_method_setter() async { await assertErrorsInCode(r''' enum E { @@ -871,6 +1184,35 @@ enum E { contextMessages: [message(testFile, 32, 3)]), ]); } + + test_static_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +enum E { + v; + static void set foo(_) {} +} + +augment enum E {; + augment static void set foo(_) {} +} +'''); + } + + test_static_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +enum E { + v; + static void set foo(_) {} +} + +augment enum E {; + static void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 81, 3, + contextMessages: [message(testFile, 32, 3)]), + ]); + } } @reflectiveTest @@ -920,6 +1262,33 @@ extension E on A { ]); } + test_instance_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + int get foo => 0; +} + +augment extension E { + augment int get foo => 0; +} +'''); + } + + test_instance_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + int get foo => 0; +} + +augment extension E { + int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 76, 3, + contextMessages: [message(testFile, 31, 3)]), + ]); + } + test_instance_getter_method() async { await assertErrorsInCode(r''' class A {} @@ -969,6 +1338,33 @@ extension E on A { ]); } + test_instance_method_method_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + void foo() {} +} + +augment extension E { + augment void foo() {} +} +'''); + } + + test_instance_method_method_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + void foo() {} +} + +augment extension E { + void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 69, 3, + contextMessages: [message(testFile, 28, 3)]), + ]); + } + test_instance_method_setter() async { await assertErrorsInCode(r''' class A {} @@ -1018,6 +1414,33 @@ extension E on A { ]); } + test_instance_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + void set foo(_) {} +} + +augment extension E { + augment void set foo(_) {} +} +'''); + } + + test_instance_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + void set foo(_) {} +} + +augment extension E { + void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 78, 3, + contextMessages: [message(testFile, 32, 3)]), + ]); + } + test_static_field_field() async { await assertErrorsInCode(r''' class A {} @@ -1093,6 +1516,33 @@ extension E on A { ]); } + test_static_getter_getter_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + static int get foo => 0; +} + +augment extension E { + augment static int get foo => 0; +} +'''); + } + + test_static_getter_getter_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + static int get foo => 0; +} + +augment extension E { + static int get foo => 0; +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 90, 3, + contextMessages: [message(testFile, 38, 3)]), + ]); + } + test_static_getter_method() async { await assertErrorsInCode(r''' class A {} @@ -1142,6 +1592,33 @@ extension E on A { ]); } + test_static_method_method_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + static void foo() {} +} + +augment extension E { + augment static void foo() {} +} +'''); + } + + test_static_method_method_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + static void foo() {} +} + +augment extension E { + static void foo() {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 83, 3, + contextMessages: [message(testFile, 35, 3)]), + ]); + } + test_static_method_setter() async { await assertErrorsInCode(r''' class A {} @@ -1190,6 +1667,33 @@ extension E on A { ]); } + test_static_setter_setter_augment() async { + await assertNoErrorsInCode(r''' +extension E on int { + static void set foo(_) {} +} + +augment extension E { + augment static void set foo(_) {} +} +'''); + } + + test_static_setter_setter_inAugmentation() async { + await assertErrorsInCode(r''' +extension E on int { + static void set foo(_) {} +} + +augment extension E { + static void set foo(_) {} +} +''', [ + error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 92, 3, + contextMessages: [message(testFile, 39, 3)]), + ]); + } + test_unitMembers_extension() async { await assertErrorsInCode(''' class A {} From b82383953d070e6aaad636413b9fcf06e385e985 Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 2 Jul 2024 21:16:39 +0000 Subject: [PATCH 2/4] [build] Link with lld on Windows when using Clang. - Make the build deterministic Bug: https://github.com/dart-lang/sdk/issues/55995 Change-Id: Ic800dd66f23bc402dfede09db3f67f01aa82d29d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373360 Reviewed-by: Alexander Aprelev Commit-Queue: Ryan Macnak --- build/config/BUILDCONFIG.gn | 5 ++++- build/config/win/BUILD.gn | 28 ++++++++++++++++++++++++++++ build/toolchain/win/BUILD.gn | 15 ++++++++++++--- tools/make_coff_timestamp.py | 19 +++++++++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 tools/make_coff_timestamp.py diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 65b305fa11bd..8022fe525e54 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -257,7 +257,10 @@ if (is_win) { "//build/config/win:winver", ] if (is_clang) { - _native_compiler_configs += [ "//build/config/win:relative_paths" ] + _native_compiler_configs += [ + "//build/config/win:relative_paths", + "//build/config/win:deterministic_builds", + ] } } if (is_posix) { diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index 3d918548e01e..1547f4500627 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn @@ -221,3 +221,31 @@ config("relative_paths") { "-no-canonical-prefixes", ] } + +if (is_clang) { + build_timestamp = + exec_script("//tools/make_coff_timestamp.py", [], "trim string") +} + +config("deterministic_builds") { + if (is_clang) { + # /Brepro lets the compiler not write the mtime field in the .obj output. + # link.exe /incremental relies on this field to work correctly, but lld + # never looks at this timestamp, so it's safe to pass this flag with + # lld and get more deterministic compiler output in return. + # In LTO builds, the compiler doesn't write .obj files containing mtimes, + # so /Brepro is ignored there. + cflags = [ "/Brepro" ] + + # lld defaults to writing the current time in the pe/coff header. + # For build reproducibility, pass an explicit timestamp. See + # build/compute_build_timestamp.py for how the timestamp is chosen. + # (link.exe also writes the current time, but it doesn't have a flag to + # override that behavior.) + ldflags = [ "/TIMESTAMP:" + build_timestamp ] + + # Use a fake fixed base directory for paths in the pdb to make the pdb + # output fully deterministic and independent of the build directory. + ldflags += [ "/PDBSourcePath:o:\fake\prefix" ] + } +} diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn index 3c9d3794cec7..cbb9a87c2c4d 100644 --- a/build/toolchain/win/BUILD.gn +++ b/build/toolchain/win/BUILD.gn @@ -140,9 +140,18 @@ template("msvc_toolchain") { ] } + if (is_clang) { + prefix = rebase_path("$clang_base_path/bin", root_build_dir) + lib = "$prefix/lld-link.exe /lib" + link = "$prefix/lld-link.exe" + } else { + lib = "lib.exe" + link = "link.exe" + } + tool("alink") { rspfile = "{{output}}.rsp" - command = "$python_path $tool_wrapper_path link-wrapper $env False lib.exe /nologo /ignore:4221 /OUT:{{output}} @$rspfile" + command = "$python_path $tool_wrapper_path link-wrapper $env False $lib /nologo /ignore:4221 /OUT:{{output}} @$rspfile" description = "LIB {{output}}" outputs = [ # Ignore {{output_extension}} and always use .lib, there's no reason to @@ -163,7 +172,7 @@ template("msvc_toolchain") { # foo.dll.lib rspfile = "${dllname}.rsp" - link_command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile" + link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile" # TODO(brettw) support manifests #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:${dllname}.manifest" @@ -216,7 +225,7 @@ template("msvc_toolchain") { rspfile = "$binary_output.rsp" pdbfile = "$binary_output.pdb" - link_command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /OUT:$binary_output /PDB:$pdbfile @$rspfile" + link_command = "$python_path $tool_wrapper_path link-wrapper $env False $link /nologo /OUT:$binary_output /PDB:$pdbfile @$rspfile" # TODO(brettw) support manifests #manifest_command = "$python_path $tool_wrapper_path manifest-wrapper $env mt.exe -nologo -manifest $manifests -out:{{output}}.manifest" diff --git a/tools/make_coff_timestamp.py b/tools/make_coff_timestamp.py new file mode 100644 index 000000000000..a92aa72735e9 --- /dev/null +++ b/tools/make_coff_timestamp.py @@ -0,0 +1,19 @@ +# Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +import subprocess +import utils +import sys + + +def Main(): + p = subprocess.Popen(['git', 'show', '--no-patch', '--format=%ct'], + shell=utils.IsWindows(), + cwd=utils.DART_DIR) + p.communicate() + return p.wait() + + +if __name__ == '__main__': + sys.exit(Main()) From 27cbf50a2629e37aa77568fcb79e65a6eade0124 Mon Sep 17 00:00:00 2001 From: asiva Date: Tue, 2 Jul 2024 22:09:59 +0000 Subject: [PATCH 3/4] [VM/FFI] Add a test case for issue dartbug.com/56064 Adding a test case for issue dartbug.com/56064 which needs to be cherry picked into the stable release. The fix was done in https://dart-review.googlesource.com/c/sdk/+/368341 TEST=new test being added Change-Id: I4e58ef5a33c335ba91b639ce4fcebd052969e07d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/374143 Reviewed-by: Ryan Macnak Commit-Queue: Siva Annamalai --- pkg/dartdev/test/commands/run_test.dart | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart index 2dcaa779ae18..0c1a58b415c4 100644 --- a/pkg/dartdev/test/commands/run_test.dart +++ b/pkg/dartdev/test/commands/run_test.dart @@ -37,6 +37,19 @@ void main() async { } '''; +final ffiScript = r''' +import "dart:ffi"; + +void main() { + print('ffi native callback test!'); + final function = NativeCallable.isolateLocal(() {}) + ..keepIsolateAlive = false; + final asDart = function.nativeFunction.asFunction(); + asDart(); + print('Done: ffi native callback test!'); +} +'''; + void Function(String) onVmServicesData( TestProject p, { bool expectDevtoolsMsg = true, @@ -502,6 +515,37 @@ void main(List args) => print("$b $args"); await server.close(); }); + test('regression test for dartbug.com/56064', () async { + final p = project(mainSrc: ffiScript); + Process process = await p.start([ + 'run', + '--enable-vm-service', + '--no-dds', + '--disable-service-auth-codes', + '--pause-isolates-on-unhandled-exceptions', + p.relativeFilePath, + ]); + final completer = Completer(); + late StreamSubscription sub; + sub = process.stdout.transform(utf8.decoder).listen((event) async { + if (event.contains(dartVMServiceRegExp)) { + await sub.cancel(); + completer.complete(); + } + }); + // Wait for process to start and print VM service message. + await completer.future; + // Now wait for the process to terminate, if the issue is not fixed + // the process will not terminate as it will be paused on the exception, + // we timeout and return 255 in that case. + int exitCode = await process.exitCode.timeout(const Duration(seconds: 5), + onTimeout: () { + process.kill(); + return 255; + }); + expect(exitCode, 0); + }); + test('without verbose CFE info', () async { final p = project(mainSrc: '''void main() {}'''); From 2f80ad6359635c59e250d6ce0c5fd354e475bd1d Mon Sep 17 00:00:00 2001 From: Kallen Tu Date: Tue, 2 Jul 2024 22:56:49 +0000 Subject: [PATCH 4/4] [cfe] Turn wildcard locals into ExpressionStatements or EmptyStatements. This CL converts VariableDeclarations to ExpressionStatements or EmptyStatements. If the declaration has an initializer, it will be converted to an ExpressionStatement, otherwise, an EmptyStatement. This will help the VM and potentially other backends, avoid allocating space for a variable declaration that will never be used. Bug: https://github.com/dart-lang/sdk/issues/55655 Change-Id: I845b7e5e61fbb0340623ec0dee7269491bc09513 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373640 Commit-Queue: Kallen Tu Reviewed-by: Chloe Stefantsova --- .../lib/src/kernel/body_builder.dart | 70 +++++++++++++++---- pkg/front_end/lib/src/kernel/forest.dart | 40 +++++++---- ...cal_member_no_shadowing.dart.strong.expect | 4 +- ...er_no_shadowing.dart.strong.modular.expect | 4 +- ...o_shadowing.dart.strong.transformed.expect | 4 +- .../wildcard_variables/local_var.dart | 9 +++ .../local_var.dart.strong.expect | 15 +++- .../local_var.dart.strong.modular.expect | 15 +++- .../local_var.dart.strong.transformed.expect | 15 +++- .../local_var_no_shadowing.dart.strong.expect | 4 +- ...ar_no_shadowing.dart.strong.modular.expect | 4 +- ...o_shadowing.dart.strong.transformed.expect | 4 +- .../wildcard_variables/local_var_order.dart | 12 ++++ .../local_var_order.dart.strong.expect | 14 ++++ ...local_var_order.dart.strong.modular.expect | 14 ++++ ...local_var_order.dart.strong.outline.expect | 8 +++ ...l_var_order.dart.strong.transformed.expect | 14 ++++ ...ocal_var_order.dart.textual_outline.expect | 3 + ...order.dart.textual_outline_modelled.expect | 3 + 19 files changed, 214 insertions(+), 42 deletions(-) create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.expect create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.modular.expect create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.outline.expect create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.transformed.expect create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline.expect create mode 100644 pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline_modelled.expect diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 050609d29c4f..265fbd351fd4 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -4065,13 +4065,26 @@ class BodyBuilder extends StackListenerImpl return; } VariableDeclaration variable = node as VariableDeclaration; - if (annotations != null) { - for (int i = 0; i < annotations.length; i++) { - variable.addAnnotation(annotations[i]); + if (variable.isWildcard && scope.kind != ScopeKind.forStatement) { + // Wildcard variable declarations can be removed, except for the ones in + // for loops. This logic turns them into `ExpressionStatement`s or + // `EmptyStatement`s so the backends don't need to allocate space for + // them. + if (variable.initializer case var initializer?) { + push(forest.createExpressionStatement( + offsetForToken(endToken), initializer)); + } else { + push(forest.createEmptyStatement(offsetForToken(endToken))); + } + } else { + if (annotations != null) { + for (int i = 0; i < annotations.length; i++) { + variable.addAnnotation(annotations[i]); + } + (variablesWithMetadata ??= []).add(variable); } - (variablesWithMetadata ??= []).add(variable); + push(variable); } - push(variable); } else { List? variables = const FixedNullableList() @@ -4085,19 +4098,52 @@ class BodyBuilder extends StackListenerImpl push(new ParserRecovery(offsetForToken(endToken))); return; } - if (annotations != null) { - VariableDeclaration first = variables.first; - for (int i = 0; i < annotations.length; i++) { - first.addAnnotation(annotations[i]); + if (scope.kind != ScopeKind.forStatement) { + // Wildcard variable declarations can be removed, except for the ones in + // for loops. This logic turns them into `ExpressionStatement`s or + // `EmptyStatement`s so the backends don't need to allocate space for + // them. + List declarationStatements = []; + for (VariableDeclaration variable in variables) { + if (variable.isWildcard) { + if (variable.initializer case var initializer?) { + declarationStatements.add(forest.createExpressionStatement( + offsetForToken(endToken), initializer)); + } else { + declarationStatements + .add(forest.createEmptyStatement(offsetForToken(endToken))); + } + } else { + declarationStatements.add(variable); + } } - (multiVariablesWithMetadata ??= >[]) - .add(variables); + Object variablesDeclaration = + forest.variablesDeclaration(declarationStatements, uri); + addVariableAnnotations( + forest + .variablesDeclarationExtractDeclarations(variablesDeclaration), + annotations); + push(variablesDeclaration); + } else { + addVariableAnnotations(variables, annotations); + push(forest.variablesDeclaration(variables, uri)); } - push(forest.variablesDeclaration(variables, uri)); } _exitLocalState(); } + void addVariableAnnotations(List annotationVariables, + List? annotations) { + if (annotations != null && annotationVariables.isNotEmpty) { + VariableDeclaration first = annotationVariables.first; + for (int i = 0; i < annotations.length; i++) { + first.addAnnotation(annotations[i]); + } + (multiVariablesWithMetadata ??= >[]) + .add(annotationVariables); + } + } + /// Stack containing assigned variables info for try statements. /// /// These are created in [beginTryStatement] and ended in either [beginBlock] diff --git a/pkg/front_end/lib/src/kernel/forest.dart b/pkg/front_end/lib/src/kernel/forest.dart index 68532235035c..0d4e43928bf8 100644 --- a/pkg/front_end/lib/src/kernel/forest.dart +++ b/pkg/front_end/lib/src/kernel/forest.dart @@ -371,7 +371,7 @@ class Forest { Statement statement = statements[i]; if (statement is _VariablesDeclaration) { copy ??= new List.of(statements.getRange(0, i)); - copy.addAll(statement.declarations); + copy.addAll(statement.variableOrWildcardInitializers); } else if (copy != null) { copy.add(statement); } @@ -547,19 +547,20 @@ class Forest { } _VariablesDeclaration variablesDeclaration( - List declarations, Uri uri) { - return new _VariablesDeclaration(declarations, uri); + List statements, Uri uri) { + return new _VariablesDeclaration(statements, uri); } List variablesDeclarationExtractDeclarations( Object? variablesDeclaration) { - return (variablesDeclaration as _VariablesDeclaration).declarations; + return (variablesDeclaration as _VariablesDeclaration).variables; } Statement wrapVariables(Statement statement) { if (statement is _VariablesDeclaration) { - return new Block( - new List.of(statement.declarations, growable: true)) + return new Block(new List.of( + statement.variableOrWildcardInitializers, + growable: true)) ..fileOffset = statement.fileOffset; } else if (statement is VariableDeclaration) { return new Block([statement]) @@ -908,11 +909,19 @@ class Forest { } class _VariablesDeclaration extends AuxiliaryStatement { - final List declarations; + /// A list of variable declarations with [ExpressionStatement]s and + /// [EmptyStatement]s from wildcard variable declarations. + final List variableOrWildcardInitializers; + + // A list of variable declarations that are not wildcard variables. + final List variables = []; final Uri uri; - _VariablesDeclaration(this.declarations, this.uri) { - setParents(declarations, this); + _VariablesDeclaration(this.variableOrWildcardInitializers, this.uri) { + setParents(variableOrWildcardInitializers, this); + for (Statement statement in variableOrWildcardInitializers) { + if (statement is VariableDeclaration) variables.add(statement); + } } @override @@ -953,12 +962,19 @@ class _VariablesDeclaration extends AuxiliaryStatement { @override // Coverage-ignore(suite): Not run. void toTextInternal(AstPrinter printer) { - for (int index = 0; index < declarations.length; index++) { + for (int index = 0; + index < variableOrWildcardInitializers.length; + index++) { + Statement statement = variableOrWildcardInitializers[index]; if (index > 0) { printer.write(', '); } - printer.writeVariableDeclaration(declarations[index], - includeModifiersAndType: index == 0); + if (statement is VariableDeclaration) { + printer.writeVariableDeclaration(statement, + includeModifiersAndType: index == 0); + } else { + printer.writeStatement(statement); + } } printer.write(';'); } diff --git a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.expect b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.expect index 28e17e539531..4551186f7324 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.expect @@ -8,8 +8,8 @@ class Field extends core::Object { : super core::Object::•() ; method member() → void { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; this.{self::Field::_} = 3; } } diff --git a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.modular.expect b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.modular.expect index 28e17e539531..4551186f7324 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.modular.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.modular.expect @@ -8,8 +8,8 @@ class Field extends core::Object { : super core::Object::•() ; method member() → void { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; this.{self::Field::_} = 3; } } diff --git a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.transformed.expect b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.transformed.expect index 28e17e539531..4551186f7324 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_member_no_shadowing.dart.strong.transformed.expect @@ -8,8 +8,8 @@ class Field extends core::Object { : super core::Object::•() ; method member() → void { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; this.{self::Field::_} = 3; } } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var.dart b/pkg/front_end/testcases/wildcard_variables/local_var.dart index deb8542745e7..bfb06478478e 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var.dart +++ b/pkg/front_end/testcases/wildcard_variables/local_var.dart @@ -6,4 +6,13 @@ test() { var _ = 1; int _ = 2; _ = 3; + + var _ = 2, _ = 2; + + int test2() => 1; + var _ = test2(); + + late bool _; + late int _, _ = 3, x = 2; + late int _ = 3, _ = 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.expect b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.expect index 7055440207c7..61b464022242 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.expect @@ -10,9 +10,20 @@ import self as self; import "dart:core" as core; static method test() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'. _ = 3; ^"; + 2; + 2; + function test2() → core::int + return 1; + test2(){() → core::int}; + ; + ; + 3; + late core::int x = 2; + 3; + 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.modular.expect b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.modular.expect index 7055440207c7..61b464022242 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.modular.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.modular.expect @@ -10,9 +10,20 @@ import self as self; import "dart:core" as core; static method test() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'. _ = 3; ^"; + 2; + 2; + function test2() → core::int + return 1; + test2(){() → core::int}; + ; + ; + 3; + late core::int x = 2; + 3; + 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.transformed.expect b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.transformed.expect index 7055440207c7..61b464022242 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var.dart.strong.transformed.expect @@ -10,9 +10,20 @@ import self as self; import "dart:core" as core; static method test() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; invalid-expression "pkg/front_end/testcases/wildcard_variables/local_var.dart:8:3: Error: Setter not found: '_'. _ = 3; ^"; + 2; + 2; + function test2() → core::int + return 1; + test2(){() → core::int}; + ; + ; + 3; + late core::int x = 2; + 3; + 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.expect b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.expect index 407215a136c1..a8a13e72c4f9 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.expect @@ -4,7 +4,7 @@ import "dart:core" as core; static field core::int _ = 100; static method main() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; self::_ = 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.modular.expect b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.modular.expect index 407215a136c1..a8a13e72c4f9 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.modular.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.modular.expect @@ -4,7 +4,7 @@ import "dart:core" as core; static field core::int _ = 100; static method main() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; self::_ = 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.transformed.expect b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.transformed.expect index 407215a136c1..a8a13e72c4f9 100644 --- a/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/wildcard_variables/local_var_no_shadowing.dart.strong.transformed.expect @@ -4,7 +4,7 @@ import "dart:core" as core; static field core::int _ = 100; static method main() → dynamic { - wildcard core::int _ = 1; - wildcard core::int _ = 2; + 1; + 2; self::_ = 3; } diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart new file mode 100644 index 000000000000..baefb1bddb3e --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart @@ -0,0 +1,12 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +String foo(String s) { + print(s); + return s; +} + +test() { + String a = foo("a"), _ = foo("b"), c = foo("c"), _ = foo("d"); +} diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.expect new file mode 100644 index 000000000000..ef645cf3fc80 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.expect @@ -0,0 +1,14 @@ +library; +import self as self; +import "dart:core" as core; + +static method foo(core::String s) → core::String { + core::print(s); + return s; +} +static method test() → dynamic { + core::String a = self::foo("a"); + self::foo("b"); + core::String c = self::foo("c"); + self::foo("d"); +} diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.modular.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.modular.expect new file mode 100644 index 000000000000..ef645cf3fc80 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.modular.expect @@ -0,0 +1,14 @@ +library; +import self as self; +import "dart:core" as core; + +static method foo(core::String s) → core::String { + core::print(s); + return s; +} +static method test() → dynamic { + core::String a = self::foo("a"); + self::foo("b"); + core::String c = self::foo("c"); + self::foo("d"); +} diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.outline.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.outline.expect new file mode 100644 index 000000000000..337677dfd948 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.outline.expect @@ -0,0 +1,8 @@ +library; +import self as self; +import "dart:core" as core; + +static method foo(core::String s) → core::String + ; +static method test() → dynamic + ; diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.transformed.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.transformed.expect new file mode 100644 index 000000000000..ef645cf3fc80 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.strong.transformed.expect @@ -0,0 +1,14 @@ +library; +import self as self; +import "dart:core" as core; + +static method foo(core::String s) → core::String { + core::print(s); + return s; +} +static method test() → dynamic { + core::String a = self::foo("a"); + self::foo("b"); + core::String c = self::foo("c"); + self::foo("d"); +} diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline.expect new file mode 100644 index 000000000000..a53117ec2800 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline.expect @@ -0,0 +1,3 @@ +String foo(String s) {} + +test() {} diff --git a/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline_modelled.expect new file mode 100644 index 000000000000..a53117ec2800 --- /dev/null +++ b/pkg/front_end/testcases/wildcard_variables/local_var_order.dart.textual_outline_modelled.expect @@ -0,0 +1,3 @@ +String foo(String s) {} + +test() {}