/// # WOW FAKE PACKAGE IS __BEST__ [PACKAGE][pkg]
/// {@category Real Libraries}
/// If you don't have this package yet, get it.
/// Don't ask questions.
///
/// Testing code [:true:] and [:false:]
///
/// Testing string escaping: `var s = 'I am a string'`
///
/// My favorite class is [Cool].
///
/// ## I am an h2
///
/// hello there
///
/// ### I am an h3
///
/// hello there
///
/// #### I am an h4
///
/// hello there
///
/// ##### I am an h5
///
/// hello
///
/// *Why should you get this package?*
///
/// * We told you so.
/// * Everyone is doing it.
/// * It smells nice.
///
/// ```
/// class Foo {
///   long line is very long long line is very long long line is very long line long line long line
/// }
/// ```
///
/// Here are some hyperlinks with angle brackets:
///
/// * <https://myfakepackage.com/withapath>
/// * <ftp://ftp.myfakepackage.com/donthidemyschema>
/// * <http://myfakepackage.com/buthidethisone>
///
/// [pkg]: http://example.org

// ignore_for_file: unused_element, unused_import

library fake;

import 'dart:async';
import 'dart:collection';
// Make sure dartdoc ignores invalid prefixes imports (#1896)
// ignore: uri_does_not_exist
//import 'dart:json' as invalidPrefix;
import 'package:meta/meta.dart' show Required;
import 'package:meta/meta.dart' as aPrefix show Immutable;
import 'csspub.dart' as css;
import 'csspub.dart' as renamedLib2;
import 'package:test_package/src//import_unusual.dart';
import 'example.dart';
import 'mylibpub.dart' as renamedLib;
import 'mylibpub.dart' as renamedLib2;
import 'two_exports.dart' show BaseClass;
export 'src/notadotdartfile';

// Verify that even though reexported, objects don't show in documentation.
export 'package:test_package/src/nodocme.dart';

// ignore: uri_does_not_exist
export 'package:test_package_imported/categoryExporting.dart'
    show IAmAClassWithCategories;

export 'src/tool.dart';

// Explicitly export ourselves, because why not.
// ignore: uri_does_not_exist
export 'package:test_package/fake.dart';

export 'src/reexport_this.dart';

/// Does not render with emoji 3ffe:2a00:100:7031::1
const int hasMarkdownInDoc = 1;

/// This function has a link to a renamed library class member.
///
/// Link to library: [renamedLib]
/// Link to constructor (implied, no new): [renamedLib.YetAnotherHelper()]
/// Link to class: [renamedLib.YetAnotherHelper]
/// Link to constructor (direct): [renamedLib.YetAnotherHelper.new]
/// Link to class member: [renamedLib.YetAnotherHelper.getMoreContents]
/// Link to function: [renamedLib.helperFunction]
/// Link to overlapping prefix: [renamedLib2.theOnlyThingInTheLibrary]
void aFunctionUsingRenamedLib() {
  renamedLib.helperFunction('hello', 3);
}

class ConstructorTester<A, B> {
  ConstructorTester(String param1) {}
  ConstructorTester.fromSomething(A foo) {}
}

class HasGenerics<X, Y, Z> {
  HasGenerics(X x, Y y, Z z) {}

  X? returnX() => null;

  Z? returnZ() => null;

  Z? doStuff(String s, X x) => null;

  /// Converts itself to a map.
  Map<X, Y>? convertToMap() => null;
}

/// Coderef to ambiguous parameter of function parameter should not crash us.
/// (#1835)
///
/// Here is a coderef: [aThingParameter]
void doAComplicatedThing(int x,
    {void doSomething(int aThingParameter, String anotherThing)?,
    void doSomethingElse(int aThingParameter, double somethingElse)?}) {}

/// Bullet point documentation.
///
/// This top level constant has bullet points.
///
/// * A bullet point.
/// * Another even better bullet point.
/// * A bullet point that wraps onto a second line, without creating a new
///   bullet point or paragraph.
/// * A fourth bullet point.
const String bulletDoced = 'Foo bar baz';

/// This class uses a pragma annotation.
@pragma('Hello world')
class HasPragma {}

const dynamic aDynamicAnnotation = 4;

@aDynamicAnnotation

/// This class has a dynamic annotation.
class HasDynamicAnnotation {}

