//===--- Types.h - API Notes Data Types --------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines data types used in the representation of API notes data.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_API_NOTES_TYPES_H
#define LLVM_CLANG_API_NOTES_TYPES_H
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <climits>

namespace llvm {
  class raw_ostream;
}

namespace clang {
namespace api_notes {

/// The file extension used for the source representation of API notes.
static const char SOURCE_APINOTES_EXTENSION[] = "apinotes";

/// The file extension used for the binary representation of API notes.
static const char BINARY_APINOTES_EXTENSION[] = "apinotesc";

using llvm::ArrayRef;
using llvm::StringRef;
using llvm::Optional;
using llvm::None;

/// Describes whether to classify a factory method as an initializer.
enum class FactoryAsInitKind {
  /// Infer based on name and type (the default).
  Infer,
  /// Treat as a class method.
  AsClassMethod,
  /// Treat as an initializer.
  AsInitializer
};

/// Opaque context ID used to refer to an Objective-C class or protocol.
class ContextID {
public:
  unsigned Value;

  explicit ContextID(unsigned value) : Value(value) { }
};

/// Describes API notes data for any entity.
///
/// This is used as the base of all API notes.
class CommonEntityInfo {
public:
  /// Message to use when this entity is unavailable.
  std::string UnavailableMsg;

  /// Whether this entity is marked unavailable.
  unsigned Unavailable : 1;

  /// Whether this entity is marked unavailable in Swift.
  unsigned UnavailableInSwift : 1;

private:
  /// Whether SwiftPrivate was specified.
  unsigned SwiftPrivateSpecified : 1;

  /// Whether this entity is considered "private" to a Swift overlay.
  unsigned SwiftPrivate : 1;

public:
  /// Swift name of this entity.
  std::string SwiftName;

  CommonEntityInfo()
    : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
      SwiftPrivate(0) { }

  Optional<bool> isSwiftPrivate() const {
    if (!SwiftPrivateSpecified) return None;
    return SwiftPrivate;
  }

  void setSwiftPrivate(Optional<bool> swiftPrivate) {
    if (swiftPrivate) {
      SwiftPrivateSpecified = 1;
      SwiftPrivate = *swiftPrivate;
    } else {
      SwiftPrivateSpecified = 0;
      SwiftPrivate = 0;
    }
  }

  friend bool operator==(const CommonEntityInfo &lhs,
                         const CommonEntityInfo &rhs) {
    return lhs.UnavailableMsg == rhs.UnavailableMsg &&
           lhs.Unavailable == rhs.Unavailable &&
           lhs.UnavailableInSwift == rhs.UnavailableInSwift &&
           lhs.SwiftPrivateSpecified == rhs.SwiftPrivateSpecified &&
           lhs.SwiftPrivate == rhs.SwiftPrivate &&
           lhs.SwiftName == rhs.SwiftName;
  }

  friend bool operator!=(const CommonEntityInfo &lhs,
                         const CommonEntityInfo &rhs) {
    return !(lhs == rhs);
  }

  friend CommonEntityInfo &operator|=(CommonEntityInfo &lhs,
                                      const CommonEntityInfo &rhs) {
    // Merge unavailability.
    if (rhs.Unavailable) {
      lhs.Unavailable = true;
      if (rhs.UnavailableMsg.length() != 0 &&
          lhs.UnavailableMsg.length() == 0) {
        lhs.UnavailableMsg = rhs.UnavailableMsg;
      }
    }

    if (rhs.UnavailableInSwift) {
      lhs.UnavailableInSwift = true;
      if (rhs.UnavailableMsg.length() != 0 &&
          lhs.UnavailableMsg.length() == 0) {
        lhs.UnavailableMsg = rhs.UnavailableMsg;
      }
    }

    if (rhs.SwiftPrivateSpecified && !lhs.SwiftPrivateSpecified) {
      lhs.SwiftPrivateSpecified = 1;
      lhs.SwiftPrivate = rhs.SwiftPrivate;
    }

    if (rhs.SwiftName.length() != 0 &&
        lhs.SwiftName.length() == 0)
      lhs.SwiftName = rhs.SwiftName;

    return lhs;
  }
};

/// Describes API notes for types.
class CommonTypeInfo : public CommonEntityInfo {
  /// The Swift type to which a given type is bridged.
  ///
  /// Reflects the swift_bridge attribute.
  Optional<std::string> SwiftBridge;

