//===--- ObjCPropertyAttributeOrderFixer.cpp -------------------*- C++--*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements ObjCPropertyAttributeOrderFixer, a TokenAnalyzer that
/// adjusts the order of attributes in an ObjC `@property(...)` declaration,
/// depending on the style.
///
//===----------------------------------------------------------------------===//

#include "ObjCPropertyAttributeOrderFixer.h"

namespace clang {
namespace format {

ObjCPropertyAttributeOrderFixer::ObjCPropertyAttributeOrderFixer(
    const Environment &Env, const FormatStyle &Style)
    : TokenAnalyzer(Env, Style) {
  // Create an "order priority" map to use to sort properties.
  unsigned Index = 0;
  for (const auto &Property : Style.ObjCPropertyAttributeOrder)
    SortOrderMap[Property] = Index++;
}

struct ObjCPropertyEntry {
  StringRef Attribute; // eg, `readwrite`
  StringRef Value;     // eg, the `foo` of the attribute `getter=foo`
};

void ObjCPropertyAttributeOrderFixer::sortPropertyAttributes(
    const SourceManager &SourceMgr, tooling::Replacements &Fixes,
    const FormatToken *BeginTok, const FormatToken *EndTok) {
  assert(BeginTok);
  assert(EndTok);
  assert(EndTok->Previous);

  // If there are zero or one tokens, nothing to do.
  if (BeginTok == EndTok || BeginTok->Next == EndTok)
    return;

  // Use a set to sort attributes and remove duplicates.
  std::set<unsigned> Ordinals;

  // Create a "remapping index" on how to reorder the attributes.
  SmallVector<int> Indices;

  // Collect the attributes.
  SmallVector<ObjCPropertyEntry> PropertyAttributes;
  bool HasDuplicates = false;
  int Index = 0;
  for (auto Tok = BeginTok; Tok != EndTok; Tok = Tok->Next) {
    assert(Tok);
    if (Tok->is(tok::comma)) {
      // Ignore the comma separators.
      continue;
    }

    // Most attributes look like identifiers, but `class` is a keyword.
    if (!Tok->isOneOf(tok::identifier, tok::kw_class)) {
      // If we hit any other kind of token, just bail.
      return;
    }

    const StringRef Attribute{Tok->TokenText};
    StringRef Value;

    // Also handle `getter=getFoo` attributes.
    // (Note: no check needed against `EndTok`, since its type is not
    // BinaryOperator or Identifier)
    assert(Tok->Next);
    if (Tok->Next->is(tok::equal)) {
      Tok = Tok->Next;
      assert(Tok->Next);
      if (Tok->Next->isNot(tok::identifier)) {
        // If we hit any other kind of token, just bail. It's unusual/illegal.
        return;
      }
      Tok = Tok->Next;
      Value = Tok->TokenText;
    }

    // Sort the indices based on the priority stored in `SortOrderMap`.
    const auto Ordinal =
        SortOrderMap.try_emplace(Attribute, SortOrderMap.size()).first->second;
    if (!Ordinals.insert(Ordinal).second) {
      HasDuplicates = true;
      continue;
    }

    if (Ordinal >= Indices.size())
      Indices.resize(Ordinal + 1);
    Indices[Ordinal] = Index++;

    // Memoize the attribute.
    PropertyAttributes.push_back({Attribute, Value});
  }

  if (!HasDuplicates) {
    // There's nothing to do unless there's more than one attribute.
    if (PropertyAttributes.size() < 2)
      return;

    int PrevIndex = -1;
    bool IsSorted = true;
    for (const auto Ordinal : Ordinals) {
      const auto Index = Indices[Ordinal];
      if (Index < PrevIndex) {
        IsSorted = false;
        break;
      }
      assert(Index > PrevIndex);
      PrevIndex = Index;
    }

    // If the property order is already correct, then no fix-up is needed.
    if (IsSorted)
      return;
  }

  // Generate the replacement text.
  std::string NewText;
  bool IsFirst = true;
  for (const auto Ordinal : Ordinals) {
    if (IsFirst)
      IsFirst = false;
    else
      NewText += ", ";

    const auto &PropertyEntry = PropertyAttributes[Indices[Ordinal]];
    NewText += PropertyEntry.Attribute;

    if (const auto Value = PropertyEntry.Value; !Value.empty()) {
      NewText += '=';
      NewText += Value;
    }
  }

  auto Range = CharSourceRange::getCharRange(
      BeginTok->getStartOfNonWhitespace(), EndTok->Previous->Tok.getEndLoc());
  auto Replacement = tooling::Replacement(SourceMgr, Range, NewText);
  auto Err = Fixes.add(Replacement);
  if (Err) {
    llvm::errs() << "Error while reodering ObjC property attributes : "
                 << llvm::toString(std::move(Err)) << "\n";
  }
}

void ObjCPropertyAttributeOrderFixer::analyzeObjCPropertyDecl(
    const SourceManager &SourceMgr, const AdditionalKeywords &Keywords,
    tooling::Replacements &Fixes, const FormatToken *Tok) {
  assert(Tok);

  // Expect `property` to be the very next token or else just bail early.
  const FormatToken *const PropertyTok = Tok->Next;
  if (!PropertyTok || PropertyTok->isNot(Keywords.kw_property))
    return;

  // Expect the opening paren to be the next token or else just bail early.
  const FormatToken *const LParenTok = PropertyTok->getNextNonComment();
  if (!LParenTok || LParenTok->isNot(tok::l_paren))
    return;

  // Get the matching right-paren, the bounds for property attributes.
  const FormatToken *const RParenTok = LParenTok->MatchingParen;
  if (!RParenTok)
    return;

  sortPropertyAttributes(SourceMgr, Fixes, LParenTok->Next, RParenTok);
}

std::pair<tooling::Replacements, unsigned>
ObjCPropertyAttributeOrderFixer::analyze(
    TokenAnnotator & /*Annotator*/,
    SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
    FormatTokenLexer &Tokens) {
  tooling::Replacements Fixes;
  const AdditionalKeywords &Keywords = Tokens.getKeywords();
  const SourceManager &SourceMgr = Env.getSourceManager();
  AffectedRangeMgr.computeAffectedLines(AnnotatedLines);

  for (AnnotatedLine *Line : AnnotatedLines) {
    assert(Line);
    if (!Line->Affected || Line->Type != LT_ObjCProperty)
      continue;
    FormatToken *First = Line->First;
    assert(First);
    if (First->Finalized)
      continue;

    const auto *Last = Line->Last;

    for (const auto *Tok = First; Tok != Last; Tok = Tok->Next) {
      assert(Tok);

      // Skip until the `@` of a `@property` declaration.
      if (Tok->isNot(TT_ObjCProperty))
        continue;

      analyzeObjCPropertyDecl(SourceMgr, Keywords, Fixes, Tok);

      // There are never two `@property` in a line (they are split
      // by other passes), so this pass can break after just one.
      break;
    }
  }
  return {Fixes, 0};
}

} // namespace format
} // namespace clang
