|  | // Copyright (c) 2025, 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 'package:analysis_server/lsp_protocol/protocol.dart'; | 
|  | import 'package:analyzer/src/test_utilities/test_code_format.dart'; | 
|  | import 'package:test/test.dart'; | 
|  |  | 
|  | import '../../tool/codebase/failing_tests.dart'; | 
|  | import '../lsp/request_helpers_mixin.dart'; | 
|  | import '../utils/test_code_extensions.dart'; | 
|  | import 'shared_test_interface.dart'; | 
|  |  | 
|  | /// Shared editable arguments tests that are used by both LSP + Legacy server | 
|  | /// tests. | 
|  | mixin SharedEditableArgumentsTests | 
|  | on SharedTestInterface, LspRequestHelpersMixin { | 
|  | late TestCode code; | 
|  |  | 
|  | /// Initializes the server with [content] and fetches editable arguments. | 
|  | Future<EditableArguments?> getEditableArgumentsFor( | 
|  | String content, { | 
|  | Future<void> Function(Uri, String)? open, | 
|  | }) async { | 
|  | // Default to the standart openFile function if we weren't overridden. | 
|  | open ??= openFile; | 
|  |  | 
|  | code = TestCode.parse(''' | 
|  | import 'package:flutter/widgets.dart'; | 
|  |  | 
|  | $content | 
|  | '''); | 
|  | createFile(testFilePath, code.code); | 
|  | await initializeServer(); | 
|  | await open(testFileUri, code.code); | 
|  | await currentAnalysis; | 
|  | return await getEditableArguments(testFileUri, code.position.position); | 
|  | } | 
|  |  | 
|  | Matcher hasArg(Matcher matcher) { | 
|  | return hasArgs(contains(matcher)); | 
|  | } | 
|  |  | 
|  | Matcher hasArgNamed(String argumentName, {String? doc}) { | 
|  | return hasArg(isArg(argumentName)); | 
|  | } | 
|  |  | 
|  | Matcher hasArgs(Matcher matcher) { | 
|  | return isA<EditableArguments>().having( | 
|  | (arguments) => arguments.arguments, | 
|  | 'arguments', | 
|  | matcher, | 
|  | ); | 
|  | } | 
|  |  | 
|  | Matcher hasDocumentation(Matcher matcher) { | 
|  | return isA<EditableArguments>().having( | 
|  | (arguments) => arguments.documentation, | 
|  | 'documentation', | 
|  | matcher, | 
|  | ); | 
|  | } | 
|  |  | 
|  | Matcher hasName(Matcher matcher) { | 
|  | return isA<EditableArguments>().having( | 
|  | (arguments) => arguments.name, | 
|  | 'name', | 
|  | matcher, | 
|  | ); | 
|  | } | 
|  |  | 
|  | Matcher isArg( | 
|  | String name, { | 
|  | Object? documentation = anything, | 
|  | Object? type = anything, | 
|  | Object? value = anything, | 
|  | Object? displayValue = anything, | 
|  | Object? hasArgument = anything, | 
|  | Object? defaultValue = anything, | 
|  | Object? isRequired = anything, | 
|  | Object? isNullable = anything, | 
|  | Object? isDeprecated = anything, | 
|  | Object? isEditable = anything, | 
|  | Object? notEditableReason = anything, | 
|  | Object? options = anything, | 
|  | }) { | 
|  | return isA<EditableArgument>() | 
|  | .having((arg) => arg.name, 'name', name) | 
|  | .having((arg) => arg.documentation, 'documentation', documentation) | 
|  | .having((arg) => arg.type, 'type', type) | 
|  | .having((arg) => arg.value, 'value', value) | 
|  | .having((arg) => arg.displayValue, 'displayValue', displayValue) | 
|  | .having((arg) => arg.hasArgument, 'hasArgument', hasArgument) | 
|  | .having((arg) => arg.defaultValue, 'defaultValue', defaultValue) | 
|  | .having((arg) => arg.isRequired, 'isRequired', isRequired) | 
|  | .having((arg) => arg.isNullable, 'isNullable', isNullable) | 
|  | .having((arg) => arg.isDeprecated, 'isDeprecated', isDeprecated) | 
|  | .having((arg) => arg.isEditable, 'isEditable', isEditable) | 
|  | .having( | 
|  | (arg) => arg.notEditableReason, | 
|  | 'notEditableReason', | 
|  | notEditableReason, | 
|  | ) | 
|  | .having((arg) => arg.options, 'options', options) | 
|  | // Some extra checks that should be true for all. | 
|  | .having( | 
|  | (arg) => | 
|  | arg.value == null || | 
|  | arg.value?.toString() != arg.displayValue?.toString(), | 
|  | 'different value and displayValues', | 
|  | isTrue, | 
|  | ) | 
|  | .having( | 
|  | (arg) => (arg.notEditableReason == null) == arg.isEditable, | 
|  | 'notEditableReason must be supplied if isEditable=false', | 
|  | isTrue, | 
|  | ) | 
|  | .having( | 
|  | (arg) => arg.value == null || arg.isEditable, | 
|  | 'isEditable must be true if there is a value', | 
|  | isTrue, | 
|  | ) | 
|  | .having( | 
|  | (arg) => | 
|  | arg.type == 'enum' | 
|  | ? (arg.options?.isNotEmpty ?? false) | 
|  | : arg.options == null, | 
|  | 'enum types must have options / non-enums must not have options', | 
|  | isTrue, | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_named_default() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({int? a = 1}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: 1))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_named_default_constantVariable() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | static const constantOne = 1; | 
|  |  | 
|  | const MyWidget({int? a = constantOne}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: 1))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_named_default_null() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({int? a = null}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: null))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_named_noDefault() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({int? a}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: null))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_named_required_noDefault() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required int? a}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: null))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_positional() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int a); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: null))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_positional_optional_default() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget([int? a = 1]); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: 1))); | 
|  | } | 
|  |  | 
|  | Future<void> test_defaultValue_positional_optional_noDefault() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget([int? a]); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('a', defaultValue: null))); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_fieldParameter_literal() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | /// Documentation for x. | 
|  | final int x; | 
|  |  | 
|  | /// Creates a MyWidget. | 
|  | const MyWidget(this.x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('x', documentation: 'Documentation for x.'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_fieldParameter_macro() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | /// {@template shared_docs} | 
|  | /// Shared docs. | 
|  | /// {@endtemplate} | 
|  | class MyWidget extends StatelessWidget { | 
|  | /// {@macro shared_docs} | 
|  | final int x; | 
|  |  | 
|  | /// Creates a MyWidget. | 
|  | const MyWidget(this.x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArg(isArg('x', documentation: 'Shared docs.'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_literal() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | /// Creates a MyWidget. | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasDocumentation(equals('Creates a MyWidget.'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_macro() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | /// {@template my_widget_docs} | 
|  | /// MyWidget shared docs. | 
|  | /// {@endtemplate} | 
|  | class MyWidget extends StatelessWidget { | 
|  | /// {@macro my_widget_docs} | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasDocumentation(equals('MyWidget shared docs.'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_missing() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasDocumentation(isNull)); | 
|  | } | 
|  |  | 
|  | Future<void> test_documentation_widgetFactory() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | /// Creates a Padded. | 
|  | @widgetFactory | 
|  | Widget padded(int x) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) { | 
|  | return padd^ed(1); | 
|  | } | 
|  | } | 
|  | '''); | 
|  | expect(result, hasDocumentation(equals('Creates a Padded.'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_hasArgument() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget( | 
|  | int? aPositionalSupplied, | 
|  | int? aPositionalNotSupplied, { | 
|  | int? aNamedSupplied, | 
|  | int? aNamedNotSupplied, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1, aNamedSupplied: 1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | unorderedEquals([ | 
|  | isArg('aPositionalSupplied', hasArgument: true), | 
|  | isArg('aPositionalNotSupplied', hasArgument: false), | 
|  | isArg('aNamedSupplied', hasArgument: true), | 
|  | isArg('aNamedNotSupplied', hasArgument: false), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isDeprecated() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | /// Creates a MyWidget. | 
|  | const MyWidget( | 
|  | @deprecated | 
|  | int aDeprecated, | 
|  | int aNotDeprecated, | 
|  | ); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1, 2); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | unorderedEquals([ | 
|  | isArg('aDeprecated', isDeprecated: true), | 
|  | isArg('aNotDeprecated', isDeprecated: false), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_positional_optional() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget([int? a, int? b, int? c]); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('a', isEditable: true), | 
|  | isArg('b', isEditable: true), | 
|  | isArg( | 
|  | 'c', | 
|  | // c is not editable because it is not guaranteed that we can insert | 
|  | // a default value for b (it could be a private value or require | 
|  | // imports). | 
|  | isEditable: false, | 
|  | notEditableReason: | 
|  | "A value for the 3rd parameter can't be added until a value " | 
|  | 'for all preceding positional parameters have been added.', | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_positional_required1() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int a, int b); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | // b is not editable because there are missing required previous | 
|  | // arguments (a). | 
|  | isArg( | 
|  | 'b', | 
|  | isEditable: false, | 
|  | notEditableReason: | 
|  | "A value for the 2nd parameter can't be added until a value " | 
|  | 'for all preceding positional parameters have been added.', | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_positional_required2() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int a, int b, int c); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | // c is not editable because there are missing required previous | 
|  | // arguments (b). | 
|  | isArg( | 
|  | 'c', | 
|  | isEditable: false, | 
|  | notEditableReason: | 
|  | "A value for the 3rd parameter can't be added until a value " | 
|  | 'for all preceding positional parameters have been added.', | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_string_adjacent() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String s); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('a' 'b'); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | isArg( | 
|  | 's', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | displayValue: 'ab', | 
|  | hasArgument: true, | 
|  | isEditable: false, | 
|  | notEditableReason: "Adjacent strings can't be edited", | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_string_interpolated() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String s); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('${context.runtimeType}'); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 's', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | displayValue: r"'${context.runtimeType}'", | 
|  | isEditable: false, | 
|  | notEditableReason: "Interpolated strings can't be edited", | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_false_string_withNewlines() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String sEscaped, String sLiteral); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | 'a\nb', | 
|  | """ | 
|  | a | 
|  | b | 
|  | """, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'sEscaped', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | displayValue: 'a\nb', | 
|  | isEditable: false, | 
|  | notEditableReason: "Strings containing newlines can't be edited", | 
|  | ), | 
|  | isArg( | 
|  | 'sLiteral', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | displayValue: 'a\nb\n', | 
|  | isEditable: false, | 
|  | notEditableReason: "Strings containing newlines can't be edited", | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_true_named() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({int? a, int? b, int? c}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(a: 1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('a', isEditable: true), | 
|  | isArg('b', isEditable: true), | 
|  | isArg('c', isEditable: true), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_true_positional_required() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int a, int b); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | isArg( | 
|  | 'b', | 
|  | // b is editable because it's the next argument and we don't need | 
|  | // to add anything additional. | 
|  | isEditable: true, | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_true_string_dollar_escaped() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String s); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('\${1}'); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | isArg( | 
|  | 's', | 
|  | type: 'string', | 
|  | value: r'${1}', | 
|  | displayValue: isNull, | 
|  | isEditable: true, | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isEditable_true_string_dollar_raw() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String s); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(r'${1}'); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | isArg( | 
|  | 's', | 
|  | type: 'string', | 
|  | value: r'${1}', | 
|  | displayValue: isNull, | 
|  | isEditable: true, | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> | 
|  | test_isEditable_true_string_tripleQuoted_withoutNewlines() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String s); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget("""string_value"""); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArg( | 
|  | isArg( | 
|  | 's', | 
|  | type: 'string', | 
|  | value: 'string_value', | 
|  | displayValue: isNull, | 
|  | isEditable: true, | 
|  | ), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isNullable() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget( | 
|  | int aPositional, | 
|  | int? aPositionalNullable, { | 
|  | int? aNamed, | 
|  | required int aRequiredNamed, | 
|  | required int? aRequiredNamedNullable | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aPositional', isNullable: false), | 
|  | isArg('aPositionalNullable', isNullable: true), | 
|  | isArg('aNamed', isNullable: true), | 
|  | isArg('aRequiredNamed', isNullable: false), | 
|  | isArg('aRequiredNamedNullable', isNullable: true), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_isRequired() async { | 
|  | failTestOnErrorDiagnostic = false; | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget( | 
|  | int aPositional, | 
|  | int? aPositionalNullable, { | 
|  | int? aNamed, | 
|  | required int aRequiredNamed, | 
|  | required int? aRequiredNamedNullable | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aPositional', isRequired: true), | 
|  | isArg('aPositionalNullable', isRequired: true), | 
|  | isArg('aNamed', isRequired: false), | 
|  | isArg('aRequiredNamed', isRequired: true), | 
|  | isArg('aRequiredNamedNullable', isRequired: true), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_bad_extensionMethod_noWidgetFactory() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | Widget padded(String a1) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(); | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => this.pad^ded('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, isNull); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_bad_functionInvocation() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | MyWidget create(String a1) => throw ''; | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | @override | 
|  | Widget build(BuildContext context) => crea^te('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, isNull); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_bad_methodInvocation() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | @widgetFactory | 
|  | MyWidget create(String a1) => throw ''; | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => crea^te('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, isNull); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_bad_nonDart() async { | 
|  | var textFilePath = pathContext.join(projectFolderPath, 'lib', 'test.txt'); | 
|  | var textFileUri = Uri.file(textFilePath); | 
|  |  | 
|  | var content = 'my text'; | 
|  | createFile(textFilePath, content); | 
|  | await initializeServer(); | 
|  | await openFile(textFileUri, content); | 
|  | await currentAnalysis; | 
|  | var result = await getEditableArguments( | 
|  | textFileUri, | 
|  | Position(line: 0, character: 0), | 
|  | ); | 
|  |  | 
|  | expect(result, isNull); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_bad_unnamedConstructor_notWidget() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | MyWidget build(BuildContext context) => MyW^idget('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, isNull); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_argumentName() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required String a1 }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(a^1: 'value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_literalValue() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required String a1 }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(a1: 'val^ue1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_nestedInvocation() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | String getString() => ''; | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(getS^tring()); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> | 
|  | test_location_good_argumentList_nestedInvocation_arguments() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | String getString(String s) => s; | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(getString('valu^e1')); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_parens_afterOpen() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required String a1 }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(^a1: 'value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_parens_beforeClose() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required String a1 }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget(a1: 'value1'^); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_argumentList_parens_beforeOpen() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({required String a1 }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget^(a1: 'value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_extensionMethod_constructorTarget() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | @widgetFactory | 
|  | Widget padded(String a1) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(); | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget().pad^ded('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_extensionMethod_thisTarget() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | @widgetFactory | 
|  | Widget padded(String a1) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => this.pad^ded('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_extensionMethod_variableTarget() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | @widgetFactory | 
|  | Widget padded(String a1) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(); | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) { | 
|  | MyWidget? foo; | 
|  | return foo!.pad^ded('value1'); | 
|  | } | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_namedConstructor_className() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget.foo('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_namedConstructor_constructorName() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget.foo(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyWidget.f^oo('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_location_good_unnamedConstructor() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('value1'); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasArgNamed('a1')); | 
|  | } | 
|  |  | 
|  | Future<void> test_name_widgetConstructor() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasName(equals('MyWidget'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_name_widgetConstructor_named() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget.named(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget.named(1); | 
|  | } | 
|  | '''); | 
|  | expect(result, hasName(equals('MyWidget'))); | 
|  | } | 
|  |  | 
|  | Future<void> test_name_widgetFactory() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | extension on MyWidget { | 
|  | @widgetFactory | 
|  | Widget padded(int x) => this; | 
|  | } | 
|  |  | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(int x); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) { | 
|  | return padd^ed(1); | 
|  | } | 
|  | } | 
|  | '''); | 
|  | expect(result, hasName(isNull)); | 
|  | } | 
|  |  | 
|  | /// Arguments should be returned in the order of the parameters in the source | 
|  | /// code. This keeps things consistent across different instances of the same | 
|  | /// Widget class and prevents the order from changing as a user adds/removes | 
|  | /// arguments. | 
|  | /// | 
|  | /// If an editor wants to sort provided arguments first (and keep these stable | 
|  | /// across add/removes) it could still do so client-side, whereas if server | 
|  | /// orders them that way, the opposite (using source-order) is not possible. | 
|  | Future<void> test_order() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | int c1 = 0, | 
|  | int c2 = 0, | 
|  | int a1 = 0, | 
|  | int a2 = 0, | 
|  | int b1 = 0, | 
|  | int b2 = 0, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget(b1: 1, a1: 1, c1: 1); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('c1'), | 
|  | isArg('c2'), | 
|  | isArg('a1'), | 
|  | isArg('a2'), | 
|  | isArg('b1'), | 
|  | isArg('b2'), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_range() async { | 
|  | var result = await getEditableArgumentsFor(r''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({int? a = null}); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => [!MyW^idget(a: 1)!]; | 
|  | } | 
|  | '''); | 
|  | expect(result!.range, code.range.range); | 
|  | } | 
|  |  | 
|  | Future<void> test_textDocument_unopenedFile() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('value1'); | 
|  | } | 
|  | ''', open: (_, _) async {}); | 
|  |  | 
|  | // Verify null version for unopened file. | 
|  | expect( | 
|  | result!.textDocument, | 
|  | isA<OptionalVersionedTextDocumentIdentifier>() | 
|  | .having((td) => td.uri, 'uri', testFileUri) | 
|  | .having((td) => td.version, 'version', null), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_textDocument_versioned() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('value1'); | 
|  | } | 
|  | '''); | 
|  |  | 
|  | // Verify initial content of 1. | 
|  | expect( | 
|  | result!.textDocument, | 
|  | isA<VersionedTextDocumentIdentifier>() | 
|  | .having((td) => td.uri, 'uri', testFileUri) | 
|  | .having((td) => td.version, 'version', 1), | 
|  | ); | 
|  |  | 
|  | // Update the content to v5. | 
|  | await replaceFile(5, testFileUri, '${code.code}\n// extra comment'); | 
|  |  | 
|  | // Verify new results have version 5. | 
|  | result = await getEditableArguments(testFileUri, code.position.position); | 
|  | expect( | 
|  | result!.textDocument, | 
|  | isA<VersionedTextDocumentIdentifier>() | 
|  | .having((td) => td.uri, 'uri', testFileUri) | 
|  | .having((td) => td.version, 'version', 5), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_textDocument_versioned_closedFile() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget(String a1); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget('value1'); | 
|  | } | 
|  | '''); | 
|  |  | 
|  | // Verify initial content of 1. | 
|  | expect( | 
|  | result!.textDocument, | 
|  | isA<VersionedTextDocumentIdentifier>() | 
|  | .having((td) => td.uri, 'uri', testFileUri) | 
|  | .having((td) => td.version, 'version', 1), | 
|  | ); | 
|  |  | 
|  | // Close the file. | 
|  | await closeFile(testFileUri); | 
|  |  | 
|  | // Verify new results have null version. | 
|  | result = await getEditableArguments(testFileUri, code.position.position); | 
|  | expect( | 
|  | result!.textDocument, | 
|  | isA<OptionalVersionedTextDocumentIdentifier>() | 
|  | .having((td) => td.uri, 'uri', testFileUri) | 
|  | .having((td) => td.version, 'version', isNull), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_bool() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | bool supplied = true, | 
|  | bool suppliedAsDefault = true, | 
|  | bool notSupplied = true, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: false, | 
|  | suppliedAsDefault: true, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'bool', | 
|  | value: false, | 
|  | hasArgument: true, | 
|  | defaultValue: true, | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'bool', | 
|  | value: true, | 
|  | hasArgument: true, | 
|  | defaultValue: true, | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'bool', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: true, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_bool_nonLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | var myVar = true; | 
|  | const myConst = true; | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | bool? aVar, | 
|  | bool? aConst, | 
|  | bool? aExpr, | 
|  | bool? aConstExpr, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | aVar: myVar, | 
|  | aConst: myConst, | 
|  | aExpr: DateTime.now().isBefore(DateTime.now()), | 
|  | aConstExpr: 1 == 2, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aVar', type: 'bool', value: isNull, displayValue: 'myVar'), | 
|  | isArg('aConst', type: 'bool', value: true, displayValue: 'myConst'), | 
|  | isArg( | 
|  | 'aExpr', | 
|  | type: 'bool', | 
|  | value: isNull, | 
|  | displayValue: 'DateTime.now().isBefore(DateTime.now())', | 
|  | ), | 
|  | isArg( | 
|  | 'aConstExpr', | 
|  | type: 'bool', | 
|  | value: false, | 
|  | displayValue: '1 == 2', | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_double() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | double supplied = 1.0, | 
|  | double suppliedAsDefault = 1.0, | 
|  | double notSupplied = 1.0, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: 2.0, | 
|  | suppliedAsDefault: 1.0, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'double', | 
|  | value: 2.0, | 
|  | hasArgument: true, | 
|  | defaultValue: 1.0, | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'double', | 
|  | value: 1.0, | 
|  | hasArgument: true, | 
|  | defaultValue: 1.0, | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'double', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: 1.0, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_double_intLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | double supplied = 1, | 
|  | double suppliedAsDefault = 1, | 
|  | double notSupplied = 1, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: 2, | 
|  | suppliedAsDefault: 1, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'double', | 
|  | value: 2, | 
|  | hasArgument: true, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'double', | 
|  | value: 1, | 
|  | hasArgument: true, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'double', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_double_nonLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | var myVar = 1.0; | 
|  | const myConst = 1.0; | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | double? aVar, | 
|  | double? aConst, | 
|  | double? aExpr, | 
|  | double? aConstExpr, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | aVar: myVar, | 
|  | aConst: myConst, | 
|  | aExpr: DateTime.now().millisecondsSinceEpoch.toDouble(), | 
|  | aConstExpr: 1.0 + myConst, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aVar', type: 'double', value: isNull, displayValue: 'myVar'), | 
|  | isArg('aConst', type: 'double', value: 1.0, displayValue: 'myConst'), | 
|  | isArg( | 
|  | 'aExpr', | 
|  | type: 'double', | 
|  | value: isNull, | 
|  | displayValue: 'DateTime.now().millisecondsSinceEpoch.toDouble()', | 
|  | ), | 
|  | isArg( | 
|  | 'aConstExpr', | 
|  | type: 'double', | 
|  | value: 2.0, | 
|  | displayValue: '1.0 + myConst', | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_enum() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | enum E { one, two } | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | E supplied = E.one, | 
|  | E suppliedAsDefault = E.one, | 
|  | E notSupplied = E.one, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: E.two, | 
|  | suppliedAsDefault: E.one, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  |  | 
|  | var optionsMatcher = equals(['E.one', 'E.two']); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'enum', | 
|  | value: 'E.two', | 
|  | hasArgument: true, | 
|  | defaultValue: 'E.one', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'enum', | 
|  | value: 'E.one', | 
|  | hasArgument: true, | 
|  | defaultValue: 'E.one', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'enum', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: 'E.one', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_enum_nonLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | enum E { one, two } | 
|  | var myVar = E.one; | 
|  | const myConst = E.one; | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | E? aVar, | 
|  | E? aConst, | 
|  | E? aExpr, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | aVar: myVar, | 
|  | aConst: myConst, | 
|  | aExpr: E.values.first, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  |  | 
|  | var optionsMatcher = equals(['E.one', 'E.two']); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'aVar', | 
|  | type: 'enum', | 
|  | value: isNull, | 
|  | displayValue: 'myVar', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | isArg( | 
|  | 'aConst', | 
|  | type: 'enum', | 
|  | value: 'E.one', | 
|  | displayValue: 'myConst', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | isArg( | 
|  | 'aExpr', | 
|  | type: 'enum', | 
|  | value: isNull, | 
|  | displayValue: 'E.values.first', | 
|  | options: optionsMatcher, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_int() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | int supplied = 1, | 
|  | int suppliedAsDefault = 1, | 
|  | int notSupplied = 1, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: 2, | 
|  | suppliedAsDefault: 1, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'int', | 
|  | value: 2, | 
|  | hasArgument: true, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'int', | 
|  | value: 1, | 
|  | hasArgument: true, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'int', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: 1, | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_int_nonLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | var myVar = 1; | 
|  | const myConst = 1; | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | int? aVar, | 
|  | int? aConst, | 
|  | int? aExpr, | 
|  | int? aConstExpr, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | aVar: myVar, | 
|  | aConst: myConst, | 
|  | aExpr: DateTime.now().millisecondsSinceEpoch, | 
|  | aConstExpr: 1 + myConst, | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aVar', type: 'int', value: isNull, displayValue: 'myVar'), | 
|  | isArg('aConst', type: 'int', value: 1, displayValue: 'myConst'), | 
|  | isArg( | 
|  | 'aExpr', | 
|  | type: 'int', | 
|  | value: isNull, | 
|  | displayValue: 'DateTime.now().millisecondsSinceEpoch', | 
|  | ), | 
|  | isArg( | 
|  | 'aConstExpr', | 
|  | type: 'int', | 
|  | value: 2, | 
|  | displayValue: '1 + myConst', | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_string() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | String supplied = 'a', | 
|  | String suppliedAsDefault = 'a', | 
|  | String notSupplied = 'a', | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | supplied: 'b', | 
|  | suppliedAsDefault: 'a', | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg( | 
|  | 'supplied', | 
|  | type: 'string', | 
|  | value: 'b', | 
|  | hasArgument: true, | 
|  | defaultValue: 'a', | 
|  | ), | 
|  | isArg( | 
|  | 'suppliedAsDefault', | 
|  | type: 'string', | 
|  | value: 'a', | 
|  | hasArgument: true, | 
|  | defaultValue: 'a', | 
|  | ), | 
|  | isArg( | 
|  | 'notSupplied', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | hasArgument: false, | 
|  | defaultValue: 'a', | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  |  | 
|  | Future<void> test_type_string_nonLiterals() async { | 
|  | var result = await getEditableArgumentsFor(''' | 
|  | var myVar = 'a'; | 
|  | const myConst = 'a'; | 
|  | class MyWidget extends StatelessWidget { | 
|  | const MyWidget({ | 
|  | String? aVar, | 
|  | String? aConst, | 
|  | String? aExpr, | 
|  | String? aConstExpr, | 
|  | }); | 
|  |  | 
|  | @override | 
|  | Widget build(BuildContext context) => MyW^idget( | 
|  | aVar: myVar, | 
|  | aConst: myConst, | 
|  | aExpr: DateTime.now().toString(), | 
|  | aConstExpr: 'a' + 'b', | 
|  | ); | 
|  | } | 
|  | '''); | 
|  | expect( | 
|  | result, | 
|  | hasArgs( | 
|  | orderedEquals([ | 
|  | isArg('aVar', type: 'string', value: isNull, displayValue: 'myVar'), | 
|  | isArg('aConst', type: 'string', value: 'a', displayValue: 'myConst'), | 
|  | isArg( | 
|  | 'aExpr', | 
|  | type: 'string', | 
|  | value: isNull, | 
|  | displayValue: 'DateTime.now().toString()', | 
|  | ), | 
|  | isArg( | 
|  | 'aConstExpr', | 
|  | type: 'string', | 
|  | value: 'ab', | 
|  | displayValue: "'a' + 'b'", | 
|  | ), | 
|  | ]), | 
|  | ), | 
|  | ); | 
|  | } | 
|  | } |