/*
 * 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.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::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 | CONTEXT_TYPE_ENUM,
       {{"toString", kBooleanType}, {"equals", kBooleanType}}},
      {AidlAnnotation::Type::JAVA_DEFAULT, "JavaDefault", CONTEXT_TYPE_INTERFACE, {}},
      {AidlAnnotation::Type::JAVA_DELEGATOR, "JavaDelegator", CONTEXT_TYPE_INTERFACE, {}},
      {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
       "JavaOnlyImmutable",
       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
           CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
       {}},
      {AidlAnnotation::Type::JAVA_SUPPRESS_LINT,
       "JavaSuppressLint",
       CONTEXT_ALL,
       {{"value", kStringArrayType, /* required= */ true}}},
      {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,
       "EnforcePermission",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {{"value", kStringType}, {"anyOf", kStringArrayType}, {"allOf", kStringArrayType}}},
      {AidlAnnotation::Type::PERMISSION_MANUAL,
       "PermissionManuallyEnforced",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {}},
      {AidlAnnotation::Type::PERMISSION_NONE,
       "RequiresNoPermission",
       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
       {}},
      {AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING,
       "PropagateAllowBlocking",
       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 @EnforcePermission annotation: " << expr.error();
      return false;
    }
  }
  return true;
}

Result<unique_ptr<android::aidl::perm::Expression>> AidlAnnotation::EnforceExpression() const {
  auto single = ParamValue<std::string>("value");
  auto anyOf = ParamValue<std::vector<std::string>>("anyOf");
  auto allOf = ParamValue<std::vector<std::string>>("allOf");
  if (single.has_value()) {
    return std::make_unique<android::aidl::perm::Expression>(single.value());
  } else if (anyOf.has_value()) {
    auto v = android::aidl::perm::AnyOf{anyOf.value()};
    return std::make_unique<android::aidl::perm::Expression>(v);
  } else if (allOf.has_value()) {
    auto v = android::aidl::perm::AllOf{allOf.value()};
    return std::make_unique<android::aidl::perm::Expression>(v);
  }
  return Error() << "No parameter for @EnforcePermission";
}

// 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;
}

static const AidlAnnotation* GetScopedAnnotation(const AidlDefinedType& defined_type,
                                                 AidlAnnotation::Type type) {
  const AidlAnnotation* annotation = GetAnnotation(defined_type.GetAnnotations(), type);
  if (annotation) {
    return annotation;
  }
  const AidlDefinedType* enclosing_type = defined_type.GetParentType();
  if (enclosing_type) {
    return GetScopedAnnotation(*enclosing_type, type);
  }
  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 {
  auto defined_type = AidlCast<AidlDefinedType>(*this);
  AIDL_FATAL_IF(!defined_type, *this) << "@VintfStability is not attached to a type";
  return GetScopedAnnotation(*defined_type, 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<android::aidl::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 @EnforcePermission 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::IsPropagateAllowBlocking() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING);
}

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

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);
}

bool AidlAnnotatable::IsJavaDelegator() const {
  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DELEGATOR);
}

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);

  bool is_mutated = mutated_;
  mutated_ = true;
  // mutate the array type to its base by removing a single dimension
  // e.g.) T[] => T, T[N][M] => T[M] (note that, M is removed)
  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);
  }
  mutated_ = is_mutated;
}

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;
}

std::vector<int32_t> AidlTypeSpecifier::GetFixedSizeArrayDimensions() const {
  AIDL_FATAL_IF(!IsFixedSizeArray(), "not a fixed-size array");
  std::vector<int32_t> dimensions;
  for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
    dimensions.push_back(dim->EvaluatedValue<int32_t>());
  }
  return dimensions;
}

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 : GetFixedSizeArrayDimensions()) {
        ret += "[" + std::to_string(dim) + "]";
      }
    } 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->Evaluate()) {
        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) {
  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)
    : AidlMember(location, comments),
      oneway_(oneway),
      type_(type),
      name_(name),
      arguments_(std::move(*args)),
      id_(id) {
  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::vector<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;
}