/// This is a class with a table.
///
/// It has multiple sentences before the table.  Because testing is a good
/// idea.
///
/// | Component | Symbol | Short Form   | Long Form         | Numeric   | 2-digit   |
/// |-----------|:------:|--------------|-------------------|-----------|-----------|
/// | era       |   G    | G (AD)       | GGGG (Anno Domini)| -         | -         |
/// | year      |   y    | -            | -                 | y (2015)  | yy (15)   |
/// | month     |   M    | MMM (Sep)    | MMMM (September)  | M (9)     | MM (09)   |
/// | day       |   d    | -            | -                 | d (3)     | dd (03)   |
/// | weekday   |   E    | EEE (Sun)    | EEEE (Sunday)     | -         | -         |
/// | hour      |   j    | -            | -                 | j (13)    | jj (13)   |
/// | hour12    |   h    | -            | -                 | h (1 PM)  | hh (01 PM)|
/// | hour24    |   H    | -            | -                 | H (13)    | HH (13)   |
/// | minute    |   m    | -            | -                 | m (5)     | mm (05)   |
/// | second    |   s    | -            | -                 | s (9)     | ss (09)   |
/// | timezone  |   z    | -            | z (Pacific Standard Time)| -  | -         |
/// | timezone  |   Z    | Z (GMT-8:00) | -                 | -         | -         |
///
/// It also has a short table with embedded links.
///
/// | [DocumentWithATable] | [Annotation] | [aMethod] |
/// |----------------------|--------------|-----------|
/// | [foo]                | Not really   | "blah"    |
/// | [bar]                | Maybe        | "stuff"   |
class DocumentWithATable {
  static const DocumentWithATable foo = DocumentWithATable();
  static const DocumentWithATable bar = DocumentWithATable();

  const DocumentWithATable();
  void aMethod(String parameter) {}
}

/// A doc reference mentioning [dynamic].
dynamic get mustGetThis => null;

Map<dynamic, String> mapWithDynamicKeys = {};

Required? useSomethingInAnotherPackage;
String? useSomethingInTheSdk;

/// Useful for annotations.
class Annotation {
  final String value;
  const Annotation(this.value);
}

/// For make-better testing of constants.
///
/// Make one of these neato classes like this:
///
/// `var constant = const ConstantClass('neat')`
///
/// This is a code block
///
///     var x = 'hello';
///     print(x);
class ConstantClass {
  final String value;

  /// Make compile-time constants with this constructor!
  /// Go ahead, it's fun.
  const ConstantClass(this.value);

  /// A named compile-time constant constructor.
  const ConstantClass.isVeryConstant(this.value);

  /// Not actually constant.
  ConstantClass.notConstant(this.value);
}

class _APrivateConstClass {
  const _APrivateConstClass();
}

class AClassWithFancyProperties {
  /// This property is quite fancy, and requires sample code to understand.
  ///
  /// ```dart
  /// AClassWithFancyProperties x = AClassWithFancyProperties();
  ///
  /// if (x.aProperty.contains('Hello')) {
  ///   print("I am indented!");
  ///   if (x.aProperty.contains('World')) {
  ///     print ("I am indented even more!!!");
  ///   }
  /// }
  /// ```
  String? aProperty;
}

const _APrivateConstClass CUSTOM_CLASS_PRIVATE = const _APrivateConstClass();

/// Type inference mixing with anonymous functions.
final importantComputations = {
  1: (List<num> a) => a[0] + a[1],
  2: (List<num> a) => a[0] - a[1],
  3: (List<num> a) => a[0] * a[1],
  4: (List<num> a) => -a[0]
};

// No dart docs on purpose. Also, a non-primitive const class.
const ConstantClass CUSTOM_CLASS = ConstantClass('custom');

/// Up is a direction.
///
/// Getting up in the morning can be hard.
const String UP = 'up';

const String NAME_SINGLEUNDERSCORE = 'yay bug hunting';

const String NAME_WITH_TWO_UNDERSCORES =
    'episode seven better be good; episode seven better be good; episode seven better be good; episode seven better be good';

/// Testing [NAME_WITH_TWO_UNDERSCORES] should not be italicized.
///
/// This name should link correctly: [NAME_SINGLEUNDERSCORE]
void short() {}

/// Dynamic-typed down.
@deprecated
const DOWN = 'down';

/// A constant integer value,
/// which is a bit redundant.
const int ZERO = 0;

/// Takes input, returns output.
@deprecated
typedef String FakeProcesses(String input);

/// A typedef with a type parameter.
typedef T GenericTypedef<T>(T input);

/// A typedef with the new style generic function syntax.
typedef NewGenericTypedef<T> = List<S> Function<S>(T, int, bool);

