// Copyright (c) 2021, 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:collection';
import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/util/comment.dart';
import 'package:path/path.dart' as path;

void main(List<String> args) async {
  final libDir = Directory('sdk/lib');
  if (!libDir.existsSync()) {
    print('Please run this tool from the root of the sdk repo.');
    exit(1);
  }

  print('Validating the dartdoc code samples from the dart: libraries.');
  print('');
  print('To run this tool, run `dart tools/verify_docs/bin/verify_docs.dart`.');
  print('');
  print('For documentation about how to author dart: code samples,'
      ' see tools/verify_docs/README.md.');
  print('');

  final coreLibraries = args.isEmpty
      ? libDir.listSync().whereType<Directory>().toList()
      : args.map((arg) => Directory(arg)).toList();
  coreLibraries.sort((a, b) => a.path.compareTo(b.path));

  // Skip some dart: libraries.
  const skipLibraries = {
    'html',
    'indexed_db',
    'svg',
    'vmservice',
    'web_audio',
    'web_gl',
    'web_sql'
  };
  coreLibraries.removeWhere(
    (lib) => skipLibraries.contains(path.basename(lib.path)),
  );

  var hadErrors = false;
  for (final dir in coreLibraries) {
    hadErrors |= !(await validateLibrary(dir));
  }

  exitCode = hadErrors ? 1 : 0;
}

Future<bool> validateLibrary(Directory dir) async {
  final libName = path.basename(dir.path);

  final analysisHelper = AnalysisHelper(libName);

  print('## dart:$libName');
  print('');

  var validDocs = true;

  for (final file in dir
      .listSync(recursive: true)
      .whereType<File>()
      .where((file) => file.path.endsWith('.dart'))) {
    validDocs &= await verifyFile(analysisHelper, libName, file, dir);
  }

  return validDocs;
}

Future<bool> verifyFile(
  AnalysisHelper analysisHelper,
  String coreLibName,
  File file,
  Directory parent,
) async {
  final text = file.readAsStringSync();
  var parseResult = parseString(
    content: text,
    featureSet: FeatureSet.latestLanguageVersion(),
    path: file.path,
    throwIfDiagnostics: false,
  );

  // Throw if there are syntactic errors.
  var syntacticErrors = parseResult.errors.where((error) {
    return error.errorCode.type == ErrorType.SYNTACTIC_ERROR;
  }).toList();
  if (syntacticErrors.isNotEmpty) {
    throw Exception(syntacticErrors);
  }

  final sampleAssumptions = findFileAssumptions(text);

  var visitor = ValidateCommentCodeSamplesVisitor(
    analysisHelper,
    coreLibName,
    file.path,
    parseResult.lineInfo,
    sampleAssumptions,
  );
  await visitor.process(parseResult);
  return !visitor.hadErrors;
}

/// Visit a compilation unit and validate the code samples found in dartdoc
/// comments.
class ValidateCommentCodeSamplesVisitor extends GeneralizingAstVisitor {
  final AnalysisHelper analysisHelper;
  final String coreLibName;
  final String filePath;
  final LineInfo lineInfo;
  final String? sampleAssumptions;

  final List<CodeSample> samples = [];
  bool hadErrors = false;

  ValidateCommentCodeSamplesVisitor(
    this.analysisHelper,
    this.coreLibName,
    this.filePath,
    this.lineInfo,
    this.sampleAssumptions,
  );

  Future process(ParseStringResult parseResult) async {
    // collect code samples
    visitCompilationUnit(parseResult.unit);

    // analyze them
    for (CodeSample sample in samples) {
      await validateCodeSample(sample);
    }
  }

  @override
  void visitAnnotatedNode(AnnotatedNode node) {
    _handleDocumentableNode(node);
    super.visitAnnotatedNode(node);
  }

  void _handleDocumentableNode(AnnotatedNode node) {
    final docComment = node.documentationComment;
    if (docComment == null || !docComment.isDocumentation) {
      return;
    }

    const sampleStart = '```dart';
    const sampleEnd = '```';

    final text = getCommentNodeRawText(docComment)!;
    final commentOffset = docComment.offset;
    final commentLineStart = lineInfo.getLocation(commentOffset).lineNumber;
    if (!text.contains(sampleStart)) {
      return;
    }

    var offset = text.indexOf(sampleStart);
    while (offset != -1) {
      // Collect template directives, like "```dart import:async".
      final codeFenceSuffix = text.substring(
          offset + sampleStart.length, text.indexOf('\n', offset));
      final directives = Set.unmodifiable(codeFenceSuffix.trim().split(' '));

      offset = text.indexOf('\n', offset) + 1;
      final end = text.indexOf(sampleEnd, offset);

      var snippet = text.substring(offset, end);
      snippet = snippet.substring(0, snippet.lastIndexOf('\n'));

      List<String> lines = snippet.split('\n');

      samples.add(
        CodeSample(
          lines.map((e) => '  ${cleanDocLine(e)}').join('\n'),
          coreLibName: coreLibName,
          directives: directives,
          lineStartOffset: commentLineStart +
              text.substring(0, offset - 1).split('\n').length -
              1,
        ),
      );

      offset = text.indexOf(sampleStart, offset);
    }
  }

