-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add AssetGraph/AssetNode #42
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Copyright (c) 2016, 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 'node.dart'; | ||
|
||
class DuplicateAssetNodeException implements Exception { | ||
final AssetNode assetNode; | ||
|
||
DuplicateAssetNodeException(this.assetNode); | ||
|
||
@override | ||
String toString() => 'DuplicateAssetNodeError: $assetNode'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Copyright (c) 2016, 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 '../asset/id.dart'; | ||
import 'exceptions.dart'; | ||
import 'node.dart'; | ||
|
||
/// Represents all the [Asset]s in the system, and all of their dependencies. | ||
class AssetGraph { | ||
/// All the [AssetNode]s in the system, indexed by [AssetId]. | ||
final _nodesById = <AssetId, AssetNode>{}; | ||
|
||
AssetGraph(); | ||
|
||
/// Checks if [id] exists in the graph. | ||
bool contains(AssetId id) => _nodesById.containsKey(id); | ||
|
||
/// Gets the [AssetNode] for [id], if one exists. | ||
AssetNode get(AssetId id) => _nodesById[id]; | ||
|
||
/// Adds [node] to the graph. | ||
void add(AssetNode node) { | ||
if (_nodesById.containsKey(node.id)) { | ||
throw new DuplicateAssetNodeException(node); | ||
} | ||
_nodesById[node.id] = node; | ||
} | ||
|
||
/// Adds the node returned by [ifAbsent] to the graph, if [id] doesn't | ||
/// already exist. | ||
/// | ||
/// Returns either the existing value or the one just added. | ||
AssetNode addIfAbsent(AssetId id, AssetNode ifAbsent()) => | ||
_nodesById.putIfAbsent(id, ifAbsent); | ||
|
||
/// Removes [node] from the graph. | ||
AssetNode remove(AssetId id) => _nodesById.remove(id); | ||
|
||
@override | ||
toString() => _nodesById.values.toList().toString(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) 2016, 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 '../asset/id.dart'; | ||
import '../builder/builder.dart'; | ||
|
||
/// A node in the asset graph. | ||
/// | ||
/// This class specifically represents normal (ie: non-generated) assets. | ||
class AssetNode { | ||
/// The asset this node represents. | ||
final AssetId id; | ||
|
||
/// The [AssetId]s of all generated assets which depend on this node. | ||
final outputs = new Set<AssetId>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems fine for now, but I want to be careful about conflating information about the graph structure with details of the build system. It feels like we should be able to swap out the graph implementation relatively easily without changing much about the rest of the implementation. Not sure we need to do anything about this now but I wanted to bring it up. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this will shake out in the coming cls as this thing actually gets used. |
||
|
||
AssetNode(this.id); | ||
|
||
@override | ||
String toString() => 'AssetNode: $id'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
} | ||
|
||
/// A generated node in the asset graph. | ||
class GeneratedAssetNode extends AssetNode { | ||
/// The builder which generated this node. | ||
final Builder builder; | ||
|
||
/// The primary input which generated this node. | ||
final AssetId primaryInput; | ||
|
||
/// The phase group number which generates this asset. | ||
final int generatingPhaseGroup; | ||
|
||
/// Whether or not this asset needs to be updated. | ||
bool needsUpdate; | ||
|
||
GeneratedAssetNode(this.builder, this.primaryInput, this.generatingPhaseGroup, | ||
this.needsUpdate, AssetId id) | ||
: super(id); | ||
|
||
@override | ||
toString() => 'GeneratedAssetNode: $id generated for input $primaryInput to ' | ||
'$builder in phase group $generatingPhaseGroup.'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copyright (c) 2016, 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:test/test.dart'; | ||
|
||
import 'package:build/src/asset_graph/graph.dart'; | ||
import 'package:build/src/asset_graph/node.dart'; | ||
|
||
import '../common/common.dart'; | ||
|
||
main() { | ||
group('AssetGraph', () { | ||
AssetGraph graph; | ||
|
||
setUp(() { | ||
graph = new AssetGraph(); | ||
}); | ||
|
||
void expectNodeDoesNotExist(AssetNode node) { | ||
expect(graph.contains(node.id), isFalse); | ||
expect(graph.get(node.id), isNull); | ||
} | ||
|
||
void expectNodeExists(AssetNode node) { | ||
expect(graph.contains(node.id), isTrue); | ||
expect(graph.get(node.id), node); | ||
} | ||
|
||
AssetNode testAddNode() { | ||
var node = makeAssetNode(); | ||
expectNodeDoesNotExist(node); | ||
graph.add(node); | ||
expectNodeExists(node); | ||
return node; | ||
} | ||
|
||
test('add, contains, get', () { | ||
for (int i = 0; i < 5; i++) { | ||
testAddNode(); | ||
} | ||
}); | ||
|
||
test('addIfAbsent', () { | ||
var node = makeAssetNode(); | ||
expect(graph.addIfAbsent(node.id, () => node), same(node)); | ||
expect(graph.contains(node.id), isTrue); | ||
|
||
var otherNode = new AssetNode(node.id); | ||
expect(graph.addIfAbsent(otherNode.id, () => otherNode), same(node)); | ||
expect(graph.contains(otherNode.id), isTrue); | ||
}); | ||
|
||
test('duplicate adds throw DuplicateAssetNodeException', () { | ||
var node = testAddNode(); | ||
expect(() => graph.add(node), throwsA(duplicateAssetNodeException)); | ||
}); | ||
|
||
test('remove', () { | ||
var nodes = <AssetNode>[]; | ||
for (int i = 0; i < 5; i++) { | ||
nodes.add(testAddNode()); | ||
} | ||
graph.remove(nodes[1].id); | ||
graph.remove(nodes[4].id); | ||
|
||
expectNodeExists(nodes[0]); | ||
expectNodeDoesNotExist(nodes[1]); | ||
expectNodeExists(nodes[2]); | ||
expectNodeDoesNotExist(nodes[4]); | ||
expectNodeExists(nodes[3]); | ||
|
||
// Doesn't throw. | ||
graph.remove(nodes[1].id); | ||
|
||
// Can be added back | ||
graph.add(nodes[1]); | ||
expectNodeExists(nodes[1]); | ||
}); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
up to you whether to change, but this could be
const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't since AssetNode isn't const :(