/// A top level variable with a generic typedef type.
NewGenericTypedef? genericTypedefCombo;

/// A complicated type parameter to ATypeTakingClass.
ATypeTakingClass<String Function(int)>? get complicatedReturn => null;

/// Lots and lots of parameters.
typedef int LotsAndLotsOfParameters(so, many, parameters, it, should, wrap,
    when, converted, to, html, documentation);

/// This class is cool!
class Cool {}

/// A map initialization making use of optional const.
const Map<int, String> myMap = {1: "hello"};

/// A variable initialization making use of optional new.
Cool aCoolVariable = Cool();

/// Perfect for mix-ins.
abstract class MixMeIn {}

/// An interface that can be implemented.
abstract class Interface {}

/// Yet another interface that can be implemented.
abstract class AnotherInterface {}

class NotAMixin {
  String get superString => "A string that's clearly important";
}

class AMixinCallingSuper extends Object {
  String get superString => "${super.toString()} but not as important as this";
}

/// I am a new style mixin using the new mixin syntax.
mixin NewStyleMixinCallingSuper on NotAMixin {
  @override

  /// I have documentation for an overridden method named [superString],
  /// different from [NotAMixin.superString].
  String get superString =>
      "${super.superString} but moderately less important than this";
}

/// Verify super-mixins don't break Dartdoc.
// ignore: mixin_inherits_from_not_object, mixin_references_super
class AClassUsingASuperMixin extends AnotherInterface with AMixinCallingSuper {}

/// A class mixing in a single new-style mixin.
class AClassUsingNewStyleMixin extends NotAMixin
    with NewStyleMixinCallingSuper {}

/// A generic class for testing type inference.
class GenericClass<T> {
  T? member;

  /// Destined to be overridden by [ModifierClass].
  T? overrideByModifierClass;

  /// Destined to be overridden by [GenericMixin].
  T? overrideByGenericMixin;

  /// Destined to be overridden by [ModifierClass] and [GenericMixin], both.
  T? overrideByBoth;

  /// Destined to be overridden by everything.
  T? overrideByEverything;
}

/// A class extending a generic class.
class ModifierClass<T> extends GenericClass<T> {
  T? modifierMember;

  @override
  T? overrideByModifierClass;

  @override
  T? overrideByBoth;

  @override
  T? overrideByEverything;
}

/// A generic mixin that requires GenericClass as a superclass.
mixin GenericMixin<T> on GenericClass<T> {
  T? mixinMember;

  @override
  T? overrideByGenericMixin;

  @override
  T? overrideByBoth;

  @override
  T? overrideByEverything;
}

/// A class verifying type inference across new-style mixins.
class TypeInferenceMixedIn extends ModifierClass<int> with GenericMixin {
  @override
  int? overrideByEverything;
}

GenericMixin<T>? aMixinReturningFunction<T>() => null;

functionUsingMixinReturningFunction() {
  // ignore: unused_local_variable
  GenericClass<int>? using = aMixinReturningFunction();
}

/// A super class, with many powers. Link to [Apple] from another library.
@deprecated
class SuperAwesomeClass {
  /// In the super class.
  List<String>? powers;

  /// In the super class.
  ///
  /// Another comment line.
  void fly(int height, Cool superCool, {String? msg}) {
    // ignore: unused_local_variable, avoid_init_to_null
    var x = null;
    // ignore: unused_local_variable
    int i, y;
    for (int z = 0; z < 100; z++) {
      print('hi');
    }
  }

  SuperAwesomeClass? operator -(other) {
    return null;
  }
}

class TypedefUsingClass {
  ParameterizedTypedef<double> x;
  TypedefUsingClass(this.x);
}

typedef void myCoolTypedef(Cool x, bool y);

/// This function returns Future<void>
Future<void> returningFutureVoid() async {}

/// This function requires a Future<void> as a parameter
void aVoidParameter(Future<void> p1) {}

/// This class extends Future<void>
abstract class ExtendsFutureVoid extends Future<void> {
  // ignore: missing_return
  factory ExtendsFutureVoid(FutureOr<void> computation()) =>
      _ExtendsFutureVoidImpl();
}

class _ExtendsFutureVoidImpl implements ExtendsFutureVoid {
  dynamic noSuchMethod(Invocation _) => null;
}

/// This class implements Future<void>
abstract class ImplementsFutureVoid implements Future<void> {}

