Add tests for most `displayString()` methods.
Significantly improve test coverage of `display_string_builder.dart`.
Fix an error involving a missing space when reading the enclosing
fragment of a local variable declaration.
Change the formatting of `ConstructorElement` to print only the type and
not the name to avoid duplication, as they were the same.
Change the formatting of `TypeAliasElement` to just print the name of
the aliased type, rather than the whole aliased element - as this rarely
provided useful information.
Change-Id: Ie1e4a3649063c2b3662ef7bd21327c17a5b1456b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/441082
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index d505960..a535440 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -112,7 +112,7 @@
''');
var hover = await prepareHover('A() +');
// element
- expect(hover.elementDescription, '(new) A A()');
+ expect(hover.elementDescription, '(new) A()');
// don't show parameter information for binary operators
expect(hover.parameter, isNull);
}
@@ -128,7 +128,7 @@
''');
var hover = await prepareHover('A(); // 1');
// element
- expect(hover.elementDescription, '(new) A A()');
+ expect(hover.elementDescription, '(new) A()');
// don't show parameter information for binary operators
expect(hover.parameter, isNull);
}
@@ -149,7 +149,7 @@
expect(hover.length, 'A.named'.length);
// element
expect(hover.dartdoc, 'my doc');
- expect(hover.elementDescription, 'A A.named()');
+ expect(hover.elementDescription, 'A.named()');
expect(hover.elementKind, 'constructor');
}
@@ -176,7 +176,7 @@
expect(hover.length, 'A.named'.length);
// element
expect(hover.dartdoc, 'my doc');
- expect(hover.elementDescription, 'A A.named()');
+ expect(hover.elementDescription, 'A.named()');
expect(hover.elementKind, 'constructor');
}
@@ -207,7 +207,7 @@
expect(hover.containingLibraryName, 'package:test/test.dart');
expect(hover.containingLibraryPath, testFile.path);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, '(const) A A(int i)');
+ expect(hover.elementDescription, '(const) A(int i)');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -231,7 +231,7 @@
expect(hover.containingLibraryName, 'package:test/test.dart');
expect(hover.containingLibraryPath, testFile.path);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, '(new) A A()');
+ expect(hover.elementDescription, '(new) A()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -256,7 +256,7 @@
expect(hover.containingLibraryName, 'package:test/test.dart');
expect(hover.containingLibraryPath, testFile.path);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, 'A A()');
+ expect(hover.elementDescription, 'A()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -280,7 +280,7 @@
expect(hover.containingLibraryName, 'package:test/test.dart');
expect(hover.containingLibraryPath, testFile.path);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, 'A<String> A()');
+ expect(hover.elementDescription, 'A<String>()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -324,7 +324,7 @@
expect(hover.containingLibraryPath, testFile.path);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, 'doc aaa\ndoc bbb');
- expect(hover.elementDescription, 'A<double> A.named()');
+ expect(hover.elementDescription, 'A<double>.named()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -351,7 +351,7 @@
expect(hover.containingLibraryPath, testFile.path);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, 'doc aaa\ndoc bbb');
- expect(hover.elementDescription, 'A<double> A()');
+ expect(hover.elementDescription, 'A<double>()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -378,7 +378,7 @@
expect(hover.containingLibraryPath, testFile.path);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, 'doc aaa\ndoc bbb');
- expect(hover.elementDescription, 'A<double> A()');
+ expect(hover.elementDescription, 'A<double>()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -401,7 +401,7 @@
expect(hover.containingLibraryPath, testFile.path);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, 'A<double> A()');
+ expect(hover.elementDescription, 'A<double>()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -1786,7 +1786,7 @@
var hover = await prepareHover('A');
_assertHover(
hover,
- elementDescription: 'typedef A = void Function(int a)',
+ elementDescription: 'typedef A = void Function(int)',
elementKind: 'type alias',
);
}
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 2393a15..4faa988 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -222,7 +222,7 @@
''';
var expected = '''
```dart
-(new) A A.named()
+(new) A.named()
```
Declared in `A` in _package:test/main.dart_.''';
await assertStringContents(content, equals(expected));
@@ -239,7 +239,7 @@
''';
var expected = '''
```dart
-(const) A A.named()
+(const) A.named()
```
Declared in `A` in _package:test/main.dart_.''';
await assertStringContents(content, equals(expected));
@@ -254,7 +254,7 @@
''';
var expected = '''
```dart
-(new) A A()
+(new) A()
```
Declared in `A` in _package:test/main.dart_.''';
await assertStringContents(content, equals(expected));
@@ -271,7 +271,7 @@
''';
var expected = '''
```dart
-(const) A A()
+(const) A()
```
Declared in `A` in _package:test/main.dart_.''';
await assertStringContents(content, equals(expected));
@@ -883,7 +883,7 @@
1,
2,
]);
- ''', contains('String String.fromCharCodes('));
+ ''', contains('String.fromCharCodes('));
Future<void> test_recordLiteral_named() => assertStringContents(r'''
void f(({int f1, int f2}) r) {
@@ -921,7 +921,7 @@
''',
startsWith('''
```dart
-(new) Foo Foo(
+(new) Foo(
String arg1,
String arg2, [
String? arg3,
@@ -941,7 +941,7 @@
''',
startsWith('''
```dart
-(new) Foo Foo(String a, String b)
+(new) Foo(String a, String b)
```'''),
);
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index 766a609..50ca0b0 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -70,7 +70,10 @@
void writeConstructorElement(ConstructorElementMixin2 element) {
_writeType(element.returnType);
- _write(' ${element.displayName}');
+ var displayName = element.name ?? '<null-name>';
+ if (displayName != 'new') {
+ _write('.$displayName');
+ }
_writeFormalParameters(
element.formalParameters,
@@ -130,8 +133,7 @@
_writeTypeParameters(element.typeParameters);
_write('(');
_writeType(element.representation.type);
- _write(' ');
- _write(element.representation.name ?? '<null-name}>');
+ _write(' ${element.representation.name ?? '<null-name>'}');
_write(')');
_writeTypesIfNotEmpty(' implements ', element.interfaces);
@@ -195,8 +197,7 @@
}
void writeLibraryElement(LibraryElementImpl element) {
- _write('library ');
- _write('${element.source.uri}');
+ _write('library ${element.uri}');
}
void writeLibraryExport(LibraryExportImpl element) {
@@ -211,15 +212,14 @@
void writeLocalFunctionElement(LocalFunctionElementImpl element) {
_writeType(element.returnType);
- _write(element.name ?? ' <null-name>');
+ _write(' ${element.name ?? '<null-name>'}');
_writeTypeParameters(element.typeParameters);
_writeFormalParameters(element.formalParameters, forElement: true);
}
void writeMethodElement(MethodElementImpl element) {
_writeType(element.returnType);
- _write(' ');
- _write(element.name ?? '<null-name>');
+ _write(' ${element.name ?? '<null-name>'}');
_writeTypeParameters(element.typeParameters);
_writeFormalParameters(
element.formalParameters,
@@ -256,11 +256,7 @@
void writePrefixElement(PrefixElementImpl element) {
var libraryImports = element.imports;
var displayName = element.displayName;
- if (libraryImports.isEmpty) {
- _write('as ');
- _write(displayName);
- return;
- }
+
var first = libraryImports.first;
_write("import '${first.libraryName}' as $displayName;");
if (libraryImports.length == 1) {
@@ -316,8 +312,7 @@
void writeTopLevelFunctionElement(TopLevelFunctionElementImpl element) {
_writeType(element.returnType);
- _write(' ');
- _write(element.name ?? ' <null-name>');
+ _write(' ${element.name ?? '<null-name>'}');
_writeTypeParameters(element.typeParameters);
_writeFormalParameters(
element.formalParameters,
@@ -331,13 +326,7 @@
_write(element.displayName);
_writeTypeParameters(element.typeParameters);
_write(' = ');
-
- var aliasedElement = element.aliasedElement;
- if (aliasedElement != null) {
- aliasedElement.appendTo(this);
- } else {
- _writeType(element.aliasedType);
- }
+ _writeType(element.aliasedType);
}
void writeTypeParameterElement(TypeParameterElementImpl element) {
@@ -404,10 +393,8 @@
}
void _writeDirectiveUri(DirectiveUri uri) {
- if (uri is DirectiveUriWithUnitImpl) {
- _write('unit ${uri.libraryFragment.source.uri}');
- } else if (uri is DirectiveUriWithSourceImpl) {
- _write('source ${uri.source}');
+ if (uri is DirectiveUriWithSourceImpl) {
+ _write('${uri.source.uri}');
} else {
_write('<unknown>');
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 76cb082..ebce8ef 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1795,6 +1795,20 @@
@Deprecated('Use metadata instead')
@override
MetadataImpl get metadata2 => metadata;
+
+ /// Append a textual representation to the given [builder].
+ void appendTo(ElementDisplayStringBuilder builder);
+
+ String displayString() {
+ var builder = ElementDisplayStringBuilder(preferTypeAlias: false);
+ appendTo(builder);
+ return builder.toString();
+ }
+
+ @override
+ String toString() {
+ return displayString();
+ }
}
abstract class ElementImpl implements Element {
@@ -6126,6 +6140,11 @@
LibraryElementImpl? get exportedLibrary2 {
return exportedLibrary;
}
+
+ @override
+ void appendTo(ElementDisplayStringBuilder builder) {
+ builder.writeLibraryExport(this);
+ }
}
/// A concrete implementation of [LibraryFragment].
@@ -6706,6 +6725,11 @@
@Deprecated('Use prefix instead')
@override
PrefixFragment? get prefix2 => prefix;
+
+ @override
+ void appendTo(ElementDisplayStringBuilder builder) {
+ builder.writeLibraryImport(this);
+ }
}
/// The provider for the lazily created `loadLibrary` function.
@@ -8226,6 +8250,11 @@
}
return null;
}
+
+ @override
+ void appendTo(ElementDisplayStringBuilder builder) {
+ builder.writePartInclude(this);
+ }
}
class PatternVariableElementImpl extends LocalVariableElementImpl
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element2.dart b/pkg/analyzer/lib/src/test_utilities/find_element2.dart
index 225a159..56daf50 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element2.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element2.dart
@@ -162,6 +162,7 @@
}
@override
+ // TODO(fshcheglov): rename to formalParameter()
FormalParameterElement parameter(String name) {
FormalParameterElement? result;
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 1f54f8f..a0d18d7 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -3233,7 +3233,7 @@
assertType(typeName.type, 'A<T2, U2>');
var constructorMember = redirected.element!;
- expect(constructorMember.displayString(), 'A<T2, U2> A.named()');
+ expect(constructorMember.displayString(), 'A<T2, U2>.named()');
expect(redirected.name!.element, constructorMember);
}
@@ -3266,7 +3266,7 @@
assertType(typeName.type, 'A<T2, U2>');
expect(redirected.name, isNull);
- expect(redirected.element!.displayString(), 'A<T2, U2> A()');
+ expect(redirected.element!.displayString(), 'A<T2, U2>()');
}
test_redirectingConstructor_propagation() async {
diff --git a/pkg/analyzer/test/src/dart/element/display_string_test.dart b/pkg/analyzer/test/src/dart/element/display_string_test.dart
index 9ca721e..bb08009 100644
--- a/pkg/analyzer/test/src/dart/element/display_string_test.dart
+++ b/pkg/analyzer/test/src/dart/element/display_string_test.dart
@@ -2,6 +2,8 @@
// 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:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/error/codes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -108,6 +110,39 @@
])''');
}
+ test_maybeWriteTypeAlias() async {
+ await assertNoErrorsInCode(r'''
+typedef A = int;
+A f() {
+ throw 0;
+}
+''');
+ var element = findElement2.function('f');
+ expect(element.displayString(preferTypeAlias: true), 'A f()');
+ }
+
+ test_maybeWriteTypeAlias_nullable() async {
+ await assertNoErrorsInCode(r'''
+typedef A = int;
+A? f() {
+ throw 0;
+}
+''');
+ var element = findElement2.function('f');
+ expect(element.displayString(preferTypeAlias: true), 'A? f()');
+ }
+
+ test_maybeWriteTypeAlias_typeArguments() async {
+ await assertNoErrorsInCode(r'''
+typedef A<T> = List<T>;
+A<int> f() {
+ throw 0;
+}
+''');
+ var element = findElement2.function('f');
+ expect(element.displayString(preferTypeAlias: true), 'A<int> f()');
+ }
+
test_property_getter() async {
await assertNoErrorsInCode(r'''
String get a => '';
@@ -142,4 +177,547 @@
// multiline: true.
expect(multiLine, 'String? m(String? a, [String? b])');
}
+
+ test_writeClassElement_base() async {
+ await assertNoErrorsInCode(r'''
+base class A {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'base class A');
+ }
+
+ test_writeClassElement_extends() async {
+ await assertNoErrorsInCode(r'''
+class B {}
+class A extends B {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'class A extends B');
+ }
+
+ test_writeClassElement_final() async {
+ await assertNoErrorsInCode(r'''
+final class A {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'final class A');
+ }
+
+ test_writeClassElement_implements() async {
+ await assertNoErrorsInCode(r'''
+class B {}
+class A implements B {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'class A implements B');
+ }
+
+ test_writeClassElement_interface() async {
+ await assertNoErrorsInCode(r'''
+interface class A {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'interface class A');
+ }
+
+ test_writeClassElement_mixin() async {
+ await assertNoErrorsInCode(r'''
+mixin class A {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'mixin class A');
+ }
+
+ test_writeClassElement_sealed() async {
+ await assertNoErrorsInCode(r'''
+sealed class A {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'sealed class A');
+ }
+
+ test_writeClassElement_superInterfaces() async {
+ await assertNoErrorsInCode(r'''
+class E {}
+mixin W {}
+class I {}
+class A extends E with W implements I {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'class A extends E with W implements I');
+ }
+
+ test_writeClassElement_typeParameters() async {
+ await assertNoErrorsInCode(r'''
+class A<T, S extends num>{}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'class A<T, S extends num>');
+ }
+
+ test_writeClassElement_with() async {
+ await assertNoErrorsInCode(r'''
+mixin B {}
+class A with B {}
+''');
+ var element = findElement2.class_('A');
+ expect(element.displayString(), 'class A with B');
+ }
+
+ test_writeConstructorElement_explicit_named() async {
+ await assertNoErrorsInCode(r'''
+final class A {
+ A.named();
+}
+''');
+ var element = findElement2.constructor('named');
+ expect(element.displayString(), 'A.named()');
+ }
+
+ test_writeConstructorElement_explicit_unnamed() async {
+ await assertNoErrorsInCode(r'''
+final class A {
+ A();
+}
+''');
+ var element = findElement2.unnamedConstructor('A');
+ expect(element.displayString(), 'A()');
+ }
+
+ test_writeConstructorElement_formalParameters() async {
+ await assertNoErrorsInCode(r'''
+final class A {
+ A(int a, bool b, {String? c});
+}
+''');
+ var element = findElement2.unnamedConstructor('A');
+ expect(element.displayString(), 'A(int a, bool b, {String? c})');
+ }
+
+ test_writeConstructorElement_synthetic() async {
+ await assertNoErrorsInCode(r'''
+final class A {}
+''');
+ var element = findElement2.unnamedConstructor('A');
+ expect(element.displayString(), 'A()');
+ }
+
+ test_writeDirectiveUri() async {
+ await assertErrorsInCode(
+ r'''
+import 'src/f.dart';
+''',
+ [error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12)],
+ );
+ var import =
+ findElement2.libraryFragment.libraryImports[0] as LibraryImportImpl;
+ expect(import.displayString(), "import package:test/src/f.dart");
+ }
+
+ test_writeDynamicElement() async {
+ var element = DynamicElementImpl.instance;
+ expect(element.displayString(), 'dynamic');
+ }
+
+ test_writeDynamicType() async {
+ await assertNoErrorsInCode(r'''
+void f(x) {}
+''');
+ var element = findElement2.parameter('x');
+ expect(element.displayString(), 'dynamic x');
+ }
+
+ test_writeEnumElement() async {
+ await assertNoErrorsInCode(r'''
+enum E {a, b}
+''');
+ var element = findElement2.enum_('E');
+ expect(element.displayString(), 'enum E');
+ }
+
+ test_writeEnumElement_implements() async {
+ await assertNoErrorsInCode(r'''
+class A {}
+enum E implements A {a, b}
+''');
+ var element = findElement2.enum_('E');
+ expect(element.displayString(), 'enum E implements A');
+ }
+
+ test_writeEnumElement_mixin() async {
+ await assertNoErrorsInCode(r'''
+mixin M {}
+enum E with M {a, b}
+''');
+ var element = findElement2.enum_('E');
+ expect(element.displayString(), 'enum E with M');
+ }
+
+ test_writeEnumElement_superInterfaces() async {
+ await assertNoErrorsInCode(r'''
+mixin M {}
+class C {}
+enum E with M implements C {a, b}
+''');
+ var element = findElement2.enum_('E');
+ expect(element.displayString(), 'enum E with M implements C');
+ }
+
+ test_writeEnumElement_typeParameters() async {
+ await assertNoErrorsInCode(r'''
+enum E<T> {a, b}
+''');
+ var element = findElement2.enum_('E');
+ expect(element.displayString(), 'enum E<T>');
+ }
+
+ test_writeFormalParameterElement_isNamed() async {
+ await assertNoErrorsInCode(r'''
+void f({required int? a}){}
+''');
+ var element = findElement2.parameter('a');
+ expect(element.displayString(), '{required int? a}');
+ }
+
+ test_writeFormalParameterElement_isOptionalPositional() async {
+ await assertNoErrorsInCode(r'''
+void f([int? a]){}
+''');
+ var element = findElement2.parameter('a');
+ expect(element.displayString(), '[int? a]');
+ }
+
+ test_writeGenericFunctionTypeElement() async {
+ await assertNoErrorsInCode(r'''
+void Function(int a)? f;
+''');
+ var tf = findNode.singleGenericFunctionType.declaredFragment!;
+ expect(tf.element.displayString(), 'void Function(int a)');
+ }
+
+ test_writeInvalidType() async {
+ await resolveTestCode(r'''
+nonexistentType a;
+''');
+ var element = findElement2.topVar('a');
+ expect(element.displayString(), 'InvalidType a');
+ }
+
+ test_writeLabelElement() async {
+ await assertErrorsInCode(
+ r'''
+void f() {
+ f: 0;
+}
+''',
+ [error(WarningCode.UNUSED_LABEL, 13, 2)],
+ );
+ var element = findElement2.label('f');
+ expect(element.displayString(), 'f');
+ }
+
+ test_writeLibraryElement() async {
+ await assertNoErrorsInCode(r'''
+library f;
+''');
+ var element = findElement2.libraryElement;
+ expect(element.displayString(), 'library package:test/test.dart');
+ }
+
+ test_writeLibraryExport() async {
+ await assertErrorsInCode(
+ r'''
+export 'src/f.dart';
+''',
+ [error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12)],
+ );
+ var export =
+ findElement2.libraryFragment.libraryExports.single as LibraryExportImpl;
+ expect(export.displayString(), "export package:test/src/f.dart");
+ }
+
+ test_writeLibraryImport() async {
+ await assertErrorsInCode(
+ r'''
+import 'src/f.dart';
+''',
+ [error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12)],
+ );
+ var import =
+ findElement2.libraryFragment.libraryImports[0] as LibraryImportImpl;
+ expect(import.displayString(), "import package:test/src/f.dart");
+ }
+
+ test_writeLocalFunctionElement() async {
+ await assertErrorsInCode(
+ r'''
+void f() {
+ void g() {}
+}
+''',
+ [error(WarningCode.UNUSED_ELEMENT, 18, 1)],
+ );
+ var element = findElement2.localFunction('g');
+ expect(element.displayString(), "void g()");
+ }
+
+ test_writeLocalFunctionElement_formalParameters() async {
+ await assertErrorsInCode(
+ r'''
+void f() {
+ void g(int a, bool b, {String? c}) {}
+}
+''',
+ [error(WarningCode.UNUSED_ELEMENT, 18, 1)],
+ );
+ var element = findElement2.localFunction('g');
+ expect(element.displayString(), "void g(int a, bool b, {String? c})");
+ }
+
+ test_writeLocalFunctionElement_typeParameters() async {
+ await assertErrorsInCode(
+ r'''
+void f() {
+ void g<T, S extends num>() {}
+}
+''',
+ [error(WarningCode.UNUSED_ELEMENT, 18, 1)],
+ );
+ var element = findElement2.localFunction('g');
+ expect(element.displayString(), "void g<T, S extends num>()");
+ }
+
+ test_writeMixinElement() async {
+ await assertNoErrorsInCode(r'''
+mixin M {}
+''');
+ var element = findElement2.mixin('M');
+ expect(element.displayString(), "mixin M on Object");
+ }
+
+ test_writeMixinElement_base() async {
+ await assertNoErrorsInCode(r'''
+base mixin M {}
+''');
+ var element = findElement2.mixin('M');
+ expect(element.displayString(), "base mixin M on Object");
+ }
+
+ test_writeMixinElement_implements() async {
+ await assertNoErrorsInCode(r'''
+class A{}
+mixin M implements A {}
+''');
+ var element = findElement2.mixin('M');
+ expect(element.displayString(), "mixin M on Object implements A");
+ }
+
+ test_writeMixinElement_typeParameters() async {
+ await assertNoErrorsInCode(r'''
+mixin M<T, S extends num> {}
+''');
+ var element = findElement2.mixin('M');
+ expect(element.displayString(), "mixin M<T, S extends num> on Object");
+ }
+
+ test_writeNeverElement() async {
+ var element = NeverElementImpl.instance;
+ expect(element.displayString(), "Never");
+ }
+
+ test_writeNeverType() async {
+ await assertErrorsInCode(
+ r'''
+Never a;
+''',
+ [error(CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_VARIABLE, 6, 1)],
+ );
+ var element = findElement2.topVar('a');
+ expect(element.displayString(), "Never a");
+ }
+
+ test_writePartInclude() async {
+ await assertErrorsInCode(
+ r'''
+part 'src/f.dart';
+''',
+ [error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 12)],
+ );
+ var element =
+ findElement2.libraryFragment.partIncludes.single as PartIncludeImpl;
+ expect(element.displayString(), 'part package:test/src/f.dart');
+ }
+
+ test_writePrefixElement_multipleImports() async {
+ await assertErrorsInCode(
+ r'''
+import 'src/f.dart' as a;
+import 'src/bar.dart' as a;
+''',
+ [
+ error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12),
+ error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 33, 14),
+ ],
+ );
+ var prefix = findElement2.prefix('a');
+ expect(
+ prefix.displayString(),
+ "import 'src/f.dart' as a;\nimport 'src/bar.dart' as a;",
+ );
+ }
+
+ test_writePrefixElement_singleImport() async {
+ await assertErrorsInCode(
+ r'''
+import 'src/f.dart' as a;
+''',
+ [error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12)],
+ );
+ var prefix = findElement2.prefix('a');
+ expect(prefix.displayString(), "import 'src/f.dart' as a;");
+ }
+
+ test_writeRecordType_named() async {
+ await assertNoErrorsInCode(r'''
+typedef A = ({int a, String b});
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = ({int a, String b})');
+ }
+
+ test_writeRecordType_nullable() async {
+ await assertNoErrorsInCode(r'''
+typedef A = (int, String)?;
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = (int, String)?');
+ }
+
+ test_writeRecordType_positional() async {
+ await assertNoErrorsInCode(r'''
+typedef A = (int, String);
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = (int, String)');
+ }
+
+ test_writeRecordType_positionalAndNamed() async {
+ await assertNoErrorsInCode(r'''
+typedef A = (int, String, {bool flag});
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = (int, String, {bool flag})');
+ }
+
+ test_writeRecordType_singlePositional() async {
+ await assertNoErrorsInCode(r'''
+typedef A = (int,);
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = (int,)');
+ }
+
+ test_writeSetterElement() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ set f(int value) {}
+}
+''');
+ var setter = findElement2.setter('f');
+ expect(setter.displayString(), 'set f(int value)');
+ }
+
+ test_writeTopLevelFunctionElement() async {
+ await assertNoErrorsInCode(r'''
+int f() => 0;
+''');
+ var function = findElement2.topFunction('f');
+ expect(function.displayString(), 'int f()');
+ }
+
+ test_writeTopLevelFunctionElement_formalParameters() async {
+ await assertNoErrorsInCode(r'''
+void f(int x, String y) {}
+''');
+ var function = findElement2.topFunction('f');
+ expect(function.displayString(), 'void f(int x, String y)');
+ }
+
+ test_writeTopLevelFunctionElement_typeParameters() async {
+ await assertNoErrorsInCode(r'''
+void f<T, S extends num>() {}
+''');
+ var function = findElement2.topFunction('f');
+ expect(function.displayString(), 'void f<T, S extends num>()');
+ }
+
+ test_writeTypeAliasElement_withAliasedElement() async {
+ await assertNoErrorsInCode(r'''
+typedef A = int;
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A = int');
+ }
+
+ test_writeTypeAliasElement_withAliasedElement_typeParameters() async {
+ await assertNoErrorsInCode(r'''
+typedef A<T> = List<T>;
+''');
+ var typeAlias = findElement2.typeAlias('A');
+ expect(typeAlias.displayString(), 'typedef A<out T> = List<T>');
+ }
+
+ test_writeTypeArguments() async {
+ await assertNoErrorsInCode(r'''
+Map<String, double> a = {'A': 1.5};
+''');
+ var element = findElement2.topVar('a');
+ expect(element.displayString(), 'Map<String, double> a');
+ }
+
+ test_writeTypeParameterElement() async {
+ await assertNoErrorsInCode(r'''
+void f<T extends num>() {}
+''');
+ var element = findElement2.typeParameter('T');
+ expect(element.displayString(), 'T extends num');
+ }
+
+ test_writeTypeParameterElement_covariant() async {
+ await assertNoErrorsInCode(r'''
+class A<in T> {}
+''');
+ var elementA = findElement2.typeParameter('T');
+ expect(elementA.displayString(), 'in T');
+ }
+
+ test_writeTypeParameterType() async {
+ await assertNoErrorsInCode(r'''
+void f<T>(T t) {}
+''');
+ var typeAlias = findElement2.parameter('t');
+ expect(typeAlias.displayString(), 'T t');
+ }
+
+ test_writeTypeParameterType_promotedBound() async {
+ await assertNoErrorsInCode(r'''
+void f<T extends num>(T t) {
+ if (t is int) {
+ t;
+ }
+}
+''');
+ var type = findNode.simple('t;').staticType!;
+ expect(type.getDisplayString(), 'T & int');
+ }
+
+ test_writeTypes() async {
+ await assertNoErrorsInCode(r'''
+class A {}
+class B {}
+class C implements A, B {}
+''');
+ var element = findElement2.class_('C');
+ expect(element.displayString(), 'class C implements A, B');
+ }
}