Skip to content

Commit

Permalink
DevX. Issue 22915. Show instantiated type alias in diagnostics.
Browse files Browse the repository at this point in the history
Bug: #22915
Change-Id: I733bcb6021a167825840027df371fd22cfc71ce3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370701
Reviewed-by: Sam Rawlins <[email protected]>
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
  • Loading branch information
scheglov authored and Commit Queue committed Jun 10, 2024
1 parent ea9eb67 commit 31a4bb7
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 2 deletions.
7 changes: 5 additions & 2 deletions pkg/analyzer/lib/error/listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart';
import 'package:meta/meta.dart';
import 'package:source_span/source_span.dart';
Expand Down Expand Up @@ -340,8 +341,10 @@ class ErrorReporter {
Map<String, List<_TypeToConvert>> typeGroups = {};
for (int i = 0; i < arguments.length; i++) {
var argument = arguments[i];
if (argument is DartType) {
String displayName = argument.getDisplayString();
if (argument is TypeImpl) {
String displayName = argument.getDisplayString(
preferTypeAlias: true,
);
List<_TypeToConvert> types =
typeGroups.putIfAbsent(displayName, () => <_TypeToConvert>[]);
types.add(_TypeToConvert(i, argument, displayName));
Expand Down
28 changes: 28 additions & 0 deletions pkg/analyzer/lib/src/dart/element/display_string_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ class ElementDisplayStringBuilder {
/// Whether to allow a display string to be written in multiple lines.
final bool _multiline;

/// Whether to write instantiated type alias when available.
final bool preferTypeAlias;

ElementDisplayStringBuilder({
@Deprecated('Only non-nullable by default mode is supported')
bool withNullability = true,
bool multiline = false,
required this.preferTypeAlias,
}) : _withNullability = withNullability,
_multiline = multiline;

Expand Down Expand Up @@ -179,6 +183,10 @@ class ElementDisplayStringBuilder {
}

void writeFunctionType(FunctionType type) {
if (_maybeWriteTypeAlias(type)) {
return;
}

type = _uniqueTypeParameters(type);

_writeType(type.returnType);
Expand All @@ -201,6 +209,10 @@ class ElementDisplayStringBuilder {
}

void writeInterfaceType(InterfaceType type) {
if (_maybeWriteTypeAlias(type)) {
return;
}

_write(type.element.name);
_writeTypeArguments(type.typeArguments);
_writeNullability(type.nullabilitySuffix);
Expand Down Expand Up @@ -245,6 +257,10 @@ class ElementDisplayStringBuilder {
}

void writeRecordType(RecordType type) {
if (_maybeWriteTypeAlias(type)) {
return;
}

var positionalFields = type.positionalFields;
var namedFields = type.namedFields;
var fieldCount = positionalFields.length + namedFields.length;
Expand Down Expand Up @@ -355,6 +371,18 @@ class ElementDisplayStringBuilder {
_write('void');
}

bool _maybeWriteTypeAlias(DartType type) {
if (preferTypeAlias) {
if (type.alias case var alias?) {
_write(alias.element.name);
_writeTypeArguments(alias.typeArguments);
_writeNullability(type.nullabilitySuffix);
return true;
}
}
return false;
}

void _write(String str) {
_buffer.write(str);
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/analyzer/lib/src/dart/element/element.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2486,9 +2486,11 @@ abstract class ElementImpl implements Element {
@Deprecated('Only non-nullable by default mode is supported')
bool withNullability = true,
bool multiline = false,
bool preferTypeAlias = false,
}) {
var builder = ElementDisplayStringBuilder(
multiline: multiline,
preferTypeAlias: preferTypeAlias,
);
appendTo(builder);
return builder.toString();
Expand Down
2 changes: 2 additions & 0 deletions pkg/analyzer/lib/src/dart/element/member.dart
Original file line number Diff line number Diff line change
Expand Up @@ -713,9 +713,11 @@ abstract class Member implements Element {
@Deprecated('Only non-nullable by default mode is supported')
bool withNullability = true,
bool multiline = false,
bool preferTypeAlias = false,
}) {
var builder = ElementDisplayStringBuilder(
multiline: multiline,
preferTypeAlias: preferTypeAlias,
);
appendTo(builder);
return builder.toString();
Expand Down
2 changes: 2 additions & 0 deletions pkg/analyzer/lib/src/dart/element/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1342,10 +1342,12 @@ abstract class TypeImpl implements DartType {
String getDisplayString({
@Deprecated('Only non-nullable by default mode is supported')
bool withNullability = true,
bool preferTypeAlias = false,
}) {
var builder = ElementDisplayStringBuilder(
// ignore:deprecated_member_use_from_same_package
withNullability: withNullability,
preferTypeAlias: preferTypeAlias,
);
appendTo(builder);
return builder.toString();
Expand Down
42 changes: 42 additions & 0 deletions pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,48 @@ I x = E.v;
]);
}

test_invalid_message_preferTypeAlias_functionType() async {
await assertErrorsInCode('''
typedef A<T> = T Function();
void f(A<int> a) {
A<String> b = a;
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 61, 1),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 65, 1,
messageContains: ['A<int>', 'A<String>']),
]);
}

test_invalid_message_preferTypeAlias_interfaceType() async {
await assertErrorsInCode('''
typedef A<T> = List<T>;
void f(A<int> a) {
A<String> b = a;
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 56, 1),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 60, 1,
messageContains: ['A<int>', 'A<String>']),
]);
}

test_invalid_message_preferTypeAlias_recordType() async {
await assertErrorsInCode('''
typedef A<T> = (T, T);
void f(A<int> a) {
A<String> b = a;
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 55, 1),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 59, 1,
messageContains: ['A<int>', 'A<String>']),
]);
}

test_invalid_noCall_functionContext() async {
await assertErrorsInCode('''
class C {}
Expand Down

0 comments on commit 31a4bb7

Please sign in to comment.