/// This class takes a type, and it might be void.
class ATypeTakingClass<T> {
  T? aMethodMaybeReturningVoid() => null;
}

class ABaseClass {}

class ATypeTakingClassMixedIn extends ABaseClass with ATypeTakingClass<void> {}

abstract class ThingToImplementInMixin {
  bool get mixinGetter;
}

mixin MixInImplementation implements ThingToImplementInMixin {
  @override
  bool get mixinGetter => true;
}

class MixedInImplementation with MixInImplementation {}

/// Names are actually wrong in this class, but when we extend it,
/// they are correct.
class ImplicitProperties {
  /// Docs for implicitGetterExplicitSetter from ImplicitProperties.
  String? implicitGetterExplicitSetter;

  /// Docs for explicitGetterImplicitSetter from ImplicitProperties.
  List<int>? explicitGetterImplicitSetter;

  /// A simple property to inherit.
  int? forInheriting;

  /// @nodoc for you
  String get explicitNonDocumentedGetter => "something";

  /// @nodoc for you but check downstream
  String get explicitNonDocumentedInBaseClassGetter => "something else";

  /// but documented here.
  double get explicitPartiallyDocumentedField => 1.3;

  /// @nodoc here, you should never see this
  set explicitPartiallyDocumentedField(double foo) {}

  /// @nodoc here, you should never see this
  String? documentedPartialFieldInSubclassOnly;

  /// Explicit getter for inheriting.
  int get explicitGetterSetterForInheriting => 12;

  /// Explicit setter for inheriting.
  set explicitGetterSetterForInheriting(int foo) {}
}

/// Classes with unusual properties?  I don't think they exist.
///
/// Or rather, dartdoc used to think they didn't exist.  Check the variations
/// on inheritance and overrides here.
abstract class ClassWithUnusualProperties extends ImplicitProperties {
  /// This getter is documented, so we should see a read-only property here.
  @override
  String get documentedPartialFieldInSubclassOnly => "overridden getter";

  @override

  /// Docs for setter of implicitGetterExplicitSetter.
  set implicitGetterExplicitSetter(String? x) {}

  @override

  /// Getter doc for explicitGetterImplicitSetter
  List<int> get explicitGetterImplicitSetter => List<int>.filled(1, 1);

  myCoolTypedef? _aFunction;

  /// Since I have a different doc, I should be documented.
  @override
  String get explicitNonDocumentedInBaseClassGetter => "something else";

  /// Getter doc for explicitGetterSetter.
  @Annotation('a Getter Annotation')
  myCoolTypedef? get explicitGetterSetter {
    return _aFunction;
  }

  /// @nodoc for a simple hidden property.
  String? simpleHidden;

  /// @nodoc on setter
  set explicitNodocGetterSetter(String s) {}

  /// @nodoc on getter
  String get explicitNodocGetterSetter => "something";

  /// This property is not synthetic, so it might reference [f] -- display it.
  @Annotation('a Setter Annotation')
  set explicitGetterSetter(myCoolTypedef? f) => _aFunction = f;

  /// This property only has a getter and no setter; no parameters to print.
  myCoolTypedef? get explicitGetter {
    return _aFunction;
  }

  /// Set to [f], and don't warn about [bar] or [baz].
  set explicitSetter(f(int bar, Cool baz, List<int> macTruck)) {}

  /// This property has some docs, too.
  final Set finalProperty = Set();

  Map? implicitReadWrite;

  /// Hey there, more things not to warn about: [f], [x], or [q].
  String aMethod(Function f(Cool x, bool q)) {
    return 'hi';
  }
}

class HtmlEscapableImplicitProperties {
  /// Docs for implicitGetterExplicitSetter from HtmlEscapableImplicitProperties.
  List<int>? implicitGetterExplicitSetter;

  /// Docs for explicitGetterImplicitSetter from HtmlEscapableImplicitProperties.
  List<int>? explicitGetterImplicitSetter;

  /// A simple property to inherit.
  List<int>? forInheriting;

  /// Explicit getter for inheriting.
  List<int> get explicitGetterSetterForInheriting => [1, 2];

  /// Explicit setter for inheriting.
  set explicitGetterSetterForInheriting(List<int> foo) {}
}

class HtmlEscapableProperties extends HtmlEscapableImplicitProperties {
  @override

  /// Docs for setter of implicitGetterExplicitSetter.
  set implicitGetterExplicitSetter(List<int>? x) {}

  @override

  /// Getter doc for explicitGetterImplicitSetter
  List<int> get explicitGetterImplicitSetter => List<int>.filled(1, 1);

