1515//
1616// ===----------------------------------------------------------------------===//
1717#include " swift/AST/Evaluator.h"
18+ #include " swift/AST/DiagnosticEngine.h"
1819#include " swift/Basic/Range.h"
20+ #include " swift/Basic/SourceManager.h"
1921#include " llvm/ADT/StringExtras.h"
2022#include " llvm/Support/Debug.h"
2123#include " llvm/Support/FileSystem.h"
@@ -248,17 +250,47 @@ void Evaluator::printDependenciesGraphviz(llvm::raw_ostream &out) const {
248250 out << " digraph Dependencies {\n " ;
249251
250252 // Emit the edges.
253+ llvm::DenseMap<AnyRequest, unsigned > inDegree;
251254 for (const auto &source : allRequests) {
252255 auto known = dependencies.find (source);
253256 assert (known != dependencies.end ());
254257 for (const auto &target : known->second ) {
255258 out << " " << getNodeName (source) << " -> " << getNodeName (target)
256259 << " ;\n " ;
260+ ++inDegree[target];
257261 }
258262 }
259263
260264 out << " \n " ;
261265
266+ static const char *colorNames[] = {
267+ " aquamarine" ,
268+ " blueviolet" ,
269+ " brown" ,
270+ " burlywood" ,
271+ " cadetblue" ,
272+ " chartreuse" ,
273+ " chocolate" ,
274+ " coral" ,
275+ " cornflowerblue" ,
276+ " crimson"
277+ };
278+ const unsigned numColorNames = sizeof (colorNames) / sizeof (const char *);
279+
280+ llvm::DenseMap<unsigned , unsigned > knownBuffers;
281+ auto getColor = [&](const AnyRequest &request) -> Optional<const char *> {
282+ SourceLoc loc = request.getNearestLoc ();
283+ if (loc.isInvalid ())
284+ return None;
285+
286+ unsigned bufferID = diags.SourceMgr .findBufferContainingLoc (loc);
287+ auto knownId = knownBuffers.find (bufferID);
288+ if (knownId == knownBuffers.end ()) {
289+ knownId = knownBuffers.insert ({bufferID, knownBuffers.size ()}).first ;
290+ }
291+ return colorNames[knownId->second % numColorNames];
292+ };
293+
262294 // Emit the nodes.
263295 for (unsigned i : indices (allRequests)) {
264296 const auto &request = allRequests[i];
@@ -271,7 +303,48 @@ void Evaluator::printDependenciesGraphviz(llvm::raw_ostream &out) const {
271303 out << " -> " ;
272304 printEscapedString (cachedValue->second .getAsString (), out);
273305 }
274- out << " \" ];\n " ;
306+ out << " \" " ;
307+
308+ if (auto color = getColor (request)) {
309+ out << " , fillcolor=\" " << *color << " \" " ;
310+ }
311+
312+ out << " ];\n " ;
313+ }
314+
315+ // Emit "fake" nodes for each of the source buffers we encountered, so
316+ // we know which file we're working from.
317+ // FIXME: This approximates a "top level" request for, e.g., type checking
318+ // an entire source file.
319+ std::vector<unsigned > sourceBufferIDs;
320+ for (const auto &element : knownBuffers) {
321+ sourceBufferIDs.push_back (element.first );
322+ }
323+ std::sort (sourceBufferIDs.begin (), sourceBufferIDs.end ());
324+ for (unsigned bufferID : sourceBufferIDs) {
325+ out << " buffer_" << bufferID << " [label=\" " ;
326+ printEscapedString (diags.SourceMgr .getIdentifierForBuffer (bufferID), out);
327+ out << " \" " ;
328+
329+ out << " , shape=\" box\" " ;
330+ out << " , fillcolor=\" "
331+ << colorNames[knownBuffers[bufferID] % numColorNames] << " \" " ;
332+ out << " ];\n " ;
333+ }
334+
335+ // Emit "false" dependencies from source buffer IDs to any requests that (1)
336+ // have no other incomining edges and (2) can be associated with a source
337+ // buffer.
338+ for (const auto &request : allRequests) {
339+ if (inDegree[request] > 0 )
340+ continue ;
341+
342+ SourceLoc loc = request.getNearestLoc ();
343+ if (loc.isInvalid ())
344+ continue ;
345+
346+ unsigned bufferID = diags.SourceMgr .findBufferContainingLoc (loc);
347+ out << " buffer_" << bufferID << " -> " << getNodeName (request) << " ;\n " ;
275348 }
276349
277350 // Done!
0 commit comments