// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:collection/collection.dart';
import 'package:test/test.dart';

import 'resolved_ast_printer.dart';

/// Set this path to automatically replace expectations in invocations of
/// [checkElementText] with the new actual texts.
const String? _testPath = null;

/// The list of replacements that update expectations.
final List<_Replacement> _replacements = [];

/// The cached content of the file with the [_testPath].
String? _testCode;

/// The cache line information for the [_testPath] file.
LineInfo? _testCodeLines;

void applyCheckElementTextReplacements() {
  if (_testPath != null && _replacements.isNotEmpty) {
    _replacements.sort((a, b) => b.offset - a.offset);
    String newCode = _testCode!;
    for (var replacement in _replacements) {
      newCode = newCode.substring(0, replacement.offset) +
          replacement.text +
          newCode.substring(replacement.end);
    }
    File(_testPath!).writeAsStringSync(newCode);
  }
}

/// Write the given [library] elements into the canonical text presentation
/// taking into account the specified 'withX' options. Then compare the
/// actual text with the given [expected] one.
void checkElementText(
  LibraryElement library,
  String expected, {
  bool withCodeRanges = false,
  bool withDisplayName = false,
  bool withExportScope = false,
  bool withNonSynthetic = false,
}) {
  var writer = _ElementWriter(
    selfUriStr: '${library.source.uri}',
    withCodeRanges: withCodeRanges,
    withDisplayName: withDisplayName,
    withExportScope: withExportScope,
    withNonSynthetic: withNonSynthetic,
  );
  writer.writeLibraryElement(library);

  String actualText = writer.buffer.toString();
  actualText =
      actualText.split('\n').map((line) => line.trimRight()).join('\n');

  if (_testPath != null && actualText != expected) {
    if (_testCode == null) {
      _testCode = File(_testPath!).readAsStringSync();
      _testCodeLines = LineInfo.fromContent(_testCode!);
    }

    try {
      throw 42;
    } catch (e, trace) {
      String traceString = trace.toString();

      // Assuming traceString contains "$_testPath:$invocationLine:$column",
      // figure out the value of invocationLine.

      int testFilePathOffset = traceString.indexOf(_testPath!);
      expect(testFilePathOffset, isNonNegative);

      // Sanity check: there must be ':' after the path.
      expect(traceString[testFilePathOffset + _testPath!.length], ':');

      int lineOffset = testFilePathOffset + _testPath!.length + ':'.length;
      int invocationLine = int.parse(traceString.substring(
          lineOffset, traceString.indexOf(':', lineOffset)));
      int invocationOffset =
          _testCodeLines!.getOffsetOfLine(invocationLine - 1);

      const String rawStringPrefix = "r'''";
      int expectationOffset =
          _testCode!.indexOf(rawStringPrefix, invocationOffset);

      // Sanity check: there must be no other strings or blocks.
      expect(_testCode!.substring(invocationOffset, expectationOffset),
          isNot(anyOf(contains("'"), contains('"'), contains('}'))));

      expectationOffset += rawStringPrefix.length;
      int expectationEnd = _testCode!.indexOf("'''", expectationOffset);

      _replacements.add(
          _Replacement(expectationOffset, expectationEnd, '\n$actualText'));
    }
  }

  // Print the actual text to simplify copy/paste into the expectation.
  // if (actualText != expected) {
  //   print('-------- Actual --------');
  //   print('$actualText------------------------');
  // }

  expect(actualText, expected);
}

/// Writes the canonical text presentation of elements.
class _ElementWriter {
  final String? selfUriStr;
  final bool withCodeRanges;
  final bool withDisplayName;
  final bool withExportScope;
  final bool withNonSynthetic;
  final StringBuffer buffer = StringBuffer();

  String indent = '';

  _ElementWriter({
    this.selfUriStr,
    required this.withCodeRanges,
    required this.withDisplayName,
    required this.withExportScope,
    required this.withNonSynthetic,
  });