  /// Getter doc for explicitGetterSetter.
  List<int> get explicitGetterSetter => List<int>.filled(1, 1);

  /// Setter doc for explicitGetterSetter.
  set explicitGetterSetter(List<int> aList) {}

  /// A final property.
  final List<int> finalProperty = List<int>.filled(1, 1);

  /// A simple property.
  List<int> simpleProperty = List<int>.filled(1, 1);

  /// A long multiple variable declaration.
  List<int>? iAmALongLongLongLongLongLongLongLongLongName,
      ensureWholeDeclarationIsVisible;
}

/// This is a very long line spread
/// across... wait for it... two physical lines.
///
/// The rest of this is not in the first paragraph.
@Annotation('value')
// ignore: deprecated_member_use
// ignore: deprecated_member_use_from_same_package
class LongFirstLine extends SuperAwesomeClass
    with MixMeIn
    implements Interface, AnotherInterface {
  static const THING = 'yup';
  static const int ANSWER = 42;

  /// An instance string property. Readable and writable.
  String? aStringProperty;

  /// A static int property.
  static int meaningOfLife = 42;

  /// The default constructor.
  @deprecated
  LongFirstLine();

  /// Named constructors are awesome.
  ///
  /// The map is a key/value pairs of data that helps create an instance.
  LongFirstLine.fromMap(Map data);

  LongFirstLine.fromHasGenerics(HasGenerics hg);

  /// No params.
  @deprecated
  void noParams() {}

  /// Returns a single string.
  String returnString() => 'cool';

  /// Two params, the first has a type annotation, the second does not.
  int twoParams(String one, two) => 42;

  /// One dynamic param, two named optionals.
  bool optionalParams(first, {second, int? third}) => true;

  /// Dynamic getter. Readable only.
  get dynamicGetter => 'could be anything';

  /// Only a setter, with a single param, of type double.
  void set onlySetter(double d) {}

  /// Adds another one of these thingies.
  LongFirstLine? operator +(LongFirstLine other) {
    return null;
  }

  /// Multiplies a thingies to this thingie and then returns a new thingie.
  LongFirstLine? operator *(LongFirstLine other) {
    return null;
  }

  static int get staticGetter => 11111;

  static void set staticOnlySetter(bool thing) {}

  /// Just a static method with no parameters.
  ///
  /// Returns an int.
  static int staticMethodNoParams() => 42;

  /// A static method that takes a single dynamic thing, and returns void.
  static void staticMethodReturnsVoid(dynamicThing) {}
}

/// My bad!
class Oops implements Exception {
  final String message;
  Oops(this.message);
}

/// Also, my bad.
@deprecated
class Doh extends Error {}

/// link to method from class [Apple.m]
class Foo2 {
  final int index;
  const Foo2(this.index);

  static const Foo2 BAR = Foo2(0);
  static const Foo2 BAZ = Foo2(1);
}

class OtherGenericsThing<A> {
  HasGenerics<A, Cool, String>? convert() => null;
}

/// Constant property.
const double PI = 3.14159;

/// Final property.
@deprecated
final int meaningOfLife = 42;

/// Simple property
String? simpleProperty;

/// Simple @nodoc property.
String? simplePropertyHidden;

/// Setter docs should be shown.
set getterSetterNodocGetter(int value) {}

/// @nodoc on getter.
int get getterSetterNodocGetter => 3;

/// @nodoc on setter
set getterSetterNodocSetter(int value) {}

/// Getter docs should be shown.
int get getterSetterNodocSetter => 4;

/// @nodoc on the setter
set getterSetterNodocBoth(String value) {}

/// And @nodoc on the getter, so entire TopLevelVariable should be invisible.
String get getterSetterNodocBoth => "I do not exist";

/// Just a setter. No partner getter.
void set justSetter(int value) {}

/// Just a getter. No partner setter.
bool get justGetter => false;

/// The setter for setAndGet.
void set setAndGet(String thing) {}

/// The getter for setAndGet.
String get setAndGet => 'hello';

/// A dynamic getter.
get dynamicGetter => 'i could be anything';

/// Top-level function 3 params and 1 optional positional param.
///
/// This is the second paragraph.
/// It has two lines.
///
/// The third parameter is a [Cool] object.
///
/// Here is a code snippet:
///
///     var thing = topLevelFunction(1, true, 3.4);
///
/// This snippet has brackets in parameters:
///
///     callMe('alert', ['hello from dart']);
///
/// Thanks for using this function!
@deprecated
String? topLevelFunction(int param1, bool param2, Cool coolBeans,
    [double optionalPositional = 0.0]) {
  return null;
}

