Initial commit of basic pack library and test application to show contents and state of local repo
This commit is contained in:
Родитель
40f08cd399
Коммит
bf578ca490
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{145D7231-C105-41BE-B646-5D400097C744}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CMSIS.Pack</RootNamespace>
|
||||
<AssemblyName>CMSIS.Pack</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Sprache, Version=2.0.0.0, Culture=neutral, PublicKeyToken=23dafc55df9bd3a3, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Sprache.JetBrains.2.0.0.44\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FileDownloadProgress.cs" />
|
||||
<Compile Include="Interfaces.cs" />
|
||||
<Compile Include="PackDescription\Api.cs" />
|
||||
<Compile Include="PackDescription\Board.cs" />
|
||||
<Compile Include="PackDescription\Component.cs" />
|
||||
<Compile Include="PackDescription\Condition.cs" />
|
||||
<Compile Include="PackDescription\DebugAccessSequence.cs" />
|
||||
<Compile Include="PackDescription\DeviceFamily.cs" />
|
||||
<Compile Include="PackDescription\Example.cs" />
|
||||
<Compile Include="PackDescription\Generator.cs" />
|
||||
<Compile Include="PackDescription\Keywords.cs" />
|
||||
<Compile Include="PackDescription\Package.cs" />
|
||||
<Compile Include="PackDescription\Parsers.cs" />
|
||||
<Compile Include="PackDescription\Release.cs" />
|
||||
<Compile Include="PackDescription\TaxonomyDescription.cs" />
|
||||
<Compile Include="PackIndexEntry.cs" />
|
||||
<Compile Include="PackIndex.cs" />
|
||||
<Compile Include="PackInstallProgress.cs" />
|
||||
<Compile Include="PackRepository.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="RepositoryPackage.cs" />
|
||||
<Compile Include="RepositoryUpdateEventArgs.cs" />
|
||||
<Compile Include="SemanticVersion.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
-->
|
||||
<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly);$(TargetFileName)" Outputs="$(OutputPath)$(_SGenDllName)" Condition="'$(GenerateSerializationAssemblies)'=='On'">
|
||||
<SGen BuildAssemblyName="$(TargetFileName)" BuildAssemblyPath="$(OutputPath)" References="@(ReferencePath)" ShouldGenerateSerializer="true" UseProxyTypes="false" KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)" DelaySign="$(DelaySign)" ToolPath="$(TargetFrameworkSDKToolsDirectory)" Platform="$(Platform)">
|
||||
<Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
|
||||
</SGen>
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
/// <summary>Value type used to indicate the static state a file download</summary>
|
||||
public struct FileDownloadProgress
|
||||
{
|
||||
public FileDownloadProgress( Uri source, TimeSpan elapsedTime, long sizeSoFar, long totalSize)
|
||||
{
|
||||
SourceUrl_ = source;
|
||||
ElapsedTime_ = elapsedTime;
|
||||
SizeSoFar_ = sizeSoFar;
|
||||
TotalSize_ = totalSize;
|
||||
}
|
||||
|
||||
public double PercentComplete
|
||||
{
|
||||
get { return 100.0 * (double)SizeSoFar/(double)TotalSize; }
|
||||
}
|
||||
|
||||
public bool IsCompleted { get { return SizeSoFar_ == -1 || TotalSize_ == -1; } }
|
||||
public Uri SourceUrl { get { return SourceUrl_; } }
|
||||
private readonly Uri SourceUrl_;
|
||||
|
||||
public TimeSpan ElapsedTime { get { return ElapsedTime_; } }
|
||||
private readonly TimeSpan ElapsedTime_;
|
||||
|
||||
public long SizeSoFar { get { return SizeSoFar_; } }
|
||||
private readonly long SizeSoFar_;
|
||||
|
||||
public long TotalSize { get { return TotalSize_; } }
|
||||
private readonly long TotalSize_;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using CMSIS.Pack.PackDescription;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
public enum PackInstallState
|
||||
{
|
||||
AvailableForDownload,
|
||||
Downloading,
|
||||
Downloaded,
|
||||
Installing,
|
||||
Installed,
|
||||
}
|
||||
|
||||
public interface IPackIndexEntry
|
||||
{
|
||||
/// <summary>File name of the compressed form of this pack</summary>
|
||||
/// <remarks>
|
||||
/// The file name is of the form: VENDOR.NAME.VERSION.pack
|
||||
/// </remarks>
|
||||
string PackName { get; }
|
||||
|
||||
/// <summary>Vendor name parsed out of the PackName from the index</summary>
|
||||
string Vendor { get; }
|
||||
|
||||
/// <summary>Name of the pack parsed out of the Pack name from the index</summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>Name of the PDSC file for this pack</summary>
|
||||
/// <remarks>
|
||||
/// The PDSC filename takes the form: VENDOR.NAME.pdsc
|
||||
/// </remarks>
|
||||
string PdscName { get; }
|
||||
|
||||
/// <summary>Full URL of the Package Description (PDSC) file for this pack</summary>
|
||||
Uri PdscUrl { get; }
|
||||
|
||||
/// <summary>FULL URL of the Package file for this pack</summary>
|
||||
Uri PackUrl { get; }
|
||||
|
||||
/// <summary>Base URI for this pack read from the index</summary>
|
||||
Uri Url { get; }
|
||||
|
||||
/// <summary>Local path name for this pack relative to the root of a repository</summary>
|
||||
/// <remarks>
|
||||
/// The local path takes the form VENDOR\NAME\VERSION
|
||||
/// </remarks>
|
||||
string LocalPath { get; }
|
||||
|
||||
/// <summary>Version of the pack</summary>
|
||||
SemanticVersion Version { get; }
|
||||
|
||||
/// <summary>Retrieves the contents of the Package Description file</summary>
|
||||
/// <returns>string containing the XML content of the description</returns>
|
||||
Task<string> GetPackageDescriptionDocumentAsync( );
|
||||
|
||||
/// <summary>Asynchronously download and parse the package description file for this pack</summary>
|
||||
/// <returns>parsed package instance for the package description</returns>
|
||||
Task<Package> GetPackageDescriptionAsync( );
|
||||
}
|
||||
|
||||
public interface IRepositoryPackage
|
||||
: IPackIndexEntry
|
||||
{
|
||||
PackInstallState InstallState { get; }
|
||||
IRepository Repository { get; }
|
||||
|
||||
Task Download( IProgress<FileDownloadProgress> progressSink );
|
||||
|
||||
Task InstallPack( IProgress<PackInstallProgress> progressSink );
|
||||
}
|
||||
|
||||
public enum RepositoryState
|
||||
{
|
||||
Idle,
|
||||
DownloadingIndex,
|
||||
DownloadingIndexPdsc,
|
||||
DownloadingPackPdsc,
|
||||
DownloadingPack,
|
||||
InstallingPack,
|
||||
UninstallingPack,
|
||||
DeletingPack
|
||||
}
|
||||
|
||||
/// <summary>Represents a remote repository and local store of the installed pack files</summary>
|
||||
public interface IRepository
|
||||
{
|
||||
/// <summary>Location of the source of packs to download from</summary>
|
||||
Uri SourceUri { get; }
|
||||
|
||||
/// <summary>Location of the locally installed packs that updates and new packs are installed into</summary>
|
||||
string LocalPath { get; }
|
||||
|
||||
DateTime LastUpdatedTimeUTC { get; }
|
||||
/// <summary>Full path to the local ".Web" folder containing the pack descriptions cached from the web source</summary>
|
||||
string WebRoot { get; }
|
||||
|
||||
/// <summary>Full path </summary>
|
||||
string DownloadRoot { get; }
|
||||
|
||||
IEnumerable<IRepositoryPackage> Packs { get; }
|
||||
|
||||
event EventHandler<RepositoryUpdateEventArgs> Updated;
|
||||
|
||||
Task UpdateLocalFromSource( );
|
||||
|
||||
Task LoadFromLocal( );
|
||||
|
||||
Task Download( IRepositoryPackage package, IProgress<FileDownloadProgress> progressSink );
|
||||
|
||||
Task InstallPack( IRepositoryPackage package, IProgress<PackInstallProgress> progressSink );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Api
|
||||
{
|
||||
internal static Api ParseFrom( XElement arg )
|
||||
{
|
||||
return new Api();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Board
|
||||
{
|
||||
internal static Board ParseFrom( XElement arg )
|
||||
{
|
||||
return new Board();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Component
|
||||
{
|
||||
internal static Component ParseFrom( XElement arg )
|
||||
{
|
||||
return new Component();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Condition
|
||||
{
|
||||
internal static Condition ParseFrom( XElement arg )
|
||||
{
|
||||
return new Condition();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
class DebugAccessSequence
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class DeviceFamily
|
||||
{
|
||||
internal static DeviceFamily ParseFrom( XElement arg )
|
||||
{
|
||||
return new DeviceFamily();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Example
|
||||
{
|
||||
public static Example ParseFrom( XElement element )
|
||||
{
|
||||
return new Example();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Generator
|
||||
{
|
||||
internal static Generator ParseFrom( XElement arg )
|
||||
{
|
||||
return new Generator( );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Keyword
|
||||
{
|
||||
internal static Keyword ParseFrom( XElement keyword )
|
||||
{
|
||||
return new Keyword();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
// Unfortunately the officially published schema has circular group definitions
|
||||
// that XSD.exe can't handle. Furthermore, some of the officially posted and
|
||||
// "validated" PDSC files don't conform to the schema. In particular, they
|
||||
// have the following issues:
|
||||
// 1) They use DVendor attributes with values that don't match the case
|
||||
// of the official schema XSD and documentation.
|
||||
// 2) They have feature[@n] using a scaled integer notation (i.e. "512K")
|
||||
// 3) Date values are occasionally missing leading 0 digits to match official
|
||||
// XSD:date types. (i.e. "2015-12-1" should be "2015-12-01")
|
||||
//
|
||||
// This class and related classes work around these issues by Manually handling
|
||||
// the deserialization and processing the offending nodes more liberally.
|
||||
public class Package
|
||||
{
|
||||
public Package( )
|
||||
{
|
||||
Releases = new List<Release>();
|
||||
Keywords = new List<Keyword>();
|
||||
Generators = new List<Generator>();
|
||||
Devices = new List<DeviceFamily>();
|
||||
Boards = new List<Board>();
|
||||
Taxonomy = new List<TaxonomyDescription>();
|
||||
Apis = new List<Api>();
|
||||
Conditions = new List<Condition>();
|
||||
Examples = new List<Example>();
|
||||
Components = new List<Component>();
|
||||
}
|
||||
|
||||
public SemanticVersion SchemaVersion { get; set; }
|
||||
public string Vendor { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public Uri Url {get; set; }
|
||||
public string SupportContact { get; set; }
|
||||
public string License { get; set; }
|
||||
|
||||
public IList<Release> Releases { get; }
|
||||
public IList<Keyword> Keywords { get; }
|
||||
public IList<Generator> Generators { get; }
|
||||
public IList<DeviceFamily> Devices { get; }
|
||||
public IList<Board> Boards { get; }
|
||||
public IList<TaxonomyDescription> Taxonomy { get; }
|
||||
public IList<Api> Apis { get; }
|
||||
public IList<Condition> Conditions { get; }
|
||||
public IList<Example> Examples { get; }
|
||||
public IList<Component> Components { get; }
|
||||
|
||||
public static async Task<Package> LoadFromAsync( string uri )
|
||||
{
|
||||
if( string.IsNullOrWhiteSpace( uri ) )
|
||||
throw new ArgumentException("Path is null or empty", nameof( uri ) );
|
||||
|
||||
var doc = await Task.Run( ()=> XDocument.Load( uri ) );
|
||||
return await ParseFromAsync( doc );
|
||||
}
|
||||
|
||||
public static async Task<Package> ParseFromAsync( string xml )
|
||||
{
|
||||
var doc = await Task.Run( ( ) => XDocument.Parse( xml ) );
|
||||
return await ParseFromAsync( doc );
|
||||
}
|
||||
|
||||
public static Task<Package> ParseFromAsync( XDocument doc )
|
||||
{
|
||||
return Task.Run( ( ) =>
|
||||
{
|
||||
var retVal = new Package( );
|
||||
var pkgElement = doc.Element( "package" );
|
||||
|
||||
retVal.Name = pkgElement.Element( "name" ).Value;
|
||||
retVal.Vendor = pkgElement.Element( "vendor" ).Value;
|
||||
retVal.Description = pkgElement.Element( "description" ).Value;
|
||||
retVal.Url = new Uri( pkgElement.Element( "url" ).Value );
|
||||
retVal.SupportContact = pkgElement.Element( "supportContact" )?.Value;
|
||||
retVal.License = pkgElement.Element( "license" )?.Value;
|
||||
|
||||
ParseElements( pkgElement.Element( "releases" ), "release", retVal.Keywords, Keyword.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "keywords" ), "keyword", retVal.Keywords, Keyword.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "generators" ), "generator", retVal.Generators, Generator.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "devices" ), "family", retVal.Devices, DeviceFamily.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "boards" ), "board", retVal.Boards, Board.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "taxonomy" ), "description", retVal.Taxonomy, TaxonomyDescription.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "apis" ), "api", retVal.Apis, Api.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "conditions" ), "condition", retVal.Conditions, Condition.ParseFrom );
|
||||
ParseElements( pkgElement.Element( "examples" ), "example", retVal.Conditions, Condition.ParseFrom );
|
||||
// TODO: figure out plan to deal with multiple child element types in components element (component, bundle)
|
||||
ParseElements( pkgElement.Element( "components" ), "component", retVal.Components, Component.ParseFrom );
|
||||
|
||||
return retVal;
|
||||
} );
|
||||
}
|
||||
static void ParseElements<T>( XElement containerElement, XName descendantName, IList<T> list, Func<XElement,T> parser )
|
||||
{
|
||||
if( containerElement == null )
|
||||
return;
|
||||
|
||||
foreach( var element in containerElement.Descendants( descendantName ) )
|
||||
{
|
||||
list.Add( parser( element ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Sprache;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
internal static class Parsers
|
||||
{
|
||||
internal static bool IsIntegerScaleChar( char arg )
|
||||
{
|
||||
return arg == 'k'
|
||||
|| arg == 'K'
|
||||
|| arg == 'm'
|
||||
|| arg == 'M';
|
||||
}
|
||||
|
||||
internal static Parser<int> Integer( int minDigits, int maxDigitis )
|
||||
{
|
||||
return from value in Parse.Digit.Repeat( minDigits, maxDigitis ).Text( )
|
||||
select int.Parse( value );
|
||||
}
|
||||
|
||||
// Official W3C XSD specs require 2 digits for the month and day
|
||||
// However, many PDSC files in the wild only have one, thus this
|
||||
// parser handles the incorrectly formed dates
|
||||
internal static Parser<DateTime> DateTime = from year in Integer( 4, 4 )
|
||||
from sep in Parse.Char( '-' )
|
||||
from month in Integer( 1, 2 )
|
||||
from sep2 in Parse.Char( '-' )
|
||||
from day in Integer( 1, 2 )
|
||||
select new DateTime( year, month, day );
|
||||
|
||||
internal static Parser<double> Double = from value in Parse.Decimal
|
||||
select double.Parse( value, CultureInfo.CurrentCulture );
|
||||
|
||||
internal static Parser<double> ScaledInteger = from value in Parse.Digit.AtLeastOnce( ).Text( )
|
||||
from scale in ScaledIntMultiplier
|
||||
select ( double )int.Parse( value ) * scale;
|
||||
|
||||
static Parser<int> ScaledIntMultiplier = Parse.Chars( 'k', 'K' ).Return( 1024 )
|
||||
.Or( Parse.Chars( 'm', 'M' ).Return( 1024 * 1024 ) )
|
||||
.Or( Parse.Return( 1 ) );
|
||||
|
||||
static Parser<double> NonConformantDecimal = ScaledInteger.Or( Double );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class Release
|
||||
{
|
||||
|
||||
public static Release ParseFrom( XElement release )
|
||||
{
|
||||
return new Release();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack.PackDescription
|
||||
{
|
||||
public class TaxonomyDescription
|
||||
{
|
||||
internal static TaxonomyDescription ParseFrom( XElement arg )
|
||||
{
|
||||
return new TaxonomyDescription();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
/// <summary>Contains the contents of a CMSIS-Pack index</summary>
|
||||
/// <remarks>
|
||||
/// The source of the index content may be loaded from a file, a URL
|
||||
/// or provided programatically to the constructor.
|
||||
/// </remarks>
|
||||
public class PackIndex
|
||||
{
|
||||
/// <summary>Default URI for the pack index</summary>
|
||||
public const string DefaultIndexUriPath = "http://www.keil.com/pack/index.idx";
|
||||
|
||||
public PackIndex( )
|
||||
{
|
||||
}
|
||||
|
||||
public PackIndex( IEnumerable<IPackIndexEntry> packs )
|
||||
{
|
||||
Packs_.AddRange( packs );
|
||||
}
|
||||
|
||||
/// <summary>Enumeration of the Packs listed in the Index</summary>
|
||||
public IEnumerable<IPackIndexEntry> Packs { get { return Packs_.AsReadOnly( ); } }
|
||||
private readonly List<IPackIndexEntry> Packs_ = new List<IPackIndexEntry>();
|
||||
|
||||
/// <summary>Download and parse the index file from the Default location <see cref="DefaultIndexUriPath"/></summary>
|
||||
/// <returns>Task for the Asynchronous operation</returns>
|
||||
public Task LoadAsync( )
|
||||
{
|
||||
return LoadAsync( new Uri( DefaultIndexUriPath ) );
|
||||
}
|
||||
|
||||
public Task LoadAsync( IProgress<FileDownloadProgress> progressSink )
|
||||
{
|
||||
return LoadAsync( new Uri( DefaultIndexUriPath ), progressSink );
|
||||
}
|
||||
|
||||
/// <summary>Download and parse the index asynchronously from a URL</summary>
|
||||
/// <param name="indexUrl">URL of the index file to download</param>
|
||||
/// <returns>Task for the Asynchronous operation</returns>
|
||||
public async Task LoadAsync( Uri indexUrl )
|
||||
{
|
||||
using( var client = new HttpClient( ) )
|
||||
{
|
||||
var content = await client.GetStringAsync( indexUrl );
|
||||
await ParseAsync( content );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Asynchronously read and parse the index from a file</summary>
|
||||
/// <param name="filePath">Path of the file to load and parse</param>
|
||||
/// <returns>Task for the Asynchronous operation</returns>
|
||||
public async Task LoadAsync( string filePath )
|
||||
{
|
||||
if( string.IsNullOrWhiteSpace( filePath ) )
|
||||
throw new ArgumentException( "Path cannot be null or empty", nameof( filePath ) );
|
||||
|
||||
if( !File.Exists( filePath ) )
|
||||
throw new FileNotFoundException( filePath );
|
||||
|
||||
var content = await Task.Run( ()=>File.ReadAllText( filePath ) );
|
||||
await ParseAsync( content );
|
||||
}
|
||||
|
||||
public Task LoadAsync( Uri uri, IProgress<FileDownloadProgress> progressSink )
|
||||
{
|
||||
using( var webClient = new WebClient() )
|
||||
{
|
||||
var sw = new Stopwatch();
|
||||
webClient.DownloadFileCompleted += ( s, e ) => progressSink.Report( new FileDownloadProgress( uri, sw.Elapsed, -1, -1 ) );
|
||||
webClient.DownloadProgressChanged += ( s, e ) => progressSink.Report( new FileDownloadProgress( uri, sw.Elapsed, e.BytesReceived, e.TotalBytesToReceive ) );
|
||||
sw.Start( );
|
||||
return webClient.DownloadFileTaskAsync( uri.Host, uri.LocalPath );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Asynchronously save the index file to the specified file location</summary>
|
||||
/// <param name="filePath">Path of the file to save to</param>
|
||||
/// <returns>Task for the Asynchronous operation</returns>
|
||||
public Task SaveAsync( string filePath )
|
||||
{
|
||||
if( string.IsNullOrWhiteSpace( filePath ) )
|
||||
throw new ArgumentException( "Path cannot be null or empty", nameof( filePath ) );
|
||||
|
||||
return Task.Run( ( ) =>
|
||||
{
|
||||
var dir = Path.GetDirectoryName( filePath );
|
||||
if( dir != null )
|
||||
{
|
||||
if( !Directory.Exists( dir ) )
|
||||
Directory.CreateDirectory( dir );
|
||||
}
|
||||
|
||||
File.WriteAllText( filePath, Content );
|
||||
} );
|
||||
}
|
||||
|
||||
/// <summary>Parses the contents of an index file</summary>
|
||||
/// <param name="indexContent">contents of a CMSIS-PACK index file</param>
|
||||
/// <returns>Task for the Asynchronous operation</returns>
|
||||
public Task ParseAsync( string indexContent )
|
||||
{
|
||||
Packs_.Clear( );
|
||||
Content = indexContent;
|
||||
|
||||
return Task.Run( ()=>
|
||||
{
|
||||
var settings = new XmlReaderSettings
|
||||
{ IgnoreComments = true
|
||||
, IgnoreProcessingInstructions = true
|
||||
, ConformanceLevel = ConformanceLevel.Fragment
|
||||
};
|
||||
|
||||
using( var strm = new StringReader( indexContent ) )
|
||||
using( var rdr = XmlReader.Create( strm, settings ) )
|
||||
{
|
||||
// Despite having an xml doc processing instruction the index file is *NOT*
|
||||
// valid XML. It has multiple pdsc elements at the root, which is invalid
|
||||
// XML. This deals with that by reading the nodes individually rather than
|
||||
// as a whole document.
|
||||
//
|
||||
// skip past the XML declaration and move to the first pdsc element
|
||||
rdr.Read( );
|
||||
rdr.ReadToFollowing( "pdsc" );
|
||||
while( rdr.ReadState != ReadState.EndOfFile )
|
||||
{
|
||||
var pdsc = ( XElement )XNode.ReadFrom( rdr );
|
||||
var pack = new PackIndexEntry( pdsc.Attribute( "url" ).Value
|
||||
, pdsc.Attribute( "name" ).Value
|
||||
, pdsc.Attribute( "version" ).Value
|
||||
);
|
||||
|
||||
Packs_.Add( pack );
|
||||
rdr.ReadToFollowing( "pdsc" );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private string Content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using CMSIS.Pack.PackDescription;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
/// <summary>Reference to a CMSIS-PACK</summary>
|
||||
/// <remarks>
|
||||
/// Packs are listed in a published index (index.idx)
|
||||
/// this class represents a single entry in the
|
||||
/// index.
|
||||
/// </remarks>
|
||||
public class PackIndexEntry
|
||||
: IPackIndexEntry
|
||||
{
|
||||
/// <summary>Creates a new PackIndexEntry from data read out of the index</summary>
|
||||
/// <param name="descriptorUri">Base URI for the pack</param>
|
||||
/// <param name="packName">Name of the pack in VENDOR.NAME form</param>
|
||||
/// <param name="packVersion">Pack version (in semantic Version 2.0 form)</param>
|
||||
public PackIndexEntry( string descriptorUri, string packName, string packVersion )
|
||||
{
|
||||
if( string.IsNullOrWhiteSpace( descriptorUri ) )
|
||||
throw new ArgumentException( "Non empty string required", nameof( descriptorUri ) );
|
||||
|
||||
if( string.IsNullOrWhiteSpace( packName ) )
|
||||
throw new ArgumentException( "Non empty string required", nameof( packName ) );
|
||||
|
||||
if( string.IsNullOrWhiteSpace( packVersion ) )
|
||||
throw new ArgumentException( "Non empty string required", nameof( packVersion ) );
|
||||
|
||||
Url = CreateUriWithTrailingSeperator( descriptorUri );
|
||||
PdscName = packName;
|
||||
var parts = PdscName.Trim().Split( '.' );
|
||||
if( parts.Length != 3 )
|
||||
throw new ArgumentException( "Invalid pack name format", nameof( packName ) );
|
||||
|
||||
Vendor = parts[ 0 ];
|
||||
Name = parts[ 1 ];
|
||||
if( !SemanticVersion.TryParse( packVersion, out Version_ ) )
|
||||
throw new ArgumentException( "Invalid semantic version provided", nameof( packVersion ) );
|
||||
}
|
||||
|
||||
/// <summary>File name of the pack file this reference is for</summary>
|
||||
/// <remarks>
|
||||
/// The file name is of the form: VENDOR.NAME.VERSION.pack
|
||||
/// </remarks>
|
||||
public string PackName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.ChangeExtension( PdscName, Version + ".pack" );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Vendor name parsed out of the PackName from the index</summary>
|
||||
public string Vendor { get; private set; }
|
||||
|
||||
/// <summary>Name of the pack parsed out of the Pack name from the index</summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>Name of the PDSC file for this pack</summary>
|
||||
/// <remarks>
|
||||
/// The PDSC filename takes the form: VENDOR.NAME.pdsc
|
||||
/// </remarks>
|
||||
public string PdscName { get; private set; }
|
||||
|
||||
/// <summary>Full URL of the Package Description (PDSC) file for this pack</summary>
|
||||
public Uri PdscUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Uri( Url, PdscName );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>FULL URL of the Package file for this pack</summary>
|
||||
public Uri PackUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Uri( Url, PackName );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Base URI for this pack read from the index</summary>
|
||||
public Uri Url { get; private set; }
|
||||
|
||||
/// <summary>Version of the pack</summary>
|
||||
public SemanticVersion Version { get { return Version_; } }
|
||||
private readonly SemanticVersion Version_;
|
||||
|
||||
public string LocalPath
|
||||
{
|
||||
get { return Path.Combine( Vendor, Name, Version.ToString( ) ); }
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the contents of the Package Description file</summary>
|
||||
/// <returns>string containing the XML content of the description</returns>
|
||||
public async Task<string> GetPackageDescriptionDocumentAsync()
|
||||
{
|
||||
using( var client = new HttpClient( ) )
|
||||
{
|
||||
client.BaseAddress = Url;
|
||||
return await client.GetStringAsync( PdscName );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Asynchronously download and parse the package description file for this pack</summary>
|
||||
/// <returns>parsed package instance for the package description</returns>
|
||||
public async Task<Package> GetPackageDescriptionAsync( )
|
||||
{
|
||||
var xml = await GetPackageDescriptionDocumentAsync( );
|
||||
return await Package.ParseFromAsync( xml );
|
||||
}
|
||||
|
||||
private static Uri CreateUriWithTrailingSeperator( string descriptorUri )
|
||||
{
|
||||
var baseUri = new UriBuilder( descriptorUri );
|
||||
baseUri.Path = baseUri.Path.TrimEnd( '\\' );
|
||||
baseUri.Path = baseUri.Path.TrimEnd( '/' );
|
||||
baseUri.Path = baseUri.Path + '/';
|
||||
|
||||
return baseUri.Uri;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
public struct PackInstallProgress
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
public class PackRepository
|
||||
: IRepository
|
||||
{
|
||||
public PackRepository( Uri source, string localPath )
|
||||
{
|
||||
SourceUri = source;
|
||||
LocalPath = localPath;
|
||||
WebRoot = Path.Combine( LocalPath, ".Web" );
|
||||
DownloadRoot = Path.Combine( LocalPath, ".Download" );
|
||||
PackIdxWatcher = new FileSystemWatcher( LocalPath, "pack.idx" );
|
||||
PackIdxWatcher.Changed += ( s, e ) => Updated( this, new RepositoryUpdateEventArgs( ) );
|
||||
}
|
||||
|
||||
public PackRepository( string localPath )
|
||||
: this( new Uri( PackIndex.DefaultIndexUriPath ), localPath )
|
||||
{
|
||||
}
|
||||
|
||||
public DateTime LastUpdatedTimeUTC
|
||||
{
|
||||
get { return File.GetLastWriteTimeUtc( Path.Combine( LocalPath, "pack.idx" ) ); }
|
||||
}
|
||||
|
||||
public string WebRoot { get; }
|
||||
|
||||
public string DownloadRoot { get; }
|
||||
|
||||
public Uri SourceUri { get; }
|
||||
|
||||
public string LocalPath { get; }
|
||||
|
||||
public event EventHandler<RepositoryUpdateEventArgs> Updated = delegate { };
|
||||
|
||||
public IEnumerable<IRepositoryPackage> Packs => Packs_.AsEnumerable( );
|
||||
private List<IRepositoryPackage> Packs_;
|
||||
|
||||
public Task Download( IRepositoryPackage package, IProgress<FileDownloadProgress> progressSink )
|
||||
{
|
||||
throw new NotImplementedException( );
|
||||
}
|
||||
|
||||
public Task InstallPack( IRepositoryPackage package, IProgress<PackInstallProgress> progressSink )
|
||||
{
|
||||
throw new NotImplementedException( );
|
||||
}
|
||||
|
||||
public async Task LoadFromLocal()
|
||||
{
|
||||
Updated( this, new RepositoryUpdateEventArgs( RepositoryState.DownloadingIndex, null ) );
|
||||
Packs_ = new List<IRepositoryPackage>( );
|
||||
var index = new PackIndex( );
|
||||
await index.LoadAsync( Path.Combine( WebRoot, "index.idx" ) );
|
||||
foreach( var pack in index.Packs )
|
||||
{
|
||||
var repositoryPack = new RepositoryPackage( this, pack, await GetInstallState( pack ) );
|
||||
Packs_.Add( repositoryPack );
|
||||
}
|
||||
}
|
||||
|
||||
public Task UpdateLocalFromSource( )
|
||||
{
|
||||
return Task.FromResult<object>( null );
|
||||
}
|
||||
|
||||
private Task<PackInstallState> GetInstallState( IPackIndexEntry pack )
|
||||
{
|
||||
return Task.Run( ( ) =>
|
||||
{
|
||||
var retVal = PackInstallState.AvailableForDownload;
|
||||
if( File.Exists( Path.Combine( DownloadRoot, pack.PackName ) ) )
|
||||
retVal = PackInstallState.Downloaded;
|
||||
|
||||
if( File.Exists( Path.Combine( LocalPath, pack.LocalPath, pack.PdscName ) ) )
|
||||
retVal = PackInstallState.Installed;
|
||||
|
||||
return retVal;
|
||||
} );
|
||||
}
|
||||
|
||||
private readonly FileSystemWatcher PackIdxWatcher;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CMSIS.Pack")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CMSIS.Pack")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0fc7a2b0-1a23-456b-b17e-0afbc0034a67")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using CMSIS.Pack.PackDescription;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
class RepositoryPackage
|
||||
: IRepositoryPackage
|
||||
{
|
||||
internal RepositoryPackage( IRepository repository, IPackIndexEntry details, PackInstallState installState )
|
||||
{
|
||||
if( repository == null )
|
||||
throw new ArgumentNullException( nameof( repository ) );
|
||||
|
||||
if( details == null )
|
||||
throw new ArgumentNullException( nameof( details ) );
|
||||
|
||||
Repository = repository;
|
||||
Details_ = details;
|
||||
InstallState = installState;
|
||||
}
|
||||
|
||||
public IPackIndexEntry Details
|
||||
{
|
||||
get { return Details_; }
|
||||
}
|
||||
private readonly IPackIndexEntry Details_;
|
||||
|
||||
public IRepository Repository { get; private set; }
|
||||
|
||||
public PackInstallState InstallState { get; private set; }
|
||||
|
||||
public string PackName
|
||||
{
|
||||
get { return Details_.PackName; }
|
||||
}
|
||||
|
||||
public string Vendor
|
||||
{
|
||||
get { return Details_.Vendor; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return Details_.Name; }
|
||||
}
|
||||
|
||||
public string PdscName
|
||||
{
|
||||
get { return Details_.PdscName; }
|
||||
}
|
||||
|
||||
public Uri PdscUrl
|
||||
{
|
||||
get { return Details_.PdscUrl; }
|
||||
}
|
||||
|
||||
public Uri PackUrl
|
||||
{
|
||||
get { return Details_.PackUrl; }
|
||||
}
|
||||
|
||||
public Uri Url
|
||||
{
|
||||
get { return Details_.Url; }
|
||||
}
|
||||
|
||||
public string LocalPath
|
||||
{
|
||||
get { return Details_.LocalPath; }
|
||||
}
|
||||
|
||||
public SemanticVersion Version
|
||||
{
|
||||
get { return Details_.Version; }
|
||||
}
|
||||
|
||||
public async Task<string> GetPackageDescriptionDocumentAsync( )
|
||||
{
|
||||
using( var strm = File.OpenText( Path.Combine( Repository.WebRoot, PdscName ) ) )
|
||||
{
|
||||
return await strm.ReadToEndAsync( );
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Package> GetPackageDescriptionAsync( )
|
||||
{
|
||||
string content = await GetPackageDescriptionDocumentAsync( );
|
||||
return await Package.ParseFromAsync( content );
|
||||
}
|
||||
|
||||
public async Task Download( IProgress<FileDownloadProgress> progressSink )
|
||||
{
|
||||
if( InstallState == PackInstallState.Downloaded )
|
||||
return;
|
||||
|
||||
if( InstallState != PackInstallState.AvailableForDownload )
|
||||
throw new InvalidOperationException( );
|
||||
|
||||
InstallState = PackInstallState.Downloading;
|
||||
try
|
||||
{
|
||||
await Repository.Download( this, progressSink );
|
||||
}
|
||||
catch
|
||||
{
|
||||
InstallState = PackInstallState.AvailableForDownload;
|
||||
throw;
|
||||
}
|
||||
InstallState = PackInstallState.Downloaded;
|
||||
}
|
||||
|
||||
public async Task InstallPack( IProgress<PackInstallProgress> progressSink )
|
||||
{
|
||||
if( InstallState == PackInstallState.Installed )
|
||||
return;
|
||||
|
||||
if( InstallState != PackInstallState.Downloaded )
|
||||
throw new InvalidOperationException( );
|
||||
|
||||
InstallState = PackInstallState.Installing;
|
||||
try
|
||||
{
|
||||
await Repository.InstallPack( this, progressSink );
|
||||
}
|
||||
catch
|
||||
{
|
||||
InstallState = PackInstallState.Downloaded;
|
||||
throw;
|
||||
}
|
||||
InstallState = PackInstallState.Downloaded;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
public class RepositoryUpdateEventArgs
|
||||
: EventArgs
|
||||
{
|
||||
public RepositoryUpdateEventArgs( )
|
||||
: this( RepositoryState.Idle, null )
|
||||
{
|
||||
}
|
||||
|
||||
public RepositoryUpdateEventArgs( RepositoryState state, IPackIndexEntry pack )
|
||||
{
|
||||
if( pack == null && ( state != RepositoryState.Idle ) && (state != RepositoryState.DownloadingIndex ) )
|
||||
throw new ArgumentNullException( nameof( pack ), "pack cannot be null for states other than idle" );
|
||||
|
||||
if( ( ( state == RepositoryState.Idle) || ( state == RepositoryState.DownloadingIndex ) ) && pack != null )
|
||||
throw new ArgumentException( "pack must be null for this state", nameof( pack ) );
|
||||
|
||||
State = state;
|
||||
Pack = pack;
|
||||
}
|
||||
|
||||
public RepositoryState State { get; private set; }
|
||||
public IPackIndexEntry Pack { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,399 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace CMSIS.Pack
|
||||
{
|
||||
/// <summary>Version structure for versions based on Semantic Versioning v2.0 as defined by http://semver.org </summary>
|
||||
/// <remarks>
|
||||
/// This class implements creating, parsing and comparing semantic version values. In
|
||||
/// addition to the standard support, this class includes an additional optional optimization
|
||||
/// where parsing a version string can assume a default patch value of 0 if none is specified.
|
||||
/// According to the formal Semantic Versioning v2.0 spec. the patch value is required, however
|
||||
/// some real world applications allow the looser definition.
|
||||
/// </remarks>
|
||||
public struct SemanticVersion
|
||||
: IComparable
|
||||
, IComparable<SemanticVersion>
|
||||
, IEquatable<SemanticVersion>
|
||||
{
|
||||
/// <summary>Constructs a semantic version from its independent parts</summary>
|
||||
/// <param name="major">Major version number</param>
|
||||
/// <param name="minor">Minor Version number</param>
|
||||
/// <param name="patch">Patch version number</param>
|
||||
/// <param name="preReleaseParts">Array of individual pre-release parts (not including the separating '.')</param>
|
||||
/// <param name="metadataParts">Array of individual Build Metadata parts (not including the separating '.')</param>
|
||||
public SemanticVersion( int major, int minor, int patch, string[] preReleaseParts, string[] metadataParts)
|
||||
{
|
||||
if( major < 0 )
|
||||
throw new ArgumentOutOfRangeException( nameof( major ) );
|
||||
|
||||
if( minor < 0 )
|
||||
throw new ArgumentOutOfRangeException( nameof( minor ) );
|
||||
|
||||
if( patch < 0 )
|
||||
throw new ArgumentOutOfRangeException( nameof( patch ) );
|
||||
|
||||
Major_ = major;
|
||||
Minor_ = minor;
|
||||
Patch_ = patch;
|
||||
PreReleaseParts_ = preReleaseParts ?? new string[0];
|
||||
BuildMetadata_ = metadataParts ?? new string[0];
|
||||
|
||||
// Validate each part conforms to an "identifier" as defined by the spec
|
||||
if(!ValidateIdentifierParts( PreReleaseParts_ ) )
|
||||
throw new ArgumentException( "Invalid identifier for pre-release part", nameof( preReleaseParts ) );
|
||||
|
||||
if( !ValidateIdentifierParts( BuildMetadata_ ) )
|
||||
throw new ArgumentException( "Invalid identifier for build metadata part", nameof( metadataParts ) );
|
||||
|
||||
HashCode = null;
|
||||
}
|
||||
|
||||
/// <summary>Constructs a semantic version from its independent parts</summary>
|
||||
/// <param name="major">Major version number</param>
|
||||
/// <param name="minor">Minor Version number</param>
|
||||
/// <param name="patch">Patch version number</param>
|
||||
public SemanticVersion( int major, int minor, int patch )
|
||||
: this( major
|
||||
, minor
|
||||
, patch
|
||||
, null
|
||||
, null
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode( )
|
||||
{
|
||||
// HashCode is the cached result value of the computed hash code determined
|
||||
// from the other read-only fields and therefore does not participate in the
|
||||
// computation of the hash.
|
||||
#pragma warning disable RECS0025 // Non-readonly field referenced in 'GetHashCode()'
|
||||
// ReSharper disable NonReadonlyFieldInGetHashCode
|
||||
if( !HashCode.HasValue )
|
||||
HashCode = ComputeHashCode( );
|
||||
|
||||
return HashCode.Value;
|
||||
// ReSharper restore NonReadonlyFieldInGetHashCode
|
||||
#pragma warning restore RECS0025 // Non-readonly field referenced in 'GetHashCode()'
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
if( !( obj is SemanticVersion ) )
|
||||
return false;
|
||||
|
||||
return Equals( (SemanticVersion)obj );
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals( SemanticVersion other )
|
||||
{
|
||||
return 0 == CompareTo( other );
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int CompareTo( object obj )
|
||||
{
|
||||
if( !( obj is SemanticVersion ) )
|
||||
throw new ArgumentException();
|
||||
|
||||
return CompareTo( ( SemanticVersion )obj );
|
||||
}
|
||||
|
||||
// Precedence Rules:
|
||||
// Paraphrased From http://semver.org/ Section 11
|
||||
// Precedence is determined by the first difference when comparing each of these
|
||||
// identifiers from left to right as follows:
|
||||
// 1) Major, minor, and patch versions are always compared numerically.
|
||||
// Example: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1.
|
||||
// 2) When major, minor, and patch are equal, a pre-release version has lower
|
||||
// precedence than a normal version.
|
||||
// Example: 1.0.0-alpha < 1.0.0.
|
||||
// 3) Precedence for two pre-release versions with the same major, minor, and
|
||||
// patch version MUST be determined by comparing each dot separated identifier
|
||||
// from left to right until a difference is found as follows:
|
||||
// a) identifiers consisting of only digits are compared numerically
|
||||
// b) identifiers with letters or hyphens are compared lexically in ASCII sort order.
|
||||
// c) Numeric identifiers always have lower precedence than non-numeric identifiers.
|
||||
// d) A larger set of pre-release fields has a higher precedence than a smaller set,
|
||||
// if all of the preceding identifiers are equal.
|
||||
// Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.
|
||||
/// <inheritdoc/>
|
||||
public int CompareTo( SemanticVersion other )
|
||||
{
|
||||
// Rule #1
|
||||
var retVal = Major.CompareTo( other.Major );
|
||||
if( retVal != 0 )
|
||||
return retVal;
|
||||
|
||||
retVal = Minor.CompareTo( other.Minor );
|
||||
if( retVal != 0 )
|
||||
return retVal;
|
||||
|
||||
retVal = Patch.CompareTo( other.Patch );
|
||||
if( retVal != 0 )
|
||||
return retVal;
|
||||
|
||||
// Rule #2
|
||||
if( PreReleaseParts.Count == 0 && other.PreReleaseParts.Count == 0 )
|
||||
return 0;
|
||||
|
||||
if( PreReleaseParts.Count == 0 )
|
||||
return 1;
|
||||
|
||||
if( other.PreReleaseParts.Count == 0 )
|
||||
return -1;
|
||||
|
||||
// Rules 3.a-c
|
||||
var partCount = Math.Min( PreReleaseParts.Count, other.PreReleaseParts.Count );
|
||||
for( var i =0; i< partCount; ++i )
|
||||
{
|
||||
// rule 3.c
|
||||
retVal = string.Compare( PreReleaseParts[ i ], other.PreReleaseParts[ i ], StringComparison.Ordinal );
|
||||
if( retVal == 0 )
|
||||
continue;
|
||||
|
||||
// Rule 3.a
|
||||
int left,right;
|
||||
if( !int.TryParse( PreReleaseParts[i], out left )
|
||||
|| !int.TryParse( other.PreReleaseParts[ i ], out right )
|
||||
)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
return left.CompareTo( right );
|
||||
}
|
||||
|
||||
// Rule #3.d
|
||||
return PreReleaseParts.Count.CompareTo( other.PreReleaseParts.Count );
|
||||
}
|
||||
|
||||
/// <summary>Indicates if this version is a development version (e.g. Major Version == 0 )</summary>
|
||||
public bool IsDevelopment { get { return Major_ == 0; } }
|
||||
|
||||
/// <summary>Indicates if this version is a pre-release version (e.g. IsDevelopment or Has pre-release parts following the Patch)</summary>
|
||||
public bool IsPrerelease { get { return IsDevelopment || PreReleaseParts.Count > 0; } }
|
||||
|
||||
/// <summary>Indicates if this is a valid version</summary>
|
||||
public bool IsValid { get { return Major_ >= 0 && Minor_ >=0 && Patch_ >= 0; } }
|
||||
|
||||
/// <summary>Major version number</summary>
|
||||
public int Major { get { return Major_; } }
|
||||
private readonly int Major_;
|
||||
|
||||
/// <summary>Minor version number</summary>
|
||||
public int Minor { get { return Minor_; } }
|
||||
private readonly int Minor_;
|
||||
|
||||
/// <summary>Patch version number</summary>
|
||||
public int Patch { get { return Patch_; } }
|
||||
private readonly int Patch_;
|
||||
|
||||
/// <summary>List of identifier parts forming the pre-release value</summary>
|
||||
/// <remarks>
|
||||
/// Pre-release values are optional and follow the patch with a '-'. The pre-release
|
||||
/// value can consist of multiple parts separated by a '.', this list contains the
|
||||
/// individual parts without the leading '-' or separating '.'.
|
||||
/// </remarks>
|
||||
public IReadOnlyList<string> PreReleaseParts
|
||||
{
|
||||
get
|
||||
{
|
||||
if( PreReleaseParts_ == null )
|
||||
return new string[ 0 ];
|
||||
|
||||
return Array.AsReadOnly( PreReleaseParts_ );
|
||||
}
|
||||
}
|
||||
private readonly string[ ] PreReleaseParts_;
|
||||
|
||||
/// <summary>List of identifier parts forming the build Metadata value</summary>
|
||||
/// <remarks>
|
||||
/// Metadata values are optional and follow the patch with a '+'. The Metadata
|
||||
/// value can consist of multiple parts separated by a '.', this list contains
|
||||
/// the individual parts without the leading '+' or separating '.'.
|
||||
/// </remarks>
|
||||
public IReadOnlyList<string> BuildMetadata
|
||||
{
|
||||
get
|
||||
{
|
||||
if( BuildMetadata_ == null )
|
||||
return new string[ 0 ];
|
||||
|
||||
return Array.AsReadOnly( BuildMetadata_ );
|
||||
}
|
||||
}
|
||||
private readonly string[ ] BuildMetadata_;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString( )
|
||||
{
|
||||
return ToString( true );
|
||||
}
|
||||
|
||||
/// <summary>Creates a valid semantic version string from the component values of this version</summary>
|
||||
/// <param name="includeBuildMetadata">Flag to indicate if the Build Metadata should be included</param>
|
||||
/// <returns>Semantic version string for this version</returns>
|
||||
/// <remarks>
|
||||
/// The <paramref name="includeBuildMetadata"/> parameter is used to control whether the build information
|
||||
/// portion of the version is included or not. The Build Metadata is the only portion of the semantic
|
||||
/// version that does not participate in precedence evaluation for comparing versions.
|
||||
/// </remarks>
|
||||
public string ToString( bool includeBuildMetadata)
|
||||
{
|
||||
var bldr = new StringBuilder( string.Format( CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch ) );
|
||||
if( PreReleaseParts.Count > 0 )
|
||||
{
|
||||
bldr.Append( '-' );
|
||||
bldr.Append( string.Join( ".", PreReleaseParts ) );
|
||||
}
|
||||
|
||||
if( BuildMetadata.Count > 0 && includeBuildMetadata)
|
||||
{
|
||||
bldr.Append( '+' );
|
||||
bldr.Append( string.Join( ".", BuildMetadata ) );
|
||||
}
|
||||
|
||||
return bldr.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Parse a semantic version string into it's component parts</summary>
|
||||
/// <param name="versionString">String containing the version to parse</param>
|
||||
/// <returns>Parsed version details</returns>
|
||||
public static SemanticVersion Parse( string versionString )
|
||||
{
|
||||
return Parse( versionString, false );
|
||||
}
|
||||
|
||||
/// <summary>Parse a semantic version string into it's component parts</summary>
|
||||
/// <param name="versionString">String containing the version to parse</param>
|
||||
/// <param name="patchOptional">Flag indicating non-standard optional default (0) for the patch if not present</param>
|
||||
/// <returns>Parsed version details</returns>
|
||||
/// <remarks>
|
||||
/// This overload of Parse allows for a non-standard version where the Patch value
|
||||
/// defaults to 0 if not present, instead of triggering an exception.
|
||||
/// </remarks>
|
||||
public static SemanticVersion Parse( string versionString, bool patchOptional )
|
||||
{
|
||||
var match = SemVersionRegEx.Match( versionString );
|
||||
if( !match.Success )
|
||||
throw new FormatException();
|
||||
|
||||
var major = int.Parse( match.Groups["Major"].Value );
|
||||
var minor = int.Parse( match.Groups["Minor"].Value );
|
||||
int patch = 0;
|
||||
var patchGroup = match.Groups["Patch"];
|
||||
if( !patchOptional || patchGroup.Success )
|
||||
patch = int.Parse( patchGroup.Value );
|
||||
|
||||
var preReleaseGroup = match.Groups["PreRelease"];
|
||||
var preReleaseParts = new string[ 0 ];
|
||||
if( preReleaseGroup.Success )
|
||||
preReleaseParts = preReleaseGroup.Value.Split( '.' );
|
||||
|
||||
var metadataGroup = match.Groups["Metadata"];
|
||||
var metadataParts = new string[ 0 ];
|
||||
if( metadataGroup.Success )
|
||||
metadataParts = metadataGroup.Value.Split( '.' );
|
||||
|
||||
return new SemanticVersion( major, minor, patch, preReleaseParts, metadataParts );
|
||||
}
|
||||
|
||||
/// <summary>Attempts to parse a version string into a new SemanticVersion instance</summary>
|
||||
/// <param name="versionString">String to parse</param>
|
||||
/// <param name="version">Version instance to construct</param>
|
||||
/// <returns>true if the string is a valid semantic version string that was successfully parsed into <paramref name="version"/></returns>
|
||||
public static bool TryParse( string versionString, out SemanticVersion version )
|
||||
{
|
||||
version = new SemanticVersion();
|
||||
var match = SemVersionRegEx.Match( versionString );
|
||||
if( !match.Success )
|
||||
return false;
|
||||
|
||||
int major,minor,patch;
|
||||
|
||||
if( !int.TryParse( match.Groups["Major"].Value, out major ) )
|
||||
return false;
|
||||
|
||||
if( !int.TryParse( match.Groups["Minor"].Value, out minor ) )
|
||||
return false;
|
||||
|
||||
if( !int.TryParse( match.Groups["Patch"].Value, out patch ) )
|
||||
return false;
|
||||
|
||||
var preReleaseGroup = match.Groups[ "PreRelease" ];
|
||||
var preReleaseParts = new string[ 0 ];
|
||||
if( preReleaseGroup.Success )
|
||||
preReleaseParts = preReleaseGroup.Value.Split( '.' );
|
||||
|
||||
var metadataGroup = match.Groups[ "Metadata" ];
|
||||
var metadataParts = new string[ 0 ];
|
||||
if( metadataGroup.Success )
|
||||
metadataParts = metadataGroup.Value.Split( '.' );
|
||||
|
||||
version = new SemanticVersion(major, minor, patch, preReleaseParts, metadataParts );
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Compares two <see cref="SemanticVersion"/> instances for equality</summary>
|
||||
/// <param name="lhs">Left hand side of the comparison</param>
|
||||
/// <param name="rhs">Right hand side of the comparison</param>
|
||||
/// <returns><see langword="true"/> if the two versions are equivalent</returns>
|
||||
public static bool operator==(SemanticVersion lhs, SemanticVersion rhs)
|
||||
{
|
||||
return lhs.Equals( rhs );
|
||||
}
|
||||
|
||||
/// <summary>Compares two <see cref="SemanticVersion"/> instances for inequality</summary>
|
||||
/// <param name="lhs">Left hand side of the comparison</param>
|
||||
/// <param name="rhs">Right hand side of the comparison</param>
|
||||
/// <returns><see langword="true"/> if the two versions are not equivalent</returns>
|
||||
public static bool operator !=( SemanticVersion lhs, SemanticVersion rhs )
|
||||
{
|
||||
return !lhs.Equals( rhs );
|
||||
}
|
||||
|
||||
private static bool ValidateIdentifierParts( IEnumerable< string > metadataParts )
|
||||
{
|
||||
var q = from part in metadataParts
|
||||
let match = IdentifierRegEx.Match( part )
|
||||
where !match.Success || match.Index != 0 || match.Length != part.Length
|
||||
select part;
|
||||
return !q.Any();
|
||||
}
|
||||
|
||||
private int ComputeHashCode()
|
||||
{
|
||||
return ToString( false ).GetHashCode( );
|
||||
}
|
||||
|
||||
// this is intentionally not a read-only field
|
||||
// its a private field and used like a C++ mutable.
|
||||
// It caches the HashCode that's expensive to compute
|
||||
// so it is only done once.
|
||||
private int? HashCode;
|
||||
|
||||
private static readonly Regex IdentifierRegEx = new Regex("[1-9A-Za-z-][0-9A-Za-z-]*");
|
||||
|
||||
// see: http://semver.org/
|
||||
// Semantic version is:
|
||||
// Major'.'Minor'.'Patch('-'Identifier('.'Identifier)*)?('+'Identifier('.'Identifier)*)?
|
||||
// Where Major,Minor and Patch match 0|[1-9][0-9]* (0 or a non-leading zero sequence of digits)
|
||||
// Identifier is a sequence of ASCII alphanumerics or '-' without a leading 0
|
||||
// the - signifies the pre-release information and impacts precedence if present
|
||||
// the + signifies the build meta data and has no impact on precedence
|
||||
private const string SemVerRegExPattern = "(?<Major>(0|[1-9][0-9]*))"
|
||||
+ @"\.(?<Minor>(0|[1-9][0-9]*))"
|
||||
+ @"(\.(?<Patch>(0|[1-9][0-9]*)))?"
|
||||
+ @"(-(?<PreRelease>[1-9A-Za-z-][0-9A-Za-z-]*(\.[1-9A-Za-z-][0-9A-Za-z-]*)*))?"
|
||||
+ @"(\+(?<Metadata>[1-9A-Za-z-][0-9A-Za-z-]*(\.[1-9A-Za-z-][0-9A-Za-z-]*)*))?";
|
||||
private static readonly Regex SemVersionRegEx = new Regex(SemVerRegExPattern);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Sprache.JetBrains" version="2.0.0.44" targetFramework="net45" />
|
||||
</packages>
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.24720.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetmfPackInstaller", "NetmfPackInstaller\NetmfPackInstaller.csproj", "{4D6FE417-4296-4C77-8B3E-26976A1F8C08}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CMSIS.Pack", "CMSIS.Pack\CMSIS.Pack.csproj", "{145D7231-C105-41BE-B646-5D400097C744}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4D6FE417-4296-4C77-8B3E-26976A1F8C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D6FE417-4296-4C77-8B3E-26976A1F8C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D6FE417-4296-4C77-8B3E-26976A1F8C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D6FE417-4296-4C77-8B3E-26976A1F8C08}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{145D7231-C105-41BE-B646-5D400097C744}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{145D7231-C105-41BE-B646-5D400097C744}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{145D7231-C105-41BE-B646-5D400097C744}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{145D7231-C105-41BE-B646-5D400097C744}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,8 @@
|
|||
<Application x:Class="NetmfPackInstaller.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
|
@ -0,0 +1,11 @@
|
|||
using System.Windows;
|
||||
|
||||
namespace NetmfPackInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace NetmfPackInstaller
|
||||
{
|
||||
[ValueConversion(typeof(LoadState),typeof(string))]
|
||||
public class LoadStateConverter
|
||||
: MarkupExtension
|
||||
, IValueConverter
|
||||
{
|
||||
public override object ProvideValue( IServiceProvider serviceProvider )
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
|
||||
{
|
||||
var state = (LoadState)value;
|
||||
switch( state )
|
||||
{
|
||||
case LoadState.LoadingIndex:
|
||||
return "Loading Index";
|
||||
case LoadState.ParsingDescriptions:
|
||||
return "Parsing Descriptors";
|
||||
case LoadState.Ready:
|
||||
return "Ready";
|
||||
default:
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
|
||||
{
|
||||
throw new NotSupportedException( );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
<Window x:Class="NetmfPackInstaller.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:NetmfPackInstaller"
|
||||
Title="CMSIS-Pack Viewer"
|
||||
Height="600"
|
||||
Width="800">
|
||||
<Window.Resources>
|
||||
<!-- Higlight pre-release packs in red/italic font -->
|
||||
<Style TargetType="{x:Type DataGridRow}"
|
||||
BasedOn="{StaticResource {x:Type DataGridRow}}">
|
||||
<Setter Property="FontStyle"
|
||||
Value="Normal" />
|
||||
<Setter Property="Foreground"
|
||||
Value="Black" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Version.IsPrerelease}"
|
||||
Value="True">
|
||||
<Setter Property="FontStyle"
|
||||
Value="Italic" />
|
||||
<Setter Property="Foreground"
|
||||
Value="Red" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- Trigger appearance of indeterminate progress while loading the index from the source URL -->
|
||||
<Style x:Key="IndexLoadProgressStyle"
|
||||
TargetType="{x:Type ProgressBar}">
|
||||
<Setter Property="Visibility"
|
||||
Value="Visible" />
|
||||
<Setter Property="Orientation"
|
||||
Value="Horizontal" />
|
||||
<Setter Property="Width"
|
||||
Value="120" />
|
||||
<Setter Property="Height"
|
||||
Value="15" />
|
||||
<Setter Property="IsIndeterminate"
|
||||
Value="True" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding State}"
|
||||
Value="Ready">
|
||||
<Setter Property="Visibility"
|
||||
Value="Collapsed" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<!-- Grouping collection view to group the Packs by Vendor-->
|
||||
<CollectionViewSource x:Key="VendorGroupViewSource"
|
||||
Source="{Binding Packs}">
|
||||
<CollectionViewSource.GroupDescriptions>
|
||||
<PropertyGroupDescription PropertyName="Vendor" />
|
||||
</CollectionViewSource.GroupDescriptions>
|
||||
</CollectionViewSource>
|
||||
|
||||
<!-- Expandalbe group container for vendor groups-->
|
||||
<Style x:Key="VendorGroupContainerStyle"
|
||||
TargetType="{x:Type GroupItem}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type GroupItem}">
|
||||
<Expander IsExpanded="True">
|
||||
<Expander.Header>
|
||||
<Grid>
|
||||
<ContentPresenter />
|
||||
</Grid>
|
||||
</Expander.Header>
|
||||
<ItemsPresenter />
|
||||
</Expander>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Header template for the Vendor group to show "<Vendor> # Pack(s)"-->
|
||||
<DataTemplate x:Key="VendorGroupHeaderTemplate"
|
||||
DataType="GroupItem">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Padding="2"
|
||||
Text="{Binding Name}" />
|
||||
<TextBlock Padding="2"
|
||||
Text="{Binding ItemCount}" />
|
||||
<TextBlock Padding="2"
|
||||
Text="Pack(s)" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<Style x:Key="ToolBarOverflowButtonStyle"
|
||||
TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="OverridesDefaultStyle"
|
||||
Value="true" />
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</Style>
|
||||
<Style x:Key="ImageButton" TargetType="{x:Type Button}">
|
||||
<Setter Property="Opacity"
|
||||
Value="1.0"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=IsEnabled}" Value="false">
|
||||
<Setter Property="Opacity" Value="0.5"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
<DockPanel>
|
||||
<ToolBarPanel DockPanel.Dock="Top"
|
||||
Orientation="Horizontal">
|
||||
<ToolBar ToolBarTray.IsLocked="True" Loaded="ToolBar_Loaded">
|
||||
<Button ToolBar.OverflowMode="Never"
|
||||
Style="{StaticResource ImageButton}"
|
||||
Command="{Binding RefreshIndexCommand}">
|
||||
<Image Source="Refresh.png"
|
||||
Stretch="None" />
|
||||
</Button>
|
||||
</ToolBar>
|
||||
</ToolBarPanel>
|
||||
<StatusBar DockPanel.Dock="Bottom"
|
||||
Height="Auto">
|
||||
<StatusBarItem DockPanel.Dock="Right">
|
||||
<TextBlock Text="{Binding LastUpdated, StringFormat=Last Updated: \{0:g\}}" />
|
||||
</StatusBarItem>
|
||||
<TextBlock Text="{Binding State, Converter={local:LoadStateConverter}}" />
|
||||
<Separator />
|
||||
<ProgressBar Style="{StaticResource ResourceKey=IndexLoadProgressStyle}" />
|
||||
</StatusBar>
|
||||
<DataGrid AutoGenerateColumns="False"
|
||||
ItemsSource="{Binding Source={StaticResource VendorGroupViewSource}}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Vendor"
|
||||
Width="SizeToCells"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding Vendor}" />
|
||||
<DataGridTextColumn Header="Name"
|
||||
Width="SizeToCells"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding Name}" />
|
||||
<DataGridTextColumn Header="Version"
|
||||
Width="SizeToCells"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding Version}" />
|
||||
<DataGridTextColumn Header="InstallState"
|
||||
Width="SizeToCells"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding InstallState}" />
|
||||
<DataGridTextColumn Header="Description"
|
||||
Width="SizeToCells"
|
||||
IsReadOnly="True"
|
||||
Binding="{Binding Description}" />
|
||||
</DataGrid.Columns>
|
||||
<DataGrid.GroupStyle>
|
||||
<GroupStyle ContainerStyle="{StaticResource VendorGroupContainerStyle}"
|
||||
HeaderTemplate="{StaticResource VendorGroupHeaderTemplate}" />
|
||||
</DataGrid.GroupStyle>
|
||||
</DataGrid>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -0,0 +1,40 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using CMSIS.Pack;
|
||||
|
||||
namespace NetmfPackInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow( )
|
||||
{
|
||||
InitializeComponent( );
|
||||
}
|
||||
|
||||
protected override async void OnActivated( System.EventArgs e )
|
||||
{
|
||||
base.OnActivated( e );
|
||||
if( DataContext != null )
|
||||
return;
|
||||
|
||||
var viewModel = new PackRepositoryViewModel( );
|
||||
DataContext = viewModel;
|
||||
await viewModel.LoadAsync( );
|
||||
}
|
||||
|
||||
private void ToolBar_Loaded( object sender, RoutedEventArgs e )
|
||||
{
|
||||
var toolBar = ( ToolBar )sender;
|
||||
foreach( FrameworkElement a in toolBar.Items )
|
||||
ToolBar.SetOverflowMode(a, OverflowMode.Never);
|
||||
|
||||
var overflowGrid = toolBar.Template.FindName( "OverflowGrid", toolBar ) as FrameworkElement;
|
||||
|
||||
if( overflowGrid != null )
|
||||
overflowGrid.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4D6FE417-4296-4C77-8B3E-26976A1F8C08}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NetmfPackInstaller</RootNamespace>
|
||||
<AssemblyName>NetmfPackInstaller</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="GalaSoft.MvvmLight">
|
||||
<HintPath>..\packages\MvvmLightLibs.5.1.1.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GalaSoft.MvvmLight.Extras">
|
||||
<HintPath>..\packages\MvvmLightLibs.5.1.1.0\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GalaSoft.MvvmLight.Platform">
|
||||
<HintPath>..\packages\MvvmLightLibs.5.1.1.0\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="LoadStateConverter.cs" />
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="PackRepositoryViewModel.cs" />
|
||||
<Compile Include="PackReferenceViewModel.cs" />
|
||||
<Compile Include="Properties\Annotations.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CMSIS.Pack\CMSIS.Pack.csproj">
|
||||
<Project>{145d7231-c105-41be-b646-5d400097c744}</Project>
|
||||
<Name>CMSIS.Pack</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Refresh.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,57 @@
|
|||
using CMSIS.Pack;
|
||||
using GalaSoft.MvvmLight;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using CMSIS.Pack.PackDescription;
|
||||
|
||||
namespace NetmfPackInstaller
|
||||
{
|
||||
public enum PackReferenceState
|
||||
{
|
||||
Initialized,
|
||||
DownloadingPdsc,
|
||||
Ready
|
||||
}
|
||||
|
||||
public class PackReferenceViewModel
|
||||
: ViewModelBase
|
||||
{
|
||||
public PackReferenceViewModel( IRepositoryPackage packRef )
|
||||
{
|
||||
if( packRef == null )
|
||||
throw new ArgumentNullException( nameof( packRef ) );
|
||||
|
||||
PackageRef = packRef;
|
||||
State = PackReferenceState.Initialized;
|
||||
}
|
||||
|
||||
public async Task LoadAndParseDescriptionAsync( )
|
||||
{
|
||||
State = PackReferenceState.DownloadingPdsc;
|
||||
|
||||
// get the PDSC async, parse to get description
|
||||
PackageDescription = await PackageRef.GetPackageDescriptionAsync( );
|
||||
State = PackReferenceState.Ready;
|
||||
}
|
||||
|
||||
public PackReferenceState State
|
||||
{
|
||||
get { return State__; }
|
||||
private set
|
||||
{
|
||||
State__ = value;
|
||||
RaisePropertyChanged( );
|
||||
}
|
||||
}
|
||||
private PackReferenceState State__;
|
||||
|
||||
public SemanticVersion Version => PackageRef.Version;
|
||||
public string Name => PackageRef.Name;
|
||||
public string Vendor => PackageRef.Vendor;
|
||||
public string Description => PackageDescription?.Description ?? string.Empty;
|
||||
public PackInstallState InstallState => PackageRef.InstallState;
|
||||
|
||||
private readonly IRepositoryPackage PackageRef;
|
||||
private Package PackageDescription;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
using System.Windows.Input;
|
||||
using CMSIS.Pack;
|
||||
using GalaSoft.MvvmLight;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using GalaSoft.MvvmLight.CommandWpf;
|
||||
|
||||
namespace NetmfPackInstaller
|
||||
{
|
||||
public enum LoadState
|
||||
{
|
||||
LoadingIndex,
|
||||
ParsingDescriptions,
|
||||
Ready,
|
||||
}
|
||||
|
||||
public class PackRepositoryViewModel
|
||||
: ViewModelBase
|
||||
{
|
||||
public PackRepositoryViewModel()
|
||||
{
|
||||
// for now, just hard code location of local repository
|
||||
// and use the default cloud URL
|
||||
Repository = new PackRepository(@"c:\Keil_v5\ARM\Pack");
|
||||
State = LoadState.LoadingIndex;
|
||||
Packs = new ObservableCollection<PackReferenceViewModel>( );
|
||||
RefreshIndexCommand_ = new RelayCommand( RefreshIndexAsync, CanRefreshIndex );
|
||||
}
|
||||
|
||||
internal async Task LoadAsync( )
|
||||
{
|
||||
await Repository.LoadFromLocal( );
|
||||
|
||||
State = LoadState.ParsingDescriptions;
|
||||
foreach( var pack in Repository.Packs )
|
||||
{
|
||||
var packVm = new PackReferenceViewModel( pack );
|
||||
await packVm.LoadAndParseDescriptionAsync( );
|
||||
Packs.Add( packVm );
|
||||
}
|
||||
|
||||
State = LoadState.Ready;
|
||||
}
|
||||
|
||||
public ICommand RefreshIndexCommand
|
||||
{
|
||||
get { return RefreshIndexCommand_; }
|
||||
}
|
||||
private readonly RelayCommand RefreshIndexCommand_;
|
||||
|
||||
public DateTime LastUpdated { get { return Repository.LastUpdatedTimeUTC.ToLocalTime(); } }
|
||||
|
||||
public ObservableCollection<PackReferenceViewModel> Packs { get; private set; }
|
||||
|
||||
public LoadState State
|
||||
{
|
||||
get { return State__; }
|
||||
private set
|
||||
{
|
||||
State__ = value;
|
||||
RaisePropertyChanged( );
|
||||
}
|
||||
}
|
||||
private LoadState State__;
|
||||
|
||||
private bool CanRefreshIndex( )
|
||||
{
|
||||
return State == LoadState.Ready;
|
||||
}
|
||||
|
||||
private async void RefreshIndexAsync( )
|
||||
{
|
||||
await Repository.UpdateLocalFromSource( );
|
||||
}
|
||||
|
||||
private readonly PackRepository Repository;
|
||||
private readonly Dispatcher Dispatcher = Dispatcher.CurrentDispatcher;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,614 @@
|
|||
using System;
|
||||
|
||||
#pragma warning disable 1591
|
||||
// ReSharper disable UnusedMember.Global
|
||||
// ReSharper disable UnusedParameter.Local
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
// ReSharper disable IntroduceOptionalParameters.Global
|
||||
// ReSharper disable MemberCanBeProtected.Global
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace NetmfPackInstaller.Annotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the value of the marked element could be <c>null</c> sometimes,
|
||||
/// so the check for <c>null</c> is necessary before its usage
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [CanBeNull] public object Test() { return null; }
|
||||
/// public void UseTest() {
|
||||
/// var p = Test();
|
||||
/// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class CanBeNullAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the value of the marked element could never be <c>null</c>
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [NotNull] public object Foo() {
|
||||
/// return null; // Warning: Possible 'null' assignment
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class NotNullAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the marked method builds string by format pattern and (optional) arguments.
|
||||
/// Parameter, which contains format string, should be given in constructor. The format string
|
||||
/// should be in <see cref="string.Format(IFormatProvider,string,object[])"/>-like form
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [StringFormatMethod("message")]
|
||||
/// public void ShowError(string message, params object[] args) { /* do something */ }
|
||||
/// public void Foo() {
|
||||
/// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Constructor | AttributeTargets.Method,
|
||||
AllowMultiple = false, Inherited = true)]
|
||||
public sealed class StringFormatMethodAttribute : Attribute
|
||||
{
|
||||
/// <param name="formatParameterName">
|
||||
/// Specifies which parameter of an annotated method should be treated as format-string
|
||||
/// </param>
|
||||
public StringFormatMethodAttribute(string formatParameterName)
|
||||
{
|
||||
FormatParameterName = formatParameterName;
|
||||
}
|
||||
|
||||
public string FormatParameterName { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the function argument should be string literal and match one
|
||||
/// of the parameters of the caller function. For example, ReSharper annotates
|
||||
/// the parameter of <see cref="System.ArgumentNullException"/>
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// public void Foo(string param) {
|
||||
/// if (param == null)
|
||||
/// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class InvokerParameterNameAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the method is contained in a type that implements
|
||||
/// <see cref="System.ComponentModel.INotifyPropertyChanged"/> interface
|
||||
/// and this method is used to notify that some property value changed
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The method should be non-static and conform to one of the supported signatures:
|
||||
/// <list>
|
||||
/// <item><c>NotifyChanged(string)</c></item>
|
||||
/// <item><c>NotifyChanged(params string[])</c></item>
|
||||
/// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
|
||||
/// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
|
||||
/// <item><c>SetProperty{T}(ref T, T, string)</c></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
/// <example><code>
|
||||
/// public class Foo : INotifyPropertyChanged {
|
||||
/// public event PropertyChangedEventHandler PropertyChanged;
|
||||
/// [NotifyPropertyChangedInvocator]
|
||||
/// protected virtual void NotifyChanged(string propertyName) { ... }
|
||||
///
|
||||
/// private string _name;
|
||||
/// public string Name {
|
||||
/// get { return _name; }
|
||||
/// set { _name = value; NotifyChanged("LastName"); /* Warning */ }
|
||||
/// }
|
||||
/// }
|
||||
/// </code>
|
||||
/// Examples of generated notifications:
|
||||
/// <list>
|
||||
/// <item><c>NotifyChanged("Property")</c></item>
|
||||
/// <item><c>NotifyChanged(() => Property)</c></item>
|
||||
/// <item><c>NotifyChanged((VM x) => x.Property)</c></item>
|
||||
/// <item><c>SetProperty(ref myField, value, "Property")</c></item>
|
||||
/// </list>
|
||||
/// </example>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
|
||||
{
|
||||
public NotifyPropertyChangedInvocatorAttribute() { }
|
||||
public NotifyPropertyChangedInvocatorAttribute(string parameterName)
|
||||
{
|
||||
ParameterName = parameterName;
|
||||
}
|
||||
|
||||
public string ParameterName { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Describes dependency between method input and output
|
||||
/// </summary>
|
||||
/// <syntax>
|
||||
/// <p>Function Definition Table syntax:</p>
|
||||
/// <list>
|
||||
/// <item>FDT ::= FDTRow [;FDTRow]*</item>
|
||||
/// <item>FDTRow ::= Input => Output | Output <= Input</item>
|
||||
/// <item>Input ::= ParameterName: Value [, Input]*</item>
|
||||
/// <item>Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
|
||||
/// <item>Value ::= true | false | null | notnull | canbenull</item>
|
||||
/// </list>
|
||||
/// If method has single input parameter, it's name could be omitted.<br/>
|
||||
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same)
|
||||
/// for method output means that the methos doesn't return normally.<br/>
|
||||
/// <c>canbenull</c> annotation is only applicable for output parameters.<br/>
|
||||
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row,
|
||||
/// or use single attribute with rows separated by semicolon.<br/>
|
||||
/// </syntax>
|
||||
/// <examples><list>
|
||||
/// <item><code>
|
||||
/// [ContractAnnotation("=> halt")]
|
||||
/// public void TerminationMethod()
|
||||
/// </code></item>
|
||||
/// <item><code>
|
||||
/// [ContractAnnotation("halt <= condition: false")]
|
||||
/// public void Assert(bool condition, string text) // regular assertion method
|
||||
/// </code></item>
|
||||
/// <item><code>
|
||||
/// [ContractAnnotation("s:null => true")]
|
||||
/// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
|
||||
/// </code></item>
|
||||
/// <item><code>
|
||||
/// // A method that returns null if the parameter is null, and not null if the parameter is not null
|
||||
/// [ContractAnnotation("null => null; notnull => notnull")]
|
||||
/// public object Transform(object data)
|
||||
/// </code></item>
|
||||
/// <item><code>
|
||||
/// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")]
|
||||
/// public bool TryParse(string s, out Person result)
|
||||
/// </code></item>
|
||||
/// </list></examples>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||
public sealed class ContractAnnotationAttribute : Attribute
|
||||
{
|
||||
public ContractAnnotationAttribute([NotNull] string contract)
|
||||
: this(contract, false) { }
|
||||
|
||||
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
|
||||
{
|
||||
Contract = contract;
|
||||
ForceFullStates = forceFullStates;
|
||||
}
|
||||
|
||||
public string Contract { get; private set; }
|
||||
public bool ForceFullStates { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that marked element should be localized or not
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [LocalizationRequiredAttribute(true)]
|
||||
/// public class Foo {
|
||||
/// private string str = "my string"; // Warning: Localizable string
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class LocalizationRequiredAttribute : Attribute
|
||||
{
|
||||
public LocalizationRequiredAttribute() : this(true) { }
|
||||
public LocalizationRequiredAttribute(bool required)
|
||||
{
|
||||
Required = required;
|
||||
}
|
||||
|
||||
public bool Required { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the value of the marked type (or its derivatives)
|
||||
/// cannot be compared using '==' or '!=' operators and <c>Equals()</c>
|
||||
/// should be used instead. However, using '==' or '!=' for comparison
|
||||
/// with <c>null</c> is always permitted.
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [CannotApplyEqualityOperator]
|
||||
/// class NoEquality { }
|
||||
/// class UsesNoEquality {
|
||||
/// public void Test() {
|
||||
/// var ca1 = new NoEquality();
|
||||
/// var ca2 = new NoEquality();
|
||||
/// if (ca1 != null) { // OK
|
||||
/// bool condition = ca1 == ca2; // Warning
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Interface | AttributeTargets.Class |
|
||||
AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class CannotApplyEqualityOperatorAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// When applied to a target attribute, specifies a requirement for any type marked
|
||||
/// with the target attribute to implement or inherit specific type or types.
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
|
||||
/// public class ComponentAttribute : Attribute { }
|
||||
/// [Component] // ComponentAttribute requires implementing IComponent interface
|
||||
/// public class MyComponent : IComponent { }
|
||||
/// </code></example>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
|
||||
[BaseTypeRequired(typeof(Attribute))]
|
||||
public sealed class BaseTypeRequiredAttribute : Attribute
|
||||
{
|
||||
public BaseTypeRequiredAttribute([NotNull] Type baseType)
|
||||
{
|
||||
BaseType = baseType;
|
||||
}
|
||||
|
||||
[NotNull] public Type BaseType { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the marked symbol is used implicitly
|
||||
/// (e.g. via reflection, in external library), so this symbol
|
||||
/// will not be marked as unused (as well as by other usage inspections)
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class UsedImplicitlyAttribute : Attribute
|
||||
{
|
||||
public UsedImplicitlyAttribute()
|
||||
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
|
||||
|
||||
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
|
||||
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
|
||||
|
||||
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
|
||||
: this(ImplicitUseKindFlags.Default, targetFlags) { }
|
||||
|
||||
public UsedImplicitlyAttribute(
|
||||
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
||||
{
|
||||
UseKindFlags = useKindFlags;
|
||||
TargetFlags = targetFlags;
|
||||
}
|
||||
|
||||
public ImplicitUseKindFlags UseKindFlags { get; private set; }
|
||||
public ImplicitUseTargetFlags TargetFlags { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be used on attributes and causes ReSharper
|
||||
/// to not mark symbols marked with such attributes as unused
|
||||
/// (as well as by other usage inspections)
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class MeansImplicitUseAttribute : Attribute
|
||||
{
|
||||
public MeansImplicitUseAttribute()
|
||||
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default) { }
|
||||
|
||||
public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
|
||||
: this(useKindFlags, ImplicitUseTargetFlags.Default) { }
|
||||
|
||||
public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
|
||||
: this(ImplicitUseKindFlags.Default, targetFlags) { }
|
||||
|
||||
public MeansImplicitUseAttribute(
|
||||
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
||||
{
|
||||
UseKindFlags = useKindFlags;
|
||||
TargetFlags = targetFlags;
|
||||
}
|
||||
|
||||
[UsedImplicitly] public ImplicitUseKindFlags UseKindFlags { get; private set; }
|
||||
[UsedImplicitly] public ImplicitUseTargetFlags TargetFlags { get; private set; }
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum ImplicitUseKindFlags
|
||||
{
|
||||
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
|
||||
/// <summary>Only entity marked with attribute considered used</summary>
|
||||
Access = 1,
|
||||
/// <summary>Indicates implicit assignment to a member</summary>
|
||||
Assign = 2,
|
||||
/// <summary>
|
||||
/// Indicates implicit instantiation of a type with fixed constructor signature.
|
||||
/// That means any unused constructor parameters won't be reported as such.
|
||||
/// </summary>
|
||||
InstantiatedWithFixedConstructorSignature = 4,
|
||||
/// <summary>Indicates implicit instantiation of a type</summary>
|
||||
InstantiatedNoFixedConstructorSignature = 8,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify what is considered used implicitly
|
||||
/// when marked with <see cref="MeansImplicitUseAttribute"/>
|
||||
/// or <see cref="UsedImplicitlyAttribute"/>
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum ImplicitUseTargetFlags
|
||||
{
|
||||
Default = Itself,
|
||||
Itself = 1,
|
||||
/// <summary>Members of entity marked with attribute are considered used</summary>
|
||||
Members = 2,
|
||||
/// <summary>Entity marked with attribute and all its members considered used</summary>
|
||||
WithMembers = Itself | Members
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This attribute is intended to mark publicly available API
|
||||
/// which should not be removed and so is treated as used
|
||||
/// </summary>
|
||||
[MeansImplicitUse]
|
||||
public sealed class PublicAPIAttribute : Attribute
|
||||
{
|
||||
public PublicAPIAttribute() { }
|
||||
public PublicAPIAttribute([NotNull] string comment)
|
||||
{
|
||||
Comment = comment;
|
||||
}
|
||||
|
||||
[NotNull] public string Comment { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells code analysis engine if the parameter is completely handled
|
||||
/// when the invoked method is on stack. If the parameter is a delegate,
|
||||
/// indicates that delegate is executed while the method is executed.
|
||||
/// If the parameter is an enumerable, indicates that it is enumerated
|
||||
/// while the method is executed
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = true)]
|
||||
public sealed class InstantHandleAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a method does not make any observable state changes.
|
||||
/// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [Pure] private int Multiply(int x, int y) { return x * y; }
|
||||
/// public void Foo() {
|
||||
/// const int a = 2, b = 2;
|
||||
/// Multiply(a, b); // Waring: Return value of pure method is not used
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
|
||||
public sealed class PureAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that a parameter is a path to a file or a folder
|
||||
/// within a web project. Path can be relative or absolute,
|
||||
/// starting from web root (~)
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public class PathReferenceAttribute : Attribute
|
||||
{
|
||||
public PathReferenceAttribute() { }
|
||||
public PathReferenceAttribute([PathReference] string basePath)
|
||||
{
|
||||
BasePath = basePath;
|
||||
}
|
||||
|
||||
[NotNull] public string BasePath { get; private set; }
|
||||
}
|
||||
|
||||
// ASP.NET MVC attributes
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcAreaMasterLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcAreaPartialViewLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcAreaViewLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcMasterLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcMasterLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcPartialViewLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||
public sealed class AspMvcViewLocationFormatAttribute : Attribute
|
||||
{
|
||||
public AspMvcViewLocationFormatAttribute(string format) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
|
||||
/// is an MVC action. If applied to a method, the MVC action name is calculated
|
||||
/// implicitly from the context. Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||
public sealed class AspMvcActionAttribute : Attribute
|
||||
{
|
||||
public AspMvcActionAttribute() { }
|
||||
public AspMvcActionAttribute([NotNull] string anonymousProperty)
|
||||
{
|
||||
AnonymousProperty = anonymousProperty;
|
||||
}
|
||||
|
||||
[NotNull] public string AnonymousProperty { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC area.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcAreaAttribute : PathReferenceAttribute
|
||||
{
|
||||
public AspMvcAreaAttribute() { }
|
||||
public AspMvcAreaAttribute([NotNull] string anonymousProperty)
|
||||
{
|
||||
AnonymousProperty = anonymousProperty;
|
||||
}
|
||||
|
||||
[NotNull] public string AnonymousProperty { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
|
||||
/// the parameter is an MVC controller. If applied to a method,
|
||||
/// the MVC controller name is calculated implicitly from the context.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||
public sealed class AspMvcControllerAttribute : Attribute
|
||||
{
|
||||
public AspMvcControllerAttribute() { }
|
||||
public AspMvcControllerAttribute([NotNull] string anonymousProperty)
|
||||
{
|
||||
AnonymousProperty = anonymousProperty;
|
||||
}
|
||||
|
||||
[NotNull] public string AnonymousProperty { get; private set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Controller.View(String, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcMasterAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Controller.View(String, Object)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcModelTypeAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
|
||||
/// the parameter is an MVC partial view. If applied to a method,
|
||||
/// the MVC partial view name is calculated implicitly from the context.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||
public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Allows disabling all inspections
|
||||
/// for MVC views within a class or a method.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public sealed class AspMvcSupressViewErrorAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcDisplayTemplateAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcEditorTemplateAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC template.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter)]
|
||||
public sealed class AspMvcTemplateAttribute : Attribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
|
||||
/// is an MVC view. If applied to a method, the MVC view name is calculated implicitly
|
||||
/// from the context. Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.Mvc.Controller.View(Object)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||
public sealed class AspMvcViewAttribute : PathReferenceAttribute { }
|
||||
|
||||
/// <summary>
|
||||
/// ASP.NET MVC attribute. When applied to a parameter of an attribute,
|
||||
/// indicates that this parameter is an MVC action name
|
||||
/// </summary>
|
||||
/// <example><code>
|
||||
/// [ActionName("Foo")]
|
||||
/// public ActionResult Login(string returnUrl) {
|
||||
/// ViewBag.ReturnUrl = Url.Action("Foo"); // OK
|
||||
/// return RedirectToAction("Bar"); // Error: Cannot resolve action
|
||||
/// }
|
||||
/// </code></example>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
|
||||
public sealed class AspMvcActionSelectorAttribute : Attribute { }
|
||||
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Parameter | AttributeTargets.Property |
|
||||
AttributeTargets.Field, Inherited = true)]
|
||||
public sealed class HtmlElementAttributesAttribute : Attribute
|
||||
{
|
||||
public HtmlElementAttributesAttribute() { }
|
||||
public HtmlElementAttributesAttribute([NotNull] string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
[NotNull] public string Name { get; private set; }
|
||||
}
|
||||
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Parameter | AttributeTargets.Field |
|
||||
AttributeTargets.Property, Inherited = true)]
|
||||
public sealed class HtmlAttributeValueAttribute : Attribute
|
||||
{
|
||||
public HtmlAttributeValueAttribute([NotNull] string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
[NotNull] public string Name { get; private set; }
|
||||
}
|
||||
|
||||
// Razor attributes
|
||||
|
||||
/// <summary>
|
||||
/// Razor attribute. Indicates that a parameter or a method is a Razor section.
|
||||
/// Use this attribute for custom wrappers similar to
|
||||
/// <c>System.Web.WebPages.WebPageBase.RenderSection(String)</c>
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, Inherited = true)]
|
||||
public sealed class RazorSectionAttribute : Attribute { }
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle( "NetmfPackInstaller" )]
|
||||
[assembly: AssemblyDescription( "" )]
|
||||
[assembly: AssemblyConfiguration( "" )]
|
||||
[assembly: AssemblyCompany( "" )]
|
||||
[assembly: AssemblyProduct( "NetmfPackInstaller" )]
|
||||
[assembly: AssemblyCopyright( "Copyright © 2015" )]
|
||||
[assembly: AssemblyTrademark( "" )]
|
||||
[assembly: AssemblyCulture( "" )]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible( false )]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 606 B |
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="CommonServiceLocator" version="1.3" targetFramework="net45" />
|
||||
<package id="MvvmLightLibs" version="5.1.1.0" targetFramework="net45" />
|
||||
</packages>
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle( "UnitTests" )]
|
||||
[assembly: AssemblyDescription( "" )]
|
||||
[assembly: AssemblyConfiguration( "" )]
|
||||
[assembly: AssemblyCompany( "" )]
|
||||
[assembly: AssemblyProduct( "UnitTests" )]
|
||||
[assembly: AssemblyCopyright( "Copyright © 2015" )]
|
||||
[assembly: AssemblyTrademark( "" )]
|
||||
[assembly: AssemblyCulture( "" )]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible( false )]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid( "92d9e867-901f-45de-8816-4c1c79457061" )]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion( "1.0.0.0" )]
|
||||
[assembly: AssemblyFileVersion( "1.0.0.0" )]
|
|
@ -0,0 +1,220 @@
|
|||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using CMSIS.Pack;
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
[TestClass]
|
||||
public class SemanticVersionTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void DefaultConstructorTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 0, ver.Minor );
|
||||
Assert.AreEqual( 0, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( "0.0.0", ver.ToString() );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentOutOfRangeException))]
|
||||
public void NegativeMajorThrowsTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( -1, 0, 0 );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException( typeof( ArgumentOutOfRangeException ) )]
|
||||
public void NegativeMinorThrowsTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, -1, 0 );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException( typeof( ArgumentOutOfRangeException ) )]
|
||||
public void NegativePatchThrowsTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 0, -1 );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NullPartsTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 0, 0, null, null );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 0, ver.Minor );
|
||||
Assert.AreEqual( 0, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( "0.0.0", ver.ToString( ) );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException( typeof(ArgumentException))]
|
||||
public void InvalidPreReleasePartTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 0, 0, new[ ] { "abcd", "12$", "bar" }, null );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException( typeof( ArgumentException ) )]
|
||||
public void InvalidMetadataPartTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 0, 0, new[ ] { "abcd" }, new[ ] { "abcd", "12$", "bar" } );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PrereleasePartsOnlyTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 1, 2, new[ ] { "abcd", "123", "bar" }, null );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 1, ver.Minor );
|
||||
Assert.AreEqual( 2, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( 3, ver.PreReleaseParts.Count );
|
||||
Assert.AreEqual( "abcd", ver.PreReleaseParts[ 0 ] );
|
||||
Assert.AreEqual( "123", ver.PreReleaseParts[ 1 ] );
|
||||
Assert.AreEqual( "bar", ver.PreReleaseParts[ 2 ] );
|
||||
Assert.AreEqual( "0.1.2-abcd.123.bar", ver.ToString( ) );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MetadataPartsOnlyTest( )
|
||||
{
|
||||
var ver = new SemanticVersion( 0, 1, 2, null, new[ ] { "abcd", "123", "bar" } );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 1, ver.Minor );
|
||||
Assert.AreEqual( 2, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( 3, ver.BuildMetadata.Count );
|
||||
Assert.AreEqual( "abcd", ver.BuildMetadata[ 0 ] );
|
||||
Assert.AreEqual( "123", ver.BuildMetadata[ 1 ] );
|
||||
Assert.AreEqual( "bar", ver.BuildMetadata[ 2 ] );
|
||||
Assert.AreEqual( "0.1.2+abcd.123.bar", ver.ToString( ) );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StaticParseTest()
|
||||
{
|
||||
var ver = SemanticVersion.Parse( "0.1.2-alpha.beta+foo-bar.baz" );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 1, ver.Minor );
|
||||
Assert.AreEqual( 2, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( 2, ver.PreReleaseParts.Count );
|
||||
Assert.AreEqual( "alpha", ver.PreReleaseParts[ 0 ] );
|
||||
Assert.AreEqual( "beta", ver.PreReleaseParts[ 1 ] );
|
||||
Assert.AreEqual( 2, ver.BuildMetadata.Count );
|
||||
Assert.AreEqual( "foo-bar", ver.BuildMetadata[ 0 ] );
|
||||
Assert.AreEqual( "baz", ver.BuildMetadata[ 1 ] );
|
||||
Assert.AreEqual( "0.1.2-alpha.beta+foo-bar.baz", ver.ToString( ) );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void StaticParseDefaultPatchTest()
|
||||
{
|
||||
var ver = SemanticVersion.Parse( "0.1-alpha.beta+foo-bar.baz", patchOptional:true );
|
||||
Assert.AreEqual( 0, ver.Major );
|
||||
Assert.AreEqual( 1, ver.Minor );
|
||||
Assert.AreEqual( 0, ver.Patch );
|
||||
Assert.IsTrue( ver.IsValid );
|
||||
Assert.IsTrue( ver.IsDevelopment );
|
||||
Assert.IsTrue( ver.IsPrerelease );
|
||||
Assert.AreEqual( 2, ver.PreReleaseParts.Count );
|
||||
Assert.AreEqual( "alpha", ver.PreReleaseParts[ 0 ] );
|
||||
Assert.AreEqual( "beta", ver.PreReleaseParts[ 1 ] );
|
||||
Assert.AreEqual( 2, ver.BuildMetadata.Count );
|
||||
Assert.AreEqual( "foo-bar", ver.BuildMetadata[ 0 ] );
|
||||
Assert.AreEqual( "baz", ver.BuildMetadata[ 1 ] );
|
||||
Assert.AreEqual( "0.1.0-alpha.beta+foo-bar.baz", ver.ToString( ) );
|
||||
VerifyToStringReverseParse( ver );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(FormatException))]
|
||||
public void StaticParseDefaultPatchExceptionTest()
|
||||
{
|
||||
SemanticVersion.Parse( "0.1-alpha.beta+foo-bar.baz" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PrecedenceRule1Test()
|
||||
{
|
||||
//1.0.0 < 2.0.0 < 2.1.0 < 2.1.1
|
||||
var versions = new []
|
||||
{ new SemanticVersion( 1, 0, 0 )
|
||||
, new SemanticVersion( 2, 0, 0 )
|
||||
, new SemanticVersion( 2, 1, 0 )
|
||||
, new SemanticVersion( 2, 1, 1 )
|
||||
};
|
||||
|
||||
VerifyPrecedence( versions );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PrecedenceRule2Test()
|
||||
{
|
||||
// 1.0.0-alpha < 1.0.0
|
||||
var versions = new [ ]
|
||||
{ SemanticVersion.Parse( "1.0.0-alpha" )
|
||||
, new SemanticVersion( 1, 0, 0 )
|
||||
};
|
||||
|
||||
VerifyPrecedence( versions );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PrecedenceRule3Test()
|
||||
{
|
||||
// 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0
|
||||
var versions = new [ ]
|
||||
{ SemanticVersion.Parse( "1.0.0-alpha" )
|
||||
, SemanticVersion.Parse( "1.0.0-alpha.1" )
|
||||
, SemanticVersion.Parse( "1.0.0-alpha.beta" )
|
||||
, SemanticVersion.Parse( "1.0.0-beta" )
|
||||
, SemanticVersion.Parse( "1.0.0-beta.2" )
|
||||
, SemanticVersion.Parse( "1.0.0-beta.11" )
|
||||
, SemanticVersion.Parse( "1.0.0-rc.1" )
|
||||
, SemanticVersion.Parse( "1.0.0" )
|
||||
};
|
||||
|
||||
VerifyPrecedence( versions );
|
||||
}
|
||||
|
||||
private static void VerifyPrecedence( SemanticVersion[ ] versions )
|
||||
{
|
||||
for( var i = 0; i < versions.Length - 1; ++i )
|
||||
{
|
||||
VerifyToStringReverseParse( versions[ i ] );
|
||||
Assert.IsTrue( versions[ i ].CompareTo( versions[ i + 1 ] ) < 0, string.Format( "FAILED Comparing '{0}' to '{1}", versions[ i ], versions[ i + 1 ] ) );
|
||||
Assert.IsTrue( versions[ i + 1 ].CompareTo( versions[ i ] ) > 0, string.Format( "FAILED Comparing '{1}' to '{0}", versions[ i ], versions[ i + 1 ] ) );
|
||||
}
|
||||
VerifyToStringReverseParse( versions[ versions.Length - 1 ] );
|
||||
}
|
||||
|
||||
private static void VerifyToStringReverseParse( SemanticVersion ver )
|
||||
{
|
||||
SemanticVersion parsed;
|
||||
Assert.IsTrue( SemanticVersion.TryParse( ver.ToString( ), out parsed ) );
|
||||
Assert.IsTrue( parsed == ver, string.Format("FAILED equality check: '{0}'=='{1}'", parsed, ver ) );
|
||||
parsed = SemanticVersion.Parse( ver.ToString() );
|
||||
Assert.IsTrue( parsed == ver, string.Format("FAILED equality check: '{0}'=='{1}'", parsed, ver ) );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E4D675B0-5DBD-45BE-A4A0-B2C0F1BF42E3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>UnitTests</RootNamespace>
|
||||
<AssemblyName>UnitTests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
<SccLocalPath>
|
||||
</SccLocalPath>
|
||||
<SccAuxPath>
|
||||
</SccAuxPath>
|
||||
<SccProvider>
|
||||
</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="SemanticVersionTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CMSIS.Pack\CMSIS.Pack.csproj">
|
||||
<Project>{145d7231-c105-41be-b646-5d400097c744}</Project>
|
||||
<Name>CMSIS.Pack</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче