Add annotations to direct the null-safety migration tool.
Change-Id: Id025c8022aaae417b70ef1cd32e0fb8ec4af3e6b
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/223940
Reviewed-by: Alexander Thomas <athom@google.com>
diff --git a/builder/bin/update_results_database.dart b/builder/bin/update_results_database.dart
index e94d20a..41a14f0 100644
--- a/builder/bin/update_results_database.dart
+++ b/builder/bin/update_results_database.dart
@@ -17,7 +17,7 @@
Future<List<Map<String, dynamic>>> readChangedResults(File resultsFile) async {
final lines = (await resultsFile.readAsLines())
- .map((line) => jsonDecode(line) as Map<String, dynamic>);
+ .map((line) => jsonDecode(line) /*!*/ as Map<String, dynamic>);
if (lines.isEmpty) {
print('Empty input results.json file');
exit(1);
diff --git a/builder/lib/src/builder.dart b/builder/lib/src/builder.dart
index 92b8307..91223d2 100644
--- a/builder/lib/src/builder.dart
+++ b/builder/lib/src/builder.dart
@@ -15,14 +15,14 @@
/// [FirestoreService] object.
/// Tryjob builds are represented by the class [Tryjob] instead.
class Build {
- final FirestoreService firestore;
- final CommitsCache commitsCache;
- final BuildInfo info;
+ final FirestoreService /*!*/ firestore;
+ final CommitsCache /*!*/ commitsCache;
+ final BuildInfo /*!*/ info;
final TestNameLock testNameLock = TestNameLock();
- int startIndex;
- int endIndex;
- Commit endCommit;
- List<Commit> commits;
+ /*late final*/ int /*!*/ startIndex;
+ /*late*/ int /*!*/ endIndex;
+ /*late*/ Commit /*!*/ endCommit;
+ List<Commit /*!*/ > commits;
Map<String, int> tryApprovals = {};
List<RevertedChanges> allRevertedChanges = [];
@@ -36,7 +36,7 @@
void log(String string) => firestore.log(string);
- Future<void> process(List<Map<String, dynamic>> changes) async {
+ Future<void> process(List<Map<String, dynamic> /*!*/ > changes) async {
log('store build commits info');
await storeBuildCommitsInfo();
log('update build info');
@@ -47,8 +47,9 @@
// TODO(karlklose): add a flag to overwrite builder results.
return;
}
- final configurations =
- changes.map((change) => change['configuration'] as String).toSet();
+ final configurations = changes
+ .map((change) => change['configuration'] as String /*!*/)
+ .toSet();
await update(configurations);
log('storing ${changes.length} change(s)');
await Pool(30).forEach(changes, guardedStoreChange).drain();
@@ -72,7 +73,7 @@
log(report.join('\n'));
}
- Future<void> update(Iterable<String> configurations) async {
+ Future<void> update(Iterable<String /*!*/ > configurations) async {
await storeConfigurationsInfo(configurations);
}
@@ -81,17 +82,18 @@
/// Saves the commit indices of the start and end of the blamelist.
Future<void> storeBuildCommitsInfo() async {
// Get indices of change. Range includes startIndex and endIndex.
- endCommit = await commitsCache.getCommit(info.commitRef);
- if (endCommit == null) {
+ final commit = await commitsCache.getCommit(info.commitRef);
+ if (commit == null) {
throw 'Result received with unknown commit hash ${info.commitRef}';
}
+ endCommit = commit;
endIndex = endCommit.index;
// If this is a new builder, use the current commit as a trivial blamelist.
if (info.previousCommitHash == null) {
startIndex = endIndex;
} else {
final startCommit = await commitsCache.getCommit(info.previousCommitHash);
- startIndex = startCommit.index + 1;
+ startIndex = startCommit /*!*/ .index + 1;
if (startIndex > endIndex) {
throw ArgumentError('Results received with empty blamelist\n'
'previous commit: ${info.previousCommitHash}\n'
@@ -109,7 +111,7 @@
endCommit
];
for (final commit in commits) {
- final index = commit.index;
+ final index = commit /*!*/ .index;
final review = commit.review;
final reverted = commit.revertOf;
if (review != null) {
@@ -139,7 +141,7 @@
await fetchReviewsAndReverts();
transformChange(change);
final failure = isFailure(change);
- bool approved;
+ bool /*!*/ approved;
var result = await firestore.findResult(change, startIndex, endIndex);
var activeResults = await firestore.findActiveResults(
change['name'], change['configuration']);
@@ -189,7 +191,7 @@
Map<String, dynamic> constructResult(
Map<String, dynamic> change, int startIndex, int endIndex,
- {bool approved, int landedReviewIndex, bool failure}) {
+ {bool /*!*/ approved, int landedReviewIndex, bool failure}) {
return {
fName: change[fName],
fResult: change[fResult],
@@ -198,9 +200,9 @@
fBlamelistStartIndex: startIndex,
fBlamelistEndIndex: endIndex,
if (startIndex != endIndex && approved) fPinnedIndex: landedReviewIndex,
- fConfigurations: <String>[change['configuration']],
+ fConfigurations: <String /*!*/ >[change['configuration']],
fApproved: approved,
if (failure) fActive: true,
- if (failure) fActiveConfigurations: <String>[change['configuration']]
+ if (failure) fActiveConfigurations: <String /*!*/ >[change['configuration']]
};
}
diff --git a/builder/lib/src/commits_cache.dart b/builder/lib/src/commits_cache.dart
index 67d5362..7fe9043 100644
--- a/builder/lib/src/commits_cache.dart
+++ b/builder/lib/src/commits_cache.dart
@@ -16,39 +16,47 @@
/// The class fetches commits from Firestore if they are present,
/// and fetches them from gitiles if not, and saves them to Firestore.
class CommitsCache {
- FirestoreService firestore;
- final http.Client httpClient;
- Map<String, Commit> byHash = {};
+ FirestoreService /*!*/ firestore;
+ final http.Client /*!*/ httpClient;
+ Map<String /*!*/, Commit> byHash = {};
Map<int, Commit> byIndex = {};
int startIndex;
int endIndex;
CommitsCache(this.firestore, this.httpClient);
- Future<Commit> getCommit(String hash) async {
- return byHash[hash] ??
- await _fetchByHash(hash) ??
- await _getNewCommits() ??
- await _fetchByHash(hash) ??
- _reportError('getCommit($hash)');
+ Future<Commit /*!*/ > getCommit(String /*!*/ hash) async {
+ var commit = byHash[hash] ?? await _fetchByHash(hash);
+ if (commit == null) {
+ await _getNewCommits();
+ commit = await _fetchByHash(hash);
+ }
+ if (commit == null) {
+ throw _makeError('getCommit($hash)');
+ }
+ return commit;
}
- Future<Commit> getCommitByIndex(int index) async {
- return byIndex[index] ??
- await _fetchByIndex(index) ??
- await _getNewCommits() ??
- await _fetchByIndex(index) ??
- _reportError('getCommitByIndex($index)');
+ Future<Commit /*!*/ > getCommitByIndex(int /*!*/ index) async {
+ var commit = byIndex[index] ?? await _fetchByIndex(index);
+ if (commit == null) {
+ await _getNewCommits();
+ commit = await _fetchByIndex(index);
+ }
+ if (commit == null) {
+ throw _makeError('getCommitByIndex($index)');
+ }
+ return commit;
}
- Commit _reportError(String message) {
+ String _makeError(String message) {
final error = 'Failed to fetch commit: $message\n'
'Commit cache holds:\n'
- ' $startIndex: ${byIndex[startIndex]}\n'
+ ' $startIndex: ${byIndex[startIndex ?? -1]}\n'
' ...\n'
- ' $endIndex: ${byIndex[endIndex]}';
+ ' $endIndex: ${byIndex[endIndex ?? -1]}';
print(error);
- throw error;
+ return error;
}
/// Add a commit to the cache. The cache must be empty, or the commit
@@ -68,7 +76,7 @@
byIndex[index] = commit;
}
- Future<Commit> _fetchByHash(String hash) async {
+ Future<Commit> _fetchByHash(String /*!*/ hash) async {
final commit = await firestore.getCommit(hash);
if (commit == null) return null;
final index = commit.index;
@@ -96,14 +104,14 @@
return commit;
}
- Future<Commit> _fetchByIndex(int index) => firestore
+ Future<Commit> _fetchByIndex(int /*!*/ index) => firestore
.getCommitByIndex(index)
.then((commit) => _fetchByHash(commit.hash));
/// This function is idempotent, so every call of it should write the
/// same info to new Firestore documents. It is safe to call multiple
/// times simultaneously. Intentionally returns null, not void.
- Future<Commit> _getNewCommits() async {
+ Future<void> _getNewCommits() async {
const prefix = ")]}'\n";
final lastCommit = await firestore.getLastCommit();
final lastHash = lastCommit.hash;
@@ -120,20 +128,19 @@
throw Exception('Gerrit response missing prefix $prefix: $protectedJson.'
'Requested URL: $url');
}
- final commits = jsonDecode(protectedJson.substring(prefix.length))['log']
- as List<dynamic>;
+ final commits = List.castFrom<dynamic, Map<String, dynamic>>(
+ jsonDecode(protectedJson.substring(prefix.length))['log']);
if (commits.isEmpty) {
print('Found no new commits between $lastHash and $branch');
- return null;
}
print('Fetched new commits from Gerrit (gitiles): $commits');
- final first = commits.last as Map<String, dynamic>;
+ final first = commits.last;
if (first['parents'].first != lastHash) {
throw 'First new commit ${first['commit']} is not'
' a child of last known commit $lastHash when fetching new commits';
}
var index = lastIndex + 1;
- for (Map<String, dynamic> commit in commits.reversed) {
+ for (final commit in commits.reversed) {
final review = _review(commit);
var reverted = _revert(commit);
var relanded = _reland(commit);
@@ -161,7 +168,6 @@
}
++index;
}
- return null;
}
/// This function is idempotent and may be called multiple times
@@ -180,11 +186,10 @@
TestingCommitsCache(firestore, httpClient) : super(firestore, httpClient);
@override
- Future<Commit> _getNewCommits() async {
+ Future<void> _getNewCommits() async {
if ((await firestore.isStaging())) {
return super._getNewCommits();
}
- return null;
}
}
diff --git a/builder/lib/src/firestore.dart b/builder/lib/src/firestore.dart
index 91f6435..13d6824 100644
--- a/builder/lib/src/firestore.dart
+++ b/builder/lib/src/firestore.dart
@@ -16,22 +16,22 @@
class Commit {
final SafeDocument document;
- final String hash;
+ final String hash /*!*/;
Commit(this.hash, this.document);
Commit.fromJson(this.hash, Map<String, dynamic> data)
: document = SafeDocument(Document(fields: taggedMap(data), name: ''));
- int get index => document.getInt('index');
+ int /*!*/ get index => document.getInt('index');
String get revertOf => document.getString(fRevertOf);
- bool get isRevert => document.fields.containsKey(fRevertOf);
+ bool /*!*/ get isRevert => document.fields.containsKey(fRevertOf);
int get review => document.getInt(fReview);
Map<String, Object> toJson() => untagMap(document.fields);
}
class FirestoreService {
- final String project;
- final FirestoreApi firestore;
- final http.Client client;
+ final String /*!*/ project;
+ final FirestoreApi /*!*/ firestore;
+ final http.Client /*!*/ client;
int documentsFetched = 0;
int documentsWritten = 0;
@@ -50,7 +50,7 @@
}
Future<List<SafeDocument>> query(
- {String from,
+ {String /*!*/ from,
Filter where,
Order orderBy,
int limit,
@@ -71,14 +71,26 @@
return runQuery(query, parent: parent);
}
- Future<Document> getDocument(String path,
- {bool throwOnNotFound = true}) async {
+ Future<Document /*!*/ > getDocument(String path) async {
+ try {
+ final document = await firestore.projects.databases.documents.get(path);
+ documentsFetched++;
+ return document;
+ } on DetailedApiRequestError {
+ log("Failed to get document '$path'");
+ rethrow;
+ }
+ }
+
+ Future<Document /*?*/ > getDocumentOrNull(
+ String path,
+ ) async {
try {
final document = await firestore.projects.databases.documents.get(path);
documentsFetched++;
return document;
} on DetailedApiRequestError catch (e) {
- if (!throwOnNotFound && e.status == 404) {
+ if (e.status == 404) {
return null;
} else {
log("Failed to get document '$path'");
@@ -116,7 +128,7 @@
Future<bool> isStaging() => Future.value(project == 'dart-ci-staging');
- Future<bool> hasPatchset(String review, String patchset) {
+ Future<bool> hasPatchset(String /*!*/ review, String /*!*/ patchset) {
return documentExists('$documents/reviews/$review/patchsets/$patchset');
}
@@ -126,8 +138,7 @@
}
Future<Commit> getCommit(String hash) async {
- final document =
- await getDocument('$documents/commits/$hash', throwOnNotFound: false);
+ final document = await getDocumentOrNull('$documents/commits/$hash');
return document != null ? Commit(hash, SafeDocument(document)) : null;
}
@@ -143,7 +154,7 @@
return _commit(lastCommit.first);
}
- Future<void> addCommit(String id, Map<String, dynamic> data) async {
+ Future<void> addCommit(String /*!*/ id, Map<String, dynamic> data) async {
try {
final document = Document()..fields = taggedMap(data);
await firestore.projects.databases.documents
@@ -161,8 +172,8 @@
Future<void> updateConfiguration(String configuration, String builder) async {
documentsWritten++;
- final record = await getDocument('$documents/configurations/$configuration',
- throwOnNotFound: false);
+ final record =
+ await getDocumentOrNull('$documents/configurations/$configuration');
if (record == null) {
final newRecord = Document()..fields = taggedMap({'builder': builder});
await firestore.projects.databases.documents.createDocument(
@@ -186,8 +197,7 @@
/// for this build.
Future<bool> updateBuildInfo(
String builder, int buildNumber, int index) async {
- final record = await getDocument('$documents/builds/$builder:$index',
- throwOnNotFound: false);
+ final record = await getDocumentOrNull('$documents/builds/$builder:$index');
if (record == null) {
final newRecord = Document()
..fields = taggedMap(
@@ -230,15 +240,14 @@
await firestore.projects.databases.documents
.createDocument(newRecord, documents, 'try_builds');
documentsWritten++;
- return true;
}
Future<String> findResult(
Map<String, dynamic> change, int startIndex, int endIndex) async {
- final name = change['name'] as String;
- final result = change['result'] as String;
- final previousResult = change['previous_result'] as String;
- final expected = change['expected'] as String;
+ final name = change['name'] as String /*!*/;
+ final result = change['result'] as String /*!*/;
+ final previousResult = change['previous_result'] as String /*!*/;
+ final expected = change['expected'] as String /*!*/;
final snapshot = await query(
from: 'results',
orderBy: orderBy('blamelist_end_index', false),
@@ -261,7 +270,7 @@
?.name;
}
- Future<Document> storeResult(Map<String, dynamic> result) async {
+ Future<Document /*!*/ > storeResult(Map<String, dynamic> result) async {
final document = Document()..fields = taggedMap(result);
final createdDocument = await firestore.projects.databases.documents
.createDocument(document, documents, 'results');
@@ -270,13 +279,13 @@
return createdDocument;
}
- Future<bool> updateResult(
+ Future<bool /*!*/ > updateResult(
String result, String configuration, int startIndex, int endIndex,
- {bool failure}) async {
+ {/*required*/ bool failure}) async {
bool approved;
await retryCommit(() async {
final document = await getDocument(result);
- final data = SafeDocument(document);
+ final data = SafeDocument(document /*!*/);
// Allow missing 'approved' field during transition period.
approved = data.getBool('approved') ?? false;
// Add the new configuration and narrow the blamelist.
@@ -334,7 +343,7 @@
/// Returns all results which are either pinned to or have a range that is
/// this single index. // TODO: rename this function
- Future<List<Map<String, Value>>> findRevertedChanges(int index) async {
+ Future<List<Map<String, Value> /*!*/ >> findRevertedChanges(int index) async {
final pinnedResults =
await query(from: 'results', where: fieldEquals('pinned_index', index));
final results = pinnedResults.map((response) => response.fields).toList();
@@ -351,11 +360,11 @@
Future<bool> storeTryChange(
Map<String, dynamic> change, int review, int patchset) async {
- final name = change['name'] as String;
- final result = change['result'] as String;
- final expected = change['expected'] as String;
- final previousResult = change['previous_result'] as String;
- final configuration = change['configuration'] as String;
+ final name = change['name'] as String /*!*/;
+ final result = change['result'] as String /*!*/;
+ final expected = change['expected'] as String /*!*/;
+ final previousResult = change['previous_result'] as String /*!*/;
+ final configuration = change['configuration'] as String /*!*/;
// Find an existing result record for this test on this patchset.
final responses = await query(
@@ -400,7 +409,7 @@
'expected': expected,
'review': review,
'patchset': patchset,
- 'configurations': <String>[configuration],
+ 'configurations': <String /*!*/ >[configuration],
'approved': approved
});
await firestore.projects.databases.documents
@@ -449,8 +458,9 @@
assert(configurations.contains(configuration));
await removeArrayEntry(
activeResult, 'active_configurations', taggedValue(configuration));
- activeResult = SafeDocument(await getDocument(activeResult.name));
- if (activeResult.getList('active_configurations').isEmpty) {
+ final document = await getDocument(activeResult.name);
+ activeResult = SafeDocument(document /*!*/);
+ if (activeResult.getList('active_configurations')?.isEmpty == true) {
activeResult.fields.remove('active_configurations');
activeResult.fields.remove('active');
final write = Write()
@@ -475,8 +485,8 @@
]);
}
- Future<List<SafeDocument>> findActiveResults(
- String name, String configuration) async {
+ Future<List<SafeDocument /*!*/ >> findActiveResults(
+ String /*!*/ name, String /*!*/ configuration) async {
final results = await query(
from: 'results',
where: compositeFilter([
@@ -504,12 +514,12 @@
.createDocument(document, documents, 'reviews', documentId: review);
}
- Future<void> deleteDocument(String name) async {
+ Future<void> deleteDocument(String /*!*/ name) async {
return _executeWrite([Write()..delete = name]);
}
Future<bool> documentExists(String name) async {
- return (await getDocument(name, throwOnNotFound: false) != null);
+ return (await getDocumentOrNull(name) != null);
}
Future _executeWrite(List<Write> writes) async {
@@ -522,7 +532,8 @@
return firestore.projects.databases.documents.batchWrite(request, database);
}
- Future<void> updateFields(Document document, List<String> fields) async {
+ Future<void> updateFields(
+ Document /*!*/ document, List<String> fields) async {
await _executeWrite([
Write()
..update = document
@@ -530,8 +541,13 @@
]);
}
- Future<void> storePatchset(String review, int patchset, String kind,
- String description, int patchsetGroup, int number) async {
+ Future<void> storePatchset(
+ String /*!*/ review,
+ int /*!*/ patchset,
+ String /*!*/ kind,
+ String /*!*/ description,
+ int /*!*/ patchsetGroup,
+ int /*!*/ number) async {
final document = Document()
..name = '$documents/reviews/$review/patchsets/$patchset'
..fields = taggedMap({
@@ -549,22 +565,21 @@
/// Returns true if a review record in the database has a landed_index field,
/// or if there is no record for the review in the database. Reviews with no
/// test failures have no record, and don't need to be linked when landing.
- Future<bool> reviewIsLanded(int review) async {
- final document =
- await getDocument('$documents/reviews/$review', throwOnNotFound: false);
+ Future<bool> reviewIsLanded(int /*!*/ review) async {
+ final document = await getDocumentOrNull('$documents/reviews/$review');
if (document == null) {
return true;
}
return document.fields.containsKey('landed_index');
}
- Future<void> linkReviewToCommit(int review, int index) async {
+ Future<void> linkReviewToCommit(int /*!*/ review, int index) async {
final document = await getDocument('$documents/reviews/$review');
document.fields['landed_index'] = taggedValue(index);
await updateFields(document, ['landed_index']);
}
- Future<void> linkCommentsToCommit(int review, int index) async {
+ Future<void> linkCommentsToCommit(int /*!*/ review, int index) async {
final comments =
await query(from: 'comments', where: fieldEquals('review', review));
if (comments.isEmpty) return;
@@ -580,7 +595,7 @@
await _executeWrite(writes);
}
- Future<List<SafeDocument>> tryApprovals(int review) async {
+ Future<List<SafeDocument /*!*/ >> tryApprovals(int review) async {
final patchsets = await query(
from: 'patchsets',
parent: 'reviews/$review',
@@ -599,7 +614,7 @@
]));
}
- Future<List<SafeDocument>> tryResults(
+ Future<List<SafeDocument /*!*/ >> tryResults(
int review, String configuration) async {
final patchsets = await query(
from: 'patchsets',
@@ -626,10 +641,11 @@
String builder, int index, bool success) async {
final path = '$documents/builds/$builder:$index';
final document = await getDocument(path);
- await _completeBuilderRecord(document, success);
+ await _completeBuilderRecord(document /*!*/, success);
}
- Future<void> _completeBuilderRecord(Document document, bool success) async {
+ Future<void> _completeBuilderRecord(
+ Document /*!*/ document, bool success) async {
await retryCommit(() async {
document.fields['success'] = taggedValue(success);
final write = Write()
diff --git a/builder/lib/src/firestore_helpers.dart b/builder/lib/src/firestore_helpers.dart
index b4bea17..aa4a92b 100644
--- a/builder/lib/src/firestore_helpers.dart
+++ b/builder/lib/src/firestore_helpers.dart
@@ -138,9 +138,3 @@
..filters = filters
..op = 'AND');
}
-
-class DataWrapper {
- final Map<String, Value> fields;
- DataWrapper(Document document) : fields = document.fields;
- DataWrapper.fields(this.fields);
-}
diff --git a/builder/lib/src/gerrit_change.dart b/builder/lib/src/gerrit_change.dart
index 1c1b9ea..0cd189e 100644
--- a/builder/lib/src/gerrit_change.dart
+++ b/builder/lib/src/gerrit_change.dart
@@ -19,15 +19,14 @@
};
static const prefix = ")]}'\n";
- http.BaseClient httpClient;
- FirestoreService firestore;
- String review;
- String patchset;
+ final http.Client httpClient;
+ final FirestoreService firestore;
+ final String /*!*/ review;
+ final String patchset;
- GerritInfo(int review, int patchset, this.firestore, this.httpClient) {
- this.review = review.toString();
- this.patchset = patchset.toString();
- }
+ GerritInfo(int review, int patchset, this.firestore, this.httpClient)
+ : review = review.toString(),
+ patchset = patchset.toString();
/// Fetches the owner, changeId, message, and date of a Gerrit change and
/// stores them in the databases.
@@ -52,9 +51,9 @@
// Add the patchset information to the patchsets subcollection.
final revisions = reviewInfo['revisions'].values.toList()
..sort((a, b) => (a['_number'] as int).compareTo(b['_number']));
- int patchsetGroupFirst;
+ int patchsetGroupFirst = 1;
for (Map<String, dynamic> revision in revisions) {
- int number = revision['_number'];
+ int number = revision['_number'] /*!*/;
if (!trivialKinds.contains(revision['kind'])) {
patchsetGroupFirst = number;
}
diff --git a/builder/lib/src/result.dart b/builder/lib/src/result.dart
index acc4367..20a95a2 100644
--- a/builder/lib/src/result.dart
+++ b/builder/lib/src/result.dart
@@ -10,11 +10,11 @@
import 'package:googleapis/firestore/v1.dart' show Value;
class ResultRecord {
- final Map<String, Value> fields;
+ final Map<String, Value> /*!*/ fields;
ResultRecord(this.fields);
- bool get approved => fields['approved'].booleanValue;
+ bool /*!*/ get approved => fields['approved'].booleanValue;
@override
String toString() => jsonEncode(fields);
@@ -23,7 +23,7 @@
return int.parse(fields['blamelist_end_index'].integerValue);
}
- bool containsActiveConfiguration(String configuration) {
+ bool containsActiveConfiguration(String /*!*/ configuration) {
for (final value in fields['active_configurations'].arrayValue.values) {
if (value.stringValue != null && value.stringValue == configuration) {
return true;
@@ -50,7 +50,7 @@
const fConfigurations = 'configurations';
const fActiveConfigurations = 'active_configurations';
-bool isChangedResult(Map<String, dynamic> change) =>
+bool isChangedResult(Map<String, dynamic> /*!*/ change) =>
change[fChanged] && (!change[fFlaky] || !change[fPreviousFlaky]);
/// Whether the change will be marked as an active failure.
@@ -96,9 +96,9 @@
class BuildInfo {
static final commitRefRegExp = RegExp(r'refs/changes/(\d*)/(\d*)');
- final String builderName;
+ final String /*!*/ builderName;
final int buildNumber;
- final String commitRef;
+ final String /*!*/ commitRef;
final String previousCommitHash;
BuildInfo(Map<String, dynamic> result)
@@ -126,11 +126,11 @@
}
class TestNameLock {
- final locks = <String, Future<void>>{};
+ final locks = <String /*!*/, Future<void>>{};
Future<void> guardedCall(Future<void> Function(Map<String, dynamic> change) f,
- Map<String, dynamic> change) async {
- final name = change[fName];
+ Map<String, dynamic> /*!*/ change) async {
+ final name = change[fName] /*!*/;
while (locks.containsKey(name)) {
await locks[name];
}
diff --git a/builder/lib/src/reverted_changes.dart b/builder/lib/src/reverted_changes.dart
index d7bf314..e16304b 100644
--- a/builder/lib/src/reverted_changes.dart
+++ b/builder/lib/src/reverted_changes.dart
@@ -23,8 +23,8 @@
class RevertedChanges {
final int index;
final int revertIndex;
- final List<Map<String, Value>> changes;
- final Map<String, List<Map<String, Value>>> changesForTest;
+ final List<Map<String, Value> /*!*/ > changes;
+ final Map<String /*!*/, List<Map<String, Value> /*!*/ >> changesForTest;
RevertedChanges(
this.index, this.revertIndex, this.changes, this.changesForTest);
diff --git a/builder/lib/src/tryjob.dart b/builder/lib/src/tryjob.dart
index c07ef13..31e371b 100644
--- a/builder/lib/src/tryjob.dart
+++ b/builder/lib/src/tryjob.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:collection/collection.dart';
-import 'package:http/http.dart' as http show BaseClient;
+import 'package:http/http.dart' as http show Client;
import 'package:pool/pool.dart';
import 'commits_cache.dart';
@@ -57,17 +57,17 @@
}
class Tryjob {
- final http.BaseClient httpClient;
- final FirestoreService firestore;
- final CommitsCache commits;
+ final http.Client /*!*/ httpClient;
+ final FirestoreService /*!*/ firestore;
+ final CommitsCache /*!*/ commits;
final counter = ChangeCounter();
- TryBuildInfo info;
+ TryBuildInfo /*!*/ info;
final TestNameLock testNameLock = TestNameLock();
- String baseRevision;
+ String /*!*/ baseRevision;
bool success = true;
- List<SafeDocument> landedResults;
- Map<String, SafeDocument> lastLandedResultByName = {};
- final String buildbucketID;
+ List<SafeDocument /*!*/ > landedResults;
+ Map<String /*!*/, SafeDocument /*!*/ > lastLandedResultByName = {};
+ final String /*!*/ buildbucketID;
Tryjob(this.info, this.buildbucketID, this.baseRevision, this.commits,
this.firestore, this.httpClient);
@@ -79,17 +79,18 @@
.update();
}
- bool isNotLandedResult(Map<String, dynamic> change) {
+ bool isNotLandedResult(Map<String, dynamic> /*!*/ change) {
return !lastLandedResultByName.containsKey(change[fName]) ||
change[fResult] !=
lastLandedResultByName[change[fName]].getString(fResult);
}
- Future<void> process(List<Map<String, dynamic>> results) async {
+ Future<void> process(List<Map<String, dynamic> /*!*/ > results) async {
await update();
log('storing ${results.length} change(s)');
- final resultsByConfiguration = groupBy<Map<String, dynamic>, String>(
- results, (result) => result['configuration']);
+ final resultsByConfiguration =
+ groupBy<Map<String, dynamic> /*!*/, String /*!*/ >(
+ results, (result) => result['configuration']);
for (final configuration in resultsByConfiguration.keys) {
if (baseRevision != null && info.previousCommitHash != null) {
@@ -120,7 +121,7 @@
log(report.join('\n'));
}
- Future<void> guardedStoreChange(Map<String, dynamic> change) =>
+ Future<void> guardedStoreChange(Map<String, dynamic> /*!*/ change) =>
testNameLock.guardedCall(storeChange, change);
Future<void> storeChange(Map<String, dynamic> change) async {
@@ -135,26 +136,25 @@
}
}
- Future<List<SafeDocument>> fetchLandedResults(String configuration) async {
+ Future<List<SafeDocument /*!*/ >> fetchLandedResults(
+ String configuration) async {
final resultsBase = await commits.getCommit(info.previousCommitHash);
final rebaseBase = await commits.getCommit(baseRevision);
- if (resultsBase.index > rebaseBase.index) {
+ if (resultsBase /*!*/ .index > rebaseBase /*!*/ .index) {
print('Try build is rebased on $baseRevision, which is before '
'the commit ${info.previousCommitHash} with CI comparison results');
return [];
}
- final reviews = <int>[];
- for (var index = resultsBase.index + 1;
- index <= rebaseBase.index;
- ++index) {
- final commit = await commits.getCommitByIndex(index);
- if (commit.review != null) {
- reviews.add(commit.review);
- }
- }
+ final reviews = [
+ for (var index = resultsBase.index + 1;
+ index <= rebaseBase.index;
+ ++index)
+ (await commits.getCommitByIndex(index))?.review
+ ];
return [
for (final landedReview in reviews)
- ...await firestore.tryResults(landedReview, configuration)
+ if (landedReview != null)
+ ...await firestore.tryResults(landedReview, configuration)
];
}
}
diff --git a/builder/test/approvals_test.dart b/builder/test/approvals_test.dart
index 7cc792b..c85a444 100644
--- a/builder/test/approvals_test.dart
+++ b/builder/test/approvals_test.dart
@@ -22,40 +22,41 @@
// To run against the staging database, use a service account.
// with write access to dart_ci_staging datastore.
-FirestoreService firestore;
-http.Client client;
-CommitsCache commitsCache;
+/*late final*/ FirestoreService /*!*/ firestore;
+/*late final*/ http.Client /*!*/ client;
+/*late final*/ CommitsCache /*!*/ commitsCache;
// The real commits and reviews we will test on, fetched from Firestore.
// These globals are populated by loadTestCommits().
const testCommitsStart = 80801;
const reviewWithComments = '215021';
-String index1; // Index of the final commit in the test range
-String commit1; // Hash of that commit
-String review; // CL number of that commit's Gerrit review
-String lastPatchset; // Final patchset in that review
-String lastPatchsetRef; // 'refs/changes/[review]/[patchset]'
-String patchsetGroup; // First patchset in the final patchset group
-String patchsetGroupRef;
-String earlyPatchset; // Patchset not in the final patchset group
-String earlyPatchsetRef;
+/*late final*/ String /*!*/ index1; // Index of the final commit in the test range
+/*late final*/ String /*!*/ commit1; // Hash of that commit
+/*late final*/ String review; // CL number of that commit's Gerrit review
+/*late final*/ String /*!*/ lastPatchset; // Final patchset in that review
+/*late final*/ String lastPatchsetRef; // 'refs/changes/[review]/[patchset]'
+/*late final*/ String /*!*/
+ patchsetGroup; // First patchset in the final patchset group
+/*late final*/ String patchsetGroupRef;
+/*late final*/ String earlyPatchset; // Patchset not in the final patchset group
+/*late final*/ String earlyPatchsetRef;
// Earlier commit with a review
-String index2;
-String commit2;
-String review2;
-String patchset2;
-String patchset2Ref;
+/*late final*/ String /*!*/ index2;
+/*late final*/ String /*!*/ commit2;
+/*late final*/ String review2;
+/*late final*/ String /*!*/ patchset2;
+/*late final*/ String patchset2Ref;
// Commits before commit2
-String index3;
-String commit3;
-String index4;
-String commit4;
+/*late final*/ String index3;
+/*late final*/ String /*!*/ commit3;
+/*late final*/ String index4;
+/*late final*/ String /*!*/ commit4;
-final buildersToRemove = <String>{};
-final testsToRemove = <String>{};
+final buildersToRemove = <String /*!*/ >{};
+final testsToRemove = <String /*!*/ >{};
void registerChangeForDeletion(Map<String, dynamic> change) {
- buildersToRemove.add(change['builder_name']);
- testsToRemove.add(change['name']);
+ buildersToRemove.add(change['builder_name'] as String /*!*/);
+ testsToRemove.add(change['name'] as String /*!*/);
}
Future<void> removeBuildersAndResults() async {
@@ -341,7 +342,7 @@
final resultName = await firestore.findResult(
change, int.parse(startIndex), int.parse(endIndex));
expect(resultName, isNotNull);
- final resultDocument = await firestore.getDocument(resultName);
+ final resultDocument = await firestore.getDocument(resultName /*!*/);
final data = untagMap(resultDocument.fields);
expect(data[fName], change[fName]);
expect(data[fBlamelistStartIndex], int.parse(startIndex));