display CommandParsingException gracefully (#5493)

* display CommandParsing gracefully

This set of changes handles CommandParsingException gracefuly (so as not to show the user a stack trace) and generalizes graceful exception display somewhat away from being type-specific.

* fix compile error by inlining constant

* remove unused test logging
This commit is contained in:
Jon Sequeira 2017-01-30 14:36:44 -08:00 committed by Piotr Puszkiewicz
parent 5aded80a7b
commit e8c5d23c29
8 changed files with 42 additions and 13 deletions

View file

@ -4,10 +4,6 @@ namespace Microsoft.DotNet.Cli.Utils
{ {
public class CommandUnknownException : GracefulException public class CommandUnknownException : GracefulException
{ {
public CommandUnknownException()
{
}
public CommandUnknownException(string commandName) : base(string.Format( public CommandUnknownException(string commandName) : base(string.Format(
LocalizableStrings.NoExecutableFoundMatchingCommand, LocalizableStrings.NoExecutableFoundMatchingCommand,
commandName)) commandName))

View file

@ -3,7 +3,7 @@
using System; using System;
namespace Microsoft.DotNet.Cli.Utils.ExceptionExtensions namespace Microsoft.DotNet.Cli.Utils
{ {
internal static class ExceptionExtensions internal static class ExceptionExtensions
{ {
@ -11,5 +11,10 @@ namespace Microsoft.DotNet.Cli.Utils.ExceptionExtensions
{ {
Reporter.Verbose.WriteLine($"Warning: Ignoring exception: {e.ToString().Yellow()}"); Reporter.Verbose.WriteLine($"Warning: Ignoring exception: {e.ToString().Yellow()}");
} }
public static bool ShouldBeDisplayedAsError(this Exception e) =>
e.Data.Contains(CLI_User_Displayed_Exception);
internal const string CLI_User_Displayed_Exception = "CLI_User_Displayed_Exception";
} }
} }

View file

@ -4,12 +4,9 @@ namespace Microsoft.DotNet.Cli.Utils
{ {
public class GracefulException : Exception public class GracefulException : Exception
{ {
public GracefulException()
{
}
public GracefulException(string message) : base(message) public GracefulException(string message) : base(message)
{ {
Data.Add(ExceptionExtensions.CLI_User_Displayed_Exception, true);
} }
public GracefulException(string format, params string[] args) : this(string.Format(format, args)) public GracefulException(string format, params string[] args) : this(string.Format(format, args))
@ -18,6 +15,7 @@ namespace Microsoft.DotNet.Cli.Utils
public GracefulException(string message, Exception innerException) : base(message, innerException) public GracefulException(string message, Exception innerException) : base(message, innerException)
{ {
Data.Add(ExceptionExtensions.CLI_User_Displayed_Exception, true);
} }
} }
} }

View file

@ -10,7 +10,6 @@ using Microsoft.DotNet.Internal.ProjectModel;
using Microsoft.DotNet.Internal.ProjectModel.Graph; using Microsoft.DotNet.Internal.ProjectModel.Graph;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.ExceptionExtensions;
using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.ProjectJsonMigration.Rules; using Microsoft.DotNet.ProjectJsonMigration.Rules;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;

View file

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System; using System;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools;
namespace Microsoft.DotNet.Cli.CommandLine namespace Microsoft.DotNet.Cli.CommandLine
@ -18,6 +19,8 @@ namespace Microsoft.DotNet.Cli.CommandLine
{ {
Command = command; Command = command;
_isRequireSubCommandMissing = isRequireSubCommandMissing; _isRequireSubCommandMissing = isRequireSubCommandMissing;
Data.Add("CLI_User_Displayed_Exception", true);
} }
public CommandLineApplication Command { get; } public CommandLineApplication Command { get; }

View file

@ -4,7 +4,6 @@
using System; using System;
using System.Runtime.Loader; using System.Runtime.Loader;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Utils.ExceptionExtensions;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
namespace Microsoft.DotNet.Cli namespace Microsoft.DotNet.Cli

View file

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Configurer; using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.PlatformAbstractions; using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.DotNet.Tools.Add; using Microsoft.DotNet.Tools.Add;
@ -76,9 +77,11 @@ namespace Microsoft.DotNet.Cli
return ProcessArgs(args); return ProcessArgs(args);
} }
} }
catch (GracefulException e) catch (Exception e) when (e.ShouldBeDisplayedAsError())
{ {
Reporter.Error.WriteLine(CommandContext.IsVerbose() ? e.ToString().Red().Bold() : e.Message.Red().Bold()); Reporter.Error.WriteLine(CommandContext.IsVerbose() ?
e.ToString().Red().Bold() :
e.Message.Red().Bold());
return 1; return 1;
} }

View file

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using FluentAssertions;
using Microsoft.DotNet.Tools.Test.Utilities;
using System;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.DotNet.New.Tests
{
public class NewCommandTests
{
[Fact]
public void WhenSwitchIsSkippedThenItPrintsError()
{
var cmd = new DotnetCommand().Execute("new Web1.1");
cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Be("Unrecognized command or argument 'Web1.1'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
}
}
}