// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TOOLS_GN_NINJA_TARGET_WRITER_H_
#define TOOLS_GN_NINJA_TARGET_WRITER_H_

#include <iosfwd>

#include "gn/path_output.h"
#include "gn/resolved_target_data.h"
#include "gn/substitution_type.h"

class OutputFile;
class Settings;
class Target;
struct SubstitutionBits;

// Generates one target's ".ninja" file. The toplevel "build.ninja" file is
// generated by the NinjaBuildWriter.
class NinjaTargetWriter {
 public:
  NinjaTargetWriter(const Target* target, std::ostream& out);
  virtual ~NinjaTargetWriter();

  // Returns a ResolvedTargetData that can be used to retrieve information
  // from targets. The instance can be set through SetResolvedTargetData()
  // or may be created on demand otherwise (which is useful to keep unit-tests
  // simple).
  const ResolvedTargetData& resolved() const;

  // Sets the ResolvedTargetData instance to return for future resolved()
  // calls. Does not transfer ownership, and allows several NinjaTargetWriter
  // instances to share the same cached information.
  void SetResolvedTargetData(ResolvedTargetData* resolved);

  // Set the vector that will receive the Ninja output file paths generated
  // by this writer. A nullptr value means no output files needs to be
  // collected.
  void SetNinjaOutputs(std::vector<OutputFile>* ninja_outputs);

  // Returns the build line to be written to the toolchain build file.
  //
  // Some targets have their rules written to separate files, and some can have
  // their rules coalesced in the main build file. For the coalesced case, this
  // function will return the rules as a string. For the separate file case,
  // the separate ninja file will be written and the return string will be the
  // subninja command to load that file.
  //
  // If |ninja_outputs| is not nullptr, it will be set with the list of
  // Ninja output paths generated by the corresponding writer.
  static std::string RunAndWriteFile(
      const Target* target,
      ResolvedTargetData* resolved = nullptr,
      std::vector<OutputFile>* ninja_outputs = nullptr);

  // Writes a stamp or phony rule for the target's public inputs if it exports
  // any. This does nothing if resolved->ExportsPublicInputs(target) returns
  // false.
  static void WritePublicInputsStampOrPhony(const Target* target,
                                            ResolvedTargetData* resolved,
                                            std::ostream& out);

  virtual void Run() = 0;

 protected:
  // Returns a writable pointer to resolved(). Only used internally.
  ResolvedTargetData* GetResolvedTargetData();

  // Writes out the substitution values that are shared between the different
  // types of tools (target gen dir, target label, etc.). Only the substitutions
  // identified by the given bits will be written.
  void WriteSharedVars(const SubstitutionBits& bits);

  // Writes out the substitution values that are shared between C compiler tools
  // and action tools. Only the substitutions identified by the given bits will
  // be written.
  // If respect_source_used is set, the generated substitution values will
  // respect the types of source code used; otherwise they will respect the bits
  // passed in.
  void WriteCCompilerVars(const SubstitutionBits& bits,
                          bool indent,
                          bool respect_source_used);

  // Writes out the substitution values that are shared between Rust tools
  // and action tools. Only the substitutions identified by the given bits will
  // be written, unless 'always_write' is specified.
  void WriteRustCompilerVars(const SubstitutionBits& bits,
                             bool indent,
                             bool always_write);

  struct InputDeps {
    std::vector<OutputFile> implicit;
    std::vector<OutputFile> order_only;
  };

  // Writes to the output stream a phony rule for input dependencies, and
  // returns the file to be appended to source rules that encodes the
  // dependencies for the current target.
  // If num_output_uses is small, this might return all input dependencies
  // directly, without writing a phony rule.
  // If there are no implicit dependencies and no additional target dependencies
  // are passed in, this returns an empty struct.
  InputDeps WriteInputDepsStampOrPhonyAndGetDep(
      const std::vector<const Target*>& additional_hard_deps,
      size_t num_output_uses) const;

  // Writes to the output file a final phony rule for the target that aliases
  // the given list of files.
  void WriteStampOrPhonyForTarget(
      const std::vector<OutputFile>& deps,
      const std::vector<OutputFile>& order_only_deps);

  // Writes the validation dependencies to the output stream.
  void WriteValidations();

  const Settings* settings_;  // Non-owning.
  const Target* target_;      // Non-owning.
  std::ostream& out_;
  PathOutput path_output_;

  // Write a Ninja output file to out_, and also add it to |*ninja_outputs_|
  // if needed.
  void WriteOutput(const OutputFile& output) const;
  void WriteOutput(OutputFile&& output) const;

  // Same as WriteOutput() for a list of Ninja output file paths.
  void WriteOutputs(const std::vector<OutputFile>& outputs) const;
  void WriteOutputs(std::vector<OutputFile>&& outputs) const;

  // The list of all Ninja output file paths generated by this writer for
  // this target. Used to implement the --ide=ninja_outputs `gn gen` flag.
  // Needs to be mutable because WriteOutput() and WriteOutputs() need to
  // be const.
  mutable std::vector<OutputFile>* ninja_outputs_ = nullptr;

  // The ResolvedTargetData instance can be set through SetResolvedTargetData()
  // or it will be created lazily when resolved() is called, hence the need
  // for 'mutable' here.
  mutable ResolvedTargetData* resolved_ptr_ = nullptr;
  mutable std::unique_ptr<ResolvedTargetData> resolved_owned_;

 private:
  void WriteCopyRules();
  void WriteEscapedSubstitution(const Substitution* type);

  NinjaTargetWriter(const NinjaTargetWriter&) = delete;
  NinjaTargetWriter& operator=(const NinjaTargetWriter&) = delete;
};

#endif  // TOOLS_GN_NINJA_TARGET_WRITER_H_
