Version 2.13.0-172.0.dev
Merge commit '5621c9f76702123df04e13412e14105c50bf7959' into 'dev'
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 850ffd7..1479595 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -106,33 +106,11 @@
print('');
print('Metrics computed in $duration');
- File uniqueDataFile() {
- var dataDir = result['mapDir'];
- var baseFileName = provider.pathContext.basename(rootPath);
- var index = 1;
- while (index < 10000) {
- var suffix = (index++).toString();
- suffix = '0000'.substring(suffix.length) + suffix + '.json';
- var fileName = baseFileName + suffix;
- var filePath = provider.pathContext.join(dataDir, fileName);
- var file = provider.getFile(filePath);
- if (!file.exists) {
- return file;
- }
- }
-
- /// If there are more than 10000 directories with the same name, just
- /// overwrite a previously generated file.
- var fileName = baseFileName + '9999';
- var filePath = provider.pathContext.join(dataDir, fileName);
- return provider.getFile(filePath);
- }
-
- if (result.wasParsed('mapDir')) {
- var dataFile = uniqueDataFile();
+ if (result.wasParsed('mapFile')) {
+ var mapFile = provider.getFile(result['mapFile'] as String);
var map =
computer.targetMetrics.map((metrics) => metrics.toJson()).toList();
- dataFile.writeAsStringSync(json.encode(map));
+ mapFile.writeAsStringSync(json.encode(map));
} else {
computer.printResults();
}
@@ -210,10 +188,10 @@
'worst mrr scores.',
negatable: false)
..addOption(
- 'mapDir',
- help: 'The absolute path of the directory to which the completion '
- 'metrics data will be written. Using this option will prevent the '
- 'completion results from being written in a textual form.',
+ 'mapFile',
+ help: 'The absolute path of the file to which the completion metrics '
+ 'data will be written. Using this option will prevent the completion '
+ 'results from being written in a textual form.',
)
..addOption(
'reduceDir',
@@ -247,8 +225,15 @@
printUsage(parser, error: 'No package path specified.');
return false;
}
- if (result.wasParsed('mapDir')) {
- return validateDir(parser, result['mapDir']);
+ if (result.wasParsed('mapFile')) {
+ var mapFilePath = result['mapFile'];
+ if (mapFilePath is! String ||
+ !PhysicalResourceProvider.INSTANCE.pathContext
+ .isAbsolute(mapFilePath)) {
+ printUsage(parser,
+ error: 'The path "$mapFilePath" must be an absolute path.');
+ return false;
+ }
}
return validateDir(parser, result.rest[0]);
}
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 4b2ee62e..60a3f5b 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -75,34 +75,12 @@
var rootPath = result.rest[0];
print('Analyzing root: "$rootPath"');
- File uniqueDataFile() {
- var dataDir = result['mapDir'];
- var baseFileName = provider.pathContext.basename(rootPath);
- var index = 1;
- while (index < 10000) {
- var suffix = (index++).toString();
- suffix = '0000'.substring(suffix.length) + suffix + '.json';
- var fileName = baseFileName + suffix;
- var filePath = provider.pathContext.join(dataDir, fileName);
- var file = provider.getFile(filePath);
- if (!file.exists) {
- return file;
- }
- }
-
- /// If there are more than 10000 directories with the same name, just
- /// overwrite a previously generated file.
- var fileName = baseFileName + '9999';
- var filePath = provider.pathContext.join(dataDir, fileName);
- return provider.getFile(filePath);
- }
-
var computer = RelevanceMetricsComputer();
var stopwatch = Stopwatch()..start();
await computer.compute(rootPath, verbose: result['verbose']);
- if (result.wasParsed('mapDir')) {
- var dataFile = uniqueDataFile();
- dataFile.writeAsStringSync(computer.data.toJson());
+ if (result.wasParsed('mapFile')) {
+ var mapFile = provider.getFile(result['mapFile'] as String);
+ mapFile.writeAsStringSync(computer.data.toJson());
} else {
writeRelevanceTable(computer.data);
}
@@ -123,9 +101,9 @@
negatable: false,
);
parser.addOption(
- 'mapDir',
- help: 'The absolute path of the directory to which the relevance data will '
- 'be written. Using this option will prevent the relevance table from '
+ 'mapFile',
+ help: 'The absolute path of the file to which the relevance data will be '
+ 'written. Using this option will prevent the relevance table from '
'being written.',
);
parser.addOption(
@@ -167,8 +145,15 @@
printUsage(parser, error: 'No package path specified.');
return false;
}
- if (result.wasParsed('mapDir')) {
- return validateDir(parser, result['mapDir']);
+ if (result.wasParsed('mapFile')) {
+ var mapFilePath = result['mapFile'];
+ if (mapFilePath is! String ||
+ !PhysicalResourceProvider.INSTANCE.pathContext
+ .isAbsolute(mapFilePath)) {
+ printUsage(parser,
+ error: 'The path "$mapFilePath" must be an absolute path.');
+ return false;
+ }
}
return validateDir(parser, result.rest[0]);
}
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index e04a8cc..eb3b8ec 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -363,8 +363,8 @@
.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT,
typeArgumentList[i],
);
+ continue;
}
- continue;
}
var fnTypeParam = fnTypeParams[i];
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index 1153c8e..8657fc7 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -289,6 +289,19 @@
visited,
),
);
+ for (var typeParameter in startType.typeFormals) {
+ var bound = typeParameter.bound;
+ if (bound != null) {
+ paths.addAll(
+ _findRawTypePathsToDeclaration(
+ startParameter,
+ bound,
+ end,
+ visited,
+ ),
+ );
+ }
+ }
for (var formalParameter in startType.parameters) {
paths.addAll(
_findRawTypePathsToDeclaration(
diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
index a325de8..45a0336 100644
--- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart
+++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart
@@ -145,6 +145,7 @@
var collector = _TypeCollector();
if (type is GenericFunctionType) {
collector.addType(type.returnType);
+ collector.visitTypeParameters(type.typeParameters);
collector.visitParameters(type.parameters);
} else {
collector.addType(type);
@@ -283,6 +284,7 @@
if (type is GenericFunctionType) {
var collector = _TypeCollector();
collector.addType(type.returnType);
+ collector.visitTypeParameters(type.typeParameters);
collector.visitParameters(type.parameters);
for (var type in collector.types) {
if (!_visitType(dependencies, type, allowTypeParameters)) {
@@ -326,4 +328,12 @@
visitParameter(parameter);
}
}
+
+ void visitTypeParameters(TypeParameterList? node) {
+ if (node != null) {
+ for (var typeParameter in node.typeParameters) {
+ addType(typeParameter.bound);
+ }
+ }
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart b/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart
index d2c6f73..c7254f7 100644
--- a/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart
@@ -102,6 +102,14 @@
]);
}
+ test_class_recursion_notInstantiated_genericFunctionType2() async {
+ await assertErrorsInCode(r'''
+class A<T extends void Function<U extends A>()> {}
+''', [
+ error(CompileTimeErrorCode.NOT_INSTANTIATED_BOUND, 42, 1),
+ ]);
+ }
+
test_class_recursion_typedef_notInstantiated() async {
await assertErrorsInCode(r'''
typedef F(C value);
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index cf8da3e..b8c2b5c 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -471,6 +471,30 @@
''');
}
+ test_methodInvocation_genericFunctionTypeArgument_match() async {
+ await assertNoErrorsInCode(r'''
+typedef F = void Function<T extends num>();
+void f<T extends void Function<X extends num>()>() {}
+void g() {
+ f<F>();
+}
+''');
+ }
+
+ test_methodInvocation_genericFunctionTypeArgument_mismatch() async {
+ await assertErrorsInCode(r'''
+class A {}
+class B {}
+typedef F = void Function<T extends A>();
+void f<T extends void Function<U extends B>()>() {}
+void g() {
+ f<F>();
+}
+''', [
+ error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 131, 1),
+ ]);
+ }
+
test_nonFunctionTypeAlias_interfaceType_parameter() async {
await assertErrorsInCode(r'''
class A {}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 9a6f814..7403527 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1778,6 +1778,20 @@
withTypeParameterVariance: true);
}
+ test_class_typeParameters_defaultType_cycle_genericFunctionType2() async {
+ featureSet = FeatureSets.genericMetadata;
+ var library = await checkLibrary(r'''
+class C<T extends void Function<U extends C>()> {}
+''');
+ checkElementText(
+ library,
+ r'''
+notSimplyBounded class C<covariant T extends void Function<U extends C<dynamic>>()> {
+}
+''',
+ withTypeParameterVariance: true);
+ }
+
test_class_typeParameters_defaultType_functionTypeAlias_contravariant_legacy() async {
featureSet = FeatureSets.beforeNullSafe;
var library = await checkLibrary(r'''
diff --git a/tests/language/regress/regress33479_test.dart b/tests/language/regress/regress33479_test.dart
index 568b6f8..a825b94 100644
--- a/tests/language/regress/regress33479_test.dart
+++ b/tests/language/regress/regress33479_test.dart
@@ -1,13 +1,17 @@
class Hest<TypeX extends Fisk> {}
+// ^^^^
+// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
// ^
// [cfe] Type variables can't have generic function types in their bounds.
typedef Fisk = void Function // don't merge lines
-// [error line 5, column 1, length 346]
+// [error line 7, column 1, length 346]
// [analyzer] COMPILE_TIME_ERROR.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
// ^
// [cfe] Generic type 'Fisk' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest'.
<TypeY extends Hest>();
+// ^^^^
+// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
main() {
Hest hest = new Hest();
diff --git a/tests/language_2/regress/regress33479_test.dart b/tests/language_2/regress/regress33479_test.dart
index 568b6f8..a825b94 100644
--- a/tests/language_2/regress/regress33479_test.dart
+++ b/tests/language_2/regress/regress33479_test.dart
@@ -1,13 +1,17 @@
class Hest<TypeX extends Fisk> {}
+// ^^^^
+// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
// ^
// [cfe] Type variables can't have generic function types in their bounds.
typedef Fisk = void Function // don't merge lines
-// [error line 5, column 1, length 346]
+// [error line 7, column 1, length 346]
// [analyzer] COMPILE_TIME_ERROR.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
// ^
// [cfe] Generic type 'Fisk' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest'.
<TypeY extends Hest>();
+// ^^^^
+// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
main() {
Hest hest = new Hest();
diff --git a/tools/VERSION b/tools/VERSION
index 8deb960..46449c0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 171
+PRERELEASE 172
PRERELEASE_PATCH 0
\ No newline at end of file