  /// The NS error domain for this type.
  Optional<std::string> NSErrorDomain;

public:
  CommonTypeInfo() : CommonEntityInfo() { }

  const Optional<std::string> &getSwiftBridge() const { return SwiftBridge; }

  void setSwiftBridge(const Optional<std::string> &swiftType) {
    SwiftBridge = swiftType;
  }

  void setSwiftBridge(const Optional<StringRef> &swiftType) {
    if (swiftType)
      SwiftBridge = *swiftType;
    else
      SwiftBridge = None;
  }

  const Optional<std::string> &getNSErrorDomain() const {
    return NSErrorDomain;
  }

  void setNSErrorDomain(const Optional<std::string> &domain) {
    NSErrorDomain = domain;
  }

  void setNSErrorDomain(const Optional<StringRef> &domain) {
    if (domain)
      NSErrorDomain = *domain;
    else
      NSErrorDomain = None;
  }

  friend CommonTypeInfo &operator|=(CommonTypeInfo &lhs,
                                    const CommonTypeInfo &rhs) {
    static_cast<CommonEntityInfo &>(lhs) |= rhs;
    if (!lhs.SwiftBridge && rhs.SwiftBridge)
      lhs.SwiftBridge = rhs.SwiftBridge;
    if (!lhs.NSErrorDomain && rhs.NSErrorDomain)
      lhs.NSErrorDomain = rhs.NSErrorDomain;
    return lhs;
  }

  friend bool operator==(const CommonTypeInfo &lhs,
                         const CommonTypeInfo &rhs) {
    return static_cast<const CommonEntityInfo &>(lhs) == rhs &&
      lhs.SwiftBridge == rhs.SwiftBridge &&
      lhs.NSErrorDomain == rhs.NSErrorDomain;
  }

  friend bool operator!=(const CommonTypeInfo &lhs,
                         const CommonTypeInfo &rhs) {
    return !(lhs == rhs);
  }
};

/// Describes API notes data for an Objective-C class or protocol.
class ObjCContextInfo : public CommonTypeInfo {
  /// Whether this class has a default nullability.
  unsigned HasDefaultNullability : 1;

  /// The default nullability.
  unsigned DefaultNullability : 2;

  /// Whether this class has designated initializers recorded.
  unsigned HasDesignatedInits : 1;

public:
  ObjCContextInfo()
    : CommonTypeInfo(),
      HasDefaultNullability(0),
      DefaultNullability(0),
      HasDesignatedInits(0)
  { }

  /// Determine the default nullability for properties and methods of this
  /// class.
  ///
  /// \returns the default nullability, if implied, or None if there is no
  Optional<NullabilityKind> getDefaultNullability() const {
    if (HasDefaultNullability)
      return static_cast<NullabilityKind>(DefaultNullability);

    return None;
  }

  /// Set the default nullability for properties and methods of this class.
  void setDefaultNullability(NullabilityKind kind) {
    HasDefaultNullability = true;
    DefaultNullability = static_cast<unsigned>(kind);
  }

  bool hasDesignatedInits() const { return HasDesignatedInits; }
  void setHasDesignatedInits(bool value) { HasDesignatedInits = value; }

  /// Strip off any information within the class information structure that is
  /// module-local, such as 'audited' flags.
  void stripModuleLocalInfo() {
    HasDefaultNullability = false;
    DefaultNullability = 0;
  }

  friend bool operator==(const ObjCContextInfo &lhs, const ObjCContextInfo &rhs) {
    return static_cast<const CommonTypeInfo &>(lhs) == rhs &&
           lhs.HasDefaultNullability == rhs.HasDefaultNullability &&
           lhs.DefaultNullability == rhs.DefaultNullability &&
           lhs.HasDesignatedInits == rhs.HasDesignatedInits;
  }

  friend bool operator!=(const ObjCContextInfo &lhs, const ObjCContextInfo &rhs) {
    return !(lhs == rhs);
  }