  void writeLibraryElement(LibraryElement e) {
    e as LibraryElementImpl;

    _writelnWithIndent('library');
    _withIndent(() {
      var name = e.name;
      if (name.isNotEmpty) {
        _writelnWithIndent('name: $name');
      }

      var nameOffset = e.nameOffset;
      if (nameOffset != -1) {
        _writelnWithIndent('nameOffset: $nameOffset');
      }

      _writeDocumentation(e);
      _writeMetadata(e);

      var imports = e.imports.where((import) => !import.isSynthetic).toList();
      _writeElements('imports', imports, _writeImportElement);

      _writeElements('exports', e.exports, _writeExportElement);

      _writelnWithIndent('definingUnit');
      _withIndent(() {
        _writeUnitElement(e.definingCompilationUnit);
      });

      _writeElements('parts', e.parts2, _writePartElement);

      if (withExportScope) {
        _writelnWithIndent('exportedReferences');
        _withIndent(() {
          _writeExportedReferences(e);
        });
        _writelnWithIndent('exportNamespace');
        _withIndent(() {
          _writeExportNamespace(e);
        });
      }
    });
  }

  void _assertNonSyntheticElementSelf(Element element) {
    expect(element.isSynthetic, isFalse);
    expect(element.nonSynthetic, same(element));
  }

  /// Assert that the [accessor] of the [property] is correctly linked to
  /// the same enclosing element as the [property].
  void _assertSyntheticAccessorEnclosing(
      PropertyInducingElement property, PropertyAccessorElement accessor) {
    if (accessor.isSynthetic) {
      // Usually we have a non-synthetic property, and a synthetic accessor.
    } else {
      // But it is possible to have a non-synthetic setter.
      // class A {
      //   final int foo;
      //   set foo(int newValue) {}
      // }
      expect(accessor.isSetter, isTrue);
    }

    expect(accessor.variable, same(property));

    var propertyEnclosing = property.enclosingElement;
    expect(accessor.enclosingElement, same(propertyEnclosing));

    if (propertyEnclosing is CompilationUnitElement) {
      expect(propertyEnclosing.accessors, contains(accessor));
    } else if (propertyEnclosing is ClassElement) {
      expect(propertyEnclosing.accessors, contains(accessor));
    }
  }

  ResolvedAstPrinter _createAstPrinter() {
    return ResolvedAstPrinter(
      selfUriStr: selfUriStr,
      sink: buffer,
      indent: indent,
      // TODO(scheglov) https://github.com/dart-lang/sdk/issues/49101
      withParameterElements: false,
      withOffsets: true,
    );
  }

  String _getElementLocationString(Element? element) {
    if (element == null || element is MultiplyDefinedElement) {
      return 'null';
    }

    String onlyName(String uri) {
      if (uri.startsWith('file:///')) {
        return uri.substring(uri.lastIndexOf('/') + 1);
      }
      return uri;
    }

    var location = element.location!;
    List<String> components = location.components.toList();
    if (components.isNotEmpty) {
      components[0] = onlyName(components[0]);
    }
    if (components.length >= 2) {
      components[1] = onlyName(components[1]);
      if (components[0] == components[1]) {
        components.removeAt(0);
      }
    }
    return components.join(';');
  }

  void _withIndent(void Function() f) {
    var savedIndent = indent;
    indent = '$savedIndent  ';
    f();
    indent = savedIndent;
  }

  void _writeBodyModifiers(ExecutableElement e) {
    if (e.isAsynchronous) {
      expect(e.isSynchronous, isFalse);
      buffer.write(' async');
    }

    if (e.isSynchronous && e.isGenerator) {
      expect(e.isAsynchronous, isFalse);
      buffer.write(' sync');
    }

    _writeIf(e.isGenerator, '*');

    if (e is ExecutableElementImpl && e.invokesSuperSelf) {
      buffer.write(' invokesSuperSelf');
    }
  }