  Future validateCodeSample(CodeSample sample) async {
    var text = sample.text;
    final lines = sample.text.split('\n').map((l) => l.trim()).toList();

    final hasImports = text.contains("import '") || text.contains('import "');

    // One of 'none', 'main', or 'expression'.
    String? template;

    if (sample.hasTemplateDirective) {
      template = sample.templateDirective;
    } else {
      // If there's no explicit template, auto-detect one.
      if (lines.any((line) =>
          line.startsWith('class ') ||
          line.startsWith('enum ') ||
          line.startsWith('extension '))) {
        template = 'none';
      } else if (lines
          .any((line) => line.startsWith('main(') || line.contains(' main('))) {
        template = 'none';
      } else if (lines.length == 1 && !lines.first.trim().endsWith(';')) {
        template = 'expression';
      } else {
        template = 'main';
      }
    }

    final assumptions = sampleAssumptions ?? '';

    if (!hasImports) {
      if (template == 'none') {
        // just use the sample text as is
      } else if (template == 'main') {
        text = "${assumptions}main() async {\n${text.trimRight()}\n}\n";
      } else if (template == 'expression') {
        text = "${assumptions}main() async {\n${text.trimRight()}\n;\n}\n";
      } else {
        throw 'unexpected template directive: $template';
      }

      for (final directive
          in sample.directives.where((str) => str.startsWith('import:'))) {
        final libName = directive.substring('import:'.length);
        text = "import 'dart:$libName';\n$text";
      }

      if (sample.coreLibName != 'internal') {
        text = "import 'dart:${sample.coreLibName}';\n$text";
      }
    }

    final result = await analysisHelper.resolveFile(text);

    if (result is ResolvedUnitResult) {
      var errors = SplayTreeSet<AnalysisError>.from(
        result.errors,
        (a, b) {
          var value = a.offset.compareTo(b.offset);
          if (value == 0) {
            value = a.message.compareTo(b.message);
          }
          return value;
        },
      );

      // Filter out unused imports, since we speculatively add imports to some
      // samples.
      errors.removeWhere(
        (e) => e.errorCode == HintCode.UNUSED_IMPORT,
      );

      // Also, don't worry about 'unused_local_variable' and related; this may
      // be intentional in samples.
      errors.removeWhere(
        (e) =>
            e.errorCode == HintCode.UNUSED_LOCAL_VARIABLE ||
            e.errorCode == HintCode.UNUSED_ELEMENT,
      );

      // Remove warnings about deprecated member use from the same library.
      errors.removeWhere(
        (e) =>
            e.errorCode == HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE ||
            e.errorCode ==
                HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE_WITH_MESSAGE,
      );

      // Handle edge case around dart:_http
      errors.removeWhere((e) {
        if (e.message.contains("'dart:_http'")) {
          return e.errorCode == HintCode.UNNECESSARY_IMPORT ||
              e.errorCode == CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY;
        }
        return false;
      });

      if (errors.isNotEmpty) {
        print('$filePath:${sample.lineStartOffset}: ${errors.length} errors');

        hadErrors = true;

        for (final error in errors) {
          final location = result.lineInfo.getLocation(error.offset);
          print(
            '  ${_severity(error.severity)}: ${error.message} '
            '[$location] (${error.errorCode.name.toLowerCase()})',
          );
        }
        print('');

        // Print out the code sample.
        print(sample.text
            .split('\n')
            .map((line) =>
                '  >${line.length >= 5 ? line.substring(5) : line.trimLeft()}')
            .join('\n'));
        print('');
      }
    } else {
      throw 'unexpected result type: ${result}';
    }

    return;
  }
}

String cleanDocLine(String line) {
  var copy = line.trimLeft();
  if (copy.startsWith('///')) {
    copy = copy.substring(3);
  } else if (copy.startsWith('*')) {
    copy = copy.substring(1);
  }
  return copy.padLeft(line.length, ' ');
}

class CodeSample {
  final String coreLibName;
  final Set<String> directives;
  final String text;
  final int lineStartOffset;

  CodeSample(
    this.text, {
    required this.coreLibName,
    this.directives = const {},
    required this.lineStartOffset,
  });

  bool get hasTemplateDirective => templateDirective != null;

  String? get templateDirective {
    const prefix = 'template:';

    String? match = directives.cast<String?>().firstWhere(
        (directive) => directive!.startsWith(prefix),
        orElse: () => null);
    return match == null ? match : match.substring(prefix.length);
  }
}

/// Find and return any '// Examples can assume:' sample text.
String? findFileAssumptions(String text) {
  var inAssumptions = false;
  var assumptions = <String>[];

  for (final line in text.split('\n')) {
    if (line == '// Examples can assume:') {
      inAssumptions = true;
    } else if (line.trim().isEmpty && inAssumptions) {
      inAssumptions = false;
    } else if (inAssumptions) {
      assumptions.add(line.substring('// '.length));
    }
  }

  return '${assumptions.join('\n')}\n';
}

String _severity(Severity severity) {
  switch (severity) {
    case Severity.info:
      return 'info';
    case Severity.warning:
      return 'warning';
    case Severity.error:
      return 'error';
  }
}

class AnalysisHelper {
  final String libraryName;
  final resourceProvider =
      OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
  final pathRoot = Platform.isWindows ? r'c:\' : '/';
  late AnalysisContextCollection collection;
  int index = 0;

  AnalysisHelper(this.libraryName) {
    resourceProvider.pathContext;

    collection = AnalysisContextCollection(
      includedPaths: ['$pathRoot$libraryName'],
      resourceProvider: resourceProvider,
    );
  }

  Future<SomeResolvedUnitResult> resolveFile(String contents) async {
    final samplePath =
        '$pathRoot$libraryName${resourceProvider.pathContext.separator}'
        'sample_${index++}.dart';
    resourceProvider.setOverlay(
      samplePath,
      content: contents,
      modificationStamp: 0,
    );

    var analysisContext = collection.contextFor(samplePath);
    var analysisSession = analysisContext.currentSession;
    return await analysisSession.getResolvedUnit(samplePath);
  }
}
