// 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. library pub.exceptions; import 'dart:io'; import 'dart:isolate'; import "package:analyzer/analyzer.dart"; import 'package:args/command_runner.dart'; import "package:http/http.dart" as http; import "package:stack_trace/stack_trace.dart"; import "package:yaml/yaml.dart"; import 'asset/dart/serialize.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); String toString() => 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 { final String message; /// The path to the file that was missing or erroneous. final String path; FileException(this.message, this.path); 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 innerError; /// The stack chain for [innerError] if it exists. final Chain innerChain; WrappedException(String message, this.innerError, [StackTrace innerTrace]) : innerChain = innerTrace == null ? null : new Chain.forTrace(innerTrace), super(message); } /// 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(innerError, [StackTrace innerTrace]) : super(innerError.toString(), innerError, innerTrace); } /// A class for errors in a command's input data. /// /// This corresponds to the [exit_codes.DATA] exit code. class DataException extends ApplicationException { DataException(String message) : 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 { PackageNotFoundException(String message, [innerError, StackTrace innerTrace]) : super(message, innerError, innerTrace); } /// All the names of user-facing exceptions. final _userFacingExceptions = new Set<String>.from([ 'ApplicationException', 'GitException', // This refers to http.ClientException. 'ClientException', // Errors coming from the Dart analyzer are probably caused by syntax errors // in user code, so they're user-facing. 'AnalyzerError', 'AnalyzerErrorGroup', // An error spawning an isolate probably indicates a transformer with an // invalid import. 'IsolateSpawnException', // IOException and subclasses. 'CertificateException', 'FileSystemException', 'HandshakeException', 'HttpException', 'IOException', 'ProcessException', 'RedirectException', 'SignalException', 'SocketException', 'StdoutException', 'TlsException', 'WebSocketException' ]); /// Returns whether [error] is a user-facing error object. /// /// This includes both [ApplicationException] and any dart:io errors. bool isUserFacingException(error) { if (error is CrossIsolateException) { return _userFacingExceptions.contains(error.type); } // TODO(nweiz): unify this list with _userFacingExceptions when issue 5897 is // fixed. return error is ApplicationException || error is AnalyzerError || error is AnalyzerErrorGroup || error is IsolateSpawnException || error is IOException || error is http.ClientException || error is YamlException || error is UsageException; }