// Copyright (c) 2019, 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/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:front_end/src/testing/package_root.dart' as package_root;
import 'package:path/src/context.dart';

/// Generate the file `diagnostics.md` based on the documentation associated
/// with the declarations of the error codes.
void main() async {
  Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
  String packageRoot = pathContext.normalize(package_root.packageRoot);
  String analyzerPath = pathContext.join(packageRoot, 'analyzer');
  List<String> docPaths = [
    pathContext.join(
        analyzerPath, 'lib', 'src', 'dart', 'error', 'hint_codes.dart'),
    pathContext.join(analyzerPath, 'lib', 'src', 'error', 'codes.dart'),
  ];
  String outputPath =
      pathContext.join(analyzerPath, 'tool', 'diagnostics', 'diagnostics.md');

  DocumentationGenerator generator = DocumentationGenerator(docPaths);
  generator.writeDocumentation(outputPath);
}

/// A class used to generate diagnostic documentation.
class DocumentationGenerator {
  /// The absolute paths of the files containing the declarations of the error
  /// codes.
  final List<String> docPaths;

  /// A map from the name of a diagnostic code to the lines of the documentation
  /// for that code.
  Map<String, List<String>> docsByCode = {};

  /// Initialize a newly created documentation generator.
  DocumentationGenerator(this.docPaths) {
    _extractAllDocs();
  }

  /// Write the documentation to the file at the given [outputPath].
  void writeDocumentation(String outputPath) async {
    IOSink sink = File(outputPath).openWrite();
    _writeHeader(sink);
    _writeGlossary(sink);
    _writeDiagnostics(sink);
    await sink.flush();
    await sink.close();
  }

  /// Return a version of the [text] in which characters that have special
  /// meaning in markdown have been escaped.
  String _escape(String text) {
    return text.replaceAll('_', '\\_');
  }

  /// Extract documentation from all of the files containing the definitions of
  /// diagnostics.
  void _extractAllDocs() {
    AnalysisContextCollection collection = new AnalysisContextCollection(
        includedPaths: docPaths,
        resourceProvider: PhysicalResourceProvider.INSTANCE);
    for (String docPath in docPaths) {
      _extractDocs(_parse(collection, docPath));
    }
  }

  /// Extract documentation from the given [field] declaration.
  List<String> _extractDoc(FieldDeclaration field) {
    Token comments = field.firstTokenAfterCommentAndMetadata.precedingComments;
    if (comments == null) {
      return null;
    }
    List<String> docs = [];
    while (comments != null) {
      String lexeme = comments.lexeme;
      if (lexeme.startsWith('// TODO')) {
        break;
      } else if (lexeme.startsWith('// ')) {
        docs.add(lexeme.substring(3));
      } else if (lexeme == '//') {
        docs.add('');
      }
      comments = comments.next;
    }
    if (docs.isEmpty) {
      return null;
    }
    return docs;
  }

  /// Extract documentation from the file that was parsed to produce the given
  /// [result].
  void _extractDocs(ParsedUnitResult result) {
    CompilationUnit unit = result.unit;
    for (CompilationUnitMember declaration in unit.declarations) {
      if (declaration is ClassDeclaration) {
        for (ClassMember member in declaration.members) {
          if (member is FieldDeclaration) {
            List<String> docs = _extractDoc(member);
            if (docs != null) {
              VariableDeclaration variable = member.fields.variables[0];
              String variableName = variable.name.name;
              if (docsByCode.containsKey(variableName)) {
                throw StateError('Duplicate diagnostic code');
              }
              String message =
                  ((variable.initializer as InstanceCreationExpression)
                          .argumentList
                          .arguments[1] as StringLiteral)
                      .stringValue;
              docs = [
                '### ${_escape(variableName.toLowerCase())}',
                '',
                ..._split('_${_escape(message)}_'),
                '',
                ...docs,
              ];
              docsByCode[variableName] = docs;
            }
          }
        }
      }
    }
  }

  /// Use the analysis context [collection] to parse the file at the given
  /// [path] and return the result.
  ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
    AnalysisSession session = collection.contextFor(path).currentSession;
    if (session == null) {
      throw new StateError('No session for "$path"');
    }
    ParsedUnitResult result = session.getParsedUnit(path);
    if (result.state != ResultState.VALID) {
      throw new StateError('Unable to parse "$path"');
    }
    return result;
  }

  /// Split the [message] into multiple lines, each of which is less than 80
  /// characters long.
  List<String> _split(String message) {
    // This uses a brute force approach because we don't expect to have messages
    // that need to be split more than once.
    int length = message.length;
    if (length <= 80) {
      return [message];
    }
    int endIndex = message.lastIndexOf(' ', 80);
    if (endIndex < 0) {
      return [message];
    }
    return [message.substring(0, endIndex), message.substring(endIndex + 1)];
  }

  /// Write the documentation for all of the diagnostics.
  void _writeDiagnostics(IOSink sink) {
    sink.write('''

## Diagnostics

The analyzer produces the following diagnostics for code that
doesn't conform to the language specification or
that might work in unexpected ways.
''');
    List<String> errorCodes = docsByCode.keys.toList();
    errorCodes.sort();
    for (String errorCode in errorCodes) {
      List<String> docs = docsByCode[errorCode];
      sink.writeln();
      for (String line in docs) {
        sink.writeln(line);
      }
    }
  }

  /// Write the glossary.
  void _writeGlossary(IOSink sink) {
    sink.write('''

## Glossary

This page uses the following terms.

### Potentially non-nullable

A type is _potentially non-nullable_ if it's either explicitly non-nullable or
if it's a type parameter. The latter case is included because the actual runtime
type might be non-nullable.
''');
  }

  /// Write the header of the file.
  void _writeHeader(IOSink sink) {
    sink.write('''
---
title: Diagnostics
description: Details for diagnostics produced by the Dart analyzer.
---

This page lists diagnostic messages produced by the Dart analyzer,
with details about what those messages mean and how you can fix your code.
For more information about the analyzer, see
[Customizing static analysis](/guides/language/analysis-options).
''');
  }
}
