Disabled the old CommandLineParser; started writing a new command line parser from scratch because I didn't manage to find a sane implementation on the internet; test coverage for the whole of Nuclex.Support is now 100.0%

git-svn-id: file:///srv/devel/repo-conversion/nusu@105 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2008-12-09 20:55:34 +00:00
parent 447fe2aea7
commit f0d76f988f
11 changed files with 367 additions and 31 deletions

View File

@ -114,11 +114,23 @@
<Compile Include="Source\Licensing\LicenseKey.Test.cs"> <Compile Include="Source\Licensing\LicenseKey.Test.cs">
<DependentUpon>LicenseKey.cs</DependentUpon> <DependentUpon>LicenseKey.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Source\Parsing\CommandLineParser.cs" /> <Compile Include="Source\Parsing\CommandLine.Option.cs">
<Compile Include="Source\Parsing\CommandLineParser.Test.cs"> <DependentUpon>CommandLine.cs</DependentUpon>
<DependentUpon>CommandLineParser.cs</DependentUpon> </Compile>
<Compile Include="Source\Parsing\CommandLine.Formatter.cs">
<DependentUpon>CommandLine.cs</DependentUpon>
</Compile>
<Compile Include="Source\Parsing\CommandLine.Test.cs">
<DependentUpon>CommandLine.cs</DependentUpon>
</Compile>
<Compile Include="Source\Parsing\BrokenCommandLineParser.cs" />
<Compile Include="Source\Parsing\BrokenCommandLineParser.Test.cs">
<DependentUpon>BrokenCommandLineParser.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Source\Parsing\CommandLine.cs" /> <Compile Include="Source\Parsing\CommandLine.cs" />
<Compile Include="Source\Parsing\CommandLine.Parser.cs">
<DependentUpon>CommandLine.cs</DependentUpon>
</Compile>
<Compile Include="Source\PathHelper.cs" /> <Compile Include="Source\PathHelper.cs" />
<Compile Include="Source\PathHelper.Test.cs"> <Compile Include="Source\PathHelper.Test.cs">
<DependentUpon>PathHelper.cs</DependentUpon> <DependentUpon>PathHelper.cs</DependentUpon>

View File

