Add handling for error cases in class_test regarding too few or too many TypeParameters in augments. Also added handling for cases involving TypeParameter bounds, and fixed several errors leading their incorrect display. Change-Id: Ice908849daae2e115b34f50e55be1f2fca82cc96 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448443 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart index c8917e3..2283d02 100644 --- a/pkg/analyzer/lib/src/dart/element/element.dart +++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4609,6 +4609,11 @@ _setters.add(fragment); fragment.enclosingFragment = this; } + + void addTypeParameter(TypeParameterFragmentImpl typeParameter) { + _typeParameters.add(typeParameter); + typeParameter.enclosingFragment = this; + } } abstract class InterfaceElementImpl extends InstanceElementImpl @@ -10127,7 +10132,8 @@ MetadataImpl get metadata2 => metadata; @override - int get offset => nameOffset ?? firstTokenOffset!; + int get offset => + nameOffset ?? firstTokenOffset ?? enclosingFragment?.offset ?? -1; void addFragment(TypeParameterFragmentImpl fragment) { fragment.element = element;
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart index ab5e759..e743c2a 100644 --- a/pkg/analyzer/lib/src/summary2/element_builder.dart +++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -195,6 +195,26 @@ lastFragment.addFragment(fragment); var lastTypeParameterFragments = lastFragment.typeParameters; + + // Trim extra type parameters. + if (lastTypeParameterFragments.length < fragment.typeParameters.length) { + fragment.typeParameters.length = lastTypeParameterFragments.length; + } + + // Synthesize missing type parameters. + if (lastTypeParameterFragments.length > fragment.typeParameters.length) { + for ( + var i = fragment.typeParameters.length; + i < lastTypeParameterFragments.length; + i++ + ) { + fragment.addTypeParameter( + TypeParameterFragmentImpl(name: lastTypeParameterFragments[i].name) + ..isSynthetic = true, + ); + } + } + for (var i = 0; i < lastTypeParameterFragments.length; i++) { lastTypeParameterFragments[i].addFragment(fragment.typeParameters[i]); }
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart index ec14073..5e80530 100644 --- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart +++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -569,7 +569,9 @@ if (bound != null) { bound.accept(this); var fragment = node.declaredFragment!; - fragment.element.bound = bound.type; + if (fragment.previousFragment == null) { + fragment.element.bound = bound.type; + } nodesToBuildType.addDeclaration(node); } }
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart index 5149ee9..d3cd9c7 100644 --- a/pkg/analyzer/lib/src/summary2/types_builder.dart +++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -396,7 +396,9 @@ void _typeParameter(TypeParameterImpl node) { var fragment = node.declaredFragment!; - fragment.element.bound = node.bound?.type; + if (fragment.previousFragment == null) { + fragment.element.bound = node.bound?.type; + } } List<TypeParameterFragmentImpl> _typeParameters(TypeParameterListImpl? node) {
diff --git a/pkg/analyzer/test/src/summary/elements/class_test.dart b/pkg/analyzer/test/src/summary/elements/class_test.dart index a3b9f1e..2fc6bba 100644 --- a/pkg/analyzer/test/src/summary/elements/class_test.dart +++ b/pkg/analyzer/test/src/summary/elements/class_test.dart
@@ -27892,7 +27892,7 @@ '''); } - test_typeParameters() async { + test_typeParameters_111() async { var library = await buildLibrary(r''' class A<T> {} augment class A<T> {} @@ -27940,6 +27940,269 @@ '''); } + test_typeParameters_121() async { + var library = await buildLibrary(r''' +class A<T> {} +augment class A<T, U> {} +augment class A<T> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F2 class A (nameOffset:28) (firstTokenOffset:14) (offset:28) + element: <testLibrary>::@class::A + previousFragment: #F1 + nextFragment: #F5 + typeParameters + #F4 T (nameOffset:30) (firstTokenOffset:30) (offset:30) + element: #E0 T + previousFragment: #F3 + nextFragment: #F6 + #F5 class A (nameOffset:53) (firstTokenOffset:39) (offset:53) + element: <testLibrary>::@class::A + previousFragment: #F2 + typeParameters + #F6 T (nameOffset:55) (firstTokenOffset:55) (offset:55) + element: #E0 T + previousFragment: #F4 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 +'''); + } + + test_typeParameters_212() async { + var library = await buildLibrary(r''' +class A<T, U> {} +augment class A<T> {} +augment class A<T, U> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F5 U (nameOffset:11) (firstTokenOffset:11) (offset:11) + element: #E1 U + nextFragment: #F6 + #F2 class A (nameOffset:31) (firstTokenOffset:17) (offset:31) + element: <testLibrary>::@class::A + previousFragment: #F1 + nextFragment: #F7 + typeParameters + #F4 T (nameOffset:33) (firstTokenOffset:33) (offset:33) + element: #E0 T + previousFragment: #F3 + nextFragment: #F8 + #F6 U (nameOffset:<null>) (firstTokenOffset:<null>) (offset:31) + element: #E1 U + previousFragment: #F5 + nextFragment: #F9 + #F7 class A (nameOffset:53) (firstTokenOffset:39) (offset:53) + element: <testLibrary>::@class::A + previousFragment: #F2 + typeParameters + #F8 T (nameOffset:55) (firstTokenOffset:55) (offset:55) + element: #E0 T + previousFragment: #F4 + #F9 U (nameOffset:58) (firstTokenOffset:58) (offset:58) + element: #E1 U + previousFragment: #F6 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 + #E1 U + firstFragment: #F5 +'''); + } + + test_typeParameters_bounds_01() async { + var library = await buildLibrary(r''' +class A<T2> {} +augment class A<T2 extends int> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T2 (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T2 + nextFragment: #F4 + #F2 class A (nameOffset:29) (firstTokenOffset:15) (offset:29) + element: <testLibrary>::@class::A + previousFragment: #F1 + typeParameters + #F4 T2 (nameOffset:31) (firstTokenOffset:31) (offset:31) + element: #E0 T2 + previousFragment: #F3 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T2 + firstFragment: #F3 +'''); + } + + test_typeParameters_bounds_10() async { + var library = await buildLibrary(r''' +class A<T extends int> {} +augment class A<T> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F2 class A (nameOffset:40) (firstTokenOffset:26) (offset:40) + element: <testLibrary>::@class::A + previousFragment: #F1 + typeParameters + #F4 T (nameOffset:42) (firstTokenOffset:42) (offset:42) + element: #E0 T + previousFragment: #F3 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 + bound: int +'''); + } + + test_typeParameters_bounds_11() async { + var library = await buildLibrary(r''' +class A<T extends int> {} +augment class A<T extends int> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F2 class A (nameOffset:40) (firstTokenOffset:26) (offset:40) + element: <testLibrary>::@class::A + previousFragment: #F1 + typeParameters + #F4 T (nameOffset:42) (firstTokenOffset:42) (offset:42) + element: #E0 T + previousFragment: #F3 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 + bound: int +'''); + } + + test_typeParameters_bounds_12() async { + var library = await buildLibrary(r''' +class A<T extends int> {} +augment class A<T extends String> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F2 class A (nameOffset:40) (firstTokenOffset:26) (offset:40) + element: <testLibrary>::@class::A + previousFragment: #F1 + typeParameters + #F4 T (nameOffset:42) (firstTokenOffset:42) (offset:42) + element: #E0 T + previousFragment: #F3 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 + bound: int +'''); + } + test_typeParameters_defaultType() async { var library = await buildLibrary(r''' class A<T extends B> {} @@ -28000,6 +28263,52 @@ firstFragment: #F7 '''); } + + test_typeParameters_differentNames() async { + var library = await buildLibrary(r''' +class A<T, U> {} +augment class A<U, T> {} +'''); + + configuration.withConstructors = false; + checkElementText(library, r''' +library + reference: <testLibrary> + fragments + #F0 <testLibraryFragment> + element: <testLibrary> + classes + #F1 class A (nameOffset:6) (firstTokenOffset:0) (offset:6) + element: <testLibrary>::@class::A + nextFragment: #F2 + typeParameters + #F3 T (nameOffset:8) (firstTokenOffset:8) (offset:8) + element: #E0 T + nextFragment: #F4 + #F5 U (nameOffset:11) (firstTokenOffset:11) (offset:11) + element: #E1 U + nextFragment: #F6 + #F2 class A (nameOffset:31) (firstTokenOffset:17) (offset:31) + element: <testLibrary>::@class::A + previousFragment: #F1 + typeParameters + #F4 U (nameOffset:33) (firstTokenOffset:33) (offset:33) + element: #E0 T + previousFragment: #F3 + #F6 T (nameOffset:36) (firstTokenOffset:36) (offset:36) + element: #E1 U + previousFragment: #F5 + classes + class A + reference: <testLibrary>::@class::A + firstFragment: #F1 + typeParameters + #E0 T + firstFragment: #F3 + #E1 U + firstFragment: #F5 +'''); + } } @reflectiveTest