void topLevelFunction2(int p1, bool p2,
    [Map<String, int> p3 = const <String, int>{}]) {}

/// A single optional positional param, no type annotation, no default value.
@greatAnnotation
void onlyPositionalWithNoDefaultNoType([@greatestAnnotation anything]) {}

/// Top-level function with 1 param and 2 optional named params, 1 with a
/// default value.
void soIntense(anything, {bool flag = true, int? value}) {}

/// [FooBar] comes from another library.
void paramFromAnotherLib(Apple thing) {}

/// An async function. It should look like I return a [Future].
thisIsAsync() async => 42;

/// Explicitly returns a Future and is marked async.
Future thisIsAlsoAsync() async => 43;

/// Explicitly return a `FutureOr`.
FutureOr thisIsFutureOr() => null;

/// Explicitly return a `FutureOr<Null>`.
FutureOr<Null> thisIsFutureOrNull() => null;

/// Has a parameter explicitly typed `FutureOr<Null>`.
void paramOfFutureOrNull(FutureOr<Null> future) {}

/// Has a type parameter bound to `FutureOr<List>`.
void typeParamOfFutureOr<T extends FutureOr<List>>() {}

/// A generic function with a type parameter.
void myGenericFunction<S>(int a, bool b, S c) {
  return;
}

/// This is a great thing.
const greatAnnotation = 'great';

/// This is the greatest thing.
const greatestAnnotation = 'greatest';

/// This function has two parameters that are functions.
///
/// Check out the [number] parameter. It's the first one.
String? functionWithFunctionParameters(int number, void thing(one, two),
        String string, Future asyncThing(three, four, five, six, seven)) =>
    null;

/// These are code syntaxes: [:true:] and [:false:]
const testingCodeSyntaxInOneLiners = 'fantastic';

/// Referencing something that [doesn't exist].
const incorrectDocReference = 'doh';

/// Tests a single field with explict getter and setter.
class WithGetterAndSetter {
  /// Returns a length.
  ///
  /// Throws some exception if used in the fourth dimension.
  int get lengthX => 1;

  /// Sets the length.
  ///
  /// Throws if set to an imaginary number.
  void set lengthX(int _length) {}
}

/// Test that we can properly handle covariant member parameters.
class CovariantMemberParams {
  covariant int? covariantField;

  set covariantSetter(covariant int x) {}

  void applyCovariantParams(
      covariant num aNumber, covariant dynamic aDynamic) {}
}

/// I have a generic and it extends [Foo2]
class HasGenericWithExtends<T extends Foo2> {}

/// Extends [ListBase]
class SpecialList<E> extends ListBase<E> {
  // ignore: annotate_overrides
  E operator [](int index) {
    return first;
  }

  // ignore: annotate_overrides
  int get length => 0;

  // ignore: annotate_overrides
  void set length(int length) {}

  // ignore: annotate_overrides
  void operator []=(int index, E value) {}
}

/// This inherits operators.
class ExtraSpecialList<E> extends SpecialList {}

/// Category information should not follow inheritance.
///
/// {@category Excellent}
/// {@category Unreal}
/// {@category More Excellence}
/// {@subCategory Things and Such}
///
class BaseForDocComments {
  /// Takes a [value] and returns a String.
  ///
  /// This methods is inside of [BaseForDocComments] class xx
  ///
  /// Also [NAME_WITH_TWO_UNDERSCORES] which is a top-level const xx
  ///
  /// Also a single underscore: [NAME_SINGLEUNDERSCORE]
  ///
  /// Returns a [String] xx
  ///
  /// Reference to another method in this class [anotherMethod] xx
  ///
  // ignore: deprecated_member_use
  // ignore: deprecated_member_use_from_same_package
  /// Reference to a top-level function in this library [topLevelFunction] xx
  ///
  /// Reference to a top-level function in another library that is imported into this library (example lib) [function1] xx
  ///
  /// Reference to a class in example lib [Apple] xx
  ///
  /// Reference to a top-level const in this library that shares the same
  /// name as a top-level name in another library [incorrectDocReference] xx
  ///
  /// Reference to a top-level const in another library [incorrectDocReferenceFromEx]
  ///
  /// Reference to prefixed-name from another lib [css.theOnlyThingInTheLibrary] xx
  ///
  /// Reference to a name that exists in this package, but is not imported
  /// in this library [doesStuff] xx
  ///
  /// Reference to a name of a class from an import of a library that exported
  /// the name [BaseClass] xx
  ///
  /// Reference to a bracket operator within this class [operator []] xxx
  ///
  /// Reference to a bracket operator in another class [SpecialList.operator []] xxx
  ///
  /// Reference containing a type parameter [ExtraSpecialList<Object>]
  ///
  /// Reference to something that doesn't exist containing a type parameter [ThisIsNotHereNoWay<MyType>]
  ///
  /// Reference to an inherited member: [ClassWithUnusualProperties.forInheriting]
  ///
  /// Reference to an inherited member in another library via class name: [ExtendedBaseReexported.action]
  ///
  /// Link to an existing file: [link](../SubForDocComments/localMethod.html)
  String? doAwesomeStuff(int value) => null;

