From f4d008a908b4768d30d9312df3e21c181504f2e4 Mon Sep 17 00:00:00 2001 From: Garrett Serack Date: Fri, 8 Jul 2016 14:49:56 -0700 Subject: [PATCH] Adding Roslyn support for unit testing --- .../AutoRest.Tooling.CSharp.Compiler.xproj | 19 +++ .../Compilation/CSharpCompiler.cs | 78 +++++++++++++ .../Compilation/CompilationResult.cs | 23 ++++ .../Compilation/Compiler.cs | 108 ++++++++++++++++++ .../Compilation/Language.cs | 12 ++ .../Compilation/ManagedAssets.cs | 79 +++++++++++++ .../Compilation/ManagedCompiler.cs | 69 +++++++++++ .../Compilation/OutputKind.cs | 16 +++ .../Compilation/ResultReasons.cs | 27 +++++ .../Compilation/TemplateUtilities.cs | 107 +++++++++++++++++ .../Extensions.cs | 28 +++++ .../Properties/AssemblyInfo.cs | 36 ++++++ .../packages.config | 17 +++ .../project.json | 28 +++++ 14 files changed, 647 insertions(+) create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/AutoRest.Tooling.CSharp.Compiler.xproj create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CSharpCompiler.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CompilationResult.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Compiler.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Language.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedAssets.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedCompiler.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/OutputKind.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ResultReasons.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/TemplateUtilities.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Extensions.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/Properties/AssemblyInfo.cs create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/packages.config create mode 100644 src/dev/AutoRest.Tooling.CSharp.Compiler/project.json diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/AutoRest.Tooling.CSharp.Compiler.xproj b/src/dev/AutoRest.Tooling.CSharp.Compiler/AutoRest.Tooling.CSharp.Compiler.xproj new file mode 100644 index 0000000000..ea7223e5e6 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/AutoRest.Tooling.CSharp.Compiler.xproj @@ -0,0 +1,19 @@ + + + + 14.0.25123 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 42dc6c97-6e79-4d0a-9a1d-dd34c99248e2 + Microsoft.Rest.CSharp.Compiler + .\obj + .\bin\ + + + 2.0 + + + + diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CSharpCompiler.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CSharpCompiler.cs new file mode 100644 index 0000000000..7b534faaa6 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CSharpCompiler.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public class CSharpCompiler : ManagedCompiler + { + private static readonly CSharpParseOptions parseOptions = new CSharpParseOptions( + LanguageVersion.CSharp6, + DocumentationMode.None); + + public CSharpCompiler(IEnumerable> sources, + IEnumerable referencesAsFilenames) + : base( + Language.CSharp, sources, + referencesAsFilenames.Select( + each => MetadataReference.CreateFromFile(each, MetadataReferenceProperties.Assembly))) + { + } + + protected sealed override CodeAnalysis.Compilation CreateCompilation(IEnumerable syntaxTrees, + OutputKind outputKind, string outputName) + { + var compilation = CSharpCompilation.Create( + outputName, + syntaxTrees, + References, + GetCompilationOptions(outputKind)); + + return compilation; + } + + protected sealed override IEnumerable ParseSources() + { + var syntaxTrees = + from source in Sources + where !string.IsNullOrWhiteSpace(source.Value) + // ParseText throws a NullRefEx on empty files + select CSharpSyntaxTree.ParseText(source.Value, parseOptions, source.Key); + + return syntaxTrees.ToList(); + } + + #region Helpers + + public static CSharpCompilationOptions GetCompilationOptions(OutputKind outputKind) + { + switch (outputKind) + { + case OutputKind.ConsoleApplication: + return new CSharpCompilationOptions( + CodeAnalysis.OutputKind.ConsoleApplication, + allowUnsafe: false, + concurrentBuild: false, + optimizationLevel: OptimizationLevel.Debug); + + case OutputKind.DynamicallyLinkedLibrary: + return new CSharpCompilationOptions( + CodeAnalysis.OutputKind.DynamicallyLinkedLibrary, + allowUnsafe: false, + concurrentBuild: false, + optimizationLevel: OptimizationLevel.Debug); + + default: + throw new NotSupportedException(); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CompilationResult.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CompilationResult.cs new file mode 100644 index 0000000000..024a30a4ac --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/CompilationResult.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System.Collections.Generic; +using System.IO; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public struct CompilationResult + { + public bool Succeeded; + + public string Reason; + + public IEnumerable Messages; + + public MemoryStream Output; + + public OutputKind OutputKind; + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Compiler.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Compiler.cs new file mode 100644 index 0000000000..ccc7004a50 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Compiler.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public abstract class Compiler + { + /// + /// Default maximum compilation time + /// + public const int DefaultTimeout = 5000; //5s + + protected Compiler(Language language, IEnumerable> sources) + { + Language = language; + Parameters = new Dictionary(StringComparer.Ordinal); + Sources = sources ?? new Dictionary(); + Timeout = DefaultTimeout; + } + + /// + /// Supported language + /// + public Language Language { get; } + + /// + /// Named parameters used by compiler, as appropriate + /// + public IDictionary Parameters { get; } + + /// + /// Source code + /// + public IEnumerable> Sources { get; } + + /// + /// Compilation timeout (in ms) + /// + /// + /// This value represents the maximum time a compilation session can take + /// before being terminated. + /// + public int Timeout { get; set; } + + public async Task Compile(OutputKind outputKind, string outputName = null) + { + var cancellationTokenSource = new CancellationTokenSource(); + + try + { + var task = InnerCompile(outputKind, outputName, cancellationTokenSource.Token); + cancellationTokenSource.CancelAfter(Timeout); + return await task.ConfigureAwait(false); + } + catch (OperationCanceledException ocex) + { + if (cancellationTokenSource.IsCancellationRequested) + { + // Trace.TraceInformation("{0}:InnerCompile timed-out.", GetType().Name); + return new CompilationResult + { + Succeeded = false, + Reason = ResultReasons.TimedOutError, + // Messages = new[] {"Maximum compilation time reached"}, + OutputKind = outputKind + }; + } + else + { + // Trace.TraceWarning("{0}:InnerCompile was unexpectedly canceled. Exception: {1}", GetType().Name, ocex); + return new CompilationResult + { + Succeeded = false, + Reason = ResultReasons.CanceledError, + // Messages = new[] {"Compilation was canceled"}, + OutputKind = outputKind + }; + } + } + catch (Exception ex) + { + // Trace.TraceError("{0}:InnerCompile failed. Exception: {1}", GetType().Name, ex); + return new CompilationResult + { + Succeeded = false, + Reason = ResultReasons.UnknownError, + // Errors = new[] {"Unknown error"}, + OutputKind = outputKind + }; + } + finally + { + cancellationTokenSource.Dispose(); + } + } + + protected abstract Task InnerCompile(OutputKind outputKind, string outputName, + CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Language.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Language.cs new file mode 100644 index 0000000000..4821df52d5 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/Language.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public enum Language + { + Unknown = 0, + CSharp = 1 + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedAssets.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedAssets.cs new file mode 100644 index 0000000000..3924cfc10e --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedAssets.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public static class ManagedAssets + { + public static string RuntimeDirectory => RuntimeEnvironment.GetRuntimeDirectory(); + + public static IEnumerable FrameworkAssemblies => new[] + { + "mscorlib.dll", + "System.dll", + "System.Core.dll", + "System.Linq.Expressions.dll", + "System.Net.dll", + "System.Net.Http.dll", + "System.Runtime.dll", + "System.Threading.Tasks.dll", + "System.Xml.dll", + "System.Xml.Linq.dll", + "Microsoft.CSharp.dll" + }.Select(each => Path.Combine(RuntimeDirectory, each)); + + // Framework assemblies + private static readonly IEnumerable frameworkAssemblies = + LoadReferences( + RuntimeEnvironment.GetRuntimeDirectory(), + "mscorlib.dll", + "System.dll", + "System.Core.dll", + "System.Linq.Expressions.dll", + "System.Net.dll", + "System.Net.Http.dll", + "System.Runtime.dll", + "System.Threading.Tasks.dll", + "System.Xml.dll", + "System.Xml.Linq.dll", + "Microsoft.CSharp.dll"); + + + public static IEnumerable All { get; } = frameworkAssemblies + .ToArray(); + + public static string ReferencesPath { get; } = ""; + + #region Helpers + + private static string GetManifestResource(string name) + { + using (var reader = new StreamReader( + typeof(ManagedAssets).GetTypeInfo().Assembly.GetManifestResourceStream(name))) + { + return reader.ReadToEnd(); + } + } + + private static IEnumerable LoadReferences(string baseDirectory, params string[] assemblyNames) + { + var references = + from assemblyName in assemblyNames + let path = Path.Combine(baseDirectory, assemblyName) + select MetadataReference.CreateFromFile(path, MetadataReferenceProperties.Assembly); + + return references.ToArray(); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedCompiler.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedCompiler.cs new file mode 100644 index 0000000000..5ce87677a3 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ManagedCompiler.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public abstract class ManagedCompiler : Compiler + { + private readonly List _references; + private readonly List _syntaxTrees; + + protected ManagedCompiler(Language language, IEnumerable> sources, + IEnumerable references) + : base(language, sources) + { + _references = new List(references ?? Enumerable.Empty()); + _syntaxTrees = new List(); + } + + protected abstract CodeAnalysis.Compilation CreateCompilation(IEnumerable syntaxTrees, + OutputKind outputKind, string outputName); + + protected sealed override Task InnerCompile(OutputKind outputKind, string outputName, + CancellationToken cancellationToken) + { + var compilation = CreateCompilation( + Parse(), + outputKind, + outputName ?? "tmp" + Guid.NewGuid().ToString("N")); + + var ms = new MemoryStream(); + var emitResult = compilation.Emit(ms, cancellationToken: cancellationToken); + + var compileResult = new CompilationResult {OutputKind = outputKind}; + + compileResult.Messages = emitResult.Diagnostics; + compileResult.Succeeded = emitResult.Success; + + if (emitResult.Success) + { + ms.Seek(0, SeekOrigin.Begin); + compileResult.Output = ms; + } + else + { + compileResult.Reason = ResultReasons.Compilation.Failed; + ms.Dispose(); + } + + return Task.FromResult(compileResult); + } + + public IEnumerable Parse() => ParseSources().Concat(_syntaxTrees); + + protected abstract IEnumerable ParseSources(); + + public IList References => _references; + + public IList SyntaxTrees => _syntaxTrees; + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/OutputKind.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/OutputKind.cs new file mode 100644 index 0000000000..0b2a846374 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/OutputKind.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public enum OutputKind + { + ConsoleApplication, + WindowsApplication, + DynamicallyLinkedLibrary, + NetModule, + WindowsRuntimeMetadata, + WindowsRuntimeApplication, + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ResultReasons.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ResultReasons.cs new file mode 100644 index 0000000000..f07a7da703 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/ResultReasons.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + internal static class ResultReasons + { + public const string CanceledError = "General.Canceled"; + public const string TimedOutError = "General.TimedOut"; + public const string UnknownError = "General.UnknownError"; + public const string Failed = "General.Failed"; + + public static class Compilation + { + public const string Failed = ResultReasons.Failed; + } + + public static class Execution + { + public const string MaximumOutput = "Executor.MaxOutput"; + public const string Failed = ResultReasons.Failed; + public const string MaximumCpuError = "Executor.MaxCPU"; + public const string Terminated = "Executor.Terminated"; + } + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/TemplateUtilities.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/TemplateUtilities.cs new file mode 100644 index 0000000000..43b56d3518 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Compilation/TemplateUtilities.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Microsoft.Rest.CSharp.Compiler.Compilation +{ + public static class TemplateUtilities + { + public static string ApplyReplacements(string contents, IDictionary replacements) + { + const int MaxReplacements = 1000; + + // + // As long as tokens are defined as strings enclosed by '$' characters, it is more + // efficient to look for $...$ occurrences than it is to search for all occurrences + // of every token in replacements. The only catch is that two matching '$' would + // effectively define a token. This case is easily resolved by requiring escaping + // of '$' with another '$' (i.e. $$ -> '$'). + // + + Debug.Assert(!replacements.ContainsKey("$$"), "\"$$\" must not be part of replacements dictionary"); + + var buffer = new StringBuilder(contents); + int tokenIndex; + string token; + + var index = 0; + var infiniteLoopGuard = 0; + + while ((tokenIndex = buffer.FindNextToken(index, out token)) != -1) + { + string replacement; + if (token == "$$") + { + // Unescape '$' and move one character forward + buffer.Replace("$$", "$", tokenIndex, 2); + index = tokenIndex + 1; + } + else if (replacements.TryGetValue(token, out replacement)) + { + // Replace token but do not modify 'startIndex' to allow for nested replacements + buffer.Replace(token, replacement, tokenIndex, token.Length); + } + else + { + // Do not replace token and fully skip it + index = tokenIndex + token.Length; + } + + if (++infiniteLoopGuard > MaxReplacements) + { + // TODO: LOC: Infinite loop guard + throw new InvalidOperationException("Exceeded token replacement limit"); + } + } + + return buffer.ToString(); + } + + #region Private & Helpers + + /// + /// Finds the next token in starting at . + /// + /// Start index of or -1 + private static int FindNextToken(this StringBuilder buffer, int startIndex, out string token) + { + var tokenStart = buffer.IndexOf('$', startIndex); + + if ((tokenStart != -1) && tokenStart + 1 < buffer.Length) + { + int tokenEnd = buffer.IndexOf('$', tokenStart + 1); + + if (tokenEnd != -1) + { + token = buffer.ToString(tokenStart, tokenEnd - tokenStart + 1); + return tokenStart; + } + } + + token = null; + return -1; + } + + /// + /// string.IndexOf equivalent for + /// + private static int IndexOf(this StringBuilder buffer, char value, int startIndex) + { + for (var i = startIndex; i < buffer.Length; i++) + { + if (buffer[i] == value) + { + return i; + } + } + return -1; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Extensions.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Extensions.cs new file mode 100644 index 0000000000..c33f3c2084 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Extensions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; + +namespace Microsoft.Rest.CSharp.Compiler +{ + public static class Extensions + { + public static string ToJson(this object @object) + { + return JsonConvert.SerializeObject( + @object, + Formatting.Indented, + new JsonSerializerSettings + { + Converters = new JsonConverter[] { new StringEnumConverter() }, + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + ObjectCreationHandling = ObjectCreationHandling.Reuse + }); + } + } +} diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/Properties/AssemblyInfo.cs b/src/dev/AutoRest.Tooling.CSharp.Compiler/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..afd8bb55fb --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/Properties/AssemblyInfo.cs @@ -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("CSharp.Compiler")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CSharp.Compiler")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[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("5408c3a4-8397-4595-8a25-e09c82fc8b41")] + +// 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")] diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/packages.config b/src/dev/AutoRest.Tooling.CSharp.Compiler/packages.config new file mode 100644 index 0000000000..baba9b0d37 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/packages.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/dev/AutoRest.Tooling.CSharp.Compiler/project.json b/src/dev/AutoRest.Tooling.CSharp.Compiler/project.json new file mode 100644 index 0000000000..a24818f4b2 --- /dev/null +++ b/src/dev/AutoRest.Tooling.CSharp.Compiler/project.json @@ -0,0 +1,28 @@ +{ + "version": "0.17.0-*", + "authors": [ "Microsoft" ], + + "packOptions": { + "summary": "CSharp Compiler for use from unit tests", + "tags": [ "Microsoft AutoRest " ], + "projectUrl": "https://github.com/Azure/AutoRest", + "licenseUrl": "https://raw.githubusercontent.com/Microsoft/dotnet/master/LICENSE" + }, + + "buildOptions": { + "delaySign": true, + "publicSign": false, + "keyFile": "../../../Tools/MSSharedLibKey.snk" + }, + + "frameworks": { + "net451": { + } + }, + + "dependencies": { + "Microsoft.CodeAnalysis.CSharp": "2.0.0-beta1", + "Newtonsoft.Json": "[9.0.1,10.0)", + "System.Threading.Tasks": "4.0.0" + } +}