| // Copyright (c) 2014, 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 'dart:isolate'; | |
| import 'package:args/command_runner.dart'; | |
| import 'package:http/http.dart' as http; | |
| import 'package:source_span/source_span.dart'; | |
| import 'package:stack_trace/stack_trace.dart'; | |
| import 'package:yaml/yaml.dart'; | |
| import 'dart.dart'; | |
| import 'http.dart'; | |
| import 'log.dart' as log; | |
| import 'source.dart'; | |
| /// An exception class for exceptions that are intended to be seen by the user. | |
| /// | |
| /// These exceptions won't have any debugging information printed when they're | |
| /// thrown. | |
| class ApplicationException implements Exception { | |
| final String message; | |
| ApplicationException(this.message); | |
| @override | |
| String toString() => message; | |
| } | |
| /// A subclass of [ApplicationException] that occurs when running a subprocess | |
| /// has failed. | |
| class RunProcessException extends ApplicationException { | |
| RunProcessException(super.message); | |
| } | |
| /// An exception class for exceptions that are intended to be seen by the user | |
| /// and are associated with a problem in a file at some path. | |
| class FileException implements ApplicationException { | |
| @override | |
| final String message; | |
| /// The path to the file that was missing or erroneous. | |
| final String path; | |
| FileException(this.message, this.path); | |
| @override | |
| String toString() => message; | |
| } | |
| /// A class for exceptions that wrap other exceptions. | |
| class WrappedException extends ApplicationException { | |
| /// The underlying exception that `this` is wrapping, if any. | |
| final Object? innerError; | |
| /// The stack chain for [innerError] if it exists. | |
| final Chain? innerChain; | |
| WrappedException(super.message, this.innerError, [StackTrace? innerTrace]) | |
| : innerChain = innerTrace == null ? null : Chain.forTrace(innerTrace); | |
| } | |
| /// A class for exceptions that shouldn't be printed at the top level. | |
| /// | |
| /// This is usually used when an exception has already been printed using | |
| /// [log.exception]. | |
| class SilentException extends WrappedException { | |
| SilentException(Object? innerError, [StackTrace? innerTrace]) | |
| : super(innerError.toString(), innerError, innerTrace); | |
| } | |
| /// A class for errors in a command's input data. | |
| /// | |
| /// This corresponds to the `data` exit code. | |
| class DataException extends ApplicationException { | |
| DataException(super.message); | |
| } | |
| /// An exception indicating that the users configuration is invalid. | |
| /// | |
| /// This corresponds to the `config` exit code; | |
| class ConfigException extends ApplicationException { | |
| ConfigException(super.message); | |
| } | |
| /// An class for exceptions where a package could not be found in a [Source]. | |
| /// | |
| /// The source is responsible for wrapping its internal exceptions in this so | |
| /// that other code in pub can use this to show a more detailed explanation of | |
| /// why the package was being requested. | |
| class PackageNotFoundException extends WrappedException { | |
| /// A hint indicating an action the user could take to resolve this problem. | |
| /// | |
| /// This will be printed after the package resolution conflict. | |
| final String? hint; | |
| PackageNotFoundException( | |
| String message, { | |
| Object? innerError, | |
| StackTrace? innerTrace, | |
| this.hint, | |
| }) : super(message, innerError, innerTrace); | |
| @override | |
| String toString() => 'Package not available ($message).'; | |
| } | |
| /// A class for exceptions where a package's checksum could not be validated. | |
| class PackageIntegrityException extends PubHttpException { | |
| PackageIntegrityException(super.message) : super(isIntermittent: true); | |
| } | |
| /// Returns whether [error] is a user-facing error object. | |
| /// | |
| /// This includes both [ApplicationException] and any dart:io errors. | |
| bool isUserFacingException(Object error) { | |
| return error is ApplicationException || | |
| error is AnalyzerErrorGroup || | |
| error is IsolateSpawnException || | |
| error is IOException || | |
| error is http.ClientException || | |
| error is YamlException || | |
| error is UsageException; | |
| } | |
| /// An exception thrown when parsing a `pubspec.yaml` or a `pubspec.lock`. | |
| /// | |
| /// These exceptions are often thrown lazily while accessing pubspec properties. | |
| /// | |
| /// By being an [ApplicationException] this will not trigger a stack-trace on | |
| /// normal operations. | |
| /// | |
| /// Works as a [SourceSpanFormatException], but can contain more context: | |
| /// An optional [explanation] that explains the operation that failed. | |
| /// An optional [hint] that gives suggestions how to proceed. | |
| class SourceSpanApplicationException extends SourceSpanFormatException | |
| implements ApplicationException { | |
| final String? explanation; | |
| final String? hint; | |
| SourceSpanApplicationException( | |
| super.message, | |
| super.span, { | |
| this.hint, | |
| this.explanation, | |
| }); | |
| @override | |
| String toString({Object? color}) { | |
| return [ | |
| if (explanation != null) explanation, | |
| span == null | |
| ? message | |
| : 'Error on ${span?.message(message, color: color)}', | |
| if (hint != null) hint, | |
| ].join('\n\n'); | |
| } | |
| } |