// Copyright (c) 2013, 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.

/// A library for compiling Dart code and manipulating analyzer parse trees.
library;

import 'dart:async';
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/error/error.dart';
import 'package:frontend_server_client/frontend_server_client.dart';
import 'package:path/path.dart' as p;

import 'exceptions.dart';
import 'io.dart';
import 'log.dart' as log;

class AnalysisContextManager {
  static final sessions = <String, AnalysisContextManager>{};

  final String packagePath;
  final AnalysisSession _session;

  factory AnalysisContextManager(String packagePath) => sessions.putIfAbsent(
        packagePath,
        () => AnalysisContextManager._(packagePath),
      );

  AnalysisContextManager._(this.packagePath)
      : _session = AnalysisContextCollection(
          includedPaths: [packagePath],
        ).contextFor(packagePath).currentSession;

  /// Parse the file with the given [path] into AST.
  ///
  /// One of the containing directories must have been used to create `this`.
  /// Throws [StateError] otherwise.
  ///
  /// Throws [AnalyzerErrorGroup] is the file has parsing errors.
  CompilationUnit parse(String path) {
    path = p.normalize(p.absolute(path));
    final parseResult = _session.getParsedUnit(path);
    if (parseResult is ParsedUnitResult) {
      if (parseResult.errors.isNotEmpty) {
        throw AnalyzerErrorGroup(parseResult.errors);
      }
      return parseResult.unit;
    } else {
      throw StateError('Unable to parse $path, ${parseResult.runtimeType}');
    }
  }

  /// Return import and export directives in the file with the given [path].
  ///
  /// Throws [AnalyzerErrorGroup] is the file has parsing errors.
  List<UriBasedDirective> parseImportsAndExports(String path) {
    final unit = parse(path);
    final uriDirectives = <UriBasedDirective>[];
    for (var directive in unit.directives) {
      if (directive is UriBasedDirective) {
        uriDirectives.add(directive);
      }
    }
    return uriDirectives;
  }
}

/// An error class that contains multiple [AnalysisError]s.
class AnalyzerErrorGroup implements Exception {
  final List<AnalysisError> errors;

  AnalyzerErrorGroup(this.errors);

  String get message => toString();

  @override
  String toString() => errors.join('\n');
}

/// Precompiles the Dart executable at [executablePath].
///
/// If the compilation succeeds it is saved to a kernel file at [outputPath].
///
/// If compilation fails, the output is cached at "[outputPath].incremental".
///
/// Whichever of "[outputPath].incremental" and [outputPath] already exists is
/// used to initialize the compiler run. To avoid the potential for
/// race-conditions, it is first copied to a temporary location, and atomically
/// moved to either [outputPath] or "[outputPath].incremental" depending on the
/// result of compilation.
///
/// The [packageConfigPath] should point at the package config file to be used
/// for `package:` uri resolution.
///
/// The [name] is used to describe the executable in logs and error messages.
///
/// The [additionalSources], if provided, instruct the compiler to include
/// additional source files into compilation even if they are not referenced
/// from the main library.
///
/// The [nativeAssets], if provided, instruct the compiler include a native
/// assets map.
Future<void> precompile({
  required String executablePath,
  required String name,
  required String outputPath,
  required String packageConfigPath,
  List<String> additionalSources = const [],
  String? nativeAssets,
}) async {
  const platformDill = 'lib/_internal/vm_platform_strong.dill';
  final sdkRoot = p.relative(p.dirname(p.dirname(Platform.resolvedExecutable)));
  String? tempDir;
  FrontendServerClient? client;
  try {
    ensureDir(p.dirname(outputPath));
    final incrementalDillPath = '$outputPath.incremental';
    tempDir = createTempDir(p.dirname(outputPath), 'tmp');
    // To avoid potential races we copy the incremental data to a temporary file
    // for just this compilation.
    final temporaryIncrementalDill =
        p.join(tempDir, '${p.basename(incrementalDillPath)}.temp');
    try {
      if (fileExists(outputPath)) {
        copyFile(outputPath, temporaryIncrementalDill);
      } else if (fileExists(incrementalDillPath)) {
        copyFile(incrementalDillPath, temporaryIncrementalDill);
      }
    } on FileSystemException {
      // Not able to copy existing file, compilation will start from scratch.
    }

    client = await FrontendServerClient.start(
      executablePath,
      temporaryIncrementalDill,
      platformDill,
      sdkRoot: sdkRoot,
      packagesJson: packageConfigPath,
      additionalSources: additionalSources,
      nativeAssets: nativeAssets,
      printIncrementalDependencies: false,
    );
    final result = await client.compile();

    // Sanity check. We've had reports of the compilation failing to provide a
    // result, perhaps due to low-memory conditions.
    // This should make this slightly easier to recognize in error reports.
    if (!fileExists(temporaryIncrementalDill)) {
      log.error(
        'Compilation did not produce any result. '
        'Expected file at `$temporaryIncrementalDill`',
        result.dillOutput,
      );
    }

    final highlightedName = log.bold(name);
    if (result.errorCount == 0) {
      log.message('Built $highlightedName.');
      // By using rename we ensure atomicity. An external observer will either
      // see the old or the new snapshot.
      renameFile(temporaryIncrementalDill, outputPath);
      // Any old incremental data is deleted in case we started from a file on
      // [incrementalDillPath].
      deleteEntry(incrementalDillPath);
    } else {
      // By using rename we ensure atomicity. An external observer will either
      // see the old or the new snapshot.
      renameFile(temporaryIncrementalDill, incrementalDillPath);
      // If compilation failed, don't leave an incorrect snapshot.
      tryDeleteEntry(outputPath);

      throw ApplicationException(
        log.yellow('Failed to build $highlightedName:\n') +
            result.compilerOutputLines.join('\n'),
      );
    }
  } finally {
    client?.kill();
    if (tempDir != null) {
      tryDeleteEntry(tempDir);
    }
  }
}