@ -26,6 +26,8 @@ using System.Text;
using NUnit.Framework; using NUnit.Framework;
#if false // Too bugged. 100% test coverage not possible.
namespace Nuclex.Support.Parsing { namespace Nuclex.Support.Parsing {
/// <summary>Ensures that the command line parser is working properly</summary> /// <summary>Ensures that the command line parser is working properly</summary>
@ -130,4 +132,6 @@ namespace Nuclex.Support.Parsing {
} // namespace Nuclex.Support.Parsing } // namespace Nuclex.Support.Parsing
#endif
#endif // UNITTEST #endif // UNITTEST

View File

@ -21,6 +21,8 @@ License along with this library
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
#if false // Too bugged. 100% test coverage not possible.
namespace Nuclex.Support.Parsing { namespace Nuclex.Support.Parsing {
/// <summary>Parses an application's command line</summary> /// <summary>Parses an application's command line</summary>
@ -179,3 +181,5 @@ namespace Nuclex.Support.Parsing {
} }
} // namespace Nuclex.Support.Parsing } // namespace Nuclex.Support.Parsing
#endif

View File

@ -0,0 +1,32 @@
#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
namespace Nuclex.Support.Parsing {
partial class CommandLine {
internal static class Formatter { }
}
} // namespace Nuclex.Support.Parsing

View File

@ -0,0 +1,49 @@
#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
namespace Nuclex.Support.Parsing {
partial class CommandLine {
/// <summary>Option that can be specified on an application's command line</summary>
public struct Option {
/// <summary>Contains the raw string the command line argument was parsed from</summary>
public string Raw; // TODO: ToString() instead
/*
/// <summary>Method used to specify the argument (either '-', '--' or '/')</summary>
public string Method;
*/
/// <summary>Name of the command line argument</summary>
public string Name;
/// <summary>Value that has been assigned to the command line argument</summary>
public string Value;
/*
/// <summary>Method used to assign the value (either '=', ':' or ' ')</summary>
public string Assignment;
*/
}
}
} // namespace Nuclex.Support.Parsing

View File

@ -0,0 +1,95 @@
#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
namespace Nuclex.Support.Parsing {
partial class CommandLine {
/// <summary>Parses command line strings</summary>
private static class Parser {
/// <summary>Parses a string containing command line arguments</summary>
/// <param name="commandLineString">String that will be parsed</param>
/// <returns>The parsed command line arguments from the string</returns>
public static CommandLine Parse(string commandLineString) {
CommandLine commandLine = new CommandLine();
if(commandLineString == null) {
return commandLine;
}
/*
for(int index = 0; index < commandLineString.Length; ) {
char currentCharacter = commandLineString[index];
// We ignore whitespaces outside of quoted values
if(char.IsWhiteSpace(currentCharacter)) {
continue;
}
switch(currentCharacter) {
case '-':
case '/': {
parseArgument(commandLine, commandLineString, ref index);
break;
}
case '"': {
parseQuotedValue(commandLine, commandLineString, ref index);
break;
}
default: {
parseUnquotedValue(commandLine, commandLineString, ref index);
break;
}
}
}
*/
return null;
}
/*
private static void parseArgument(
CommandLine commandLine, string commandLineString, ref int index
) {
}
private static void parseQuotedValue(
CommandLine commandLine, string commandLineString, ref int index
) {
}
private static void parseUnquotedValue(
CommandLine commandLine, string commandLineString, ref int index
) {
int endIndex = commandLineString.IndexOfAny(WhitespaceCharacters, index);
StringSegment argument = new StringSegment(commandLineString, index, endIndex - index);
}
private static readonly char[] WhitespaceCharacters = new char[] { ' ', '\t' };
*/
}
}
} // namespace Nuclex.Support.Parsing

View File

@ -0,0 +1,51 @@
#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
#if UNITTEST
using NUnit.Framework;
namespace Nuclex.Support.Parsing {
/// <summary>Ensures that the command line parser is working properly</summary>
[TestFixture]
public class CommandLineTest {
/// <summary>Validates that normal arguments can be parsed</summary>
[Test]
public void TestParseOptions() {
CommandLine.Parse("Hello -World /This --Is \"a test\"");
}
/// <summary>Validates that null can be parsed</summary>
[Test]
public void TestParseNull() {
Assert.IsNotNull(CommandLine.Parse(null));
}
}
} // namespace Nuclex.Support.Parsing
#endif // UNITTEST

View File

@ -1,46 +1,89 @@
using System; #region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace Nuclex.Support.Source.Parsing { namespace Nuclex.Support.Parsing {
#if false
/// <summary> /// <summary>
/// Parses an application's command line parameters for easier consumption /// Manages an application's command line parameters
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// At the time of the creation of this parser, there are already several command line /// At the time of the creation of this component, there are already several command
/// parsing libraries out there. Most of them, however, do way too much at once or at /// line parsing libraries out there. Most of them, however, do way too much at once
/// the very least use one huge, untested clutter of classes and methods to arrive /// or at the very least rely on huge, untested clutters of classes and methods to
/// at their results. /// arrive at their results.
/// </para> /// </para>
/// <para> /// <para>
/// This parser does nothing more than parse the command line arguments. It doesn't /// This class does nothing more than represent the command line to the application.
/// interpret them and it doesn't check them for validity. Due to this, it can easily /// It can parse a command line
/// parse the command line arguments. It doesn't
/// interpret them and it doesn't check them for validity. This promotes simplicity
/// and allows t
/// be unit-tested and is an ideal building block to create actual command line /// be unit-tested and is an ideal building block to create actual command line
/// interpreters that connect the parameters to program instructions and or fill /// interpreters that connect the parameters to program instructions and or fill
/// structures in code. /// structures in code.
/// </para> /// </para>
/// <para>
/// Terminology
/// <list type="table">
/// <item>
/// <term>Command line</term>
/// <description>
/// The entire command line either as a string or as
/// an already parsed data structure
/// </description>
/// </item>
/// <item>
/// <term>Option / Argument</term>
/// <description>
/// Can be specified on the command line and typically alters the behavior
/// of the application or changes a setting. For example, '--normalize' or
/// '/safemode'.
/// </description>
/// </item>
/// <item>
/// <term>Value</term>
/// <description>
/// Can either sit loosely in the command line (eg. 'update' or 'textfile.txt')
/// or as assignment to an option (eg. '--width=1280' or '/overwrite:always')
/// </description>
/// </item>
/// </list>
/// </para>
/// </remarks> /// </remarks>
public class CommandLine { public partial class CommandLine {
public static CommandLine Parse(string commandLine) {}
/// <summary>Initializes a new command line</summary>
public CommandLine() { }
/// <summary>Parses the command line arguments from the provided string</summary>
/// <param name="commandLineString">String containing the command line arguments</param>
/// <returns>The parsed command line</returns>
public static CommandLine Parse(string commandLineString) {
return Parser.Parse(commandLineString);
} }
public struct CommandLineOption {
/// <summary>Contains the raw string the command line argument was parsed from</summary>
public string Raw;
/// <summary>Method used to specify the argument (either '-', '--' or '/')</summary>
public string Method;
/// <summary>Name of the command line argument</summary>
public string Name;
/// <summary>Value that has been assigned to the command line argument</summary>
public string Value;
/// <summary>Method used to assign the value (either '=', ':' or ' ')</summary>
public string Assignment;
} }
#endif
} } // namespace Nuclex.Support.Parsing

