blob: 4e6da6bc84a3a50b4867bd4633914e5a0527297c [file] [log] [blame]
// Copyright (c) 2020, 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 'dart:convert';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
/// Class with the capability of writing out a machine-readable summary of
/// migration results.
class MigrationSummary {
/// Path to which the summary should be written.
final String? summaryPath;
final ResourceProvider resourceProvider;
/// Path to the package being migrated. Entries in the summary will refer to
/// files relative to this root.
final String rootPath;
/// Map from relative file path to a map from fix name to count.
final Map<String, Map<String, int>> _changesByRelativePath = {};
MigrationSummary(this.summaryPath, this.resourceProvider, this.rootPath);
/// Records information about the [changes] made to a [source] file.
void recordChanges(Source source, Map<int?, List<AtomicEdit>> changes) {
var changeSummary = <String, int>{};
var hintsSeen = <HintComment>{};
for (var entry in changes.entries) {
for (var edit in entry.value) {
var info = edit.info;
if (info != null) {
var hint = info.hintComment;
if (hint == null || hintsSeen.add(hint)) {
var description = info.description;
var key = _keyForKind(description.kind);
changeSummary[key] = (changeSummary[key] ?? 0) + 1;
}
}
}
}
_changesByRelativePath[resourceProvider.pathContext
.relative(source.fullName, from: rootPath)] = changeSummary;
}
/// Writes out the summary data accumulated so far
void write() {
resourceProvider.getFile(summaryPath!).writeAsStringSync(jsonEncode({
'changes': {'byPath': _changesByRelativePath}
}));
}
String _keyForKind(NullabilityFixKind kind) {
switch (kind) {
case NullabilityFixKind.addThen:
return 'addThen';
case NullabilityFixKind.addImport:
return 'addImport';
case NullabilityFixKind.addLate:
return 'addLate';
case NullabilityFixKind.addLateDueToHint:
return 'addLateDueToHint';
case NullabilityFixKind.addLateDueToTestSetup:
return 'addLateDueToTestSetup';
case NullabilityFixKind.addLateFinalDueToHint:
return 'addLateFinalDueToHint';
case NullabilityFixKind.addRequired:
return 'addRequired';
case NullabilityFixKind.addType:
return 'addType';
case NullabilityFixKind.changeMethodName:
return 'changeMethodName';
case NullabilityFixKind.checkExpression:
return 'checkExpression';
case NullabilityFixKind.checkExpressionDueToHint:
return 'checkExpressionDueToHint';
case NullabilityFixKind.compoundAssignmentHasNullableSource:
return 'compoundAssignmentHasNullableSource';
case NullabilityFixKind.compoundAssignmentHasBadCombinedType:
return 'compoundAssignmentHasBadCombinedType';
case NullabilityFixKind.conditionFalseInStrongMode:
return 'conditionFalseInStrongMode';
case NullabilityFixKind.conditionTrueInStrongMode:
return 'conditionTrueInStrongMode';
case NullabilityFixKind.downcastExpression:
return 'downcastExpression';
case NullabilityFixKind.makeTypeNullable:
return 'makeTypeNullable';
case NullabilityFixKind.makeTypeNullableDueToHint:
return 'makeTypeNullableDueToHint';
case NullabilityFixKind.noValidMigrationForNull:
return 'noValidMigrationForNull';
case NullabilityFixKind.nullAwarenessUnnecessaryInStrongMode:
return 'nullAwarenessUnnecessaryInStrongMode';
case NullabilityFixKind.nullAwareAssignmentUnnecessaryInStrongMode:
return 'nullAwareAssignmentUnnecessaryInStrongMode';
case NullabilityFixKind.otherCastExpression:
return 'otherCastExpression';
case NullabilityFixKind.removeAs:
return 'removeAs';
case NullabilityFixKind.removeDeadCode:
return 'removeDeadCode';
case NullabilityFixKind.removeLanguageVersionComment:
return 'removeLanguageVersionComment';
case NullabilityFixKind.replaceVar:
return 'replaceVar';
case NullabilityFixKind.typeNotMadeNullable:
return 'typeNotMadeNullable';
case NullabilityFixKind.typeNotMadeNullableDueToHint:
return 'typeNotMadeNullableDueToHint';
case NullabilityFixKind.removeNullableAnnotation:
return 'removeNullableAnnotation';
}
}
}