  void anotherMethod() {}

  /// Some really great topics.
  bool get getterWithDocs => true;

  String operator [](String key) => "${key}'s value";

  final bool? initializeMe;

  int? somethingShadowy;

  /// I'm not really a constructor, but I'm allowed to exist anyway.
  int? aConstructorShadowed;

  BaseForDocComments(this.initializeMe, [bool? somethingShadowy]);

  BaseForDocComments.aNonDefaultConstructor(this.initializeMe);

  BaseForDocComments.aConstructorShadowed(this.initializeMe);

  factory BaseForDocComments.aFactoryConstructor() => BaseForDocComments(true);
}

/// Verify that we can define and use macros inside accessors.
enum MacrosFromAccessors {
  /// Define a macro.
  /// {@template test_package_docs:accessorMacro}
  /// This is a macro defined in an Enum accessor.
  /// {@endtemplate}
  macroDefinedHere,

  /// Reference a macro.
  /// {@macro test_package_docs:accessorMacro}
  macroReferencedHere,
}

/// Testing if docs for inherited method are correct.
/// {@category NotSoExcellent}
class SubForDocComments extends BaseForDocComments {
  SubForDocComments(bool thing) : super(thing);

  /// Reference to [foo] and [bar]
  void localMethod(String foo, bar) {}

  @override
  final bool getterWithDocs = false;
}

typedef void VoidCallback();

/// Adds a callback.
void addCallback(VoidCallback callback) {}

typedef int Callback2(String);

/// Adds another callback.
void addCallback2(Callback2 callback) {}

const required = 'required';

/// Paints an image into the given rectangle in the canvas.
void paintImage1(
    {required String canvas,
    required int rect,
    required ExtraSpecialList image,
    BaseForDocComments? colorFilter,
    String repeat = LongFirstLine.THING}) {
  // nothing to do here -
}

/// Paints an image into the given rectangle in the canvas.
void paintImage2(String fooParam,
    [@required String? canvas,
    @required int? rect,
    @required ExtraSpecialList? image,
    BaseForDocComments? colorFilter,
    String repeat = LongFirstLine.THING]) {
  // nothing to do here -
}

/// This is to test referring to a constructor.
///
/// This should refer to a class: [ReferToADefaultConstructor].
/// This should refer to the constructor: [ReferToADefaultConstructor.new].
class ReferToADefaultConstructor {
  /// A default constructor.
  ReferToADefaultConstructor();
}

/// Test operator references: [OperatorReferenceClass.==].
class OperatorReferenceClass {
  OperatorReferenceClass();

  @override
  bool operator ==(Object other) {
    return false;
  }
}

class _PrivateClassDefiningSomething {
  bool aMethod() {
    return false;
  }
}

class InheritingClassOne extends _PrivateClassDefiningSomething {}

class InheritingClassTwo extends _PrivateClassDefiningSomething {}

class ReferringClass {
  /// Here I am referring by full names, to [fake.InheritingClassOne.aMethod],
  /// and to [fake.InheritingClassTwo.aMethod].  With luck, both of these
  /// two resolve correctly.
  bool notAMethodFromPrivateClass() {
    return false;
  }
}

//
// Test classes for extension discovery.
//

extension Arm on Megatron<int> {
  bool get hasLeftArm => true;
}

extension Leg on Megatron<String> {
  bool get hasRightLeg => true;
}

class Megatron<T> {}

class SuperMegaTron<T extends String> extends Megatron<String> {}

extension Uphill on AnotherExtended<SubclassBaseTest> {
  bool get hasDirection => false;
}

class SubclassBaseTest extends BaseTest {}

class BaseTest {}

