From 8eba5201159e001520f93bf5d398dfacf5930fd1 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Tue, 1 Jun 2021 15:27:23 +0000 Subject: [PATCH] [analyzer] Fix resolving target kinds As the analyzer is shipped with the SDK, it may have to analyze sources using a newer version of package:meta than the one it was compiled with. If that new version adds a new TargetKind, attempting to resolve that constant with `TargetKind.values[index]` may cause a range error. Further, if a new TargetKind is not added at the end of that enum, the analyzer will misinterpret the constant values. This CL fixes both issues by comparing target kinds by their name. Unknown target kinds from a newer meta version are ignored since the analyzer would not be capable of analyzing them either way. Bug: 46183 Change-Id: Ibbb7063ae9939e95f846076d7fe462e222a8a5bb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/201760 Reviewed-by: Brian Wilkerson Commit-Queue: Brian Wilkerson --- .../src/error/best_practices_verifier.dart | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart index 90a736934c6..285d5f70cfa 100644 --- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart +++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart @@ -41,6 +41,10 @@ import 'package:meta/meta_meta.dart'; class BestPracticesVerifier extends RecursiveAstVisitor { static const String _TO_INT_METHOD_NAME = "toInt"; + static final Map _targetKindsByName = { + for (final kind in TargetKind.values) kind.toString(): kind, + }; + /// The class containing the AST nodes being visited, or `null` if we are not /// in the scope of a class. ClassElementImpl? _enclosingClass; @@ -1623,9 +1627,23 @@ class BestPracticesVerifier extends RecursiveAstVisitor { if (annotation.isTarget) { var value = annotation.computeConstantValue()!; var kinds = {}; + for (var kindObject in value.getField('kinds')!.toSetValue()!) { + // We can't directly translate the index from the analyzed TargetKind + // constant to TargetKinds.values because the analyzer from the SDK + // may have been compiled with a different version of pkg:meta. var index = kindObject.getField('index')!.toIntValue()!; - kinds.add(TargetKind.values[index]); + var targetKindClass = + (kindObject.type as InterfaceType).element as EnumElementImpl; + // Instead, map constants to their TargetKind by comparing getter + // names. + var getter = targetKindClass.constants[index]; + var name = 'TargetKind.${getter.name}'; + + var foundTargetKind = _targetKindsByName[name]; + if (foundTargetKind != null) { + kinds.add(foundTargetKind); + } } return kinds; }