View File

@ -78,6 +78,7 @@ namespace Nuclex.Support.Plugins {
PluginHost testHost = new PluginHost(testEmployer, testRepository); PluginHost testHost = new PluginHost(testEmployer, testRepository);
Assert.AreSame(testEmployer, testHost.Employer);
Assert.AreEqual(1, testEmployer.Factories.Count); Assert.AreEqual(1, testEmployer.Factories.Count);
} }
@ -121,6 +122,7 @@ namespace Nuclex.Support.Plugins {
Assembly self = Assembly.GetAssembly(GetType()); Assembly self = Assembly.GetAssembly(GetType());
testRepository.AddAssembly(self); testRepository.AddAssembly(self);
Assert.AreSame(testEmployer, testHost.Employer);
Assert.AreEqual(1, testEmployer.Factories.Count); Assert.AreEqual(1, testEmployer.Factories.Count);
} }
@ -137,6 +139,8 @@ namespace Nuclex.Support.Plugins {
// the unit testing tool // the unit testing tool
Assembly self = Assembly.GetAssembly(GetType()); Assembly self = Assembly.GetAssembly(GetType());
testRepository.AddAssembly(self); testRepository.AddAssembly(self);
Assert.AreSame(testRepository, testHost.Repository);
} }
/// <summary> /// <summary>
@ -154,6 +158,7 @@ namespace Nuclex.Support.Plugins {
Assembly self = Assembly.GetAssembly(GetType()); Assembly self = Assembly.GetAssembly(GetType());
testRepository.AddAssembly(self); testRepository.AddAssembly(self);
Assert.AreSame(testRepository, testHost.Repository);
Assert.AreEqual(0, testEmployer.Factories.Count); Assert.AreEqual(0, testEmployer.Factories.Count);
} }

View File

@ -188,6 +188,41 @@ namespace Nuclex.Support {
Assert.IsFalse(helloWorld1Segment != helloWorld2Segment); Assert.IsFalse(helloWorld1Segment != helloWorld2Segment);
} }
/// <summary>Tests the ToString() method of the string segment</summary>
[Test]
public void TestToString() {
StringSegment helloWorldSegment = new StringSegment("hello world", 4, 3);
Assert.AreEqual("o w", helloWorldSegment.ToString());
}
/// <summary>
/// Tests the ToString() method of the string segment with an invalid string
/// </summary>
[Test, ExpectedException(typeof(ArgumentNullException))]
public void TestToStringWithInvalidString() {
StringSegment helloWorldSegment = new StringSegment(null, 4, 3);
Assert.IsNotNull(helloWorldSegment.ToString());
}
/// <summary>
/// Tests the ToString() method of the string segment with an invalid offset
/// </summary>
[Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void TestToStringWithInvalidOffset() {
StringSegment helloWorldSegment = new StringSegment("hello world", -4, 3);
Assert.IsNotNull(helloWorldSegment.ToString());
}
/// <summary>
/// Tests the ToString() method of the string segment with an invalid count
/// </summary>
[Test, ExpectedException(typeof(ArgumentOutOfRangeException))]
public void TestToStringWithInvalidCount() {
StringSegment helloWorldSegment = new StringSegment("hello world", 4, -3);
Assert.IsNotNull(helloWorldSegment.ToString());
}
} }
} // namespace Nuclex.Support } // namespace Nuclex.Support

View File

@ -201,6 +201,12 @@ namespace Nuclex.Support {
return !(left == right); return !(left == right);
} }
/// <summary>Returns a string representation of the string segment</summary>
/// <returns>The string representation of the string segment</returns>
public override string ToString() {
return this.text.Substring(this.offset, this.count);
}
/// <summary>String wrapped by the string segment</summary> /// <summary>String wrapped by the string segment</summary>
private string text; private string text;
/// <summary>Offset in the original string the segment begins at</summary> /// <summary>Offset in the original string the segment begins at</summary>