Skip to content

Commit

Permalink
[analyzer] Fix resolving target kinds
Browse files Browse the repository at this point in the history
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 <[email protected]>
Commit-Queue: Brian Wilkerson <[email protected]>
  • Loading branch information
simolus3 authored and [email protected] committed Jun 1, 2021
1 parent 10b83a4 commit 8eba520
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion pkg/analyzer/lib/src/error/best_practices_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ import 'package:meta/meta_meta.dart';
class BestPracticesVerifier extends RecursiveAstVisitor<void> {
static const String _TO_INT_METHOD_NAME = "toInt";

static final Map<String, TargetKind> _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;
Expand Down Expand Up @@ -1623,9 +1627,23 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
if (annotation.isTarget) {
var value = annotation.computeConstantValue()!;
var kinds = <TargetKind>{};

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;
}
Expand Down

0 comments on commit 8eba520

Please sign in to comment.