  friend ObjCContextInfo &operator|=(ObjCContextInfo &lhs,
                                     const ObjCContextInfo &rhs) {
    // Merge inherited info.
    static_cast<CommonTypeInfo &>(lhs) |= rhs;

    // Merge nullability.
    if (!lhs.getDefaultNullability()) {
      if (auto nullable = rhs.getDefaultNullability()) {
        lhs.setDefaultNullability(*nullable);
      }
    }

    lhs.HasDesignatedInits |= rhs.HasDesignatedInits;

    return lhs;
  }
  
  void dump(llvm::raw_ostream &os);
};

/// API notes for a variable/property.
class VariableInfo : public CommonEntityInfo {
  /// Whether this property has been audited for nullability.
  unsigned NullabilityAudited : 1;

  /// The kind of nullability for this property. Only valid if the nullability
  /// has been audited.
  unsigned Nullable : 2;

  /// The C type of the variable, as a string.
  std::string Type;

public:
  VariableInfo()
    : CommonEntityInfo(),
      NullabilityAudited(false),
      Nullable(0) { }

  Optional<NullabilityKind> getNullability() const {
    if (NullabilityAudited)
      return static_cast<NullabilityKind>(Nullable);

    return None;
  }

  void setNullabilityAudited(NullabilityKind kind) {
    NullabilityAudited = true;
    Nullable = static_cast<unsigned>(kind);
  }

  const std::string &getType() const { return Type; }
  void setType(const std::string &type) { Type = type; }

  friend bool operator==(const VariableInfo &lhs, const VariableInfo &rhs) {
    return static_cast<const CommonEntityInfo &>(lhs) == rhs &&
           lhs.NullabilityAudited == rhs.NullabilityAudited &&
           lhs.Nullable == rhs.Nullable &&
           lhs.Type == rhs.Type;
  }

  friend bool operator!=(const VariableInfo &lhs, const VariableInfo &rhs) {
    return !(lhs == rhs);
  }

  friend VariableInfo &operator|=(VariableInfo &lhs,
                                  const VariableInfo &rhs) {
    static_cast<CommonEntityInfo &>(lhs) |= rhs;
    if (!lhs.NullabilityAudited && rhs.NullabilityAudited)
      lhs.setNullabilityAudited(*rhs.getNullability());
    if (lhs.Type.empty() && !rhs.Type.empty())
      lhs.Type = rhs.Type;
    return lhs;
  }
};

/// Describes API notes data for an Objective-C property.
class ObjCPropertyInfo : public VariableInfo {
  unsigned SwiftImportAsAccessorsSpecified : 1;
  unsigned SwiftImportAsAccessors : 1;

public:
  ObjCPropertyInfo()
      : VariableInfo(), SwiftImportAsAccessorsSpecified(false),
        SwiftImportAsAccessors(false) {}

  /// Merge class-wide information into the given property.
  friend ObjCPropertyInfo &operator|=(ObjCPropertyInfo &lhs,
                                      const ObjCContextInfo &rhs) {
    static_cast<VariableInfo &>(lhs) |= rhs;

    // Merge nullability.
    if (!lhs.getNullability()) {
      if (auto nullable = rhs.getDefaultNullability()) {
        lhs.setNullabilityAudited(*nullable);
      }
    }

    return lhs;
  }

  Optional<bool> getSwiftImportAsAccessors() const {
    if (SwiftImportAsAccessorsSpecified)
      return SwiftImportAsAccessors;
    return None;
  }
  void setSwiftImportAsAccessors(Optional<bool> value) {
    if (value.hasValue()) {
      SwiftImportAsAccessorsSpecified = true;
      SwiftImportAsAccessors = value.getValue();
    } else {
      SwiftImportAsAccessorsSpecified = false;
      SwiftImportAsAccessors = false;
    }
  }

  friend ObjCPropertyInfo &operator|=(ObjCPropertyInfo &lhs,
                                      const ObjCPropertyInfo &rhs) {
    lhs |= static_cast<const VariableInfo &>(rhs);
    if (!lhs.SwiftImportAsAccessorsSpecified &&
        rhs.SwiftImportAsAccessorsSpecified) {
      lhs.SwiftImportAsAccessorsSpecified = true;
      lhs.SwiftImportAsAccessors = rhs.SwiftImportAsAccessors;
    }
    return lhs;
  }
};

/// Describes a function or method parameter.
class ParamInfo : public VariableInfo {
  /// Whether noescape was specified.
  unsigned NoEscapeSpecified : 1;

  /// Whether the this parameter has the 'noescape' attribute.
  unsigned NoEscape : 1;

public:
  ParamInfo() : VariableInfo(), NoEscapeSpecified(false), NoEscape(false) { }

  Optional<bool> isNoEscape() const {
    if (!NoEscapeSpecified) return None;
    return NoEscape;
  }
  void setNoEscape(Optional<bool> noescape) {
    if (noescape) {
      NoEscapeSpecified = true;
      NoEscape = *noescape;
    } else {
      NoEscapeSpecified = false;
      NoEscape = false;
    }
  }

  friend ParamInfo &operator|=(ParamInfo &lhs, const ParamInfo &rhs) {
    static_cast<VariableInfo &>(lhs) |= rhs;
    if (!lhs.NoEscapeSpecified && rhs.NoEscapeSpecified) {
      lhs.NoEscapeSpecified = true;
      lhs.NoEscape = rhs.NoEscape;
    }
    return lhs;
  }

  friend bool operator==(const ParamInfo &lhs, const ParamInfo &rhs) {
    return static_cast<const VariableInfo &>(lhs) == rhs &&
           lhs.NoEscapeSpecified == rhs.NoEscapeSpecified &&
           lhs.NoEscape == rhs.NoEscape;
  }

  friend bool operator!=(const ParamInfo &lhs, const ParamInfo &rhs) {
    return !(lhs == rhs);
  }
};

/// A temporary reference to an Objective-C selector, suitable for
/// referencing selector data on the stack.
///
/// Instances of this struct do not store references to any of the
/// data they contain; it is up to the user to ensure that the data
/// referenced by the identifier list persists.
struct ObjCSelectorRef {
  unsigned NumPieces;
  ArrayRef<StringRef> Identifiers;
};

/// API notes for a function or method.
class FunctionInfo : public CommonEntityInfo {
private:
  static unsigned const NullabilityKindMask = 0x3;
  static unsigned const NullabilityKindSize = 2;

public:
  /// Whether the signature has been audited with respect to nullability.
  /// If yes, we consider all types to be non-nullable unless otherwise noted.
  /// If this flag is not set, the pointer types are considered to have
  /// unknown nullability.
  unsigned NullabilityAudited : 1;

  /// Number of types whose nullability is encoded with the NullabilityPayload.
  unsigned NumAdjustedNullable : 8;

  /// Stores the nullability of the return type and the parameters.
  //  NullabilityKindSize bits are used to encode the nullability. The info
  //  about the return type is stored at position 0, followed by the nullability
  //  of the parameters.
  uint64_t NullabilityPayload = 0;

  /// The result type of this function, as a C type.
  std::string ResultType;

  /// The function parameters.
  std::vector<ParamInfo> Params;

  FunctionInfo()
    : CommonEntityInfo(),
      NullabilityAudited(false),
      NumAdjustedNullable(0) { }

  static unsigned getMaxNullabilityIndex() {
    return ((sizeof(NullabilityPayload) * CHAR_BIT)/NullabilityKindSize);
  }

  void addTypeInfo(unsigned index, NullabilityKind kind) {
    assert(index <= getMaxNullabilityIndex());
    assert(static_cast<unsigned>(kind) < NullabilityKindMask);
    NullabilityAudited = true;
    if (NumAdjustedNullable < index + 1)
      NumAdjustedNullable = index + 1;

    // Mask the bits.
    NullabilityPayload &= ~(NullabilityKindMask << (index * NullabilityKindSize));

    // Set the value.
    unsigned kindValue =
      (static_cast<unsigned>(kind)) << (index * NullabilityKindSize);
    NullabilityPayload |= kindValue;
  }

  /// Adds the return type info.
  void addReturnTypeInfo(NullabilityKind kind) {
    addTypeInfo(0, kind);
  }

  /// Adds the parameter type info.
  void addParamTypeInfo(unsigned index, NullabilityKind kind) {
    addTypeInfo(index + 1, kind);
  }

private:
  NullabilityKind getTypeInfo(unsigned index) const {
    assert(NullabilityAudited &&
           "Checking the type adjustment on non-audited method.");
    // If we don't have info about this parameter, return the default.
    if (index > NumAdjustedNullable)
      return NullabilityKind::NonNull;
    return static_cast<NullabilityKind>(( NullabilityPayload
                                          >> (index * NullabilityKindSize) )
                                         & NullabilityKindMask);
  }

public:
  NullabilityKind getParamTypeInfo(unsigned index) const {
    return getTypeInfo(index + 1);
  }
  
  NullabilityKind getReturnTypeInfo() const {
    return getTypeInfo(0);
  }

  friend bool operator==(const FunctionInfo &lhs, const FunctionInfo &rhs) {
    return static_cast<const CommonEntityInfo &>(lhs) == rhs &&
           lhs.NullabilityAudited == rhs.NullabilityAudited &&
           lhs.NumAdjustedNullable == rhs.NumAdjustedNullable &&
           lhs.NullabilityPayload == rhs.NullabilityPayload &&
           lhs.ResultType == rhs.ResultType &&
           lhs.Params == rhs.Params;
  }

  friend bool operator!=(const FunctionInfo &lhs, const FunctionInfo &rhs) {
    return !(lhs == rhs);
  }

};

/// Describes API notes data for an Objective-C method.
class ObjCMethodInfo : public FunctionInfo {
public:
  /// Whether this is a designated initializer of its class.
  unsigned DesignatedInit : 1;

  /// Whether to treat this method as a factory or initializer.
  unsigned FactoryAsInit : 2;

  /// Whether this is a required initializer.
  unsigned Required : 1;

  ObjCMethodInfo()
    : FunctionInfo(),
      DesignatedInit(false),
      FactoryAsInit(static_cast<unsigned>(FactoryAsInitKind::Infer)),
      Required(false) { }

  FactoryAsInitKind getFactoryAsInitKind() const {
    return static_cast<FactoryAsInitKind>(FactoryAsInit);
  }

  void setFactoryAsInitKind(FactoryAsInitKind kind) {
    FactoryAsInit = static_cast<unsigned>(kind);
  }

  friend bool operator==(const ObjCMethodInfo &lhs, const ObjCMethodInfo &rhs) {
    return static_cast<const FunctionInfo &>(lhs) == rhs &&
           lhs.DesignatedInit == rhs.DesignatedInit &&
           lhs.FactoryAsInit == rhs.FactoryAsInit &&
           lhs.Required == rhs.Required;
  }

  friend bool operator!=(const ObjCMethodInfo &lhs, const ObjCMethodInfo &rhs) {
    return !(lhs == rhs);
  }

  void mergePropInfoIntoSetter(const ObjCPropertyInfo &pInfo);

  void mergePropInfoIntoGetter(const ObjCPropertyInfo &pInfo);

  /// Merge class-wide information into the given method.
  friend ObjCMethodInfo &operator|=(ObjCMethodInfo &lhs,
                                    const ObjCContextInfo &rhs) {
    // Merge nullability.
    if (!lhs.NullabilityAudited) {
      if (auto nullable = rhs.getDefaultNullability()) {
        lhs.NullabilityAudited = true;
        lhs.addTypeInfo(0, *nullable);
      }
    }

    return lhs;
  }

  void dump(llvm::raw_ostream &os);
};

/// Describes API notes data for a global variable.
class GlobalVariableInfo : public VariableInfo {
public:
  GlobalVariableInfo() : VariableInfo() { }
};

/// Describes API notes data for a global function.
class GlobalFunctionInfo : public FunctionInfo {
public:
  GlobalFunctionInfo() : FunctionInfo() { }
};

/// Describes API notes data for an enumerator.
class EnumConstantInfo : public CommonEntityInfo {
public:
  EnumConstantInfo() : CommonEntityInfo() { }
};

/// Describes API notes data for a tag.
class TagInfo : public CommonTypeInfo {
public:
  TagInfo() : CommonTypeInfo() { }
};

/// The kind of a swift_wrapper/swift_newtype.
enum class SwiftWrapperKind {
  None,
  Struct,
  Enum
};

/// Describes API notes data for a typedef.
class TypedefInfo : public CommonTypeInfo {
public:
  Optional<SwiftWrapperKind> SwiftWrapper;

  TypedefInfo() : CommonTypeInfo() { }
};

/// Descripts a series of options for a module
struct ModuleOptions {
  bool SwiftInferImportAsMember = false;
};

} // end namespace api_notes
} // end namespace clang

#endif // LLVM_CLANG_API_NOTES_TYPES_H