class AnotherExtended<T extends BaseTest> extends BaseTest {}

class BigAnotherExtended extends AnotherExtended<SubclassBaseTest> {}

extension ExtensionCheckLeft on Implemented1 {
  int get left => 3;
}

extension ExtensionCheckRight on Implemented2 {
  int get right => 4;
}

extension ExtensionCheckCenter on BaseExtended {
  bool get center => true;
}

class BaseExtended {}

class Implemented1 {}

class Implemented2 {}

class Implementor extends BaseExtended
    implements Implemented1, Implemented2, Implementor2 {}

extension ExtensionCheckImplementor2 on Implementor2 {
  int get test => 1;
}

class Implementor2 implements Implemented1 {}

class OldSchoolMixin {
  aThing() {}
}

mixin NewSchoolMixin {}

extension OnNewSchool on NewSchoolMixin {
  String get bar => 'hello';
}

extension OnOldSchool on OldSchoolMixin {
  int get foo => 4;
}

class School with OldSchoolMixin, NewSchoolMixin {}

abstract class ImplementingClassForTool {
  /// Invokes a tool from inherited documentation via `implemented`
  ///
  /// {@tool drill}
  /// This is some drill text right here.
  /// {@end-tool}
  void invokeToolParentDoc();
}

/// The method [invokeToolParentDoc] gets its documentation from an interface class.
abstract class CanonicalPrivateInheritedToolUser
    implements ImplementingClassForTool {
  @override
  void invokeToolParentDoc() {
    print('hello, tool world');
  }
}

/*
 * Complex extension methods + typedefs case.
 *
 * TODO(jcollins-g): add unit tests around behavior when #2701 is implemented.
 * Until #2701 is fixed we mostly are testing that we don't crash because
 * DoSomething2X is declared.
 */

typedef R Function1<A, R>(A a);
typedef R Function2<A, B, R>(A a, B b);

extension DoSomething2X<A, B, R> on Function1<A, Function1<B, R>> {
  Function2<A, B, R> something() => (A first, B second) => this(first)(second);
}

abstract class IntermediateAbstract extends Object {
  /// This is an override.
  @override
  bool operator ==(Object other) => false;
}

/// This should inherit [==] from [IntermediateAbstract].
class IntermediateAbstractSubclass extends IntermediateAbstract {}

/// Test parameter comment resolution in factory constructors and methods.
class FactoryConstructorThings {
  bool? aName;
  int? anotherName;
  String? yetAnotherName;
  final List<String> initViaFieldFormal;

  FactoryConstructorThings(this.initViaFieldFormal);

  factory FactoryConstructorThings.anotherName({
    bool? aName,
    List<int>? anotherName,
    int? anotherDifferentName,
    String? differentName,
  }) {
    return FactoryConstructorThings([]);
  }

  factory FactoryConstructorThings.anotherConstructor({
    bool? anotherName,
    bool? redHerring,
  }) {
    return FactoryConstructorThings([]);
  }

  void aMethod(bool yetAnotherName) {}
}

DTypeParam?
    aTopLevelTypeParameterFunction<DTypeParam extends TypeParameterThings>(
            DTypeParam typedParam) =>
        typedParam;

abstract class TypeParameterThings<ATypeParam,
    BTypeParam extends FactoryConstructorThings> {
  ATypeParam? aName;
  List<BTypeParam>? aThing;

  /// Here are some docs to inherit referencing [ATypeParam], [BTypeParam], and [CTypeParam].
  BTypeParam? aMethod<CTypeParam>(ATypeParam aParam, CTypeParam anotherParam);
}

/// Test that inheriting documentation can still reference parent type
/// parameters.
class TypeParameterThingsExtended
    extends TypeParameterThings<String, FactoryConstructorThings> {
  @override
  FactoryConstructorThings? aMethod<QTypeParam>(
          String aParam, QTypeParam anotherParam) =>
      null;
}

/// Test that overriding documentation uses local type parameters.
class TypeParameterThingsExtendedQ
    extends TypeParameterThings<String, FactoryConstructorThings> {
  @override

  /// I override documentation so I can reference [QTypeParam].
  FactoryConstructorThings? aMethod<QTypeParam>(
          String aParam, QTypeParam anotherParam) =>
      null;
}

/// We should still be able to reference [fParam.fParamA], [fParam.fParamB],
/// and [fParam.fParamC].
void set aSetterWithFunctionParameter(
    bool fParam(int fParamA, String fParamB, String fParamC)) {}
