text: //===-------- AbstractSourceFileDepGraphFactory.cpp -----------------------===//
  //
  // This source file is part of the Swift.org open source project
  //
  // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
  // Licensed under Apache License v2.0 with Runtime Library Exception
  //
  // See https://swift.org/LICENSE.txt for license information
  // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
  //
  //===----------------------------------------------------------------------===//
  
  #include "swift/AST/AbstractSourceFileDepGraphFactory.h"
  
  // may not all be needed
  #include "swift/AST/DiagnosticEngine.h"
  #include "swift/AST/DiagnosticsFrontend.h"
  #include "swift/AST/FileSystem.h"
  #include "swift/AST/FineGrainedDependencies.h"
  #include "swift/Basic/FileSystem.h"
  #include "swift/Basic/LLVM.h"
  #include "swift/Basic/ReferenceDependencyKeys.h"
  #include "llvm/ADT/MapVector.h"
  #include "llvm/ADT/SetVector.h"
  #include "llvm/ADT/SmallVector.h"
  #include "llvm/Support/YAMLParser.h"
  
  using namespace swift;
  using namespace fine_grained_dependencies;
  
  //==============================================================================
  // MARK: AbstractSourceFileDepGraphFactory - client interface
  //==============================================================================
  
  AbstractSourceFileDepGraphFactory::AbstractSourceFileDepGraphFactory(
      bool hadCompilationError, StringRef swiftDeps,
      Fingerprint fileFingerprint, bool emitDotFileAfterConstruction,
      DiagnosticEngine &diags)
      : hadCompilationError(hadCompilationError), swiftDeps(swiftDeps.str()),
        fileFingerprint(fileFingerprint),
        emitDotFileAfterConstruction(emitDotFileAfterConstruction), diags(diags) {
  }
  
  SourceFileDepGraph AbstractSourceFileDepGraphFactory::construct() {
    addSourceFileNodesToGraph();
    if (!hadCompilationError) {
      addAllDefinedDecls();
      addAllUsedDecls();
    }
    assert(g.verify());
    if (emitDotFileAfterConstruction)
      g.emitDotFile(swiftDeps, diags);
    return std::move(g);
  }
  
  //==============================================================================
  // MARK: AbstractSourceFileDepGraphFactory - adding a defined or used Decl
  //==============================================================================
  void AbstractSourceFileDepGraphFactory::addSourceFileNodesToGraph() {
    g.findExistingNodePairOrCreateAndAddIfNew(
        DependencyKey::createKeyForWholeSourceFile(DeclAspect::interface,
                                                   swiftDeps),
        Fingerprint{fileFingerprint});
  }
  
  void AbstractSourceFileDepGraphFactory::addADefinedDecl(
      const DependencyKey &interfaceKey, Optional<Fingerprint> fingerprint) {
  
    auto nodePair =
        g.findExistingNodePairOrCreateAndAddIfNew(interfaceKey, fingerprint);
    // Since the current type fingerprints only include tokens in the body,
    // when the interface hash changes, it is possible that the type in the
    // file has changed.
    g.addArc(g.getSourceFileNodePair().getInterface(), nodePair.getInterface());
  }
  
  void AbstractSourceFileDepGraphFactory::addAUsedDecl(
      const DependencyKey &defKey, const DependencyKey &useKey) {
    auto *defNode =
        g.findExistingNodeOrCreateIfNew(defKey, None, false /* = !isProvides */);
  
    // If the depended-upon node is defined in this file, then don't
    // create an arc to the user, when the user is the whole file.
    // Otherwise, if the defNode's type-body fingerprint changes,
    // the whole file will be marked as dirty, losing the benefit of the
    // fingerprint.
  
    //  if (defNode->getIsProvides() &&
    //      useKey.getKind() == NodeKind::sourceFileProvide)
    //    return;
  
    // Turns out the above three lines cause miscompiles, so comment them out
    // for now. We might want them back if we can change the inputs to this
    // function to be more precise.
  
    // Example of a miscompile:
    // In main.swift
    // func foo(_: Any) { print("Hello Any") }
    //    foo(123)
    // Then add the following line to another file:
    // func foo(_: Int) { print("Hello Int") }
    // Although main.swift needs to get recompiled, the commented-out code below
    // prevents that.
  
    auto nullableUse = g.findExistingNode(useKey);
    assert(nullableUse.isNonNull() && "Use must be an already-added provides");
    auto *useNode = nullableUse.get();
    assert(useNode->getIsProvides() && "Use (using node) must be a provides");
    g.addArc(defNode, useNode);
  }
  