blob: 0f977eddb05331c549b43b06efde5741381b7ba2 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
/// A listener used to gather instrumentation information from the migration
/// engine.
class InstrumentationListener implements NullabilityMigrationInstrumentation {
/// The instrumentation information being gathered.
InstrumentationInformation data = InstrumentationInformation();
/// Initialize a newly created listener.
InstrumentationListener();
@override
void explicitTypeNullability(
Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node) {
data.nodeInformation[node] = NodeInformation(
_filePathForSource(source), typeAnnotation, null, 'the explicit type ');
_sourceInfo(source).explicitTypeNullability[typeAnnotation] = node;
}
@override
void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
_storeNodeInformation(decoratedType, element.source, null, element, '');
}
@override
void externalDecoratedTypeParameterBound(
TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType) {
_storeNodeInformation(
decoratedType, typeParameter.source, null, typeParameter, 'bound of ');
}
@override
void fix(SingleNullabilityFix fix, Iterable<FixReasonInfo> reasons) {
_sourceInfo(fix.source).fixes[fix] =
reasons.where((reason) => reason != null).toList();
}
@override
void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo) {
data.edgeOrigin[edge] = originInfo;
}
@override
void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always) {
data.never = never;
data.always = always;
}
@override
void implicitReturnType(
Source source, AstNode node, DecoratedTypeInfo decoratedReturnType) {
_storeNodeInformation(
decoratedReturnType, source, node, null, 'return type of ');
}
@override
void implicitType(
Source source, AstNode node, DecoratedTypeInfo decoratedType) {
_storeNodeInformation(decoratedType, source, node, null, 'type of ');
}
@override
void implicitTypeArguments(
Source source, AstNode node, Iterable<DecoratedTypeInfo> types) {
int i = 0;
for (var type in types) {
_storeNodeInformation(
type, source, node, null, 'implicit type argument $i of ');
i++;
}
}
@override
void propagationStep(PropagationInfo info) {
data.propagationSteps.add(info);
}
String _filePathForSource(Source source) {
return source.fullName;
}
/// Return the source information associated with the given [source], creating
/// it if there has been no previous information for that source.
SourceInformation _sourceInfo(Source source) =>
data.sourceInformation.putIfAbsent(source, () => SourceInformation());
void _storeNodeInformation(DecoratedTypeInfo decoratedType, Source source,
AstNode astNode, Element element, String description) {
// Make sure source info exists for the given source.
_sourceInfo(source);
data.nodeInformation[decoratedType.node] = NodeInformation(
_filePathForSource(source), astNode, element, description);
var dartType = decoratedType.type;
if (dartType is InterfaceType) {
for (int i = 0; i < dartType.typeArguments.length; i++) {
_storeNodeInformation(decoratedType.typeArgument(i), source, astNode,
element, 'type argument $i of $description');
}
} else if (dartType is FunctionType) {
_storeNodeInformation(decoratedType.returnType, source, astNode, element,
'return type of $description');
int i = 0;
for (var parameter in dartType.parameters) {
if (parameter.isNamed) {
var name = parameter.name;
_storeNodeInformation(decoratedType.namedParameter(name), source,
astNode, element, 'named parameter $name of $description');
} else {
_storeNodeInformation(decoratedType.positionalParameter(i), source,
astNode, element, 'positional parameter $i of $description');
i++;
}
}
}
}
}