  void _writeClassElement(ClassElement e) {
    _writeIndentedLine(() {
      _writeIf(e.isAbstract && !e.isMixin, 'abstract ');
      _writeIf(e.isMacro, 'macro ');
      _writeIf(!e.isSimplyBounded, 'notSimplyBounded ');

      if (e.isEnum) {
        buffer.write('enum ');
      } else if (e.isMixin) {
        buffer.write('mixin ');
      } else {
        buffer.write('class ');
      }
      _writeIf(e.isMixinApplication, 'alias ');

      _writeName(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeParameterElements(e.typeParameters);

      var supertype = e.supertype;
      if (supertype != null &&
          (supertype.element.name != 'Object' || e.mixins.isNotEmpty)) {
        _writeType('supertype', supertype);
      }

      if (e.isMixin) {
        var superclassConstraints = e.superclassConstraints;
        if (superclassConstraints.isEmpty) {
          throw StateError('At least Object is expected.');
        }
        _writeTypeList('superclassConstraints', superclassConstraints);
      }

      _writeTypeList('mixins', e.mixins);
      _writeTypeList('interfaces', e.interfaces);

      _writeElements('fields', e.fields, _writePropertyInducingElement);

      var constructors = e.constructors;
      if (e.isMixin) {
        expect(constructors, isEmpty);
      } else {
        expect(constructors, isNotEmpty);
        _writeElements('constructors', constructors, _writeConstructorElement);
      }

      _writeElements('accessors', e.accessors, _writePropertyAccessorElement);
      _writeElements('methods', e.methods, _writeMethodElement);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeCodeRange(Element e) {
    if (withCodeRanges && !e.isSynthetic) {
      e as ElementImpl;
      _writelnWithIndent('codeOffset: ${e.codeOffset}');
      _writelnWithIndent('codeLength: ${e.codeLength}');
    }
  }

  void _writeConstantInitializer(Element e) {
    if (e is ConstVariableElement) {
      var initializer = e.constantInitializer;
      if (initializer != null) {
        _writelnWithIndent('constantInitializer');
        _withIndent(() {
          _writeNode(initializer);
        });
      }
    }
  }

  void _writeConstructorElement(ConstructorElement e) {
    e as ConstructorElementImpl;

    // Check that the reference exists, and filled with the element.
    var reference = e.reference;
    if (reference == null) {
      fail('Every constructor must have a reference.');
    } else {
      var classReference = reference.parent!.parent!;
      // We need this `if` for duplicate declarations.
      // The reference might be filled by another declaration.
      if (identical(classReference.element, e.enclosingElement)) {
        expect(reference.element, same(e));
      }
    }

    _writeIndentedLine(() {
      _writeIf(e.isSynthetic, 'synthetic ');
      _writeIf(e.isExternal, 'external ');
      _writeIf(e.isConst, 'const ');
      _writeIf(e.isFactory, 'factory ');
      expect(e.isAbstract, isFalse);
      _writeName(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeDisplayName(e);

      var periodOffset = e.periodOffset;
      var nameEnd = e.nameEnd;
      if (periodOffset != null && nameEnd != null) {
        _writelnWithIndent('periodOffset: $periodOffset');
        _writelnWithIndent('nameEnd: $nameEnd');
      }

      _writeParameterElements(e.parameters);

      _writeElements(
        'constantInitializers',
        e.constantInitializers,
        _writeNode,
      );

      var superConstructor = e.superConstructor;
      if (superConstructor != null) {
        if (!superConstructor.enclosingElement.isDartCoreObject) {
          _writeElementReference('superConstructor', superConstructor);
        }
      }

      var redirectedConstructor = e.redirectedConstructor;
      if (redirectedConstructor != null) {
        _writeElementReference('redirectedConstructor', redirectedConstructor);
      }

      _writeNonSyntheticElement(e);
    });

    expect(e.isAsynchronous, isFalse);
    expect(e.isGenerator, isFalse);

    if (e.isSynthetic) {
      expect(e.nameOffset, -1);
      expect(e.nonSynthetic, same(e.enclosingElement));
    } else {
      if (!e.isTempAugmentation) {
        expect(e.nameOffset, isPositive);
      }
    }
  }

  void _writeDirectiveUri(DirectiveUri uri) {
    if (uri is DirectiveUriWithUnit) {
      _writelnWithIndent('${uri.unit.source.uri}');
    } else if (uri is DirectiveUriWithSource) {
      _writelnWithIndent("source '${uri.source.uri}'");
    } else if (uri is DirectiveUriWithRelativeUri) {
      _writelnWithIndent("relativeUri '${uri.relativeUri}'");
    } else if (uri is DirectiveUriWithRelativeUriString) {
      _writelnWithIndent("relativeUriString '${uri.relativeUriString}'");
    } else {
      _writelnWithIndent('noRelativeUriString');
    }
  }

  void _writeDisplayName(Element e) {
    if (withDisplayName) {
      _writelnWithIndent('displayName: ${e.displayName}');
    }
  }

  void _writeDocumentation(Element element) {
    var documentation = element.documentationComment;
    if (documentation != null) {
      var str = documentation;
      str = str.replaceAll('\n', r'\n');
      str = str.replaceAll('\r', r'\r');
      _writelnWithIndent('documentationComment: $str');
    }
  }

  void _writeElementReference(String name, Element element) {
    var printer = _createAstPrinter();
    printer.writeElement(name, element);
  }

  void _writeElements<T>(String name, List<T> elements, void Function(T) f) {
    if (elements.isNotEmpty) {
      _writelnWithIndent(name);
      _withIndent(() {
        for (var element in elements) {
          f(element);
        }
      });
    }
  }

  void _writeExportedReferences(LibraryElementImpl e) {
    final exportedReferences = e.exportedReferences.toList();
    exportedReferences.sortBy((e) => e.reference.toString());

    for (final exported in exportedReferences) {
      _writeIndentedLine(() {
        if (exported is ExportedReferenceDeclared) {
          buffer.write('declared ');
        } else if (exported is ExportedReferenceExported) {
          buffer.write('exported${exported.indexes} ');
        }
        // TODO(scheglov) Use the same writer as for resolved AST.
        buffer.write(exported.reference);
      });
    }
  }

  void _writeExportElement(ExportElement e) {
    _writeIndentedLine(() {
      _writeUri(e.exportedLibrary?.source);
    });

    _withIndent(() {
      _writeMetadata(e);
      _writeNamespaceCombinators(e.combinators);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeExportNamespace(LibraryElement e) {
    var map = e.exportNamespace.definedNames;
    var names = map.keys.toList()..sort();
    for (var name in names) {
      var element = map[name];
      var elementLocationStr = _getElementLocationString(element);
      _writelnWithIndent('$name: $elementLocationStr');
    }
  }

  void _writeExtensionElement(ExtensionElement e) {
    _writeIndentedLine(() {
      _writeName(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeParameterElements(e.typeParameters);
      _writeType('extendedType', e.extendedType);
    });

    _withIndent(() {
      _writeElements('fields', e.fields, _writePropertyInducingElement);
      _writeElements('accessors', e.accessors, _writePropertyAccessorElement);
      _writeElements('methods', e.methods, _writeMethodElement);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeFieldFormalParameterField(ParameterElement e) {
    if (e is FieldFormalParameterElement) {
      var field = e.field;
      if (field != null) {
        _writeElementReference('field', field);
      } else {
        _writelnWithIndent('field: <null>');
      }
    }
  }

  void _writeFunctionElement(FunctionElement e) {
    expect(e.isStatic, isTrue);

    _writeIndentedLine(() {
      _writeIf(e.isExternal, 'external ');
      _writeName(e);
      _writeBodyModifiers(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeParameterElements(e.typeParameters);
      _writeParameterElements(e.parameters);
      _writeType('returnType', e.returnType);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeIf(bool flag, String str) {
    if (flag) {
      buffer.write(str);
    }
  }

  void _writeImportElement(ImportElement e) {
    _writeIndentedLine(() {
      _writeUri(e.importedLibrary?.source);
      _writeIf(e.isDeferred, ' deferred');

      var prefix = e.prefix;
      if (prefix != null) {
        buffer.write(' as ');
        _writeName(prefix);
      }
    });

    _withIndent(() {
      _writeMetadata(e);
      _writeNamespaceCombinators(e.combinators);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeIndentedLine(void Function() f) {
    buffer.write(indent);
    f();
    buffer.writeln();
  }

  void _writelnWithIndent(String line) {
    buffer.write(indent);
    buffer.writeln(line);
  }

  void _writeMetadata(Element element) {
    var annotations = element.metadata;
    if (annotations.isNotEmpty) {
      _writelnWithIndent('metadata');
      _withIndent(() {
        for (var annotation in annotations) {
          annotation as ElementAnnotationImpl;
          _writeNode(annotation.annotationAst);
        }
      });
    }
  }

  void _writeMethodElement(MethodElement e) {
    _writeIndentedLine(() {
      _writeIf(e.isSynthetic, 'synthetic ');
      _writeIf(e.isStatic, 'static ');
      _writeIf(e.isAbstract, 'abstract ');
      _writeIf(e.isExternal, 'external ');

      _writeName(e);
      _writeBodyModifiers(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeInferenceError(e);

      _writeTypeParameterElements(e.typeParameters);
      _writeParameterElements(e.parameters);
      _writeType('returnType', e.returnType);
      _writeNonSyntheticElement(e);
    });

    if (e.isSynthetic && e.enclosingElement is EnumElementImpl) {
      expect(e.name, 'toString');
      expect(e.nonSynthetic, same(e.enclosingElement));
    } else {
      _assertNonSyntheticElementSelf(e);
    }
  }

  void _writeName(Element e) {
    // TODO(scheglov) Use 'name' everywhere.
    var name = e is ConstructorElement ? e.name : e.displayName;
    buffer.write(name);
    buffer.write(name.isNotEmpty ? ' @' : '@');
    buffer.write(e.nameOffset);
  }

  void _writeNamespaceCombinator(NamespaceCombinator e) {
    _writeIndentedLine(() {
      if (e is ShowElementCombinator) {
        buffer.write('show: ');
        buffer.write(e.shownNames.join(', '));
      } else if (e is HideElementCombinator) {
        buffer.write('hide: ');
        buffer.write(e.hiddenNames.join(', '));
      }
    });
  }

  void _writeNamespaceCombinators(List<NamespaceCombinator> elements) {
    _writeElements('combinators', elements, _writeNamespaceCombinator);
  }

  void _writeNode(AstNode node) {
    buffer.write(indent);
    node.accept(
      _createAstPrinter(),
    );
  }

  void _writeNonSyntheticElement(Element e) {
    if (withNonSynthetic) {
      _writeElementReference('nonSynthetic', e.nonSynthetic);
    }
  }

  void _writeParameterElement(ParameterElement e) {
    _writeIndentedLine(() {
      if (e.isRequiredPositional) {
        buffer.write('requiredPositional ');
      } else if (e.isOptionalPositional) {
        buffer.write('optionalPositional ');
      } else if (e.isRequiredNamed) {
        buffer.write('requiredNamed ');
      } else if (e.isOptionalNamed) {
        buffer.write('optionalNamed ');
      }

      _writeIf(e.isConst, 'const ');
      _writeIf(e.isCovariant, 'covariant ');
      _writeIf(e.isFinal, 'final ');

      if (e is FieldFormalParameterElement) {
        buffer.write('this.');
      } else if (e is SuperFormalParameterElement) {
        buffer.write('super.');
      }

      _writeName(e);
    });

    _withIndent(() {
      _writeType('type', e.type);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeParameterElements(e.typeParameters);
      _writeParameterElements(e.parameters);
      _writeConstantInitializer(e);
      _writeNonSyntheticElement(e);
      _writeFieldFormalParameterField(e);
      _writeSuperConstructorParameter(e);
    });
  }

  void _writeParameterElements(List<ParameterElement> elements) {
    _writeElements('parameters', elements, _writeParameterElement);
  }

  void _writePartElement(PartElement e) {
    final uri = e.uri;
    _writeDirectiveUri(uri);

    _withIndent(() {
      _writeMetadata(e);
      if (uri is DirectiveUriWithUnit) {
        _writeUnitElement(uri.unit);
      }
    });
  }

  void _writePropertyAccessorElement(PropertyAccessorElement e) {
    e as PropertyAccessorElementImpl;

    PropertyInducingElement variable = e.variable;
    expect(variable, isNotNull);

    var variableEnclosing = variable.enclosingElement;
    if (variableEnclosing is CompilationUnitElement) {
      expect(variableEnclosing.topLevelVariables, contains(variable));
    } else if (variableEnclosing is ClassElement) {
      expect(variableEnclosing.fields, contains(variable));
    }

    if (e.isGetter) {
      expect(variable.getter, same(e));
      if (variable.setter != null) {
        expect(variable.setter!.variable, same(variable));
      }
    } else {
      expect(variable.setter, same(e));
      if (variable.getter != null) {
        expect(variable.getter!.variable, same(variable));
      }
    }

    if (e.isSynthetic) {
      expect(e.nameOffset, -1);
    } else {
      if (!e.isTempAugmentation) {
        expect(e.nameOffset, isPositive);
      }
      _assertNonSyntheticElementSelf(e);
    }

    _writeIndentedLine(() {
      _writeIf(e.isSynthetic, 'synthetic ');
      _writeIf(e.isStatic, 'static ');
      _writeIf(e.isAbstract, 'abstract ');
      _writeIf(e.isExternal, 'external ');

      if (e.isGetter) {
        buffer.write('get ');
      } else {
        buffer.write('set ');
      }

      _writeName(e);
      _writeBodyModifiers(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);

      expect(e.typeParameters, isEmpty);
      _writeParameterElements(e.parameters);
      _writeType('returnType', e.returnType);
      _writeNonSyntheticElement(e);
    });
  }

  void _writePropertyInducingElement(PropertyInducingElement e) {
    e as PropertyInducingElementImpl;

    DartType type = e.type;
    expect(type, isNotNull);

    if (e.isSynthetic) {
      expect(e.nameOffset, -1);
    } else {
      expect(e.getter, isNotNull);
      _assertSyntheticAccessorEnclosing(e, e.getter!);

      if (e.setter != null) {
        _assertSyntheticAccessorEnclosing(e, e.setter!);
      }

      if (!e.isTempAugmentation) {
        expect(e.nameOffset, isPositive);
      }
      _assertNonSyntheticElementSelf(e);
    }

    _writeIndentedLine(() {
      _writeIf(e.isSynthetic, 'synthetic ');
      _writeIf(e.isStatic, 'static ');
      _writeIf(e is FieldElementImpl && e.isAbstract, 'abstract ');
      _writeIf(e is FieldElementImpl && e.isCovariant, 'covariant ');
      _writeIf(e is FieldElementImpl && e.isExternal, 'external ');
      _writeIf(e.isLate, 'late ');
      _writeIf(e.isFinal, 'final ');
      _writeIf(e.isConst, 'const ');
      _writeIf(e is FieldElementImpl && e.isEnumConstant, 'enumConstant ');

      _writeName(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeInferenceError(e);
      _writeType('type', e.type);
      _writeConstantInitializer(e);
      _writeNonSyntheticElement(e);
    });
  }

  void _writeSuperConstructorParameter(ParameterElement e) {
    if (e is SuperFormalParameterElement) {
      var superParameter = e.superConstructorParameter;
      if (superParameter != null) {
        _writeElementReference('superConstructorParameter', superParameter);
      } else {
        _writelnWithIndent('superConstructorParameter: <null>');
      }
    }
  }

  void _writeType(String name, DartType type) {
    _createAstPrinter().writeType(type, name: name);
  }

  void _writeTypeAliasElement(TypeAliasElement e) {
    e as TypeAliasElementImpl;

    _writeIndentedLine(() {
      _writeIf(e.isFunctionTypeAliasBased, 'functionTypeAliasBased ');
      _writeIf(!e.isSimplyBounded, 'notSimplyBounded ');
      _writeName(e);
    });

    _withIndent(() {
      _writeDocumentation(e);
      _writeMetadata(e);
      _writeCodeRange(e);
      _writeTypeParameterElements(e.typeParameters);

      var aliasedType = e.aliasedType;
      _writeType('aliasedType', aliasedType);
      // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44629
      // TODO(scheglov) Remove it when we stop providing it everywhere.
      if (aliasedType is FunctionType) {
        expect(aliasedType.element, isNull);
      }

      var aliasedElement = e.aliasedElement;
      if (aliasedElement is GenericFunctionTypeElementImpl) {
        _writelnWithIndent('aliasedElement: GenericFunctionTypeElement');
        _withIndent(() {
          _writeTypeParameterElements(aliasedElement.typeParameters);
          _writeParameterElements(aliasedElement.parameters);
          _writeType('returnType', aliasedElement.returnType);
        });
      }
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeTypeInferenceError(Element e) {
    TopLevelInferenceError? inferenceError;
    if (e is MethodElementImpl) {
      inferenceError = e.typeInferenceError;
    } else if (e is PropertyInducingElementImpl) {
      inferenceError = e.typeInferenceError;
    }

    if (inferenceError != null) {
      String kindName = inferenceError.kind.toString();
      if (kindName.startsWith('TopLevelInferenceErrorKind.')) {
        kindName = kindName.substring('TopLevelInferenceErrorKind.'.length);
      }
      _writelnWithIndent('typeInferenceError: $kindName');
    }
  }

  void _writeTypeList(String name, List<DartType> types) {
    _createAstPrinter().writeTypeList(name, types);
  }

  void _writeTypeParameterElement(TypeParameterElement e) {
    e as TypeParameterElementImpl;

    _writeIndentedLine(() {
      buffer.write('${e.variance} ');
      _writeName(e);
    });

    _withIndent(() {
      _writeCodeRange(e);

      var bound = e.bound;
      if (bound != null) {
        _writeType('bound', bound);
      }

      var defaultType = e.defaultType;
      if (defaultType != null) {
        _writeType('defaultType', defaultType);
      }

      _writeMetadata(e);
    });

    _assertNonSyntheticElementSelf(e);
  }

  void _writeTypeParameterElements(List<TypeParameterElement> elements) {
    _writeElements('typeParameters', elements, _writeTypeParameterElement);
  }

  void _writeUnitElement(CompilationUnitElement e) {
    _writeElements('classes', e.classes, _writeClassElement);
    _writeElements('enums', e.enums, _writeClassElement);
    _writeElements('extensions', e.extensions, _writeExtensionElement);
    _writeElements('mixins', e.mixins, _writeClassElement);
    _writeElements('typeAliases', e.typeAliases, _writeTypeAliasElement);
    _writeElements(
      'topLevelVariables',
      e.topLevelVariables,
      _writePropertyInducingElement,
    );
    _writeElements(
      'accessors',
      e.accessors,
      _writePropertyAccessorElement,
    );
    _writeElements('functions', e.functions, _writeFunctionElement);
  }

  void _writeUri(Source? source) {
    if (source != null) {
      Uri uri = source.uri;
      String uriStr = uri.toString();
      if (uri.isScheme('file')) {
        uriStr = uri.pathSegments.last;
      }
      buffer.write(uriStr);
    } else {
      buffer.write('<unresolved>');
    }
  }
}

class _Replacement {
  final int offset;
  final int end;
  final String text;

  _Replacement(this.offset, this.end, this.text);
}

extension on ClassElement {
  bool get isMacro {
    final self = this;
    return self is ClassElementImpl && self.isMacro;
  }
}
