chromium/tools/clang/rewrite_autofill_form_data/tests/field-to-function-original.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <vector>

namespace autofill {

struct FormFieldData {
  FormFieldData();
  FormFieldData(const FormFieldData&);
  FormFieldData& operator=(const FormFieldData&);
  std::u16string value;
  int something_else;
};

// References in compiler-generated code must not be rewritten.
FormFieldData::FormFieldData() = default;
FormFieldData::FormFieldData(const FormFieldData&) = default;
FormFieldData& FormFieldData::operator=(const FormFieldData&) = default;

class AutofillField : public FormFieldData {};

}  // namespace autofill

namespace testing {

template <typename Class, typename FieldType>
void Field(FieldType Class::*field, int matcher) {}

template <typename Class, typename FieldType>
void Property(FieldType Class::*field(), int matcher) {}

}  // namespace testing

namespace base {

std::u16string ASCIIToUTF16(std::string x) {
  return u"arbitrary string";
}

}  // namespace base

namespace not_autofill {

struct FormFieldData {
  std::u16string value;
  int something_else;
};

}  // namespace not_autofill

// Tests that a read reference `f.value` is replaced with `r.value()`.
std::u16string FunRead() {
  autofill::FormFieldData f;
  return f.value;
}

// Tests that `f.value` at the left of an assignment is replaced with
// `f.set_value(rhs)`.
void FunWrite() {
  ::autofill::FormFieldData f;
  f.value = u"foo";
}

// Tests that a read reference `f->value` is replaced with `r->value()`.
std::u16string FunReadPointer() {
  autofill::FormFieldData f;
  autofill::FormFieldData* g = &f;
  return g->value;
}

// Tests that `f->value` at the left of an assignment is replaced with
// `f->set_value(rhs)`.
void FunWritePointer() {
  autofill::FormFieldData f;
  autofill::FormFieldData* g = &f;
  g->value = u"foo";
}

// Tests that a read reference `f.value()` in a member function is replaced with
// `f.value()`.
class Class {
  static const std::u16string& value(const autofill::FormFieldData& f) {
    return f.value;
  }
};

// Tests that a references at the left and right hand side of an assignment aer
// replaced appropriately.
void FunReadAndWrite() {
  ::autofill::FormFieldData f;
  ::autofill::FormFieldData g;
  f.value = g.value;
}

// Like FunReadAndWrite() but additionally tests that a constness doesn't affect
// the rewriting.
void FunReadConstAndWrite() {
  ::autofill::FormFieldData f;
  const ::autofill::FormFieldData g;
  f.value = g.value;
}

// Like FunReadConstAndWrite() but additionally tests that redundant
// parentheses doesn't affect the rewriting.
void FunReadConstAndWriteWithParentheses() {
  ::autofill::FormFieldData f;
  const ::autofill::FormFieldData g;
  ((f).value) = ((g).value);
}

// Like FunReadConstAndWrite() but additionally tests that additional whitespace
// doesn't affect the rewriting of a read reference and that the comments
// survive the rewriting.
void FunReadWithWhitespace() {
  autofill::FormFieldData f;
  std::u16string s = f       // comment 1
                         .   // comment 2
                     value;  // comment 3
}

// Like FunReadConstAndWrite() but additionally tests that additional
// whitespace doesn't affect the rewriting of a write reference and that the
// comments survive the rewriting.
void FunWriteWithWhitespace() {
  autofill::FormFieldData f;
  f          // comment 1
      .      // comment 2
      value  // comment 3
      =      // comment 4
      u"foo";
}

// Tests whether explicit `operator=()` is rewritten. This is desirable but
// currently not implemented.
void FunWriteExplicitOperator() {
  ::autofill::FormFieldData f;
  f.value.operator=(u"foo");  // Currently not properly rewritten.
}

namespace autofill {

// Tests that references are rewritten even if the object's type isn't fully
// qualified.
std::u16string FunReadImplicitNamespace() {
  FormFieldData f;
  return f.value;
}

// Tests that a reference at the left of an assignment is replaced with
// set_value(), and that a more complex right-hand side experission is
// preserved.
void FunWriteCallExpr() {
  std::string value;
  FormFieldData field;
  field.value = base::ASCIIToUTF16(value);
}

}  // namespace autofill

// Like FunWriteCallExpr() but with a more complex expression at the right-hand
// side. It involves UTF-16 string literals to test that the rewriter uses the
// correct clang::LangOptions (and not the default argument).
void FunWriteComplexCallExpr() {
  auto g = [](const std::u16string& s) { return s; };
  autofill::FormFieldData f;
  f.value = u"bar" + g(std::u16string(u"foo") + u"qux");
}

// Tests that the replacement does not touch classes from other namespaces.
std::u16string FunReadNotAutofill() {
  ::not_autofill::FormFieldData f;
  return f.value;
}

// Tests that write references on members of a derived class are rewritten.
void FunWriteDerived() {
  autofill::AutofillField f;
  f.value = u"bar";
}

// Tests that read references on vector elements are rewritten.
std::u16string FunReadVector() {
  std::vector<autofill::FormFieldData> fields;
  fields.emplace_back();
  return fields[0].value;
}

// Tests that write references on vector elements are rewritten.
void FunWriteVector() {
  std::vector<autofill::FormFieldData> fields;
  fields.emplace_back();
  fields[0].value = u"foo";
}

// Tests that pointers to members are not rewritten.
std::u16string FunFieldPointer() {
  using autofill::FormFieldData;
  FormFieldData f;
  std::u16string FormFieldData::*ptr = &FormFieldData::value;
  return f.*ptr;
}

// Tests that Field(&Class::member, ...) is replaced with
// Property(&Class::member, ...).
void FunMatcher() {
  ::testing::Field(&autofill::FormFieldData::value, {});
  ::testing::Field(&autofill::FormFieldData::something_else, {});
  ::testing::Field(&not_autofill::FormFieldData::value, {});
  ::testing::Field(&not_autofill::FormFieldData::something_else, {});
  using ::testing::Field;
  using ::testing::Property;
  Field(&autofill::FormFieldData::value, {});
  Field(&autofill::FormFieldData::something_else, {});
  Field(&not_autofill::FormFieldData::value, {});
  Field(&not_autofill::FormFieldData::something_else, {});
}