Unverified Commit 32474dca authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] provide more context for build_system invalidation (#77961)

parent 541bff40
...@@ -1027,12 +1027,16 @@ class Node { ...@@ -1027,12 +1027,16 @@ class Node {
/// One or more reasons why a task was invalidated. /// One or more reasons why a task was invalidated.
/// ///
/// May be empty if the task was skipped. /// May be empty if the task was skipped.
final Set<InvalidatedReason> invalidatedReasons = <InvalidatedReason>{}; final Map<InvalidatedReasonKind, InvalidatedReason> invalidatedReasons = <InvalidatedReasonKind, InvalidatedReason>{};
/// Whether this node needs an action performed. /// Whether this node needs an action performed.
bool get dirty => _dirty; bool get dirty => _dirty;
bool _dirty = false; bool _dirty = false;
InvalidatedReason _invalidate(InvalidatedReasonKind kind) {
return invalidatedReasons[kind] ??= InvalidatedReason(kind);
}
/// Collect hashes for all inputs to determine if any have changed. /// Collect hashes for all inputs to determine if any have changed.
/// ///
/// Returns whether this target can be skipped. /// Returns whether this target can be skipped.
...@@ -1060,7 +1064,8 @@ class Node { ...@@ -1060,7 +1064,8 @@ class Node {
if (fileStore.currentAssetKeys.containsKey(absolutePath)) { if (fileStore.currentAssetKeys.containsKey(absolutePath)) {
final String currentHash = fileStore.currentAssetKeys[absolutePath]; final String currentHash = fileStore.currentAssetKeys[absolutePath];
if (currentHash != previousAssetKey) { if (currentHash != previousAssetKey) {
invalidatedReasons.add(InvalidatedReason.inputChanged); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.inputChanged);
reason.data.add(absolutePath);
_dirty = true; _dirty = true;
} }
} else { } else {
...@@ -1074,13 +1079,15 @@ class Node { ...@@ -1074,13 +1079,15 @@ class Node {
// output paths changed. // output paths changed.
if (!currentOutputPaths.contains(previousOutput)) { if (!currentOutputPaths.contains(previousOutput)) {
_dirty = true; _dirty = true;
invalidatedReasons.add(InvalidatedReason.outputSetChanged); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.outputSetChanged);
reason.data.add(previousOutput);
// if this isn't a current output file there is no reason to compute the key. // if this isn't a current output file there is no reason to compute the key.
continue; continue;
} }
final File file = fileSystem.file(previousOutput); final File file = fileSystem.file(previousOutput);
if (!file.existsSync()) { if (!file.existsSync()) {
invalidatedReasons.add(InvalidatedReason.outputMissing); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.outputMissing);
reason.data.add(file.path);
_dirty = true; _dirty = true;
continue; continue;
} }
...@@ -1089,7 +1096,8 @@ class Node { ...@@ -1089,7 +1096,8 @@ class Node {
if (fileStore.currentAssetKeys.containsKey(absolutePath)) { if (fileStore.currentAssetKeys.containsKey(absolutePath)) {
final String currentHash = fileStore.currentAssetKeys[absolutePath]; final String currentHash = fileStore.currentAssetKeys[absolutePath];
if (currentHash != previousHash) { if (currentHash != previousHash) {
invalidatedReasons.add(InvalidatedReason.outputChanged); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.outputChanged);
reason.data.add(absolutePath);
_dirty = true; _dirty = true;
} }
} else { } else {
...@@ -1104,7 +1112,8 @@ class Node { ...@@ -1104,7 +1112,8 @@ class Node {
_dirty = true; _dirty = true;
final String missingMessage = missingInputs.map((File file) => file.path).join(', '); final String missingMessage = missingInputs.map((File file) => file.path).join(', ');
logger.printTrace('invalidated build due to missing files: $missingMessage'); logger.printTrace('invalidated build due to missing files: $missingMessage');
invalidatedReasons.add(InvalidatedReason.inputMissing); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.inputMissing);
reason.data.addAll(missingInputs.map((File file) => file.path));
} }
// If we have files to diff, compute them asynchronously and then // If we have files to diff, compute them asynchronously and then
...@@ -1112,7 +1121,8 @@ class Node { ...@@ -1112,7 +1121,8 @@ class Node {
if (sourcesToDiff.isNotEmpty) { if (sourcesToDiff.isNotEmpty) {
final List<File> dirty = fileStore.diffFileList(sourcesToDiff); final List<File> dirty = fileStore.diffFileList(sourcesToDiff);
if (dirty.isNotEmpty) { if (dirty.isNotEmpty) {
invalidatedReasons.add(InvalidatedReason.inputChanged); final InvalidatedReason reason = _invalidate(InvalidatedReasonKind.inputChanged);
reason.data.addAll(dirty.map((File file) => file.path));
_dirty = true; _dirty = true;
} }
} }
...@@ -1120,8 +1130,35 @@ class Node { ...@@ -1120,8 +1130,35 @@ class Node {
} }
} }
/// Data about why a target was re-run.
class InvalidatedReason {
InvalidatedReason(this.kind);
final InvalidatedReasonKind kind;
/// Absolute file paths of inputs or outputs, depending on [kind].
final List<String> data = <String>[];
@override
String toString() {
switch (kind) {
case InvalidatedReasonKind.inputMissing:
return 'The following inputs were missing: ${data.join(',')}';
case InvalidatedReasonKind.inputChanged:
return 'The following inputs have updated contents: ${data.join(',')}';
case InvalidatedReasonKind.outputChanged:
return 'The following outputs have updated contents: ${data.join(',')}';
case InvalidatedReasonKind.outputMissing:
return 'The following outputs were missing: ${data.join(',')}';
case InvalidatedReasonKind.outputSetChanged:
return 'The following outputs were removed from the output set: ${data.join(',')}';
}
assert(false);
return null;
}
}
/// A description of why a target was rerun. /// A description of why a target was rerun.
enum InvalidatedReason { enum InvalidatedReasonKind {
/// An input file that was expected is missing. This can occur when using /// An input file that was expected is missing. This can occur when using
/// depfile dependencies, or if a target is incorrectly specified. /// depfile dependencies, or if a target is incorrectly specified.
inputMissing, inputMissing,
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_tools/src/build_system/build_system.dart';
import '../../src/common.dart';
void main() {
testWithoutContext('InvalidatedReason formats message per invalidation kind', () {
final InvalidatedReason inputChanged = InvalidatedReason(InvalidatedReasonKind.inputChanged)
..data.add('a.dart');
final InvalidatedReason outputChanged = InvalidatedReason(InvalidatedReasonKind.outputChanged)
..data.add('b.dart');
final InvalidatedReason inputMissing = InvalidatedReason(InvalidatedReasonKind.inputMissing)
..data.add('c.dart');
final InvalidatedReason outputMissing = InvalidatedReason(InvalidatedReasonKind.outputMissing)
..data.add('d.dart');
final InvalidatedReason outputSetChanged = InvalidatedReason(InvalidatedReasonKind.outputSetChanged)
..data.add('e.dart');
expect(inputChanged.toString(), 'The following inputs have updated contents: a.dart');
expect(outputChanged.toString(), 'The following outputs have updated contents: b.dart');
expect(inputMissing.toString(), 'The following inputs were missing: c.dart');
expect(outputMissing.toString(), 'The following outputs were missing: d.dart');
expect(outputSetChanged.toString(), 'The following outputs were removed from the output set: e.dart');
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment