/*
 * Copyright (C) 2015, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "aidl_language.h"
#include "aidl_typenames.h"
#include "parser.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <iostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>

#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/result.h>
#include <android-base/strings.h>

#include "aidl.h"
#include "aidl_language_y.h"
#include "comments.h"
#include "logging.h"
#include "permission/parser.h"

#ifdef _WIN32
int isatty(int  fd)
{
    return (fd == 0);
}
#endif

using android::aidl::IoDelegate;
using android::base::Error;
using android::base::Join;
using android::base::Result;
using android::base::Split;
using std::cerr;
using std::pair;
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace {
bool IsJavaKeyword(const char* str) {
  static const std::vector<std::string> kJavaKeywords{
      "abstract", "assert", "boolean",    "break",     "byte",       "case",      "catch",
      "char",     "class",  "const",      "continue",  "default",    "do",        "double",
      "else",     "enum",   "extends",    "final",     "finally",    "float",     "for",
      "goto",     "if",     "implements", "import",    "instanceof", "int",       "interface",
      "long",     "native", "new",        "package",   "private",    "protected", "public",
      "return",   "short",  "static",     "strictfp",  "super",      "switch",    "synchronized",
      "this",     "throw",  "throws",     "transient", "try",        "void",      "volatile",
      "while",    "true",   "false",      "null",
  };
  return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
}
}  // namespace

AidlNode::~AidlNode() {
  if (!visited_) {
    unvisited_locations_.push_back(location_);
  }
}

void AidlNode::ClearUnvisitedNodes() {
  unvisited_locations_.clear();
}

const std::vector<AidlLocation>& AidlNode::GetLocationsOfUnvisitedNodes() {
  return unvisited_locations_;
}

void AidlNode::MarkVisited() const {
  visited_ = true;
}

AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
    : location_(location), comments_(comments) {}

std::string AidlNode::PrintLine() const {
  std::stringstream ss;
  ss << location_.file_ << ":" << location_.begin_.line;
  return ss.str();
}

std::string AidlNode::PrintLocation() const {
  std::stringstream ss;
  ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
     << location_.end_.line << ":" << location_.end_.column;
  return ss.str();
}

std::vector<AidlLocation> AidlNode::unvisited_locations_;

static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", /*array=*/std::nullopt,
                                           nullptr, Comments{}};
static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", DynamicArray{},
                                                nullptr, Comments{}};
static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", /*array=*/std::nullopt, nullptr,
                                        Comments{}};
static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", /*array=*/std::nullopt,
                                         nullptr, Comments{}};
static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", /*array=*/std::nullopt,
                                            nullptr, Comments{}};

const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
  static const std::vector<Schema> kSchemas{
      {AidlAnnotation::Type::NULLABLE,
       "nullable",
       CONTEXT_TYPE_SPECIFIER,
       {{"heap", kBooleanType}}},
      {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
      {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
      {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
      {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
       "UnsupportedAppUsage",
       CONTEXT_TYPE | CONTEXT_MEMBER,
       {{"expectedSignature", kStringType},
        {"implicitMember", kStringType},
        {"maxTargetSdk", kIntType},
        {"publicAlternatives", kStringType},
        {"trackingBug", kLongType}}},
      {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
       "JavaOnlyStableParcelable",
       CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
       {}},
      {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
      {AidlAnnotation::Type::BACKING,
       "Backing",
       CONTEXT_TYPE_ENUM,
       {{"type", kStringType, /* required= */ true}}},
      {AidlAnnotation::Type::JAVA_PASSTHROUGH,
       "JavaPassthrough",
       CONTEXT_ALL,
       {{"annotation", kStringType, /* required= */ true}},
       /* repeatable= */ true},
      {AidlAnnotation::Type::JAVA_DERIVE,
       "JavaDerive",
       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
       {{"toString", kBooleanType}, {"equals", kBooleanType}}},
      {AidlAnnotation::Type::JAVA_DEFAULT, "JavaDefault", CONTEXT_TYPE_INTERFACE, {}},
      {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
       "JavaOnlyImmutable",
       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
           CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
       {}},
      {AidlAnnotation::Type::FIXED_SIZE,
       "FixedSize",
       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
       {}},
      {AidlAnnotation::Type::DESCRIPTOR,
       "Descriptor",
       CONTEXT_TYPE_INTERFACE,
       {{"value", kStringType, /* required= */ true}}},
      {AidlAnnotation::Type::RUST_DERIVE,
       "RustDerive",
       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
       {{"Copy", kBooleanType},
        {"Clone", kBooleanType},
        {"PartialOrd", kBooleanType},
        {"Ord", kBooleanType},
        {"PartialEq", kBooleanType},
        {"Eq", kBooleanType},
        {"Hash", kBooleanType}}},
      {AidlAnnotation::Type::SUPPRESS_WARNINGS,
       "SuppressWarnings",
       CONTEXT_TYPE | CONTEXT_MEMBER,
       {{"value", kStringArrayType, /* required= */ true}}},
      {AidlAnnotation::Type::PERMISSION_ENFORCE,
       "Enforce",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {{"value", kStringType, /* required= */ true}}},
      {AidlAnnotation::Type::PERMISSION_MANUAL,
       "PermissionManuallyEnforced",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {}},
      {AidlAnnotation::Type::PERMISSION_NONE,
       "NoPermissionRequired",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {}},
  };
  return kSchemas;
}

std::string AidlAnnotation::TypeToString(Type type) {
  for (const Schema& schema : AllSchemas()) {
    if (type == schema.type) return schema.name;
  }
  AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
  __builtin_unreachable();
}

std::unique_ptr<AidlAnnotation> AidlAnnotation::Parse(
    const AidlLocation& location, const string& name,
    std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
    const Comments& comments) {
  const Schema* schema = nullptr;
  for (const Schema& a_schema : AllSchemas()) {
    if (a_schema.name == name) {
      schema = &a_schema;
    }
  }

  if (schema == nullptr) {
    std::ostringstream stream;
    stream << "'" << name << "' is not a recognized annotation. ";
    stream << "It must be one of:";
    for (const Schema& s : AllSchemas()) {
      stream << " " << s.name;
    }
    stream << ".";
    AIDL_ERROR(location) << stream.str();
    return {};
  }

  return std::unique_ptr<AidlAnnotation>(
      new AidlAnnotation(location, *schema, std::move(parameter_list), comments));
}

AidlAnnotation::AidlAnnotation(const AidlLocation& location, const Schema& schema,
                               std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
                               const Comments& comments)
    : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}

struct ConstReferenceFinder : AidlVisitor {
  const AidlConstantReference* found;
  void Visit(const AidlConstantReference& ref) override {
    if (!found) found = &ref;
  }
  static const AidlConstantReference* Find(const AidlConstantValue& c) {
    ConstReferenceFinder finder;
    VisitTopDown(finder, c);
    return finder.found;
  }
};

// Checks if annotation complies with the schema
// - every parameter is known and has well-typed value.
// - every required parameter is present.
bool AidlAnnotation::CheckValid() const {
  for (const auto& name_and_param : parameters_) {
    const std::string& param_name = name_and_param.first;
    const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;

    const ParamType* param_type = schema_.ParamType(param_name);
    if (!param_type) {
      std::ostringstream stream;
      stream << "Parameter " << param_name << " not supported ";
      stream << "for annotation " << GetName() << ". ";
      stream << "It must be one of:";
      for (const auto& param : schema_.parameters) {
        stream << " " << param.name;
      }
      AIDL_ERROR(this) << stream.str();
      return false;
    }

    const auto& found = ConstReferenceFinder::Find(*param);
    if (found) {
      AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
                        << found->GetFieldName() << ".";
      return false;
    }

    if (!param->CheckValid()) {
      AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
                       << GetName() << ".";
      return false;
    }

    const std::string param_value =
        param->ValueString(param_type->type, AidlConstantValueDecorator);
    // Assume error on empty string.
    if (param_value == "") {
      AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
                       << GetName() << ".";
      return false;
    }
  }
  bool success = true;
  for (const auto& param : schema_.parameters) {
    if (param.required && parameters_.count(param.name) == 0) {
      AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
      success = false;
    }
  }
  if (!success) {
    return false;
  }
  // For @Enforce annotations, validates the expression.
  if (schema_.type == AidlAnnotation::Type::PERMISSION_ENFORCE) {
    auto expr = EnforceExpression();
    if (!expr.ok()) {
      AIDL_ERROR(this) << "Unable to parse @Enforce annotation: " << expr.error();
      return false;
    }
  }
  return true;
}

Result<unique_ptr<perm::Expression>> AidlAnnotation::EnforceExpression() const {
  auto perm_expr = ParamValue<std::string>("value");
  if (perm_expr.has_value()) {
    return perm::Parser::Parse(perm_expr.value());
  }
  return Error() << "No value parameter for @Enforce";
}

// Checks if the annotation is applicable to the current context.
// For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
// nodes.
bool AidlAnnotation::CheckContext(TargetContext context) const {
  if (schema_.target_context & static_cast<uint32_t>(context)) {
    return true;
  }
  const static map<TargetContext, string> context_name_map{
      {CONTEXT_TYPE_INTERFACE, "interface"},
      {CONTEXT_TYPE_ENUM, "enum"},
      {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
      {CONTEXT_TYPE_UNION, "union"},
      {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
      {CONTEXT_CONST, "constant"},
      {CONTEXT_FIELD, "field"},
      {CONTEXT_METHOD, "method"},
      {CONTEXT_TYPE_SPECIFIER, "type"},
  };
  vector<string> available;
  for (const auto& [context, name] : context_name_map) {
    if (schema_.target_context & context) {
      available.push_back(name);
    }
  }
  AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
                   << Join(available, ", ") << "}.";
  return false;
}

std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
    const ConstantValueDecorator& decorator) const {
  std::map<std::string, std::string> raw_params;
  for (const auto& name_and_param : parameters_) {
    const std::string& param_name = name_and_param.first;
    const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
    const ParamType* param_type = schema_.ParamType(param_name);
    AIDL_FATAL_IF(!param_type, this);
    raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
  }
  return raw_params;
}

std::string AidlAnnotation::ToString() const {
  if (parameters_.empty()) {
    return "@" + GetName();
  } else {
    vector<string> param_strings;
    for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
      param_strings.emplace_back(name + "=" + value);
    }
    return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
  }
}

void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
  for (const auto& [name, value] : parameters_) {
    (void)name;
    traverse(*value);
  }
}

static const AidlAnnotation* GetAnnotation(
    const vector<std::unique_ptr<AidlAnnotation>>& annotations, AidlAnnotation::Type type) {
  for (const auto& a : annotations) {
    if (a->GetType() == type) {
      AIDL_FATAL_IF(a->Repeatable(), a)
          << "Trying to get a single annotation when it is repeatable.";
      return a.get();
    }
  }
  return nullptr;
}

AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
    : AidlCommentable(location, comments) {}

bool AidlAnnotatable::IsNullable() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
}

bool AidlAnnotatable::IsHeapNullable() const {
  auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
  if (annot) {
    return annot->ParamValue<bool>("heap").value_or(false);
  }
  return false;
}

bool AidlAnnotatable::IsUtf8InCpp() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
}

bool AidlAnnotatable::IsSensitiveData() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
}

bool AidlAnnotatable::IsVintfStability() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
}

bool AidlAnnotatable::IsJavaOnlyImmutable() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
}

bool AidlAnnotatable::IsFixedSize() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
}

const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
}

const AidlAnnotation* AidlAnnotatable::RustDerive() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
}

const AidlAnnotation* AidlAnnotatable::BackingType() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
}

std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
  auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
  if (annot) {
    auto names = annot->ParamValue<std::vector<std::string>>("value");
    AIDL_FATAL_IF(!names.has_value(), this);
    return std::move(names.value());
  }
  return {};
}

// Parses the @Enforce annotation expression.
std::unique_ptr<perm::Expression> AidlAnnotatable::EnforceExpression() const {
  auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_ENFORCE);
  if (annot) {
    auto perm_expr = annot->EnforceExpression();
    if (!perm_expr.ok()) {
      // This should have been caught during validation.
      AIDL_FATAL(this) << "Unable to parse @Enforce annotation: " << perm_expr.error();
    }
    return std::move(perm_expr.value());
  }
  return {};
}

bool AidlAnnotatable::IsPermissionManual() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_MANUAL);
}

bool AidlAnnotatable::IsPermissionNone() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_NONE);
}

bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
  return lang == Options::Language::JAVA &&
         GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
}

bool AidlAnnotatable::IsHide() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
}

bool AidlAnnotatable::JavaDerive(const std::string& method) const {
  auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
  if (annotation != nullptr) {
    return annotation->ParamValue<bool>(method).value_or(false);
  }
  return false;
}

bool AidlAnnotatable::IsJavaDefault() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEFAULT);
}

std::string AidlAnnotatable::GetDescriptor() const {
  auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
  if (annotation != nullptr) {
    return annotation->ParamValue<std::string>("value").value();
  }
  return "";
}

bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
  for (const auto& annotation : GetAnnotations()) {
    if (!annotation->CheckValid()) {
      return false;
    }
  }

  std::map<AidlAnnotation::Type, AidlLocation> declared;
  for (const auto& annotation : GetAnnotations()) {
    const auto& [iter, inserted] =
        declared.emplace(annotation->GetType(), annotation->GetLocation());
    if (!inserted && !annotation->Repeatable()) {
      AIDL_ERROR(this) << "'" << annotation->GetName()
                       << "' is repeated, but not allowed. Previous location: " << iter->second;
      return false;
    }
  }

  return true;
}

string AidlAnnotatable::ToString() const {
  vector<string> ret;
  for (const auto& a : annotations_) {
    ret.emplace_back(a->ToString());
  }
  std::sort(ret.begin(), ret.end());
  return Join(ret, " ");
}

AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
                                     std::optional<ArrayType> array,
                                     vector<unique_ptr<AidlTypeSpecifier>>* type_params,
                                     const Comments& comments)
    : AidlAnnotatable(location, comments),
      AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
      unresolved_name_(unresolved_name),
      array_(std::move(array)),
      split_name_(Split(unresolved_name, ".")) {}

void AidlTypeSpecifier::ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const {
  AIDL_FATAL_IF(!array_.has_value(), this);
  // Declaring array of generic type cannot happen, it is grammar error.
  AIDL_FATAL_IF(IsGeneric(), this);

  if (IsFixedSizeArray() && std::get<FixedSizeArray>(*array_).dimensions.size() > 1) {
    auto& dimensions = std::get<FixedSizeArray>(*array_).dimensions;
    auto dim = std::move(dimensions.front());
    dimensions.erase(dimensions.begin());
    func(*this);
    dimensions.insert(dimensions.begin(), std::move(dim));
  } else {
    ArrayType array_type = std::move(array_.value());
    array_ = std::nullopt;
    func(*this);
    array_ = std::move(array_type);
  }
}

bool AidlTypeSpecifier::MakeArray(ArrayType array_type) {
  // T becomes T[] or T[N]
  if (!IsArray()) {
    array_ = std::move(array_type);
    return true;
  }
  // T[N] becomes T[N][M]
  if (auto fixed_size_array = std::get_if<FixedSizeArray>(&array_type);
      fixed_size_array != nullptr && IsFixedSizeArray()) {
    // concat dimensions
    for (auto& dim : fixed_size_array->dimensions) {
      std::get<FixedSizeArray>(*array_).dimensions.push_back(std::move(dim));
    }
    return true;
  }
  return false;
}

string AidlTypeSpecifier::Signature() const {
  string ret = GetName();
  if (IsGeneric()) {
    vector<string> arg_names;
    for (const auto& ta : GetTypeParameters()) {
      arg_names.emplace_back(ta->Signature());
    }
    ret += "<" + Join(arg_names, ",") + ">";
  }
  if (IsArray()) {
    if (IsFixedSizeArray()) {
      for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
        ret += "[" + dim->ValueString(kIntType, AidlConstantValueDecorator) + "]";
      }
    } else {
      ret += "[]";
    }
  }
  return ret;
}

string AidlTypeSpecifier::ToString() const {
  string ret = Signature();
  string annotations = AidlAnnotatable::ToString();
  if (annotations != "") {
    ret = annotations + " " + ret;
  }
  return ret;
}

// When `scope` is specified, name is resolved first based on it.
// `scope` can be null for built-in types and fully-qualified types.
bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames, const AidlScope* scope) {
  AIDL_FATAL_IF(IsResolved(), this);
  std::string name = unresolved_name_;
  if (scope) {
    name = scope->ResolveName(name);
  }
  AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(name);
  if (result.is_resolved) {
    fully_qualified_name_ = result.canonical_name;
    split_name_ = Split(fully_qualified_name_, ".");
    defined_type_ = result.defined_type;
  }
  return result.is_resolved;
}

const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
  return defined_type_;
}

bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlAnnotatable::CheckValid(typenames)) {
    return false;
  }
  if (IsGeneric()) {
    const auto& types = GetTypeParameters();
    for (const auto& arg : types) {
      if (!arg->CheckValid(typenames)) {
        return false;
      }
    }

    const string& type_name = GetName();
    // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
    if (type_name == "List" || type_name == "Map") {
      if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
            return !type_ptr->IsArray() &&
                   (typenames.GetEnumDeclaration(*type_ptr) ||
                    AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
          })) {
        AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
        return false;
      }
    }
    const auto defined_type = typenames.TryGetDefinedType(type_name);
    const auto parameterizable =
        defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
    const bool is_user_defined_generic_type =
        parameterizable != nullptr && parameterizable->IsGeneric();
    const size_t num_params = GetTypeParameters().size();
    if (type_name == "List") {
      if (num_params > 1) {
        AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
                         << "'";
        return false;
      }
      static const char* kListUsage =
          "List<T> supports interface/parcelable/union, String, IBinder, and ParcelFileDescriptor.";
      const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
      if (contained_type.IsArray()) {
        AIDL_ERROR(this) << "List of arrays is not supported. " << kListUsage;
        return false;
      }
      const string& contained_type_name = contained_type.GetName();
      if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
        if (contained_type_name != "String" && contained_type_name != "IBinder" &&
            contained_type_name != "ParcelFileDescriptor") {
          AIDL_ERROR(this) << "List<" << contained_type_name << "> is not supported. "
                           << kListUsage;
          return false;
        }
      }
    } else if (type_name == "Map") {
      if (num_params != 0 && num_params != 2) {
        AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
                         << "'" << Signature() << "'";
        return false;
      }
      if (num_params == 2) {
        const string& key_type = GetTypeParameters()[0]->Signature();
        if (key_type != "String") {
          AIDL_ERROR(this) << "The type of key in map must be String, but it is "
                           << "'" << key_type << "'";
          return false;
        }
      }
    } else if (is_user_defined_generic_type) {
      const size_t allowed = parameterizable->GetTypeParameters().size();
      if (num_params != allowed) {
        AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
                         << num_params;
        return false;
      }
    } else {
      AIDL_ERROR(this) << type_name << " is not a generic type.";
      return false;
    }
  }

  const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
                                      GetTypeParameters().size() == 1 &&
                                      GetTypeParameters()[0]->GetName() == "String";
  if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
    AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
    return false;
  }

  if (GetName() == "void") {
    if (IsArray() || IsNullable() || IsUtf8InCpp()) {
      AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
      return false;
    }
  }

  if (IsArray()) {
    if (GetName() == "ParcelableHolder" || GetName() == "List" || GetName() == "Map" ||
        GetName() == "CharSequence") {
      AIDL_ERROR(this) << "Arrays of " << GetName() << " are not supported.";
      return false;
    }
  }

  if (IsNullable()) {
    if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
      AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
      return false;
    }
    const auto defined_type = typenames.TryGetDefinedType(GetName());
    if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
      AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
      return false;
    }
    if (GetName() == "ParcelableHolder") {
      AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
      return false;
    }
    if (IsHeapNullable()) {
      if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
        AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
        return false;
      }
    }
  }

  if (IsFixedSizeArray()) {
    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
      if (!dim->CheckValid()) {
        return false;
      }
      if (dim->GetType() > AidlConstantValue::Type::INT32) {
        AIDL_ERROR(this) << "Array size must be a positive number: " << dim->Literal();
        return false;
      }
      auto value = dim->EvaluatedValue<int32_t>();
      if (value < 0) {
        AIDL_ERROR(this) << "Array size must be a positive number: " << value;
        return false;
      }
    }
  }
  return true;
}

void AidlTypeSpecifier::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
  AidlAnnotatable::TraverseChildren(traverse);
  if (IsGeneric()) {
    for (const auto& tp : GetTypeParameters()) {
      traverse(*tp);
    }
  }
  if (IsFixedSizeArray()) {
    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
      traverse(*dim);
    }
  }
}

std::string AidlConstantValueDecorator(
    const AidlTypeSpecifier& type,
    const std::variant<std::string, std::vector<std::string>>& raw_value) {
  if (type.IsArray()) {
    const auto& values = std::get<std::vector<std::string>>(raw_value);
    return "{" + Join(values, ", ") + "}";
  }
  const std::string& value = std::get<std::string>(raw_value);
  if (auto defined_type = type.GetDefinedType(); defined_type) {
    auto enum_type = defined_type->AsEnumDeclaration();
    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
    return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
  }
  return value;
}

AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
                                                 AidlTypeSpecifier* type, const std::string& name)
    : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
  default_user_specified_ = false;
}

AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
                                                 AidlTypeSpecifier* type, const std::string& name,
                                                 AidlConstantValue* default_value)
    : AidlMember(location, type->GetComments()),
      type_(type),
      name_(name),
      default_user_specified_(true),
      default_value_(default_value) {}

bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
  if (GetDefaultValue()) {
    return true;
  }
  // null is accepted as a valid default value in all backends
  if (GetType().IsNullable()) {
    return true;
  }
  return false;
}

bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
  bool valid = true;
  valid &= type_->CheckValid(typenames);

  if (type_->GetName() == "void") {
    AIDL_ERROR(this) << "Declaration " << name_
                     << " is void, but declarations cannot be of void type.";
    valid = false;
  }

  if (default_value_ == nullptr) return valid;
  valid &= default_value_->CheckValid();

  if (!valid) return false;

  return !ValueString(AidlConstantValueDecorator).empty();
}

string AidlVariableDeclaration::GetCapitalizedName() const {
  AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
  string str = name_;
  str[0] = static_cast<char>(toupper(str[0]));
  return str;
}

string AidlVariableDeclaration::ToString() const {
  string ret = type_->ToString() + " " + name_;
  if (default_value_ != nullptr && default_user_specified_) {
    ret += " = " + ValueString(AidlConstantValueDecorator);
  }
  return ret;
}

string AidlVariableDeclaration::Signature() const {
  return type_->Signature() + " " + name_;
}

std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
  if (default_value_ != nullptr) {
    return default_value_->ValueString(GetType(), decorator);
  } else {
    return "";
  }
}

void AidlVariableDeclaration::TraverseChildren(
    std::function<void(const AidlNode&)> traverse) const {
  traverse(GetType());
  if (auto default_value = GetDefaultValue(); default_value) {
    traverse(*default_value);
  }
}

AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
                           AidlTypeSpecifier* type, const std::string& name)
    : AidlVariableDeclaration(location, type, name),
      direction_(direction),
      direction_specified_(true) {}

AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
                           const std::string& name)
    : AidlVariableDeclaration(location, type, name),
      direction_(AidlArgument::IN_DIR),
      direction_specified_(false) {}

static std::string to_string(AidlArgument::Direction direction) {
  switch (direction) {
    case AidlArgument::IN_DIR:
      return "in";
    case AidlArgument::OUT_DIR:
      return "out";
    case AidlArgument::INOUT_DIR:
      return "inout";
  }
}

string AidlArgument::GetDirectionSpecifier() const {
  string ret;
  if (direction_specified_) {
    ret = to_string(direction_);
  }
  return ret;
}

string AidlArgument::ToString() const {
  if (direction_specified_) {
    return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
  } else {
    return AidlVariableDeclaration::ToString();
  }
}

static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
  std::vector<std::string> out;
  for (const auto& d : directions) {
    out.push_back(to_string(d));
  }

  if (out.size() <= 1) {  // [] => "" or [A] => "A"
    return Join(out, "");
  } else if (out.size() == 2) {  // [A,B] => "A or B"
    return Join(out, " or ");
  } else {  // [A,B,C] => "A, B, or C"
    out.back() = "or " + out.back();
    return Join(out, ", ");
  }
}

bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
  if (!GetType().CheckValid(typenames)) {
    return false;
  }

  const auto& aspect = typenames.GetArgumentAspect(GetType());

  if (aspect.possible_directions.size() == 0) {
    AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
    return false;
  }

  // when direction is not specified, "in" is assumed and should be the only possible direction
  if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
    AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
                     << " can be an " << FormatDirections(aspect.possible_directions)
                     << " parameter.";
    return false;
  }

  if (aspect.possible_directions.count(GetDirection()) == 0) {
    AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
                     << " parameter because " << aspect.name << " can only be an "
                     << FormatDirections(aspect.possible_directions) << " parameter.";
    return false;
  }

  return true;
}

bool AidlCommentable::IsHidden() const {
  return android::aidl::HasHideInComments(GetComments());
}

bool AidlCommentable::IsDeprecated() const {
  return android::aidl::FindDeprecated(GetComments()).has_value();
}

AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
    : AidlAnnotatable(location, comments) {}

AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
                                                 AidlTypeSpecifier* type, const std::string& name,
                                                 AidlConstantValue* value)
    : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}

bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
  bool valid = true;
  valid &= type_->CheckValid(typenames);
  valid &= value_->CheckValid();
  if (!valid) return false;

  const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
  if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
    AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
    return false;
  }

  return true;
}

string AidlConstantDeclaration::ToString() const {
  return "const " + type_->ToString() + " " + name_ + " = " +
         ValueString(AidlConstantValueDecorator);
}

string AidlConstantDeclaration::Signature() const {
  return type_->Signature() + " " + name_;
}

AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
                       const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
                       const Comments& comments)
    : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
  has_id_ = false;
}

AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
                       const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
                       const Comments& comments, int id, bool is_user_defined)
    : AidlMember(location, comments),
      oneway_(oneway),
      type_(type),
      name_(name),
      arguments_(std::move(*args)),
      id_(id),
      is_user_defined_(is_user_defined) {
  has_id_ = true;
  delete args;
  for (const unique_ptr<AidlArgument>& a : arguments_) {
    if (a->IsIn()) { in_arguments_.push_back(a.get()); }
    if (a->IsOut()) { out_arguments_.push_back(a.get()); }
  }
}

string AidlMethod::Signature() const {
  vector<string> arg_signatures;
  for (const auto& arg : GetArguments()) {
    arg_signatures.emplace_back(arg->GetType().Signature());
  }
  return GetName() + "(" + Join(arg_signatures, ", ") + ")";
}

string AidlMethod::ToString() const {
  vector<string> arg_strings;
  for (const auto& arg : GetArguments()) {
    arg_strings.emplace_back(arg->ToString());
  }
  string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
               Join(arg_strings, ", ") + ")";
  if (HasId()) {
    ret += " = " + std::to_string(GetId());
  }
  return ret;
}

bool AidlMethod::CheckValid(const AidlTypenames& typenames) const {
  if (!GetType().CheckValid(typenames)) {
    return false;
  }

  // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
  if (GetType().GetName() == "ParcelableHolder") {
    AIDL_ERROR(this) << "ParcelableHolder cannot be a return type";
    return false;
  }
  if (IsOneway() && GetType().GetName() != "void") {
    AIDL_ERROR(this) << "oneway method '" << GetName() << "' cannot return a value";
    return false;
  }

  set<string> argument_names;
  for (const auto& arg : GetArguments()) {
    auto it = argument_names.find(arg->GetName());
    if (it != argument_names.end()) {
      AIDL_ERROR(this) << "method '" << GetName() << "' has duplicate argument name '"
                       << arg->GetName() << "'";
      return false;
    }
    argument_names.insert(arg->GetName());

    if (!arg->CheckValid(typenames)) {
      return false;
    }

    if (IsOneway() && arg->IsOut()) {
      AIDL_ERROR(this) << "oneway method '" << this->GetName() << "' cannot have out parameters";
      return false;
    }

    // check that the name doesn't match a keyword
    if (IsJavaKeyword(arg->GetName().c_str())) {
      AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
      return false;
    }

    // Reserve a namespace for internal use
    if (android::base::StartsWith(arg->GetName(), "_aidl")) {
      AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
      return false;
    }

    if (arg->GetType().GetName() == "void") {
      AIDL_ERROR(arg->GetType()) << "'void' is an invalid type for the parameter '"
                                 << arg->GetName() << "'";
      return false;
    }
  }
  return true;
}

AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
                                 const Comments& comments, const std::string& package,
                                 std::vector<std::unique_ptr<AidlMember>>* members)
    : AidlMember(location, comments), AidlScope(this), name_(name), package_(package) {
  // adjust name/package when name is fully qualified (for preprocessed files)
  if (package_.empty() && name_.find('.') != std::string::npos) {
    // Note that this logic is absolutely wrong.  Given a parcelable
    // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
    // the class is just Bar.  However, this was the way it was done in the past.
    //
    // See b/17415692
    auto pos = name.rfind('.');
    // name is the last part.
    name_ = name.substr(pos + 1);
    // package is the initial parts (except the last).
    package_ = name.substr(0, pos);
  }
  if (members) {
    for (auto& m : *members) {
      if (auto constant = AidlCast<AidlConstantDeclaration>(*m); constant) {
        constants_.emplace_back(constant);
      } else if (auto variable = AidlCast<AidlVariableDeclaration>(*m); variable) {
        variables_.emplace_back(variable);
      } else if (auto method = AidlCast<AidlMethod>(*m); method) {
        methods_.emplace_back(method);
      } else if (auto type = AidlCast<AidlDefinedType>(*m); type) {
        type->SetEnclosingScope(this);
        types_.emplace_back(type);
      } else {
        AIDL_FATAL(*m) << "Unknown member type.";
      }
      members_.push_back(m.release());
    }
    delete members;
  }
}

bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlAnnotatable::CheckValid(typenames)) {
    return false;
  }
  if (!CheckValidWithMembers(typenames)) {
    return false;
  }
  return true;
}

std::string AidlDefinedType::GetCanonicalName() const {
  if (auto parent = GetParentType(); parent) {
    return parent->GetCanonicalName() + "." + GetName();
  }
  if (package_.empty()) {
    return GetName();
  }
  return GetPackage() + "." + GetName();
}

bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
  bool success = true;

  for (const auto& t : GetNestedTypes()) {
    success = success && t->CheckValid(typenames);
  }

  if (auto parameterizable = AsParameterizable();
      parameterizable && parameterizable->IsGeneric() && !GetNestedTypes().empty()) {
    AIDL_ERROR(this) << "Generic types can't have nested types.";
    return false;
  }

  std::set<std::string> nested_type_names;
  for (const auto& t : GetNestedTypes()) {
    bool duplicated = !nested_type_names.emplace(t->GetName()).second;
    if (duplicated) {
      AIDL_ERROR(t) << "Redefinition of '" << t->GetName() << "'.";
      success = false;
    }
    // nested type can't have a parent name
    if (t->GetName() == GetName()) {
      AIDL_ERROR(t) << "Nested type '" << GetName() << "' has the same name as its parent.";
      success = false;
    }
    // Having unstructured parcelables as nested types doesn't make sense because they are defined
    // somewhere else in native languages (e.g. C++, Java...).
    if (AidlCast<AidlParcelable>(*t)) {
      AIDL_ERROR(t) << "'" << t->GetName()
                    << "' is nested. Unstructured parcelables should be at the root scope.";
      return false;
    }
  }

  if (!TopologicalVisit(GetNestedTypes(), [](auto&) {})) {
    AIDL_ERROR(this) << GetName()
                     << " has nested types with cyclic references. C++ and NDK backends don't "
                        "support cyclic references.";
    return false;
  }

  for (const auto& v : GetFields()) {
    const bool field_valid = v->CheckValid(typenames);
    success = success && field_valid;
  }

  // field names should be unique
  std::set<std::string> fieldnames;
  for (const auto& v : GetFields()) {
    bool duplicated = !fieldnames.emplace(v->GetName()).second;
    if (duplicated) {
      AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
      success = false;
    }
  }

  // immutable parcelables should have immutable fields.
  if (IsJavaOnlyImmutable()) {
    for (const auto& v : GetFields()) {
      if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
        AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
                      << "non-immutable field named '" << v->GetName() << "'.";
        success = false;
      }
    }
  }

  set<string> constant_names;
  for (const auto& constant : GetConstantDeclarations()) {
    if (constant_names.count(constant->GetName()) > 0) {
      AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
      success = false;
    }
    constant_names.insert(constant->GetName());
    success = success && constant->CheckValid(typenames);
  }

  return success;
}

bool AidlDefinedType::CheckValidForGetterNames() const {
  bool success = true;
  std::set<std::string> getters;
  for (const auto& v : GetFields()) {
    bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
    if (duplicated) {
      AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
                    << "' after capitalizing the first letter";
      success = false;
    }
  }
  return success;
}

const AidlDefinedType* AidlDefinedType::GetParentType() const {
  AIDL_FATAL_IF(GetEnclosingScope() == nullptr, this) << "Scope is not set.";
  return AidlCast<AidlDefinedType>(GetEnclosingScope()->GetNode());
}

const AidlDefinedType* AidlDefinedType::GetRootType() const {
  const AidlDefinedType* root = this;
  for (auto parent = root->GetParentType(); parent; parent = parent->GetParentType()) {
    root = parent;
  }
  return root;
}

// Resolve `name` in the current scope. If not found, delegate to the parent
std::string AidlDefinedType::ResolveName(const std::string& name) const {
  // For example, in the following, t1's type Baz means x.Foo.Bar.Baz
  // while t2's type is y.Baz.
  // package x;
  // import y.Baz;
  // parcelable Foo {
  //   parcelable Bar {
  //     enum Baz { ... }
  //     Baz t1; // -> should be x.Foo.Bar.Baz
  //   }
  //   Baz t2; // -> should be y.Baz
  //   Bar.Baz t3; // -> should be x.Foo.Bar.Baz
  // }
  AIDL_FATAL_IF(!GetEnclosingScope(), this)
      << "Type should have an enclosing scope.(e.g. AidlDocument)";
  if (AidlTypenames::IsBuiltinTypename(name)) {
    return name;
  }

  const auto first_dot = name.find_first_of('.');
  // For "Outer.Inner", we look up "Outer" in the import list.
  const std::string class_name =
      (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
  // Keep ".Inner", to make a fully-qualified name
  const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);

  // check if it is a nested type
  for (const auto& type : GetNestedTypes()) {
    if (type->GetName() == class_name) {
      return type->GetCanonicalName() + nested_type;
    }
  }

  return GetEnclosingScope()->ResolveName(name);
}

template <>
const AidlDefinedType* AidlCast<AidlDefinedType>(const AidlNode& node) {
  struct Visitor : AidlVisitor {
    const AidlDefinedType* defined_type = nullptr;
    void Visit(const AidlInterface& t) override { defined_type = &t; }
    void Visit(const AidlEnumDeclaration& t) override { defined_type = &t; }
    void Visit(const AidlStructuredParcelable& t) override { defined_type = &t; }
    void Visit(const AidlUnionDecl& t) override { defined_type = &t; }
    void Visit(const AidlParcelable& t) override { defined_type = &t; }
  } v;
  node.DispatchVisit(v);
  return v.defined_type;
}

const AidlDocument& AidlDefinedType::GetDocument() const {
  const AidlDefinedType* root = GetRootType();
  auto scope = root->GetEnclosingScope();
  AIDL_FATAL_IF(!scope, this) << "no scope defined.";
  auto doc = AidlCast<AidlDocument>(scope->GetNode());
  AIDL_FATAL_IF(!doc, this) << "root scope is not a document.";
  return *doc;
}

AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
                               const std::string& package, const Comments& comments,
                               const std::string& cpp_header, std::vector<std::string>* type_params,
                               std::vector<std::unique_ptr<AidlMember>>* members)
    : AidlDefinedType(location, name, comments, package, members),
      AidlParameterizable<std::string>(type_params),
      cpp_header_(cpp_header) {
  // Strip off quotation marks if we actually have a cpp header.
  if (cpp_header_.length() >= 2) {
    cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
  }
}

template <typename T>
bool AidlParameterizable<T>::CheckValid() const {
  return true;
};

template <>
bool AidlParameterizable<std::string>::CheckValid() const {
  if (!IsGeneric()) {
    return true;
  }
  std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
  if (set.size() != GetTypeParameters().size()) {
    AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
    return false;
  }
  return true;
}

bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlDefinedType::CheckValid(typenames)) {
    return false;
  }
  if (!AidlParameterizable<std::string>::CheckValid()) {
    return false;
  }

  bool success = true;
  if (IsFixedSize()) {
    for (const auto& v : GetFields()) {
      if (!typenames.CanBeFixedSize(v->GetType())) {
        AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
                      << "non-fixed size field named " << v->GetName() << ".";
        success = false;
      }
    }
  }

  return success;
}

AidlStructuredParcelable::AidlStructuredParcelable(
    const AidlLocation& location, const std::string& name, const std::string& package,
    const Comments& comments, std::vector<std::string>* type_params,
    std::vector<std::unique_ptr<AidlMember>>* members)
    : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}

bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlParcelable::CheckValid(typenames)) {
    return false;
  }

  bool success = true;

  if (IsJavaOnlyImmutable()) {
    // Immutable parcelables provide getters
    if (!CheckValidForGetterNames()) {
      success = false;
    }
  }

  return success;
}

// TODO: we should treat every backend all the same in future.
bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
  if (this->GetName() == "FileDescriptor" &&
      (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
    AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
    return false;
  }

  if (lang != Options::Language::JAVA) {
    if (this->GetName() == "List" && !this->IsGeneric()) {
      AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
      return false;
    }
    if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
      AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
      return false;
    }
  }

  return true;
}

// TODO: we should treat every backend all the same in future.
bool AidlDefinedType::LanguageSpecificCheckValid(Options::Language lang) const {
  struct Visitor : AidlVisitor {
    Visitor(Options::Language lang) : lang(lang) {}
    void Visit(const AidlTypeSpecifier& type) override {
      success = success && type.LanguageSpecificCheckValid(lang);
    }
    Options::Language lang;
    bool success = true;
  } v(lang);
  VisitTopDown(v, *this);
  return v.success;
}

AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
                               AidlConstantValue* value, const Comments& comments)
    : AidlCommentable(location, comments),
      name_(name),
      value_(value),
      value_user_specified_(value != nullptr) {}

bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
  if (GetValue() == nullptr) {
    return false;
  }
  if (!GetValue()->CheckValid()) {
    return false;
  }
  if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
    AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
    return false;
  }
  return true;
}

string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
                                   const ConstantValueDecorator& decorator) const {
  return GetValue()->ValueString(backing_type, decorator);
}

AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
                                         std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
                                         const std::string& package, const Comments& comments)
    : AidlDefinedType(location, name, comments, package, nullptr),
      enumerators_(std::move(*enumerators)) {
  // Fill missing enumerator values with <prev + 1>
  // This can't be done in Autofill() because type/ref resolution depends on this.
  // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
  // resolved if A has no value set.
  const AidlEnumerator* previous = nullptr;
  for (const auto& enumerator : enumerators_) {
    if (enumerator->GetValue() == nullptr) {
      auto loc = enumerator->GetLocation();
      if (previous == nullptr) {
        enumerator->SetValue(
            std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
      } else {
        auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
        enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
            loc, std::move(prev_value), "+",
            std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
      }
    }
    previous = enumerator.get();
  }
}

bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
  if (auto annot = BackingType(); annot != nullptr) {
    // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
    // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
    // need to call CheckValid().
    if (!annot->CheckValid()) {
      return false;
    }
    auto type = annot->ParamValue<std::string>("type").value();
    backing_type_ = typenames.MakeResolvedType(annot->GetLocation(), type, false);
  } else {
    // Default to byte type for enums.
    backing_type_ = typenames.MakeResolvedType(GetLocation(), "byte", false);
  }

  // we only support/test a few backing types, so make sure this is a supported
  // one (otherwise boolean might work, which isn't supported/tested in all
  // backends)
  static std::set<string> kBackingTypes = {"byte", "int", "long"};
  if (kBackingTypes.find(backing_type_->GetName()) == kBackingTypes.end()) {
    AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName()
                     << ". Backing type must be one of: " << Join(kBackingTypes, ", ");
    return false;
  }
  return true;
}

bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlDefinedType::CheckValid(typenames)) {
    return false;
  }
  if (!GetMembers().empty()) {
    AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
    return false;
  }
  if (backing_type_ == nullptr) {
    AIDL_ERROR(this) << "Enum declaration missing backing type.";
    return false;
  }
  bool success = true;
  for (const auto& enumerator : enumerators_) {
    success = success && enumerator->CheckValid(GetBackingType());
  }

  return success;
}

AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
                             const std::string& package, const Comments& comments,
                             std::vector<std::string>* type_params,
                             std::vector<std::unique_ptr<AidlMember>>* members)
    : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}

bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
  // visit parents
  if (!AidlParcelable::CheckValid(typenames)) {
    return false;
  }

  // unions provide getters always
  if (!CheckValidForGetterNames()) {
    return false;
  }

  // now, visit self!
  bool success = true;

  // TODO(b/170807936) do we need to allow ParcelableHolder in union?
  for (const auto& v : GetFields()) {
    if (v->GetType().GetName() == "ParcelableHolder") {
      AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
      success = false;
    }
  }

  if (GetFields().empty()) {
    AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
    return false;
  }

  // first member should have useful default value (implicit or explicit)
  const auto& first = GetFields()[0];
  if (!first->HasUsefulDefaultValue()) {
    // Most types can be initialized without a default value. For example,
    // interface types are inherently nullable. But, enum types should have
    // an explicit default value.
    if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
      AIDL_ERROR(first)
          << "The union's first member should have a useful default value. Enum types can be "
             "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
      return false;
    }
    // In Java, array types are initialized as null without a default value. To be sure that default
    // initialized unions are accepted by other backends we require arrays also have a default
    // value.
    if (first->GetType().IsArray()) {
      AIDL_ERROR(first)
          << "The union's first member should have a useful default value. Arrays can be "
             "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
      return false;
    }
  }

  return success;
}

AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
                             const Comments& comments, bool oneway, const std::string& package,
                             std::vector<std::unique_ptr<AidlMember>>* members)
    : AidlDefinedType(location, name, comments, package, members) {
  for (auto& m : GetMethods()) {
    m.get()->ApplyInterfaceOneway(oneway);
  }
}

bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
  if (!AidlDefinedType::CheckValid(typenames)) {
    return false;
  }
  // Has to be a pointer due to deleting copy constructor. No idea why.
  map<string, const AidlMethod*> method_names;
  for (const auto& m : GetMethods()) {
    if (!m->CheckValid(typenames)) {
      return false;
    }

    auto it = method_names.find(m->GetName());
    // prevent duplicate methods
    if (it == method_names.end()) {
      method_names[m->GetName()] = m.get();
    } else {
      AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
      AIDL_ERROR(it->second) << "previously defined here.";
      return false;
    }

    static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
                                        "getTransactionName(int)"};

    if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
      AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
      return false;
    }

    if (!CheckValidPermissionAnnotations(*m.get())) {
      return false;
    }
  }

  bool success = true;
  set<string> constant_names;
  for (const auto& constant : GetConstantDeclarations()) {
    if (constant_names.count(constant->GetName()) > 0) {
      AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
      success = false;
    }
    constant_names.insert(constant->GetName());
    success = success && constant->CheckValid(typenames);
  }
  return success;
}

bool AidlInterface::CheckValidPermissionAnnotations(const AidlMethod& m) const {
  if (IsPermissionNone() || IsPermissionManual()) {
    if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual() ||
        m.GetType().EnforceExpression()) {
      std::string interface_annotation = IsPermissionNone()
                                             ? "requiring no permission"
                                             : "manually implementing permission checks";
      AIDL_ERROR(m) << "The interface " << GetName() << " is annotated as " << interface_annotation
                    << " but the method " << m.GetName() << " is also annotated.\n"
                    << "Consider distributing the annotation to each method.";
      return false;
    }
  } else if (EnforceExpression()) {
    if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual()) {
      AIDL_ERROR(m) << "The interface " << GetName()
                    << " enforces permissions using annotations"
                       " but the method "
                    << m.GetName() << " is also annotated.\n"
                    << "Consider distributing the annotation to each method.";
      return false;
    }
  }
  return true;
}

std::string AidlInterface::GetDescriptor() const {
  std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
  if (annotatedDescriptor != "") {
    return annotatedDescriptor;
  }
  return GetCanonicalName();
}

AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
                           std::set<string> imports,
                           std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
                           bool is_preprocessed)
    : AidlCommentable(location, comments),
      AidlScope(this),
      imports_(std::move(imports)),
      defined_types_(std::move(defined_types)),
      is_preprocessed_(is_preprocessed) {
  for (const auto& t : defined_types_) {
    t->SetEnclosingScope(this);
  }
}

// Resolves type name in the current document.
// - built-in types
// - imported types
// - top-level type
std::string AidlDocument::ResolveName(const std::string& name) const {
  if (AidlTypenames::IsBuiltinTypename(name)) {
    return name;
  }

  const auto first_dot = name.find_first_of('.');
  // For "Outer.Inner", we look up "Outer" in the import list.
  const std::string class_name =
      (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
  // Keep ".Inner", to make a fully-qualified name
  const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);

  for (const auto& import : Imports()) {
    if (SimpleName(import) == class_name) {
      return import + nested_type;
    }
  }

  // check if it is a top-level type.
  for (const auto& type : DefinedTypes()) {
    if (type->GetName() == class_name) {
      return type->GetCanonicalName() + nested_type;
    }
  }

  // name itself might be fully-qualified name.
  return name;
}
