[
  {
    "path": ".gitignore",
    "content": "*.suo\n*/bin/\n*/obj/\n*.orig\n*.user\n*.nupkg\n*.GhostDoc.xml\nMoonSpeak.sln.ide/\ntools\npackages\n.vs\n_ReSharper*\n"
  },
  {
    "path": "BuildAndPack.ps1",
    "content": "param(\n    [parameter(Position=0)]\n    [string] $VersionSuffix,\n    [parameter(Position=1)]\n    [string] $GitCommitId,\n    [parameter(Position=2)]\n    [string[]] $MsBuildArgs,\n    [switch] $CIBuild\n)\n\nif (-not $semver)\n{\n    set-variable -name semver -scope global -value (get-content .\\semver.txt)\n}\n\nif ($VersionSuffix -or $CIBuild)\n{\n    $version = \"$semver$VersionSuffix\"\n}\nelse\n{\n    $epoch = [math]::truncate((new-timespan -start (get-date -date \"01/01/1970\") -end (get-date)).TotalSeconds)\n    $version = \"$semver-local$epoch\"\n}\n\nif(-not $GitCommitId)\n{\n    $GitCommitId = $(git rev-parse HEAD)\n}\n\n$solutionDir = \"$((Resolve-Path .).Path)\\\"\n$defaultArgs = \"/v:n\", \"/nologo\",\n    \"/p:SolutionDir=$solutionDir\",\n    \"/p:RepositoryCommit=$GitCommitId\",\n    \"/p:Version=$version\",\n    \"/p:Configuration=Release\",\n    \"/p:SEPrecompilerPath=$solutionDir\\StackExchange.Precompilation.Build\\bin\\Release\\net462\"\nif ($MsBuildArgs)\n{\n    $defaultArgs += $MsBuildArgs\n}\n& msbuild ($defaultArgs + \"/t:Restore\")\n& msbuild ($defaultArgs + \"/t:Build,Pack\")\n\nif ($LastExitCode -ne 0)\n{\n    throw \"MSBuild failed\"\n}\n\n.\\Test.ConsoleApp\\bin\\Release\\net462\\Test.ConsoleApp.exe\n\nif ($LastExitCode -ne 0)\n{\n    throw \"Test.ConsoleApp failed to run\"\n}\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "<Project>\n  <PropertyGroup>\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <IsPackable>false</IsPackable> <!-- enabled on each packable project exlpicitly -->\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\" '$(Configuration)' == 'Release' \">\n    <DebugType>embedded</DebugType>\n    <PackageOutputPath>$(SolutionDir)packages\\obj\\</PackageOutputPath>\n    <Authors>m0sa</Authors>\n    <Copyright>Stack Exchange 2017</Copyright>\n    <PackageTags>Razor AspNet MsBuild Roslyn Metaprogramming</PackageTags>\n    <RepositoryUrl>https://github.com/StackExchange/StackExchange.Precompilation.git</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <ProjectUrl>https://github.com/StackExchange/StackExchange.Precompilation</ProjectUrl>\n    <PackageReleaseNotes><![CDATA[\nVersion 5.1.0\n* updating roslyn packages to 2.10.0\n* updating mvc packages to 5.2.7\n* fixing SourceLink support for native pdbs\n\nVersion 5.0.0\n* updating how Precompilation.Build resolves it's Workspaces dependency\n* retiring Precompilation.Metaprogramming\n* support running compilation modules at runtime in RoslynRazorViewEngine\n* split out System.Web / MVC5 portions into a separate package\n* bumping aspnet mvc packages to 5.2.4\n* updating roslyn packages to 2.8.2\n\nVersion 4.7.0\n* updated roslyn packages to 2.7.0\n* cleaned up diagnostics numbers\n* report source text in razor HttpParseExceptions\n* report razor parser errors diagnostics during precompilation\n\nVersion 4.6.1\n* fixed perf regression due to missing app.config with proper GC settings in the .Build package\n* updated roslyn packages to latest version (2.6.1)\n* fixed remoting runtime exception in long builds\n\nVersion 4.6\n* updated roslyn packages to latest version (2.6)\n* fixed case where layout and view page weren't resolvable by the same view engine\n\nVersion 4.5\n* upped MVC5 to latest minor version (5.2.3)\n* razor cache directory option can ge passed in via PRECOMPILATION_RAZORCACHEDIRECTORY environment variable\n\nVersion 4.4\n* added configurable support for caching the razor (.cshtml -> .cs) generation step\n* added optional razorCache element to the precompilation configuration section\n* fixing non-default langversion bug\n* better handling of failing precompilation modules\n* don't ouput hidden diagnostics to console\n* updated roslyn packages to 2.4.0\n\nVersion 4.1.1\n* updated roslyn packages to 2.3.2\n\nVersion 4.1.0\n* updated roslyn packages to 2.3.1\n* don't emit pdb files when debugtype embedded\n* pathmap support\n]]>\n    </PackageReleaseNotes>\n  </PropertyGroup>\n</Project>"
  },
  {
    "path": "README.md",
    "content": "StackExchange.Precompilation\n============================\n\n[![Build status](https://ci.appveyor.com/api/projects/status/lvt06wa9io6k64c3/branch/master?svg=true)](https://ci.appveyor.com/project/StackExchange/stackexchange-precompilation/branch/master)\n\nReplacing csc.exe\n-----------------\n\n- `Install-Package StackExchange.Precompilation.Build -Pre`\n\nReplacing aspnet_compiler.exe for .cshtml precompilation\n--------------------------------------------------------\n\n- `Install-Package StackExchange.Precompilation.Build -Pre`\n- Add `<PropertyGroup><SEPrecompilerIncludeRazor>true</SEPrecompilerIncludeRazor></PropertyGroup>` to your .csproj file (usually replacing the `MvcBuildViews` property)\n\n#### Using precompiled views\n\n- [Add the PrecompiledViewEngine to ViewEngines](https://github.com/StackExchange/StackExchange.Precompilation/blob/fd536b764983e2674a4549b7be6f26e971190c1e/Test.WebApp/Global.asax.cs#L29)\n\n#### Using C# 7 in ASP.NET MVC 5\n\n- [Add the RoslynRazorViewEngine to ViewEngines](https://github.com/StackExchange/StackExchange.Precompilation/blob/fd536b764983e2674a4549b7be6f26e971190c1e/Test.WebApp/Global.asax.cs#L32)\n\nMeta-programming\n----------------\n\n- Create a new project \n- `Install-Package StackExchange.Precompilation -Pre`\n- Implement the ICompileModule interface\n- `Install-Package StackExchange.Precompilation.Build -Pre` in the target project\n- [Configure your new module](https://github.com/StackExchange/StackExchange.Precompilation/blob/fd536b764983e2674a4549b7be6f26e971190c1e/Test.ConsoleApp/App.config#L8) in the target project's web.config or app.config\n\n\nDevelopment\n-----------\n\nif you have an existing project with StackExchange.Precompilation packages and encounter a bug you can simply:\n\n- pull this repo\n- increment semver.txt\n- make the fix in the source code\n- run BuildAndPack.ps1 (requires a console with VS env vars in your PATH, I recommend powershell with Posh-VsVars)\n- setup a nuget source pointing at .\\packages\\obj\n- after that you can update the packages StackExchange.Precompilation in your target project from the packages\\obj source\n- this gives you local *-local{timestamp} suffixed packages instead of the *-alpha{build} ones produced by the CI build\n- PROTIP: if you want to attach an debugger to the compilation of your project or any of the Test.* projects, add a `System.Diagnostics.Debugger.Launch()` statement somewhere in the code ;)\n- CI *-alpha{build} packages are available on the stackoverflow myget feed https://www.myget.org/F/stackoverflow/api/v2\n"
  },
  {
    "path": "Release.ps1",
    "content": "set-variable -name semver -scope global -value (get-content .\\semver.txt)\n\ngit tag -a \"releases/$semver\" -m \"creating $semver release\"\n\ngit push --tags"
  },
  {
    "path": "StackExchange.Precompilation/AfterCompileContext.cs",
    "content": "using System.Collections.Generic;\nusing System.IO;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace StackExchange.Precompilation\n{\n    public class AfterCompileContext : ICompileContext\n    {\n        public CSharpCommandLineArguments Arguments { get; internal set; }\n\n        public CSharpCompilation Compilation { get; internal set; }\n\n        public Stream AssemblyStream { get; internal set; }\n\n        public Stream SymbolStream { get; internal set; }\n\n        public Stream XmlDocStream { get; internal set; }\n\n        public IList<Diagnostic> Diagnostics { get; internal set; }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/AppDomainHelper.cs",
    "content": "using System;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Precompilation helper methods.\n    /// </summary>\n    public static class AppDomainHelper\n    {\n        /// <summary>\n        /// The friednly name of the <see cref=\"AppDomain\"/> hosting the compilation.\n        /// </summary>\n        public const string CsCompilationAppDomainName = \"csMoonSpeak\";\n\n        /// <summary>\n        /// </summary>\n        /// <param name=\"appDomain\"></param>\n        /// <returns>Returns <c>true</c> if the <paramref name=\"appDomain\"/> is a Precompilation domain.</returns>\n        public static bool IsPrecompilation(this AppDomain appDomain)\n        {\n            return (appDomain ?? AppDomain.CurrentDomain).FriendlyName == CsCompilationAppDomainName;\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/Attributes.cs",
    "content": "[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(\"StackExchange.Precompiler\")]\n[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(\"StackExchange.Precompilation.Build\")]\n[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(\"StackExchange.Precompilation.MVC5\")]"
  },
  {
    "path": "StackExchange.Precompilation/BeforeCompileContext.cs",
    "content": "using System.Collections.Generic;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace StackExchange.Precompilation\n{\n    public class BeforeCompileContext : ICompileContext\n    {\n        public CSharpCommandLineArguments Arguments { get; set; }\n\n        public CSharpCompilation Compilation { get; set; }\n\n        public IList<Diagnostic> Diagnostics { get; internal set; }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/CompileContext.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace StackExchange.Precompilation\n{\n\n    internal class CompileContext\n    {\n        private readonly ICollection<ICompileModule> _modules;\n        public BeforeCompileContext BeforeCompileContext { get; private set; }\n        public AfterCompileContext AfterCompileContext { get; private set; }\n        public CompileContext(ICollection<ICompileModule> modules)\n        {\n            _modules = modules;\n        }\n        public void Before(BeforeCompileContext context)\n        {\n            Apply(context, x => BeforeCompileContext = x, m => m.BeforeCompile);\n        }\n        public void After(AfterCompileContext context)\n        {\n            Apply(context, x => AfterCompileContext = x, m => m.AfterCompile);\n        }\n        private void Apply<TContext>(TContext ctx, Action<TContext> setter, Func<ICompileModule, Action<TContext>> actionGetter)\n            where TContext : ICompileContext\n        {\n            setter(ctx);\n            foreach(var module in _modules)\n            {\n                try\n                {\n                    var action = actionGetter(module);\n                    action(ctx);\n                }\n                catch (Exception ex)\n                {\n                    var methodName = ctx is BeforeCompileContext ? nameof(ICompileModule.BeforeCompile) : nameof(ICompileModule.AfterCompile);\n                    throw new PrecompilationModuleException($\"Precompilation module '{module.GetType().FullName}.{methodName}({typeof(TContext)})' failed\", ex);\n                }\n            }\n        }\n    }\n\n    internal class PrecompilationModuleException : Exception\n    {\n        public PrecompilationModuleException(string message, Exception inner) : base(message, inner)\n        {\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/CompileModuleElement.cs",
    "content": "using System.Configuration;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// A compile module configuration element.\n    /// </summary>\n    /// <seealso cref=\"ICompileModule\"/>\n    public class CompileModuleElement : ConfigurationElement\n    {\n        /// <summary>\n        /// The type of the <see cref=\"ICompileModule\"/> to be loaded at compile time.\n        /// </summary>\n        [ConfigurationProperty(\"type\", IsRequired = true, DefaultValue = null)]\n        public string Type { get { return (string)base[\"type\"]; } }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/CompileModulesCollection.cs",
    "content": "using System.Configuration;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// A collection of <see cref=\"CompileModuleElement\"/> instances.\n    /// </summary>\n    public class CompileModulesCollection : ConfigurationElementCollection\n    {\n        protected override ConfigurationElement CreateNewElement()\n        {\n            return new CompileModuleElement();\n        }\n\n        protected override object GetElementKey(ConfigurationElement element)\n        {\n            return ((CompileModuleElement)element).Type;\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/CompiledFromDirectoryAttribute.cs",
    "content": "﻿using System;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Decorates a precompiled MVC assembly. Used to calculate relative view paths.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Assembly)]\n    public class CompiledFromDirectoryAttribute : Attribute\n    {\n        /// <summary>\n        /// Gets the source directory path.\n        /// </summary>\n        public string SourceDirectory { get; private set; }\n\n        /// <summary></summary>\n        /// <param name=\"sourceDirectory\"></param>\n        public CompiledFromDirectoryAttribute(string sourceDirectory)\n        {\n            SourceDirectory = sourceDirectory;\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/CompiledFromFileAttribute.cs",
    "content": "﻿using System;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Decorates a precompiled MVC page.\n    /// </summary>\n    [AttributeUsage(AttributeTargets.Class)]\n    public class CompiledFromFileAttribute : Attribute\n    {\n        /// <summary>\n        /// Gets the source file path.\n        /// </summary>\n        public string SourceFile { get; private set; }\n\n        /// <summary></summary>\n        /// <param name=\"sourceFile\"></param>\n        public CompiledFromFileAttribute(string sourceFile)\n        {\n            SourceFile = sourceFile;\n        }\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation/ICompileContext.cs",
    "content": "﻿using System.Collections.Generic;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace StackExchange.Precompilation\n{\n    public interface ICompileContext\n    {\n        CSharpCommandLineArguments Arguments { get; }\n\n        CSharpCompilation Compilation { get; }\n\n        IList<Diagnostic> Diagnostics { get; }\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation/ICompileModule.cs",
    "content": "namespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Allows plugging into the compilation pipeline. Has to be registered in app/web.config\n    /// </summary>\n    /// <remarks>\n    ///   <example>\n    ///     <code language=\"xml\"><![CDATA[\n    /// <configuration>\n    ///   <configSections>\n    ///     <section name=\"stackExchange.precompiler\" type=\"StackExchange.Precompilation.PrecompilerSection, StackExchange.Precompilation\" />\n    ///   </configSections>\n    ///   <stackExchange.precompiler>\n    ///     <modules>\n    ///       <add type=\"MyAssembly.MyModule, MyAssembly\" />\n    ///     </modules>\n    ///   </stackExchange.precompiler>\n    /// </coniguration>]]>\n    ///     </code>\n    ///   </example>\n    /// </remarks>\n    public interface ICompileModule\n    {\n        /// <summary>\n        /// Called before anything is emitted\n        /// </summary>\n        /// <param name=\"context\"></param>\n        void BeforeCompile(BeforeCompileContext context);\n\n        /// <summary>\n        /// Called after the compilation is emitted. Changing the compilation will not have any effect at this point\n        /// but the assembly can be changed before it is saved on disk or loaded into memory.\n        /// </summary>\n        /// <param name=\"context\"></param>\n        void AfterCompile(AfterCompileContext context);\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/IMetadataReference.cs",
    "content": "﻿"
  },
  {
    "path": "StackExchange.Precompilation/PrecompilationModuleLoader.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\n\nnamespace StackExchange.Precompilation\n{\n    internal class PrecompilationModuleLoader\n    {\n        /// <summary>Fires when a <see cref=\"CompileModuleElement\" /> cannot be resolved to an actual <see cref=\"System.Type\" />.</summary>\n        /// <remarks>Register the handlers before touching <see cref=\"LoadedModules\" />.</remarks>\n        public event Action<CompileModuleElement, Exception> ModuleInitializationFailed;\n\n        /// <summary>Gets a cached collection of loaded modules.</summary>\n        public ICollection<ICompileModule> LoadedModules => _loadedModules.Value;\n\n        private readonly Lazy<ICollection<ICompileModule>> _loadedModules;\n        private readonly PrecompilerSection _configuration;\n\n        public PrecompilationModuleLoader(PrecompilerSection configuration)\n        {\n            _configuration = configuration;\n            _loadedModules = new Lazy<ICollection<ICompileModule>>(() =>\n            {\n                var result = new List<ICompileModule>();\n                if (_configuration == null || _configuration.CompileModules == null)\n                {\n                    return result;\n                }\n\n                foreach(var module in _configuration.CompileModules.Cast<CompileModuleElement>())\n                {\n                    try\n                    {\n                        var type = Type.GetType(module.Type, true);\n                        if (Activator.CreateInstance(type, true) is ICompileModule cm)\n                        {\n                            result.Add(cm);\n                        }\n                        else\n                        {\n                            throw new TypeLoadException($\"{module.Type} is not an {nameof(ICompileModule)}.\");\n                        }\n                    }\n                    catch(Exception ex)\n                    {\n                        ModuleInitializationFailed?.Invoke(module, ex);\n                    }\n                }\n                return result;\n            });\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/PrecompilerSection.cs",
    "content": "using System.Configuration;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Defines the <c>stackExchange.precompiler</c> <see cref=\"ConfigurationSection\"/>.\n    /// </summary>\n    /// <seealso cref=\"ICompileModule\"/>\n    public class PrecompilerSection : ConfigurationSection\n    {\n        /// <summary>\n        /// Gets the <see cref=\"CompileModulesCollection\"/>.\n        /// </summary>\n        [ConfigurationProperty(\"modules\", IsRequired = false)]\n        [ConfigurationCollection(typeof(CompileModulesCollection))]\n        public CompileModulesCollection CompileModules => (CompileModulesCollection)base[\"modules\"];\n\n        /// <summary>\n        /// Gets the <c>stackExchange.precompiler</c> section from the <see cref=\"ConfigurationManager\"/>.\n        /// </summary>\n        public static PrecompilerSection Current => (PrecompilerSection)ConfigurationManager.GetSection(\"stackExchange.precompiler\");\n\n        [ConfigurationProperty(\"razorCache\", IsRequired = false)]\n        public RazorCacheElement RazorCache => (RazorCacheElement)base[\"razorCache\"];\n\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/RazorCacheElement.cs",
    "content": "using System.Configuration;\n\nnamespace StackExchange.Precompilation\n{\n    public class RazorCacheElement : ConfigurationElement\n    {\n        /// <summary>\n        /// The type of the <see cref=\"ICompileModule\"/> to be loaded at compile time.\n        /// </summary>\n        [ConfigurationProperty(\"directory\", IsRequired = true, DefaultValue = null)]\n        public string Directory => (string)base[\"directory\"];\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation/StackExchange.Precompilation.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFrameworks>net462;netstandard20</TargetFrameworks>\n    <Description>Hooks into the ASP.NET MVC pipeline to enable usage of C# 7.2, and views precompiled with StackExchange.Precompilation.Build</Description>\n    <IsPackable>true</IsPackable>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n  </PropertyGroup>\n  <ItemGroup>\n    <PackageReference Include=\"System.Configuration.ConfigurationManager\" Version=\"4.4.1\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"2.10.0\" ExcludeAssets=\"analyzers\"/>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "StackExchange.Precompilation.Build/App.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n    <startup>\n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6.2\" />\n    </startup>\n    <runtime>\n        <gcServer enabled=\"true\" />\n        <gcConcurrent enabled=\"false\" />\n    </runtime>\n</configuration>\n"
  },
  {
    "path": "StackExchange.Precompilation.Build/Attributes.cs",
    "content": "[assembly:System.Runtime.CompilerServices.InternalsVisibleToAttribute(\"StackExchange.Precompilation.MVC5\")]"
  },
  {
    "path": "StackExchange.Precompilation.Build/Compilation.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing Microsoft.CodeAnalysis.Text;\nusing Microsoft.CodeAnalysis.Emit;\nusing System.Collections.Immutable;\nusing Microsoft.CodeAnalysis.Diagnostics;\nusing Microsoft.CodeAnalysis.Host;\nusing System.Composition.Hosting;\nusing Microsoft.CodeAnalysis.Host.Mef;\nusing System.Composition;\nusing System.Threading;\n\nnamespace StackExchange.Precompilation\n{\n    internal class Compilation\n    {\n        private readonly PrecompilationCommandLineArgs _precompilationCommandLineArgs;\n\n        internal CSharpCommandLineArguments CscArgs { get; private set; }\n        internal DirectoryInfo CurrentDirectory { get; private set; }\n        internal List<Diagnostic> Diagnostics { get; private set; }\n        internal Encoding Encoding { get; private set; }\n\n        private const string DiagnosticCategory = \"StackExchange.Precompilation\";\n        private static DiagnosticDescriptor FailedToCreateModule =\n            new DiagnosticDescriptor(\"SE001\", \"Failed to instantiate ICompileModule\", \"Failed to instantiate ICompileModule '{0}': {1}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        private static DiagnosticDescriptor FailedToCreateCompilation =\n            new DiagnosticDescriptor(\"SE002\", \"Failed to create compilation\", \"{0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor ViewGenerationFailed =\n            new DiagnosticDescriptor(\"SE003\", \"View generation failed\", \"View generation failed: {0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor FailedParsingSourceTree =\n            new DiagnosticDescriptor(\"SE004\", \"Failed parsing source tree\", \"Failed parasing source tree: {0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor PrecompilationModuleFailed =\n            new DiagnosticDescriptor(\"SE005\", \"Precompilation module failed\", \"{0}: {1}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        private static DiagnosticDescriptor AnalysisFailed =\n            new DiagnosticDescriptor(\"SE006\", \"Analysis failed\", \"{0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        private static DiagnosticDescriptor UnhandledException =\n            new DiagnosticDescriptor(\"SE007\", \"Unhandled exception\", \"Unhandled exception: {0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor ERR_FileNotFound =\n            new DiagnosticDescriptor(\"CS2001\", \"FileNotFound\", \"Source file '{0}' could not be found\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor ERR_BinaryFile =\n            new DiagnosticDescriptor(\"CS2015\", \"BinaryFile\", \"'{0}' is a binary file instead of a text file\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor ERR_NoSourceFile =\n            new DiagnosticDescriptor(\"CS1504\", \"NoSourceFile\", \"Source file '{0}' could not be opened ('{1}')\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor CachingFailed =\n            new DiagnosticDescriptor(\"SE008\", \"Razor caching failed\", \"Caching generated cshtml for '{0}' failed, deleting file '{1}' - '{2}'\", DiagnosticCategory, DiagnosticSeverity.Warning, true);\n        internal static DiagnosticDescriptor CachingFailedHard =\n            new DiagnosticDescriptor(\"SE009\", \"Razor caching failed hard\", \"Caching generated cshtml for '{0}' to '{1}' failed, unabled to delete cache file\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n        internal static DiagnosticDescriptor RazorParserError =\n            new DiagnosticDescriptor(\"SE010\", \"Razor parser error\", \"Razor parser error: {0}\", DiagnosticCategory, DiagnosticSeverity.Error, true);\n\n        public Compilation(PrecompilationCommandLineArgs precompilationCommandLineArgs)\n        {\n            _precompilationCommandLineArgs = precompilationCommandLineArgs;\n\n            CurrentDirectory = new DirectoryInfo(_precompilationCommandLineArgs.BaseDirectory);\n\n            AppDomain.CurrentDomain.SetData(\"DataDirectory\", Path.Combine(CurrentDirectory.FullName, \"App_Data\")); // HACK mocking ASP.NET's ~/App_Data aka. |DataDirectory|\n\n            // HACK moar HttpRuntime stuff\n            AppDomain.CurrentDomain.SetData(\".appDomain\", AppDomain.CurrentDomain.FriendlyName);\n            AppDomain.CurrentDomain.SetData(\".appPath\", CurrentDirectory.FullName);\n            AppDomain.CurrentDomain.SetData(\".appVPath\", \"/\");\n        }\n\n        public async Task<bool> RunAsync(CancellationToken cancellationToken = default(CancellationToken))\n        {\n            try\n            {\n                // this parameter was introduced in rc3, all call to it seem to be using RuntimeEnvironment.GetRuntimeDirectory()\n                // https://github.com/dotnet/roslyn/blob/0382e3e3fc543fc483090bff3ab1eaae39dfb4d9/src/Compilers/CSharp/csc/Program.cs#L18\n                var sdkDirectory = RuntimeEnvironment.GetRuntimeDirectory();\n\n                CscArgs = CSharpCommandLineParser.Default.Parse(_precompilationCommandLineArgs.Arguments, _precompilationCommandLineArgs.BaseDirectory, sdkDirectory);\n                Diagnostics = new List<Diagnostic>(CscArgs.Errors);\n\n                // load those before anything else hooks into our AssemlbyResolve.\n                var loader = new PrecompilationModuleLoader(PrecompilerSection.Current);\n                loader.ModuleInitializationFailed += (module, ex) =>\n                {\n                    Diagnostics.Add(Diagnostic.Create(\n                        FailedToCreateModule,\n                        Location.Create(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, new TextSpan(), new LinePositionSpan()),\n                        module.Type,\n                        ex.Message));\n                };\n                var compilationModules = loader.LoadedModules;\n\n                if (Diagnostics.Any())\n                {\n                    return false;\n                }\n                Encoding = CscArgs.Encoding ?? new UTF8Encoding(false); // utf8 without bom\n\n                var outputPath = Path.Combine(CscArgs.OutputDirectory, CscArgs.OutputFileName);\n                var pdbPath = CscArgs.PdbPath ?? Path.ChangeExtension(outputPath, \".pdb\");\n\n                using (var container = CreateCompositionHost())\n                using (var workspace = CreateWokspace(container))\n                using (var peStream = new MemoryStream())\n                using (var pdbStream = CscArgs.EmitPdb && CscArgs.EmitOptions.DebugInformationFormat != DebugInformationFormat.Embedded ? new MemoryStream() : null)\n                using (var xmlDocumentationStream = !string.IsNullOrWhiteSpace(CscArgs.DocumentationPath) ? new MemoryStream() : null)\n                {\n                    EmitResult emitResult = null;\n\n                    var documentExtenders = workspace.Services.FindLanguageServices<IDocumentExtender>(_ => true).ToList();\n                    var project = CreateProject(workspace, documentExtenders);\n                    CSharpCompilation compilation = null;\n                    CompilationWithAnalyzers compilationWithAnalyzers = null;\n                    try\n                    {\n                        Diagnostics.AddRange((await Task.WhenAll(documentExtenders.Select(x => x.Complete()))).SelectMany(x => x));\n                        compilation = await project.GetCompilationAsync(cancellationToken) as CSharpCompilation;\n                    }\n                    catch (Exception ex)\n                    {\n                        Diagnostics.Add(Diagnostic.Create(FailedToCreateCompilation, Location.None, ex));\n                        return false;\n                    }\n\n                    var analyzers = project.AnalyzerReferences.SelectMany(x => x.GetAnalyzers(project.Language)).ToImmutableArray();\n                    if (!analyzers.IsEmpty)\n                    {\n                        compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, project.AnalyzerOptions, cancellationToken);\n                        compilation = compilationWithAnalyzers.Compilation as CSharpCompilation;\n                    }\n\n                    var context = new CompileContext(compilationModules);\n                    context.Before(new BeforeCompileContext\n                    {\n                        Arguments = CscArgs,\n                        Compilation = compilation.AddSyntaxTrees(GeneratedSyntaxTrees()),\n                        Diagnostics = Diagnostics,\n                    });\n\n                    CscArgs = context.BeforeCompileContext.Arguments;\n                    compilation = context.BeforeCompileContext.Compilation;\n\n                    var analysisTask = compilationWithAnalyzers?.GetAnalysisResultAsync(cancellationToken);\n\n                    using (var win32Resources = CreateWin32Resource(compilation))\n                    {\n                        // PathMapping is also required here, to actually get the symbols to line up:\n                        // https://github.com/dotnet/roslyn/blob/9d081e899b35294b8f1793d31abe5e2c43698844/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs#L616\n                        // PathUtilities.NormalizePathPrefix is internal, but callable via the SourceFileResolver, that we set in CreateProject\n                        var emitOptions = CscArgs.EmitOptions\n                            .WithPdbFilePath(compilation.Options.SourceReferenceResolver.NormalizePath(pdbPath, CscArgs.BaseDirectory));\n\n                        // https://github.com/dotnet/roslyn/blob/41950e21da3ac2c307fb46c2ca8c8509b5059909/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs#L437\n                        emitResult = compilation.Emit(\n                            peStream: peStream,\n                            pdbStream: pdbStream,\n                            xmlDocumentationStream: xmlDocumentationStream,\n                            win32Resources: win32Resources,\n                            manifestResources: CscArgs.ManifestResources,\n                            options: emitOptions,\n                            sourceLinkStream: TryOpenFile(CscArgs.SourceLink, out var sourceLinkStream) ? sourceLinkStream : null,\n                            embeddedTexts: CscArgs.EmbeddedFiles.AsEnumerable()\n                                .Select(x => TryOpenFile(x.Path, out var embeddedText) ? EmbeddedText.FromStream(x.Path, embeddedText) : null)\n                                .Where(x => x != null),\n                            debugEntryPoint: null,\n                            cancellationToken: cancellationToken);\n                    }\n\n                    Diagnostics.AddRange(emitResult.Diagnostics);\n\n                    try\n                    {\n                        var analysisResult = analysisTask == null ? null : await analysisTask;\n                        if (analysisResult != null)\n                        {\n                            Diagnostics.AddRange(analysisResult.GetAllDiagnostics());\n\n                            foreach (var info in analysisResult.AnalyzerTelemetryInfo)\n                            {\n                                Console.WriteLine($\"hidden: {info.Key} {info.Value.ExecutionTime.TotalMilliseconds:#}ms\");\n                            }\n                        }\n                    }\n                    catch (OperationCanceledException)\n                    {\n                        Console.WriteLine(\"warning: analysis canceled\");\n                    }\n                    catch (Exception ex)\n                    {\n                        Diagnostics.Add(Diagnostic.Create(AnalysisFailed, Location.None, ex));\n                        return false;\n                    }\n\n                    if (!emitResult.Success || HasErrors)\n                    {\n                        return false;\n                    }\n\n                    context.After(new AfterCompileContext\n                    {\n                        Arguments = CscArgs,\n                        AssemblyStream = peStream,\n                        Compilation = compilation,\n                        Diagnostics = Diagnostics,\n                        SymbolStream = pdbStream,\n                        XmlDocStream = xmlDocumentationStream,\n                    });\n\n                    if (!HasErrors)\n                    {\n                        // do not create the output files if emit fails\n                        // if the output files are there, msbuild incremental build thinks the previous build succeeded\n                        await Task.WhenAll(\n                            DumpToFileAsync(outputPath, peStream, cancellationToken),\n                            DumpToFileAsync(pdbPath, pdbStream, cancellationToken),\n                            DumpToFileAsync(CscArgs.DocumentationPath, xmlDocumentationStream, cancellationToken));\n                        return true;\n                    }\n\n                    return false;\n                }\n            }\n            catch (PrecompilationModuleException pmex)\n            {\n                Diagnostics.Add(Diagnostic.Create(PrecompilationModuleFailed, Location.None, pmex.Message, pmex.InnerException));\n                return false;\n            }\n            catch (Exception ex)\n            {\n                Diagnostics.Add(Diagnostic.Create(UnhandledException, Location.None, ex));\n                return false;\n            }\n            finally\n            {\n                // strings only, since the Console.Out textwriter is another app domain...\n                // https://stackoverflow.com/questions/2459994/is-there-a-way-to-print-a-new-line-when-using-message\n                for (var i = 0; i < Diagnostics.Count; i++)\n                {\n                    var d = Diagnostics[i];\n                    if (!d.IsSuppressed && d.Severity != DiagnosticSeverity.Hidden)\n                    {\n                        Console.WriteLine(d.ToString().Replace(\"\\r\", \"\").Replace(\"\\n\", \"\\\\n\"));\n                    }\n                }\n            }\n        }\n\n        private bool HasErrors => Diagnostics.Any(x => !x.IsSuppressed && x.Severity == DiagnosticSeverity.Error);\n\n        private const string WorkspaceKind = nameof(StackExchange) + \".\" + nameof(StackExchange.Precompilation);\n\n        // all of this is because DesktopAnalyzerAssemblyLoader needs full paths\n        [ExportWorkspaceService(typeof(IAnalyzerService), WorkspaceKind), Shared]\n        private class CompilationAnalyzerService : IAnalyzerService, IWorkspaceService\n        {\n            private readonly IAnalyzerAssemblyLoader _loader = new CompilationAnalyzerAssemblyLoader();\n\n            public IAnalyzerAssemblyLoader GetLoader() => _loader;\n        }\n\n        private class CompilationAnalyzerAssemblyLoader : IAnalyzerAssemblyLoader\n        {\n            private static Type DesktopAssemblyLoader = Type.GetType(\"Microsoft.CodeAnalysis.DesktopAnalyzerAssemblyLoader, Microsoft.CodeAnalysis.Workspaces.Desktop\");\n            private static IAnalyzerAssemblyLoader _desktopLoader = (IAnalyzerAssemblyLoader)Activator.CreateInstance(DesktopAssemblyLoader);\n\n            private string ResolvePath(string path) => Path.IsPathRooted(path) ? path : Path.GetFullPath(path);\n\n            public void AddDependencyLocation(string fullPath) => _desktopLoader.AddDependencyLocation(ResolvePath(fullPath));\n\n            public Assembly LoadFromPath(string fullPath) => _desktopLoader.LoadFromPath(ResolvePath(fullPath));\n        }\n\n        private CompositionHost CreateCompositionHost()\n        {\n            var assemblies = new[]\n            {\n                \"Microsoft.CodeAnalysis.Workspaces\",\n                \"Microsoft.CodeAnalysis.CSharp.Workspaces\",\n                \"Microsoft.CodeAnalysis.Workspaces.Desktop\",\n                \"StackExchange.Precompilation.MVC5\",\n            };\n\n            var parts = new List<Type>();\n            foreach (var a in assemblies)\n            {\n                try\n                {\n                    parts.AddRange(Assembly.Load(a)?.GetTypes() ?? Enumerable.Empty<Type>());\n                }\n                catch (ReflectionTypeLoadException thatsWhyWeCantHaveNiceThings)\n                {\n                    // https://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes(v=vs.110).aspx#Anchor_2\n                    parts.AddRange(thatsWhyWeCantHaveNiceThings.Types.Where(x => x != null));\n                }\n                catch (FileNotFoundException nfe) when (nfe.FileName == \"StackExchange.Precompilation.MVC5\")\n                {\n                    // enable this to be loaded dynamically\n                }\n            }\n\n            return new ContainerConfiguration()\n                .WithParts(parts)\n                .WithPart<CompilationAnalyzerService>()\n                .WithPart<CompilationAnalyzerAssemblyLoader>()\n                .CreateContainer();\n        }\n\n        private static AdhocWorkspace CreateWokspace(CompositionHost container)\n        {\n            var host = MefHostServices.Create(container);\n            // belive me, I did try DesktopMefHostServices.DefaultServices\n            var workspace = new AdhocWorkspace(host, WorkspaceKind);\n            return workspace;\n        }\n\n        private Project CreateProject(AdhocWorkspace workspace, List<IDocumentExtender> documentExtenders)\n        {\n            var projectInfo = CommandLineProject.CreateProjectInfo(CscArgs.OutputFileName, \"C#\", Environment.CommandLine, _precompilationCommandLineArgs.BaseDirectory, workspace);\n\n            projectInfo = projectInfo\n                .WithCompilationOptions(CscArgs.CompilationOptions\n                    .WithSourceReferenceResolver(new SourceFileResolver(CscArgs.SourcePaths, CscArgs.BaseDirectory, CscArgs.PathMap))) // required for path mapping support\n                .WithDocuments(\n                    projectInfo\n                        .Documents\n                        .Select(d => documentExtenders.Aggregate(d, (doc, ex) => ex.Extend(doc))));\n\n            return workspace.AddProject(projectInfo);\n        }\n\n        private bool TryOpenFile(string path, out Stream stream)\n        {\n            stream = null;\n            if (string.IsNullOrEmpty(path))\n            {\n                return false;\n            }\n            if (!File.Exists(path))\n            {\n                Diagnostics.Add(Diagnostic.Create(ERR_FileNotFound, null, path));\n                return false;\n            }\n            try\n            {\n                stream = File.OpenRead(path);\n                return true;\n            }\n            catch (Exception ex)\n            {\n                Diagnostics.Add(Diagnostic.Create(ERR_NoSourceFile, null, path, ex.Message));\n                return false;\n            }\n        }\n\n        private Stream CreateWin32Resource(CSharpCompilation compilation)\n        {\n            if (TryOpenFile(CscArgs.Win32ResourceFile, out var stream)) return stream;\n\n            using (var manifestStream = compilation.Options.OutputKind != OutputKind.NetModule && TryOpenFile(CscArgs.Win32Manifest, out var manifest) ? manifest : null)\n            using (var iconStream = TryOpenFile(CscArgs.Win32Icon, out var icon) ? icon : null)\n                return compilation.CreateDefaultWin32Resources(true, CscArgs.NoWin32Manifest, manifestStream, iconStream);\n        }\n\n        private static async Task DumpToFileAsync(string path, MemoryStream stream, CancellationToken cancellationToken)\n        {\n            if (stream?.Length > 0)\n            {\n                stream.Position = 0;\n                using (var file = File.Create(path))\n                using (cancellationToken.Register(() => { try { File.Delete(path); } catch { } }))\n                {\n                    await stream.CopyToAsync(file, 4096, cancellationToken);\n                }\n            }\n        }\n\n        private sealed class NaiveReferenceResolver : MetadataReferenceResolver\n        {\n            private NaiveReferenceResolver() { }\n            public static NaiveReferenceResolver Instance { get; } = new NaiveReferenceResolver();\n            public override bool Equals(object other) => other is NaiveReferenceResolver;\n\n            public override int GetHashCode() => 42;\n\n            public override ImmutableArray<PortableExecutableReference> ResolveReference(string reference, string baseFilePath, MetadataReferenceProperties properties)\n                => ImmutableArray.Create(MetadataReference.CreateFromFile(reference, properties));\n        }\n\n        private IEnumerable<SyntaxTree> GeneratedSyntaxTrees()\n        {\n            yield return SyntaxFactory.ParseSyntaxTree($\"[assembly: {typeof(CompiledFromDirectoryAttribute).FullName}(@\\\"{CurrentDirectory.FullName}\\\")]\", CscArgs.ParseOptions);\n        }\n\n        public Location AsLocation(string path)\n        {\n            return Location.Create(path, new TextSpan(), new LinePositionSpan());\n        }\n    }\n\n    public interface IDocumentExtender : ILanguageService\n    {\n        DocumentInfo Extend(DocumentInfo document);\n        Task<ICollection<Diagnostic>> Complete();\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation.Build/CompilationAssemblyResolver.cs",
    "content": "﻿using System;\nusing System.Collections.Concurrent;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace StackExchange.Precompilation\n{\n\n    class CompilationAssemblyResolver : MarshalByRefObject\n    {\n        internal static void Register(AppDomain domain, string[] references)\n        {\n            CompilationAssemblyResolver resolver =\n                domain.CreateInstanceFromAndUnwrap(\n                  Assembly.GetExecutingAssembly().Location,\n                  typeof(CompilationAssemblyResolver).FullName) as CompilationAssemblyResolver;\n            resolver.RegisterDomain(domain);\n            resolver.Setup(references);\n        }\n\n        private AppDomain domain;\n        private readonly ConcurrentDictionary<string, Lazy<Assembly>> resolvedAssemblies = new ConcurrentDictionary<string, Lazy<Assembly>>();\n\n        private void Setup(string[] references)\n        {\n            void Resolve(AssemblyName name, Func<Assembly> loader)\n            {\n                var resolved = new Lazy<Assembly>(loader, LazyThreadSafetyMode.ExecutionAndPublication);\n                var keyName = new AssemblyName(ApplyPolicy(name.FullName));\n                resolvedAssemblies.AddOrUpdate(keyName.FullName, resolved, (key, existing) => existing); // TODO log conflicting binds?\n                resolvedAssemblies.AddOrUpdate(keyName.Name, resolved, (key, existing) => existing); // TODO log conflicting partial binds?\n            }\n\n            // load runtime references from tools/*.dll\n\n            var location = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);\n            Directory.EnumerateFiles(location, \"*.dll\")\n                .AsParallel()\n                .ForAll(dll =>\n                {\n                    try\n                    {\n                        var assemblyName = AssemblyName.GetAssemblyName(dll);\n                        Resolve(assemblyName, () => Assembly.LoadFile(dll));\n                    }\n                    catch (Exception ex)\n                    {\n                        Console.WriteLine(\"hidden: failed to resolve assembly {0}: {1}\", dll, ex.Message);\n                    }\n                });\n\n            // load all the other references\n            references\n                .AsParallel()\n                .Select(x =>\n                {\n                    try\n                    {\n                        return AssemblyName.GetAssemblyName(x);\n                    }\n                    catch (Exception ex)\n                    {\n                        Console.WriteLine($\"warning: Couldn't load reference from '{x}' - '{ex.Message}'\");\n                        return null;\n                    }\n                })\n                .Where(x => x != null)\n                .ForAll(name => Resolve(name, () =>\n                {\n                    var path = new Uri(name.CodeBase).LocalPath;\n                    try\n                    {\n                        return Assembly.LoadFile(path);\n                    }\n                    catch (Exception ex)\n                    {\n                        Console.WriteLine($\"warning: Couldn't load reference '{name.FullName}' from '{path}' - '{ex.Message}'\");\n                        return null;\n                    }\n                }));\n        }\n\n        private void RegisterDomain(AppDomain domain)\n        {\n            this.domain = domain;\n            this.domain.AssemblyResolve += ResolveAssembly;\n        }\n\n        private string ApplyPolicy(string name)\n        {\n            while (true) {\n                var newName = domain.ApplyPolicy(name);\n                if (newName == name) return name;\n                name = newName;\n            }\n        }\n\n        private Assembly ResolveAssembly(object sender, ResolveEventArgs e)\n        {\n            var name = ApplyPolicy(e.Name);\n            var assemblyName = new AssemblyName(name);\n\n            return resolvedAssemblies.GetOrAdd(assemblyName.FullName, NullAssembly).Value ??\n                   resolvedAssemblies.GetOrAdd(assemblyName.Name, NullAssembly).Value;\n        }\n\n        private static Lazy<Assembly> NullAssembly(string key) => new Lazy<Assembly>(() => null, LazyThreadSafetyMode.ExecutionAndPublication);\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation.Build/CompilationProxy.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\n\nnamespace StackExchange.Precompilation\n{\n    class CompilationProxy : MarshalByRefObject\n    {\n        public static bool RunCs(string[] args)\n        {\n            var precompilationArgs = PrecompilationCommandLineParser.Parse(args, Directory.GetCurrentDirectory());\n\n            CompilationProxy proxy = null;\n            AppDomain compilationDomain = null;\n            try\n            {\n                var currentSetup = AppDomain.CurrentDomain.SetupInformation;\n                var setup = new AppDomainSetup()\n                {\n                    ApplicationName = currentSetup.ApplicationName,\n                    ApplicationBase = currentSetup.ApplicationBase,\n                    ConfigurationFile = precompilationArgs.AppConfig,\n                    DisallowBindingRedirects = true,\n                };\n\n                if (setup.ConfigurationFile == null)\n                {\n                    setup.ConfigurationFile = new[] { \"app.config\", \"web.config\" }.Select(x => Path.Combine(precompilationArgs.BaseDirectory, x)).FirstOrDefault(File.Exists);\n                    if (!string.IsNullOrWhiteSpace(setup.ConfigurationFile))\n                    {\n                        Console.WriteLine(\"WARNING: '\" + setup.ConfigurationFile + \"' used as fallback config file\");\n                    }\n                }\n\n                compilationDomain = AppDomain.CreateDomain(\n                    AppDomainHelper.CsCompilationAppDomainName,\n                    AppDomain.CurrentDomain.Evidence,\n                    setup);\n                compilationDomain.UnhandledException += (s, e) =>\n                {\n                    Console.WriteLine(\"error: \" + e);\n                };\n\n                var references = precompilationArgs.References; //.Concat(Directory.EnumerateFiles(AppDomain.CurrentDomain.BaseDirectory).Where(r => assemblyExt.Contains(Path.GetExtension(r)))).ToArray()\n                CompilationAssemblyResolver.Register(compilationDomain, references);\n\n\n                proxy = (CompilationProxy)compilationDomain.CreateInstanceAndUnwrap(\n                    typeof(CompilationProxy).Assembly.FullName,\n                    typeof(CompilationProxy).FullName);\n\n                Console.CancelKeyPress += (s, e) => proxy?.ForceStop();\n                return proxy.RunCs(precompilationArgs);\n            }\n            finally\n            {\n                proxy?.ForceStop();\n                // runtime has exited, finish off by unloading the runtime appdomain\n                if (compilationDomain != null) AppDomain.Unload(compilationDomain);\n            }\n        }\n\n        public override object InitializeLifetimeService() => null;\n\n        private CancellationTokenSource _cts;\n\n        // ReSharper disable MemberCanBeMadeStatic.Local\n        // making the methods below static would not be a good idea, they need to run in the _compilation app domain\n        private bool RunCs(PrecompilationCommandLineArgs precompilationArgs)\n        {\n            _cts = new CancellationTokenSource();\n            return new Compilation(precompilationArgs).RunAsync(_cts.Token).Result;\n        }\n\n        private void ForceStop()\n        {\n            var cts = _cts;\n            _cts = null;\n            cts?.Cancel();\n            cts?.Dispose();\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation.Build/ICompilationProxy.cs",
    "content": "﻿namespace StackExchange.Precompilation\n{\n    interface ICompilationProxy\n    {\n        object InitializeLifetimeService();\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation.Build/PrecompilationCommandLineArgs.cs",
    "content": "using System;\n\nnamespace StackExchange.Precompilation\n{\n    [Serializable]\n    public class PrecompilationCommandLineArgs : MarshalByRefObject\n    {\n        /// <summary>\n        /// Unprocessed arguments.\n        /// </summary>\n        public string[] Arguments { get; set; }\n\n        /// <summary>\n        /// The current directory in which the compilation was started.\n        /// </summary>\n        public string BaseDirectory { get; set; }\n\n        /// <summary>\n        /// The value of the /appconfig switch if present.\n        /// </summary>\n        public string AppConfig { get; set; }\n\n        /// <summary>\n        /// The values of the /reference switches.\n        /// </summary>\n        public string[] References { get; set; }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation.Build/PrecompilationCommandLineParser.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Text.RegularExpressions;\n\nnamespace StackExchange.Precompilation\n{\n    // we need the values of the /reference and the /appconfig switches before we spin up the app domain\n    // to get those we need to either spin up a new AppDomain and load Microsoft.CodeAnalysis.CSharp to use CSharpCommandLineParser or parse the args ourselves\n    // https://msdn.microsoft.com/en-us/library/78f4aasd.aspx\n    public class PrecompilationCommandLineParser\n    {\n        private static readonly Regex UnespacedBackslashes = new Regex(@\"(?!\\\\+\"\")\\\\+\", RegexOptions.Compiled);\n        private static readonly Regex QuotesAfterSingleBackSlash = new Regex(@\"(?<=(^|[^\\\\])((\\\\\\\\)+)?)\"\"\", RegexOptions.ExplicitCapture | RegexOptions.Compiled);\n        private static readonly Regex Escaped = new Regex(@\"\\\\(\\\\|\"\")\", RegexOptions.Compiled);\n\n        public static string[] SplitCommandLine(string commandLine)\n        {\n            return Split(commandLine)\n                .TakeWhile(arg => !arg.StartsWith(\"#\", StringComparison.Ordinal))\n                .Select(dirty => UnespacedBackslashes.Replace(dirty, \"$0$0\"))\n                .Select(normalized => QuotesAfterSingleBackSlash.Replace(normalized, \"\"))\n                .Select(unquoted => Escaped.Replace(unquoted, \"$1\"))\n                .Where(arg => !string.IsNullOrEmpty(arg))\n                .Select(str => str.Trim())\n                .ToArray();\n        }\n\n        private static IEnumerable<string> Split(string commandLine)\n        {\n            var isQuoted = false;\n            var backslashCount = 0;\n            var splitIndex = 0;\n            var length = commandLine.Length;\n\n            for (var i = 0; i < length; i++)\n            {\n                var c = commandLine[i];\n                switch (c)\n                {\n                    case '\\\\':\n                        backslashCount += 1;\n                        break;\n                    case '\\\"':\n                        if (backslashCount % 2 == 0) isQuoted = !isQuoted;\n                        goto default;\n                    case ' ':\n                    case '\\t':\n                    case '\\n':\n                    case '\\r':\n                        if (!isQuoted)\n                        {\n                            var take = i - splitIndex;\n                            if (take > 0)\n                            {\n                                yield return commandLine.Substring(splitIndex, take);\n                            }\n                            splitIndex = i + 1;\n                        }\n                        goto default;\n                    default:\n                        backslashCount = 0;\n                        break;\n                }\n            }\n\n            if (splitIndex < length)\n            {\n                yield return commandLine.Substring(splitIndex);\n            }\n        }\n\n        private static readonly Regex Reference = new Regex(@\"/r(eference)?:(?<alias>[\\w_]+=)?\", RegexOptions.IgnoreCase | RegexOptions.Compiled);\n\n        public static PrecompilationCommandLineArgs Parse(string[] arguments, string baseDirectory)\n        {\n            var result = new PrecompilationCommandLineArgs { Arguments = arguments, BaseDirectory = baseDirectory };\n            if (arguments == null) return result;\n\n            var loadedRsp = new HashSet<string>();\n            var references = new HashSet<string>();\n            for(var i = 0; i < arguments.Length; i++)\n            {\n                var arg = arguments[i];\n                var reference = Reference.Match(arg);\n                if(arg.StartsWith(\"@\"))\n                {\n                    if (!loadedRsp.Add(arg = ParseFileFromArg(arg, '@'))) continue;\n                    arguments = arguments.Concat(File.ReadAllLines(arg).SelectMany(SplitCommandLine)).ToArray();\n                }\n                else if(reference.Success)\n                {\n                    // don't care about reference aliases in the compilation appdomain\n                    // https://msdn.microsoft.com/en-us/library/ms173212.aspx\n                    references.Add(ParseFileFromArg(arg, reference.Groups[\"alias\"].Success ? '=' : ':'));\n                }\n                else if(arg.StartsWith(\"/appconfig:\"))\n                {\n                    result.AppConfig = ParseFileFromArg(arg);\n                }\n            }\n            result.References = references.ToArray();\n            return result;\n        }\n\n        private static string ParseFileFromArg(string arg, char delimiter = ':')\n        {\n            return Path.GetFullPath(arg.Substring(arg.IndexOf(delimiter) + 1));\n        }\n    }\n}"
  },
  {
    "path": "StackExchange.Precompilation.Build/Program.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing Microsoft.CodeAnalysis.CSharp;\n\nnamespace StackExchange.Precompilation\n{\n    static class Program\n    {\n        static void Main(string[] args)\n        {\n            try\n            {\n                if (!CompilationProxy.RunCs(args))\n                {\n                    Environment.ExitCode = 1;\n                }\n            }\n            catch (Exception ex)\n            {\n                var agg = ex as AggregateException;\n                Console.WriteLine(\"ERROR: An unhandled exception occured\");\n                if (agg != null)\n                {\n                    agg = agg.Flatten();\n                    foreach (var inner in agg.InnerExceptions)\n                    {\n                        Console.Error.WriteLine(\"error: \" + inner);\n                    }\n                }\n                else\n                {\n                    Console.Error.WriteLine(\"error: \" + ex);\n                }\n                Environment.ExitCode = 2;\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation.Build/StackExchange.Precompilation.Build.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n<PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net462</TargetFramework>\n    <AssemblyName>StackExchange.Precompiler</AssemblyName>\n    <Description>Replaces CSC and aspnet_compiler.exe with StackExchange.Precompiler for compiling C# (.cs) and Razor View (.cshtml) files in asp.net mvc 5 projects.</Description>\n    <IsTool>true</IsTool>\n    <IsPackable>true</IsPackable>\n    <PackageId>StackExchange.Precompilation.Build</PackageId>\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\n    <BeforePack>_ToolsSetup;$(BeforePack)</BeforePack>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\StackExchange.Precompilation\\StackExchange.Precompilation.csproj\">\n      <Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>\n      <Name>StackExchange.Precompilation</Name>\n    </ProjectReference>\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp.Workspaces\" Version=\"2.10.0\" PrivateAssets=\"all\" />\n    <PackageReference Include=\"Microsoft.DiaSymReader.Native\" Version=\"1.7.0\" PrivateAssets=\"all\" />\n  </ItemGroup>\n\n  <Target Name=\"_ToolsSetup\">\n    <ItemGroup>\n      <_BinOutputs Include=\"bin\\$(Configuration)\\$(TargetFramework)\\*.*\"  />\n      <None Include=\"@(_BinOutputs)\" Pack=\"true\" PackagePath=\"tools\\%(Filename)%(Extension)\" Condition=\"'%(Extension)' == '.dll' or '%(Extension)' == '.pdb' or '%(Extension)' == '.config'\" />\n      <None Include=\"*.targets\" Pack=\"true\" PackagePath=\"build\" />\n    </ItemGroup>\n  </Target>\n\n</Project>"
  },
  {
    "path": "StackExchange.Precompilation.Build/StackExchange.Precompilation.Build.packages.config",
    "content": "﻿  <!--\n    HACK\n\n    We need to include the native DiaSymReader Native runtime files in order to support sourcelink etc.\n    Roslyn does it too: https://github.com/dotnet/roslyn/blob/1fe72cd3f196005a1a407c582f60145d096b2f43/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj#L26-L37\n    We make build/Microsoft.DiaSymRerader.Native.props from the package do it, via the existance of this dummy packages.config file.\n   -->\n"
  },
  {
    "path": "StackExchange.Precompilation.Build/StackExchange.Precompilation.Build.targets",
    "content": "﻿<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n    <PropertyGroup>\n        <!-- CREDITS:\n                https://razorgenerator.codeplex.com/SourceControl/latest#RazorGenerator.MsBuild/RazorGenerator.MsBuild.targets\n                http://www.nuget.org/packages/Microsoft.Net.ToolsetCompilers -> /tools/Microsoft.Net.ToolsetCompilers.props\n        -->\n        <SEPrecompilerSkip Condition=\"'$(SEPrecompilerSkip)' == ''\">false</SEPrecompilerSkip>\n        <SEPrecompilerIncludeRazor Condition=\"'$(SEPrecompilerIncludeRazor)' == ''\">false</SEPrecompilerIncludeRazor>\n        <CompileDependsOn>\n            $(CompileDependsOn);\n            SEPrecompilerCore;\n        </CompileDependsOn>\n        <SEPrecompilerTools>$(MSBuildThisFileDirectory)..\\tools</SEPrecompilerTools>\n        <UseAppConfigForCompiler Condition=\"'$(UseAppConfigForCompiler)' == '' and '$(SEPrecompilerSkip)' != 'true'\">true</UseAppConfigForCompiler>\n    </PropertyGroup>\n    <Target Name=\"SEPrecompilerSetup\">\n        <PropertyGroup>\n            <SEPrecompilerPath Condition=\"'$(SEPrecompilerPath)' == ''\">$(SEPrecompilerTools)</SEPrecompilerPath>\n            <SEPrecompilerCscToolPath>$(SEPrecompilerPath)</SEPrecompilerCscToolPath>\n            <SEPrecompilerCscToolExe>StackExchange.Precompiler.exe</SEPrecompilerCscToolExe>\n        </PropertyGroup>\n    </Target>\n    <Target Name=\"SEPrecompilerCore\"\n            BeforeTargets=\"CoreCompile\"\n            AfterTargets=\"AfterResolveReferences\"\n            Condition=\"'$(BuildingProject)' == 'true' and '$(SEPrecompilerSkip)' != 'true'\"\n            DependsOnTargets=\"SEPrecompilerSetup\">\n        <PropertyGroup>\n            <CscToolPath>$(SEPrecompilerCscToolPath)</CscToolPath>\n            <CscToolExe>$(SEPrecompilerCscToolExe)</CscToolExe>\n        </PropertyGroup>\n        <ItemGroup>\n            <Compile Include=\"@(Content)\" Condition=\"'$(SEPrecompilerIncludeRazor)' == 'true' and '%(Extension)' == '.cshtml'\" />\n            <Compile Include=\"@(None)\"    Condition=\"'$(SEPrecompilerIncludeRazor)' == 'true' and '%(Extension)' == '.cshtml'\" />\n        </ItemGroup>\n    </Target>\n</Project>\n"
  },
  {
    "path": "StackExchange.Precompilation.Tests/CommandLineTests.cs",
    "content": "﻿using System;\nusing System.IO;\nusing System.Linq;\nusing NUnit.Framework;\n\nnamespace StackExchange.Precompilation.Tests\n{\n    [TestFixture]\n    public class CommandLineTests\n    {\n        // test cases from https://github.com/dotnet/roslyn/blob/9c66e81c1424d8f4999f70eb8b85f0e76f253c30/src/Compilers/Core/CodeAnalysisTest/CommonCommandLineParserTests.cs#L83\n        [Test]\n        [TestCase(\"\", new string[0])]\n        [TestCase(\"   \\t   \", new string[0])]\n        [TestCase(\"   abc\\tdef baz    quuz   \", new[] { \"abc\", \"def\", \"baz\", \"quuz\" })]\n        [TestCase(@\"  \"\"abc def\"\"  fi\"\"ddle dee de\"\"e  \"\"hi there \"\"dude  he\"\"llo there\"\"  \", new [] { @\"abc def\", @\"fiddle dee dee\", @\"hi there dude\", @\"hello there\" })]\n        [TestCase(@\"  \"\"abc def \\\"\" baz quuz\"\" \"\"\\\"\"straw berry\"\" fi\\\"\"zz \\\"\"buzz fizzbuzz\", new [] { @\"abc def \"\" baz quuz\", @\"\"\"straw berry\", @\"fi\"\"zz\", @\"\"\"buzz\", @\"fizzbuzz\" })]\n        [TestCase(@\"  \\\\\"\"abc def\"\"  \\\\\\\"\"abc def\"\" \", new [] { @\"\\abc def\", @\"\\\"\"abc\", @\"def\" })]\n        [TestCase(@\"  \\\\\\\\\"\"abc def\"\"  \\\\\\\\\\\"\"abc def\"\" \", new [] { @\"\\\\abc def\", @\"\\\\\"\"abc\", @\"def\" })]\n        [TestCase(@\"  \\\\\\\\\"\"abc def\"\"  \\\\\\\\\\\"\"abc def\"\" q a r \", new [] { @\"\\\\abc def\", @\"\\\\\"\"abc\", @\"def q a r\" })]\n        [TestCase(@\"abc #Comment ignored\", new [] { @\"abc\" })]\n        public static void SplitArguments(string input, string[] expected)\n        {\n            var actual = PrecompilationCommandLineParser.SplitCommandLine(input);\n\n            CollectionAssert.AreEqual(expected, actual);\n        }\n\n        [Test]\n        public void ParseArguments()\n        {\n            Assert.DoesNotThrow(() => PrecompilationCommandLineParser.Parse(null, null));\n            Assert.DoesNotThrow(() => PrecompilationCommandLineParser.Parse(new string[0], null));\n            Assert.DoesNotThrow(() => PrecompilationCommandLineParser.Parse(null, \"\"));\n            Assert.DoesNotThrow(() => PrecompilationCommandLineParser.Parse(new string[0], \"\"));\n        }\n\n        [Test]\n        [TestCase(\"a b c\", new string[0], (string)null)]\n        [TestCase(\"a b /r:c.dll\", new[] { \"c.dll\" }, (string)null)]\n        [TestCase(\"a b /r:a=c.dll\", new[] { \"c.dll\" }, (string)null)]\n        [TestCase(\"a b /reference:a=c.dll\", new[] { \"c.dll\" }, (string)null)]\n        [TestCase(\"a b /r:c.dll /r:d.dll\", new[] { \"c.dll\", \"d.dll\" }, (string)null)]\n        [TestCase(\"a b /r:c.dll /appconfig:moar.config /r:d.dll\", new[] { \"c.dll\", \"d.dll\" }, \"moar.config\")]\n        [TestCase(\"a b /r:alias=c.dll /appconfig:moar.config /reference:d.dll\", new[] { \"c.dll\", \"d.dll\" }, \"moar.config\")]\n        public void ParseArgumentCases(string cmdline, string[] references, string appconfig)\n        {\n            var dir = Guid.NewGuid().ToString();\n            var args = PrecompilationCommandLineParser.SplitCommandLine(cmdline);\n            var parsed = PrecompilationCommandLineParser.Parse(args, dir);\n            Func<string, string> resolvePath = Path.GetFullPath;\n\n            Assert.AreEqual(dir, parsed.BaseDirectory);\n            Assert.AreEqual(appconfig == null ? null : resolvePath(appconfig), parsed.AppConfig);\n            CollectionAssert.AreEqual(references.Select(resolvePath), parsed.References);\n        }\n    }\n}\n"
  },
  {
    "path": "StackExchange.Precompilation.Tests/StackExchange.Precompilation.Tests.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net462</TargetFramework>\n    <Platform>x86</Platform>\n    <PlatformTarget>x86</PlatformTarget>\n  </PropertyGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"15.5.0\" />\n    <PackageReference Include=\"NUnit\" Version=\"3.11.0\" />\n    <PackageReference Include=\"NUnit3TestAdapter\" Version=\"3.11.2\" />\n    <ProjectReference Include=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.csproj\">\n      <Project>{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}</Project>\n      <Name>StackExchange.Precompilation.Build</Name>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "StackExchange.Precompilation.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.27428.2015\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"StackExchange.Precompilation.Build\", \"StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.csproj\", \"{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"StackExchange.Precompilation\", \"StackExchange.Precompilation\\StackExchange.Precompilation.csproj\", \"{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \".nuget\", \".nuget\", \"{5958EFE5-C8D6-4759-9A8E-8C64558314FD}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t.nuget\\NuGet.Config = .nuget\\NuGet.Config\n\t\t.nuget\\NuGet.exe = .nuget\\NuGet.exe\n\t\t.nuget\\NuGet.targets = .nuget\\NuGet.targets\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Test.Module\", \"Test.Module\\Test.Module.csproj\", \"{5FCAECC3-787B-473F-A372-783D0C235190}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Test.ConsoleApp\", \"Test.ConsoleApp\\Test.ConsoleApp.csproj\", \"{BA716DA2-4E3C-4D9F-B9C2-78C0EAEF66D7}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Test.WebApp\", \"Test.WebApp\\Test.WebApp.csproj\", \"{5B0105A4-256B-4A88-852C-6F5E9D185515}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9} = {31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{A6462B41-5067-4F2B-B5B8-B7BD1B2D75CB}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tBuildAndPack.ps1 = BuildAndPack.ps1\n\t\tPrepareForPack.ps1 = PrepareForPack.ps1\n\t\tsemver.txt = semver.txt\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"StackExchange.Precompilation.Tests\", \"StackExchange.Precompilation.Tests\\StackExchange.Precompilation.Tests.csproj\", \"{B6306D9B-0770-44DF-AADE-5703B1DCFD67}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3} = {C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}\n\t\t{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D} = {3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"Test.WebApp.ExternalViews\", \"Test.WebApp.ExternalViews\\Test.WebApp.ExternalViews.csproj\", \"{2BA24772-F7B0-4652-A430-2F4C2262E882}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{5FCAECC3-787B-473F-A372-783D0C235190} = {5FCAECC3-787B-473F-A372-783D0C235190}\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9} = {31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}\n\tEndProjectSection\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"StackExchange.Precompilation.MVC5\", \"StackExhcange.Precompilation.MVC5\\StackExchange.Precompilation.MVC5.csproj\", \"{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{31DFCCCC-2F44-405E-A2D7-BB1AC718E7B9}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{5FCAECC3-787B-473F-A372-783D0C235190}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{5FCAECC3-787B-473F-A372-783D0C235190}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{5FCAECC3-787B-473F-A372-783D0C235190}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{5FCAECC3-787B-473F-A372-783D0C235190}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{BA716DA2-4E3C-4D9F-B9C2-78C0EAEF66D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{BA716DA2-4E3C-4D9F-B9C2-78C0EAEF66D7}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{BA716DA2-4E3C-4D9F-B9C2-78C0EAEF66D7}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{BA716DA2-4E3C-4D9F-B9C2-78C0EAEF66D7}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{5B0105A4-256B-4A88-852C-6F5E9D185515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{5B0105A4-256B-4A88-852C-6F5E9D185515}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{5B0105A4-256B-4A88-852C-6F5E9D185515}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{5B0105A4-256B-4A88-852C-6F5E9D185515}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{B6306D9B-0770-44DF-AADE-5703B1DCFD67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{B6306D9B-0770-44DF-AADE-5703B1DCFD67}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{B6306D9B-0770-44DF-AADE-5703B1DCFD67}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{B6306D9B-0770-44DF-AADE-5703B1DCFD67}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{2BA24772-F7B0-4652-A430-2F4C2262E882}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{2BA24772-F7B0-4652-A430-2F4C2262E882}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{2BA24772-F7B0-4652-A430-2F4C2262E882}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{2BA24772-F7B0-4652-A430-2F4C2262E882}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{C8F659BD-D0D1-4404-9CC5-3F14ED4B28F3}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {153D37EE-CF3F-42D8-9703-EE953797B3A9}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/Hacks.cs",
    "content": "﻿using Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing System;\nusing System.Reflection;\nusing System.Web.Mvc;\n\nnamespace StackExchange.Precompilation\n{\n    static class Hacks\n    {\n        private static readonly Action<WebViewPage, string> WebViewPage_OverridenLayoutPathSetter = \n            (Action<WebViewPage, string>)typeof(WebViewPage)\n            .GetProperty(\"OverridenLayoutPath\", BindingFlags.Instance | BindingFlags.NonPublic)\n            .SetMethod\n            .CreateDelegate(typeof(Action<WebViewPage, string>));\n\n        /// <summary>\n        /// Sets the WebViewPage.OverridenLayoutPath internal property, the only way to handle\n        /// <see cref=\"ViewResult.MasterName\" /> values.\n        /// </summary>\n        /// <remarks>\n        /// Using reflection to get a mis-spelled internal property setter and calling it via reflection.\n        /// What could possibly go wrong?\n        /// </remarks>\n        public static void SetOverriddenLayoutPath(WebViewPage webViewPage, string overridenLayoutPath) =>\n            WebViewPage_OverridenLayoutPathSetter.Invoke(webViewPage, overridenLayoutPath);\n\n        /// <summary>\n        /// Bear with me, so, in case a the view engine is being executed in a page targeting net45+ (including net46*)\n        /// on a system that has net47+ installed, mscorlib contained referenced by BuildManager already\n        /// contains ValueTuple, but due to this package referencing CodeAnalysis.Common, which also pulls in\n        /// the System.ValueTuple package, that gets copied to /bin, and is therefore also picked up as a\n        /// reference in build manager.\n        /// This causes compilation.GetTypeByMetadataName(\"System.ValueTuple`2\") to return null due to an\n        /// ambigous match, resulting in the lovely CS8137 and CS8179 warnings, at runtime.\n        /// The contents of the /bin directory get included due to the default <![CDATA[<add name=\"*\" />]]> entry.\n        /// <![CDATA[<remove name=\"*\" />]]> doesn't work since it fails to load the assembly generated for global.asax.cs\n        /// <![CDATA[<remove name=\"System.ValueTuple\" />]]> doesn't work, since the wildcard takes preference\n        /// https://referencesource.microsoft.com/#System.Web/Configuration/CompilationSection.cs,119d7e4aae57b4b6\n        /// <para />\n        /// So when this is the case, we need to remove the reference to the System.ValueTuple.dll\n        /// </summary>\n        /// <param name=\"compilation\"></param>\n        /// <returns></returns>\n        public static CSharpCompilation MakeValueTuplesWorkWhenRunningOn47RuntimeAndTargetingNet45Plus(CSharpCompilation compilation)\n        {\n            var mscorlibAssembly = typeof(object).Assembly;\n            var valueTupleAssembly = typeof(ValueTuple).Assembly;\n            if (mscorlibAssembly != valueTupleAssembly &&\n                compilation.GetAssemblyOrModuleSymbol(RoslynRazorViewEngine.ResolveReference(mscorlibAssembly)) is IAssemblySymbol mscorlib)\n            {\n                compilation = compilation.RemoveReferences(RoslynRazorViewEngine.ResolveReference(valueTupleAssembly));\n            }\n\n            return compilation;\n        }\n    }\n}\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/PrecompilationView.cs",
    "content": "﻿using System;\nusing System.Web.Mvc;\nusing System.Web.WebPages;\n\nnamespace StackExchange.Precompilation\n{\n    internal class PrecompilationView : IView\n    {\n        private readonly string _virtualPath;\n        private readonly string _masterPath;\n        private readonly Type _viewType;\n        private readonly ProfiledVirtualPathProviderViewEngine _viewEngine;\n        private readonly bool _runViewStart;\n\n        public PrecompilationView(string virtualPath, string masterPath, Type viewType, bool runViewStart, ProfiledVirtualPathProviderViewEngine viewEngine)\n        {\n            _virtualPath = virtualPath;\n            _masterPath = masterPath;\n            _viewType = viewType;\n            _runViewStart = runViewStart;\n            _viewEngine = viewEngine;\n        }\n\n        private WebPageBase CreatePage(ViewContext viewContext, System.IO.TextWriter writer, out WebPageContext pageContext, out WebPageRenderingBase startPage)\n        {\n            var basePage = (WebPageBase)Activator.CreateInstance(_viewType);\n            basePage.VirtualPath = _virtualPath;\n            basePage.VirtualPathFactory = _viewEngine.VirtualPathFactory;\n\n            pageContext = new WebPageContext(viewContext.HttpContext, basePage, viewContext.ViewData?.Model);\n\n            startPage = _runViewStart\n                ? StartPage.GetStartPage(basePage, \"_ViewStart\", _viewEngine.FileExtensions)\n                : null;\n\n            var viewPage = basePage as WebViewPage;\n            if (viewPage != null)\n            {\n                if (!string.IsNullOrEmpty(_masterPath))\n                {\n                    Hacks.SetOverriddenLayoutPath(viewPage, _masterPath);\n                }\n\n                viewPage.ViewContext = viewContext;\n                viewPage.ViewData = viewContext.ViewData;\n                viewPage.InitHelpers();\n            }\n\n            return basePage;\n        }\n\n        public void Render(ViewContext viewContext, System.IO.TextWriter writer)\n        {\n            using (_viewEngine.DoProfileStep(\"Render\"))\n            {\n                var webViewPage = CreatePage(viewContext, writer, out var pageContext, out var startPage);\n\n                using (_viewEngine.DoProfileStep(\"ExecutePageHierarchy\"))\n                {\n                    webViewPage.ExecutePageHierarchy(pageContext, writer, startPage);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/PrecompilationVirtualPathFactory.cs",
    "content": "﻿using System;\nusing System.Web.WebPages;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// <see cref=\"WebPageExecutingBase.VirtualPathFactory\"/> is used for resolving virtual paths once a view has\n    /// been resolved. Setting it to an <see cref=\"IVirtualPathFactory\"/> assumes that all underlying virtual paths\n    /// are resolvable (layouts partials etc) are resolvable using the given instance. This can lead to some side \n    /// effect when different view engines are combined, and the matching views are intermixed.\n    /// </summary>\n    /// <remarks>\n    /// This is our version of the <see cref=\"VirtualPathFactoryManager\"/>, which is meant for extending the pipeline,\n    /// mentioned above, but is not extendable in the sense that it always falls back to <see cref=\"System.Web.Compilation.BuildManager\"/>,\n    /// which calls the old csc.exe in the framework dir, not the shiny one from our nuget package,\n    /// and can thus cause unexpected behavior at runtime.\n    /// </remarks>\n    internal class PrecompilationVirtualPathFactory : IVirtualPathFactory\n    {\n        private readonly PrecompiledViewEngine _precompiled;\n        private readonly RoslynRazorViewEngine _runtime;\n\n        public PrecompilationVirtualPathFactory(PrecompiledViewEngine precompiled = null, RoslynRazorViewEngine runtime = null)\n        {\n            _precompiled = precompiled;\n            _runtime = runtime;\n        }\n\n        public object CreateInstance(string virtualPath)\n        {\n            if (_precompiled?.TryLookupCompiledType(virtualPath) is Type precompiledType)\n            {\n                return Activator.CreateInstance(precompiledType);\n            }\n            else if (_runtime?.GetTypeFromVirtualPath(virtualPath) is Type runtimeType)\n            {\n                return Activator.CreateInstance(runtimeType);\n            }\n            else\n            {\n                return null;\n            }\n        }\n\n        public bool Exists(string virtualPath)\n        {\n            if (_precompiled?.TryLookupCompiledType(virtualPath) != null)\n            {\n                return true;\n            }\n            else if (_runtime?.FileExists(virtualPath) == true)\n            {\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n    }\n}\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/PrecompiledViewEngine.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Globalization;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Web;\nusing System.Web.Mvc;\nusing System.Web.Routing;\nusing System.Web.WebPages;\n\nnamespace StackExchange.Precompilation\n{\n\n    /// <summary>\n    /// Supports loading of precompiled views.\n    /// </summary>\n    public class PrecompiledViewEngine : ProfiledVirtualPathProviderViewEngine\n    {\n        /// <summary>\n        /// Gets the view paths\n        /// </summary>\n        public IEnumerable<string> ViewPaths { get; private set; }\n\n        private readonly Dictionary<string, Type> _views;\n\n        /// <summary>\n        /// Creates a new PrecompiledViewEngine instance, scanning all assemblies in <paramref name=\"findAssembliesInPath\"/> for precompiled views.\n        /// Precompiled views are types deriving from <see cref=\"WebPageRenderingBase\"/> decorated with a <see cref=\"CompiledFromFileAttribute\" />\n        /// </summary>\n        /// <param name=\"findAssembliesInPath\">The path to scan for assemblies with precompiled views.</param>\n        /// <remarks>\n        /// Use this constructor if you use aspnet_compiler.exe with it's targetDir parameter instead of StackExchange.Precompilation.Build.\n        /// </remarks>\n        public PrecompiledViewEngine(string findAssembliesInPath)\n            : this(FindViewAssemblies(findAssembliesInPath).ToArray())\n        {\n        }\n\n        /// <summary>\n        /// Creates a new PrecompiledViewEngine instance, scanning the provided <paramref name=\"assemblies\"/> for precompiled views.\n        /// Precompiled views are types deriving from <see cref=\"WebPageRenderingBase\"/> decorated with a <see cref=\"CompiledFromFileAttribute\" />\n        /// </summary>\n        /// <param name=\"assemblies\">The assemblies to scan for precompiled views.</param>\n        public PrecompiledViewEngine(params Assembly[] assemblies)\n        {\n            AreaViewLocationFormats = new[]\n            {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\",\n            };\n            AreaMasterLocationFormats = new[]\n            {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\",\n            };\n            AreaPartialViewLocationFormats = new[]\n            {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\",\n            };\n            FileExtensions = new[]\n            {\n                \"cshtml\",\n            };\n            MasterLocationFormats = new[]\n            {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\",\n            };\n            PartialViewLocationFormats = new[]\n            {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\",\n            };\n            ViewLocationFormats = new[]\n            {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\",\n            };\n\n            _views = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);\n\n            foreach (var asm in assemblies)\n            {\n                // https://msdn.microsoft.com/en-us/library/system.reflection.assembly.gettypes(v=vs.110).aspx#Anchor_2\n                Type[] asmTypes;\n                try\n                {\n                    asmTypes = asm.GetTypes();\n                }\n                catch (ReflectionTypeLoadException thatsWhyWeCantHaveNiceThings)\n                {\n                    asmTypes = thatsWhyWeCantHaveNiceThings.Types;\n                }\n                var viewTypes = asmTypes.Where(t => typeof(WebPageRenderingBase).IsAssignableFrom(t)).ToList();\n\n                var sourceDirectory = asm.GetCustomAttribute<CompiledFromDirectoryAttribute>()?.SourceDirectory;\n\n                foreach (var view in viewTypes)\n                {\n                    var attr = view.GetCustomAttribute<CompiledFromFileAttribute>();\n                    if (attr != null)\n                    {\n                        _views[MakeVirtualPath(attr.SourceFile, sourceDirectory)] = view;\n                    }\n                }\n            }\n\n            ViewPaths = _views.Keys.OrderBy(_ => _).ToList();\n        }\n\n        /// <inheritdoc />\n        protected override IVirtualPathFactory CreateVirtualPathFactory() => new PrecompilationVirtualPathFactory(\n            precompiled: this,\n            runtime: ViewEngines.Engines.OfType<RoslynRazorViewEngine>().FirstOrDefault());\n\n        private static string MakeVirtualPath(string absoluteViewPath, string absoluteDirectoryPath = null)\n        {\n            if (absoluteDirectoryPath != null && absoluteViewPath.StartsWith(absoluteDirectoryPath))\n            {\n                return MakeVirtualPath(absoluteViewPath, absoluteDirectoryPath.Length - (absoluteDirectoryPath.EndsWith(\"\\\\\") ? 1 : 0));\n            }\n\n            // we could just bail here, but let's make a best effort...\n            var firstArea = absoluteViewPath.IndexOf(@\"\\Areas\\\");\n            if (firstArea != -1)\n            {\n                return MakeVirtualPath(absoluteViewPath, firstArea);\n            }\n            else\n            {\n                var firstView = absoluteViewPath.IndexOf(@\"\\Views\\\");\n                if (firstView == -1) throw new Exception(\"Couldn't make virtual for: \" + absoluteViewPath);\n\n                return MakeVirtualPath(absoluteViewPath, firstView);\n            }\n        }\n\n        private static string MakeVirtualPath(string absoluteViewPath, int startIndex)\n        {\n            var tail = absoluteViewPath.Substring(startIndex);\n            var vp = \"~\" + tail.Replace(@\"\\\", \"/\");\n\n            return vp;\n        }\n\n        private static List<Assembly> FindViewAssemblies(string dirPath)\n        {\n            var pendingDirs = new List<string>();\n            pendingDirs.Add(dirPath);\n\n            var ret = new List<Assembly>();\n\n            while (pendingDirs.Count > 0)\n            {\n                var dir = pendingDirs[0];\n                pendingDirs.RemoveAt(0);\n\n                pendingDirs.AddRange(Directory.EnumerateDirectories(dir));\n\n                var dlls = Directory.EnumerateFiles(dir, \"*.dll\").Where(w => Path.GetFileNameWithoutExtension(w).Contains(\"_Web_\"));\n\n                foreach (var dll in dlls)\n                {\n                    try\n                    {\n                        var pdb = Path.Combine(Path.GetDirectoryName(dll), Path.GetFileNameWithoutExtension(dll) + \".pdb\");\n\n                        var asmBytes = File.ReadAllBytes(dll);\n                        var pdbBytes = File.Exists(pdb) ? File.ReadAllBytes(pdb) : null;\n\n                        Assembly asm;\n\n                        if (pdbBytes == null)\n                        {\n                            asm = Assembly.Load(asmBytes);\n                        }\n                        else\n                        {\n                            asm = Assembly.Load(asmBytes, pdbBytes);\n                        }\n\n                        ret.Add(asm);\n\n                        Debug.WriteLine(\"Loading view assembly: \" + dll);\n                    }\n                    catch (Exception) { }\n                }\n            }\n\n            return ret;\n        }\n\n        /// <inheritdoc />\n        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) =>\n            CreateViewImpl(partialPath, masterPath: null, runViewStart: false);\n\n        /// <inheritdoc />\n        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) =>\n            CreateViewImpl(viewPath, masterPath, runViewStart: true);\n\n\n        internal Type TryLookupCompiledType(string viewPath)\n        {\n            Type compiledView;\n            if (!_views.TryGetValue(viewPath, out compiledView))\n            {\n                return null;\n            }\n\n            return compiledView;\n        }\n        private IView CreateViewImpl(string viewPath, string masterPath, bool runViewStart)\n        {\n            var compiledType = TryLookupCompiledType(viewPath);\n            if (compiledType == null)\n            {\n                return null;\n            }\n\n            return new PrecompilationView(viewPath, masterPath, compiledType, runViewStart, this);\n        }\n\n        /// <inheritdoc />\n        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)\n        {\n            if (controllerContext == null) throw new ArgumentNullException(nameof(controllerContext));\n            if (string.IsNullOrEmpty(partialViewName)) throw new ArgumentException($\"\\\"{nameof(partialViewName)}\\\" argument cannot be null or empty.\", nameof(partialViewName));\n\n            var areaName = AreaHelpers.GetAreaName(controllerContext.RouteData);\n\n            var locationsSearched = new List<string>(\n                DisplayModeProvider.Modes.Count * (\n                    ((PartialViewLocationFormats?.Length ?? 0) +\n                    (areaName != null ? AreaPartialViewLocationFormats?.Length ?? 0 : 0)))\n            );\n\n            var viewPath = ResolveViewPath(partialViewName, areaName, PartialViewLocationFormats, AreaPartialViewLocationFormats, locationsSearched, controllerContext);\n\n            return string.IsNullOrEmpty(viewPath)\n                ? new ViewEngineResult(locationsSearched)\n                : new ViewEngineResult(CreatePartialView(controllerContext, viewPath), this);\n        }\n\n        /// <inheritdoc />\n        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)\n        {\n            // All this madness is essentially re-written from the VirtualPathProviderViewEngine class, but that class\n            // checks on things like cache and whether the file exists and a whole bunch of stuff that's unnecessary.\n            // Plus: unecessary allocations :(\n\n            if (controllerContext == null) throw new ArgumentNullException(nameof(controllerContext));\n            if (string.IsNullOrEmpty(viewName)) throw new ArgumentException($\"\\\"{nameof(viewName)}\\\" argument cannot be null or empty.\", nameof(viewName));\n\n            var areaName = AreaHelpers.GetAreaName(controllerContext.RouteData);\n\n            // minimize re-allocations of List\n            var locationsSearched = new List<string>(\n                DisplayModeProvider.Modes.Count * (\n                    ((ViewLocationFormats?.Length ?? 0) +\n                    (areaName != null ? AreaViewLocationFormats?.Length ?? 0 : 0)) +\n                    (MasterLocationFormats?.Length ?? 0) +\n                    (areaName != null ? AreaMasterLocationFormats?.Length ?? 0 : 0))\n            );\n\n            var viewPath = ResolveViewPath(viewName, areaName, ViewLocationFormats, AreaViewLocationFormats, locationsSearched, controllerContext);\n            var masterPath = ResolveViewPath(masterName, areaName, MasterLocationFormats, AreaMasterLocationFormats, locationsSearched, controllerContext);\n\n            if (string.IsNullOrEmpty(viewPath) ||\n                (string.IsNullOrEmpty(masterPath) && !string.IsNullOrEmpty(masterName)))\n            {\n                return new ViewEngineResult(locationsSearched);\n            }\n\n            return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);\n        }\n\n        private string ResolveViewPath(string viewName, string areaName, string[] viewLocationFormats, string[] areaViewLocationFormats, List<string> viewLocationsSearched, ControllerContext controllerContext)\n        {\n            if (string.IsNullOrEmpty(viewName))\n            {\n                return null;\n            }\n\n            var controllerName = controllerContext.RouteData.GetRequiredString(\"controller\");\n            if (IsSpecificPath(viewName))\n            {\n                var normalized = NormalizeViewName(viewName);\n\n                viewLocationsSearched.Add(viewName);\n                return _views.ContainsKey(normalized) ? normalized : null;\n            }\n\n            areaViewLocationFormats = (areaName == null ? null : areaViewLocationFormats) ?? new string[0];\n            viewLocationFormats = viewLocationFormats ?? new string[0];\n\n            var httpContext = controllerContext.HttpContext;\n            var availableDisplayModes = DisplayModeProvider.GetAvailableDisplayModesForContext(httpContext, controllerContext.DisplayMode);\n            foreach (var displayMode in availableDisplayModes)\n            {\n                for (var i = 0; i < areaViewLocationFormats.Length; i++)\n                {\n                    var path = string.Format(areaViewLocationFormats[i], viewName, controllerName, areaName);\n                    if (TryResolveView(httpContext, displayMode, ref path, viewLocationsSearched)) return path;\n                }\n\n                for (var i = 0; i < viewLocationFormats.Length; i++)\n                {\n                    var path = string.Format(viewLocationFormats[i], viewName, controllerName);\n                    if (TryResolveView(httpContext, displayMode, ref path, viewLocationsSearched)) return path;\n                }\n            }\n\n            return null;\n        }\n\n        private bool TryResolveView(HttpContextBase httpContext, IDisplayMode displayMode, ref string path, ICollection<string> viewLocationsSearched)\n        {\n            path = NormalizeViewName(VirtualPathUtility.ToAppRelative(path)); // resolve relative path portions\n            var displayInfo = displayMode.GetDisplayInfo(httpContext, path, _views.ContainsKey);\n\n            if (displayInfo == null || displayInfo.FilePath == null)\n            {\n                viewLocationsSearched.Add(path);\n                return false;\n            }\n\n            path = displayInfo.FilePath;\n            return true;\n        }\n\n        private static string NormalizeViewName(string viewName)\n        {\n            return viewName[0] == '/' ? (\"~\" + viewName) : viewName;\n        }\n\n        private static bool IsSpecificPath(string path) => path.Length > 0 && (path[0] == '~' || path[0] == '/');\n    }\n\n    // Hooray, another MVC5 class that should be public but ISN'T\n    internal static class AreaHelpers\n    {\n        public static string GetAreaName(RouteBase route)\n        {\n            var routeWithArea = route as IRouteWithArea;\n            if (routeWithArea != null)\n                return routeWithArea.Area;\n\n            var castRoute = route as Route;\n            return castRoute?.DataTokens?[\"area\"] as string;\n        }\n\n        public static string GetAreaName(RouteData routeData)\n        {\n            object area;\n            if (routeData.DataTokens.TryGetValue(\"area\", out area))\n            {\n                return area as string;\n            }\n\n            return GetAreaName(routeData.Route);\n        }\n    }\n}\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/ProfiledVirtualPathProviderViewEngine.cs",
    "content": "﻿using System;\nusing System.Web.Mvc;\nusing System.Web.WebPages;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// Base class for implementing <see cref=\"VirtualPathProviderViewEngine\"/> derived types that provide custom profiling steps.\n    /// </summary>\n    public abstract class ProfiledVirtualPathProviderViewEngine : VirtualPathProviderViewEngine\n    {\n        /// <summary>\n        /// Triggers when the engine performs a step that can be profiled.\n        /// </summary>\n        public Func<string, IDisposable> ProfileStep { get; set; }\n\n        internal IVirtualPathFactory VirtualPathFactory => _virtualPathFactoryFactory.Value;\n\n        protected abstract IVirtualPathFactory CreateVirtualPathFactory();\n\n        private readonly Lazy<IVirtualPathFactory> _virtualPathFactoryFactory; // sorry, I had to...\n        \n        /// <inheritdoc />\n        protected ProfiledVirtualPathProviderViewEngine()\n        {\n            _virtualPathFactoryFactory = new Lazy<IVirtualPathFactory>(CreateVirtualPathFactory);\n        }\n    }\n\n    internal static class ProfileVirtualPathProviderViewEngineExtensions\n    {\n        /// <summary>\n        /// Invokes the <see cref=\"ProfiledVirtualPathProviderViewEngine.ProfileStep\"/> if it's set.\n        /// </summary>\n        public static IDisposable DoProfileStep(this ProfiledVirtualPathProviderViewEngine instance, string name) =>\n            instance?.ProfileStep?.Invoke(name);\n    }\n}\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/RazorParser.cs",
    "content": "using System;\nusing System.Linq;\nusing System.CodeDom;\nusing System.CodeDom.Compiler;\nusing System.Collections.Concurrent;\nusing System.IO;\nusing System.Security.Cryptography;\nusing System.Web.Configuration;\nusing System.Web.Razor;\nusing System.Web.WebPages.Razor;\nusing System.Web.WebPages.Razor.Configuration;\nusing Microsoft.CodeAnalysis;\nusing System.Threading.Tasks;\nusing System.Threading;\nusing Microsoft.CodeAnalysis.Text;\nusing RazorWorker = System.Func<System.Web.Razor.RazorEngineHost, Microsoft.CodeAnalysis.TextAndVersion, System.Threading.Tasks.Task<System.IO.Stream>>;\nusing System.Composition;\nusing Microsoft.CodeAnalysis.Host;\nusing Microsoft.CodeAnalysis.Host.Mef;\n\nnamespace StackExchange.Precompilation\n{\n    [ExportLanguageServiceFactoryAttribute(typeof(IDocumentExtender), LanguageNames.CSharp)]\n    class RazorParserFactory : ILanguageServiceFactory\n    {\n        public ILanguageService CreateLanguageService(HostLanguageServices languageServices) =>\n            new RazorParser(languageServices.WorkspaceServices.Workspace);\n    }\n\n    class RazorParser : IDocumentExtender, IDisposable\n    {\n        private readonly Workspace _workspace;\n        private readonly WebConfigurationFileMap _configMap;\n        private readonly DirectoryInfo _cacheDirectory;\n        private readonly BlockingCollection<RazorTextLoader> _workItems;\n        private readonly Lazy<Task> _backgroundWorkers;\n        private readonly CancellationToken _cancellationToken;\n\n        public RazorParser(Workspace workspace)\n        {\n            var dir = PrecompilerSection.Current?.RazorCache?.Directory;\n//             dir = string.IsNullOrWhiteSpace(dir)\n//                 ? Environment.GetEnvironmentVariable(nameof(Precompilation) + \"_\" + nameof(PrecompilerSection.RazorCache) + nameof(RazorCacheElement.Directory))\n//                 : dir;\n//             if (!string.IsNullOrWhiteSpace(dir) && ! dir exists)\n//             Directory.CreateDirectory(Path.Combine(CscArgs.OutputDirectory, dir))\n\n//             if (cacheDirectory.Exists != true)\n//             {\n//                 throw new ArgumentException($\"Specified directory '{cacheDirectory.FullName}' doesn't exist.\", nameof(cacheDirectory));\n//             }\n\n            _workItems = new BlockingCollection<RazorTextLoader>();\n            _workspace = workspace;\n            _configMap = new WebConfigurationFileMap { VirtualDirectories = { { \"/\", new VirtualDirectoryMapping(Environment.CurrentDirectory, true) } } };\n            _backgroundWorkers = new Lazy<Task>(\n                () => _cancellationToken.IsCancellationRequested\n                    ? Task.CompletedTask\n                    : Task.WhenAll(Enumerable.Range(0, Environment.ProcessorCount).Select(_ => Task.Run(BackgroundWorker, _cancellationToken))),\n                LazyThreadSafetyMode.ExecutionAndPublication);\n        }\n\n        private async Task BackgroundWorker()\n        {\n            foreach(var loader in _workItems.GetConsumingEnumerable(_cancellationToken))\n            {\n                if (_cancellationToken.IsCancellationRequested)\n                {\n                    loader.Result.SetCanceled();\n                    continue;\n                }\n                try\n                {\n                    var originalText = await loader.OriginalLoader.LoadTextAndVersionAsync(_workspace, null, default(CancellationToken));\n                    var viewFullPath = originalText.FilePath;\n                    var viewVirtualPath = GetRelativeUri(originalText.FilePath, Environment.CurrentDirectory);\n                    var viewConfig = WebConfigurationManager.OpenMappedWebConfiguration(_configMap, viewVirtualPath);\n                    var host = viewConfig.GetSectionGroup(\"system.web.webPages.razor\") is RazorWebSectionGroup razorConfig\n                        ? WebRazorHostFactory.CreateHostFromConfig(razorConfig, viewVirtualPath, viewFullPath)\n                        : WebRazorHostFactory.CreateDefaultHost(viewVirtualPath, viewFullPath);\n\n                    // having this as a field would require the ASP.NET MVC dependency even for console apps...\n                    RazorWorker worker = RazorWorker;\n                    if (_cacheDirectory != null)\n                    {\n                        worker = CachedRazorWorker;\n                    }\n\n                    using (var stream = await worker(host, originalText))\n                    {\n                        var generatedText = TextAndVersion.Create(\n                            SourceText.From(stream, originalText.Text.Encoding, originalText.Text.ChecksumAlgorithm, canBeEmbedded: originalText.Text.CanBeEmbedded, throwIfBinaryDetected: true),\n                            originalText.Version,\n                            originalText.FilePath);\n\n                        loader.Result.TrySetResult(generatedText);\n                    }\n                }\n                catch (Exception ex)\n                {\n                    loader.Result.TrySetException(ex);\n                }\n            }\n        }\n\n        void IDisposable.Dispose()\n        {\n            _workItems?.Dispose();\n        }\n\n        private async Task<Stream> CachedRazorWorker(RazorEngineHost host, TextAndVersion originalText)\n        {\n            var cacheFile = GetCachedFileInfo();\n            if (cacheFile.Exists)\n            {\n                return cacheFile.OpenRead();\n            }\n            else\n            {\n                (var success, var source) = await RazorWorkerImpl(host, originalText);\n\n                FileStream fs = null;\n                try\n                {\n                    if (success)\n                    {\n                        fs = cacheFile.Create();\n                        await source.CopyToAsync(fs, 4096, _cancellationToken);\n                        await fs.FlushAsync(_cancellationToken);\n                    }\n                }\n                catch (Exception ex)\n                {\n                    ReportDiagnostic(Diagnostic.Create(Compilation.CachingFailed, Location.None, originalText.FilePath, cacheFile.FullName, ex));\n                    for (var i = 0; i < 10 && cacheFile.Exists; i++)\n                    {\n                        await Task.Delay(100 * i);\n                        try { cacheFile.Delete(); } catch { }\n                    }\n                    if (cacheFile.Exists)\n                    {\n                        ReportDiagnostic(Diagnostic.Create(Compilation.CachingFailedHard, Location.None, originalText.FilePath, cacheFile.FullName));\n                    }\n                }\n                finally\n                {\n                    fs?.Dispose();\n                    source.Position = 0;\n                }\n\n                return source; // return the in-memory stream, since it's faster\n            }\n\n\n            FileInfo GetCachedFileInfo()\n            {\n                using (var md5 = MD5.Create())\n                using (var str = new MemoryStream())\n                using (var sw = new StreamWriter(str))\n                {\n\n                    // all those things can affect the generated c#\n                    // so we need to include them in the hash...\n                    sw.WriteLine(host.CodeLanguage.LanguageName);\n                    sw.WriteLine(host.CodeLanguage.CodeDomProviderType.FullName);\n                    sw.WriteLine(host.DefaultBaseClass);\n                    sw.WriteLine(host.DefaultClassName);\n                    sw.WriteLine(host.DefaultNamespace);\n                    sw.WriteLine(string.Join(\";\",host.NamespaceImports));\n                    sw.WriteLine(host.StaticHelpers);\n                    sw.WriteLine(host.TabSize);\n                    sw.WriteLine(originalText.FilePath);\n                    originalText.Text.Write(sw, _cancellationToken); // .cshtml content\n\n                    sw.Flush();\n                    str.Position = 0;\n                    var hashBytes = md5.ComputeHash(str);\n                    var fileName = BitConverter.ToString(hashBytes).Replace(\"-\",\"\") + \".cs\";\n                    var filePath = Path.Combine(_cacheDirectory.FullName, fileName);\n                    return new FileInfo(filePath);\n                }\n            }\n        }\n        private readonly ConcurrentBag<Diagnostic> _diagnostics = new ConcurrentBag<Diagnostic>();\n        private void ReportDiagnostic(Diagnostic d) => _diagnostics.Add(d);\n\n        private Task<Stream> RazorWorker(RazorEngineHost host, TextAndVersion originalText) =>\n            RazorWorkerImpl(host, originalText).ContinueWith(x => x.Result.result, TaskContinuationOptions.OnlyOnRanToCompletion);\n\n        private Task<(bool success, Stream result)> RazorWorkerImpl(RazorEngineHost host, TextAndVersion originalText)\n        {\n            var success = true;\n            var generatedStream = new MemoryStream(capacity: originalText.Text.Length * 8); // generated .cs files contain a lot of additional crap vs actualy cshtml\n            var viewFullPath = originalText.FilePath;\n            using (var sourceReader = new StreamReader(generatedStream, originalText.Text.Encoding, false, 4096, leaveOpen: true))\n            using (var provider = CodeDomProvider.CreateProvider(\"csharp\"))\n            using (var generatedWriter = new StreamWriter(generatedStream, originalText.Text.Encoding, 4096, leaveOpen: true))\n            {\n                // write cshtml into generated stream and rewind\n                originalText.Text.Write(generatedWriter);\n                generatedWriter.Flush();\n                generatedStream.Position = 0;\n\n                // generated code and clear memory stream\n                var engine = new RazorTemplateEngine(host);\n                var razorOut = engine.GenerateCode(sourceReader, null, null, viewFullPath);\n\n                if (!razorOut.Success)\n                {\n                    success = false;\n                    foreach(var error in razorOut.ParserErrors)\n                    {\n                        var position = new LinePosition(error.Location.LineIndex, error.Location.CharacterIndex - 1);\n                        ReportDiagnostic(Diagnostic.Create(\n                            Compilation.RazorParserError,\n                            Location.Create(\n                                originalText.FilePath,\n                                new TextSpan(error.Location.AbsoluteIndex, error.Length),\n                                new LinePositionSpan(position, position)),\n                            error.Message));\n                    }\n                }\n\n                // add the CompiledFromFileAttribute to the generated class\n                razorOut.GeneratedCode\n                    .Namespaces.OfType<CodeNamespace>().FirstOrDefault()?\n                    .Types.OfType<CodeTypeDeclaration>().FirstOrDefault()?\n                    .CustomAttributes.Add(\n                        new CodeAttributeDeclaration(\n                            new CodeTypeReference(typeof(CompiledFromFileAttribute)),\n                            new CodeAttributeArgument(new CodePrimitiveExpression(viewFullPath))\n                        ));\n\n                // reuse the memory stream for code generation\n                generatedStream.Position = 0;\n                generatedStream.SetLength(0);\n                var codeGenOptions = new CodeGeneratorOptions { VerbatimOrder = true, ElseOnClosing = false, BlankLinesBetweenMembers = false };\n                provider.GenerateCodeFromCompileUnit(razorOut.GeneratedCode, generatedWriter, codeGenOptions);\n\n                // rewind\n                generatedWriter.Flush();\n                generatedStream.Position = 0;\n            }\n\n            return Task.FromResult((success: success, stream: (Stream)generatedStream));\n        }\n\n        private string GetRelativeUri(string filespec, string folder)\n        {\n            Uri pathUri = new Uri(filespec);\n            if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))\n            {\n                folder += Path.DirectorySeparatorChar;\n            }\n            Uri folderUri = new Uri(folder);\n            return \"/\" + folderUri.MakeRelativeUri(pathUri).ToString().TrimStart('/');\n        }\n\n        public DocumentInfo Extend(DocumentInfo document)\n        {\n            if (Path.GetExtension(document.Name) != \".cshtml\") return document;\n\n            var razorLoader = new RazorTextLoader(this, document.TextLoader);\n            _workItems.Add(razorLoader);\n            return document.WithTextLoader(razorLoader);\n        }\n\n        public async Task<System.Collections.Generic.ICollection<Diagnostic>> Complete()\n        {\n            _workItems.CompleteAdding();\n            if (_backgroundWorkers.IsValueCreated || !_workItems.IsCompleted)\n            {\n                await _backgroundWorkers.Value;\n            }\n            return _diagnostics.ToList();\n        }\n\n        private Task EnsureWorkers() => _backgroundWorkers.Value;\n\n        private sealed class RazorTextLoader : TextLoader\n        {\n            public TextLoader OriginalLoader { get; }\n            public TaskCompletionSource<TextAndVersion> Result { get; }\n\n            private readonly RazorParser _parser;\n\n            public RazorTextLoader(RazorParser parser, TextLoader originalLoader)\n            {\n                _parser = parser;\n                OriginalLoader = originalLoader;\n                Result =  new TaskCompletionSource<TextAndVersion>();\n            }\n\n            private Task _worker;\n            public override Task<TextAndVersion> LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)\n            {\n                _worker = _worker ?? _parser.EnsureWorkers(); // ensuring that lazy workers are running\n                return Result.Task;\n            }\n        }\n    }\n}"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/RoslynRazorViewEngine.cs",
    "content": "﻿using Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing Microsoft.CodeAnalysis.Emit;\nusing Microsoft.CodeAnalysis.Text;\nusing System;\nusing System.CodeDom;\nusing System.CodeDom.Compiler;\nusing System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing System.Web;\nusing System.Web.Compilation;\nusing System.Web.Hosting;\nusing System.Web.Mvc;\nusing System.Web.Razor;\nusing System.Web.Razor.Generator;\nusing System.Web.Razor.Parser.SyntaxTree;\nusing System.Web.WebPages;\nusing System.Web.WebPages.Razor;\n\nnamespace StackExchange.Precompilation\n{\n    /// <summary>\n    /// A replacement for the <see cref=\"RazorViewEngine\"/> that uses roslyn (<see cref=\"Microsoft.CodeAnalysis\"/>) instead of <see cref=\"System.CodeDom\"/> to compile views.\n    /// </summary>\n    public class RoslynRazorViewEngine : ProfiledVirtualPathProviderViewEngine\n    {\n        /// <summary>\n        /// Creates a new <see cref=\"RoslynRazorViewEngine\"/> instance.\n        /// </summary>\n        public RoslynRazorViewEngine()\n        {\n            AreaViewLocationFormats = new[] {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\"\n            };\n\n            AreaMasterLocationFormats = new[] {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\"\n            };\n\n            AreaPartialViewLocationFormats = new[] {\n                \"~/Areas/{2}/Views/{1}/{0}.cshtml\",\n                \"~/Areas/{2}/Views/Shared/{0}.cshtml\"\n            };\n            ViewLocationFormats = new[] {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\"\n            };\n            MasterLocationFormats = new[] {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\"\n            };\n            PartialViewLocationFormats = new[] {\n                \"~/Views/{1}/{0}.cshtml\",\n                \"~/Views/Shared/{0}.cshtml\"\n            };\n            FileExtensions = new[] {\n                \"cshtml\"\n            };\n        }\n\n        /// <summary>When set to <c>true</c>, configured <see cref=\"ICompileModule\" />s are used when the views are compiled</summary>\n        public bool UseCompilationModules { get; set; }\n\n        private readonly ICompileModule[] _noModule = new ICompileModule[0];\n        private readonly PrecompilationModuleLoader _moduleLoader = new PrecompilationModuleLoader(PrecompilerSection.Current);\n\n        /// <inheritdoc />\n        protected override IVirtualPathFactory CreateVirtualPathFactory() => new PrecompilationVirtualPathFactory(\n            runtime: this,\n            precompiled: ViewEngines.Engines.OfType<PrecompiledViewEngine>().FirstOrDefault());\n\n        /// <inheritdoc />\n        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) =>\n            new PrecompilationView(partialPath, null, GetTypeFromVirtualPath(partialPath), false, this);\n\n        /// <inheritdoc />\n        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) =>\n            new PrecompilationView(viewPath, masterPath, GetTypeFromVirtualPath(viewPath), true, this);\n\n        internal bool FileExists(string virtualPath) =>\n            HostingEnvironment.VirtualPathProvider.FileExists(virtualPath);\n\n        internal Type GetTypeFromVirtualPath(string virtualPath)\n        {\n            virtualPath = VirtualPathUtility.ToAbsolute(virtualPath);\n\n            var cacheKey = \"RoslynRazor_\" + virtualPath;\n            var type = HttpRuntime.Cache[cacheKey] as Type;\n            if (type == null)\n            {\n                type = GetTypeFromVirtualPathNoCache(virtualPath);\n\n                // Cache it, and make it dependent on the razor file\n                var cacheDependency = HostingEnvironment.VirtualPathProvider.GetCacheDependency(virtualPath, new string[] { virtualPath }, DateTime.UtcNow);\n                HttpRuntime.Cache.Insert(cacheKey, type, cacheDependency);\n            }\n\n            return type;\n        }\n\n        private Type GetTypeFromVirtualPathNoCache(string virtualPath)\n        {\n            using (this.DoProfileStep($\"{nameof(RoslynRazorViewEngine)}: Compiling {virtualPath}\"))\n            {\n                OnCodeGenerationStarted();\n                var args = new CompilingPathEventArgs(virtualPath, WebRazorHostFactory.CreateHostFromConfig(virtualPath));\n                OnBeforeCompilePath(args);\n                var host = args.Host;\n                var razorResult = RunRazorGenerator(virtualPath, host);\n                var syntaxTree = GetSyntaxTree(host, razorResult);\n                var assembly = CompileToAssembly(host, syntaxTree, UseCompilationModules ? _moduleLoader.LoadedModules : _noModule);\n                return assembly.GetType($\"{host.DefaultNamespace}.{host.DefaultClassName}\");\n            }\n        }\n\n        private GeneratorResults RunRazorGenerator(string virtualPath, WebPageRazorHost host)\n        {\n            var file = HostingEnvironment.VirtualPathProvider.GetFile(virtualPath);\n            var engine = new RazorTemplateEngine(host);\n            using (var viewStream = file.Open())\n            using (var viewReader = new StreamReader(viewStream))\n            {\n                var razorResult = engine.GenerateCode(viewReader, className: null, rootNamespace: null, sourceFileName: host.PhysicalPath);\n                if (!razorResult.Success)\n                {\n                    var sourceCode = (string)null;\n                    if (viewStream.CanSeek)\n                    {\n                        viewStream.Seek(0, SeekOrigin.Begin);\n                        sourceCode = viewReader.ReadToEnd();\n                    }\n                    throw CreateExceptionFromParserError(razorResult.ParserErrors.Last(), virtualPath, sourceCode);\n                }\n                OnCodeGenerationCompleted(razorResult.GeneratedCode, host);\n                return razorResult;\n            }\n        }\n\n        private static SyntaxTree GetSyntaxTree(WebPageRazorHost host, GeneratorResults razorResult)\n        {\n            // Use CodeDom to generate source code from the CodeCompileUnit\n            // Use roslyn to parse it back\n            using (var codeDomProvider = CodeDomProvider.CreateProvider(host.CodeLanguage.LanguageName))\n            using (var viewCodeStream = new MemoryStream())\n            using (var viewCodeWriter = new StreamWriter(viewCodeStream))\n            {\n                codeDomProvider.GenerateCodeFromCompileUnit(razorResult.GeneratedCode, viewCodeWriter, new CodeGeneratorOptions());\n                viewCodeWriter.Flush();\n                viewCodeStream.Position = 0;\n                var sourceText = SourceText.From(viewCodeStream);\n\n                // We need a different file path for the generated file, otherwise breakpoints won't get\n                // hit due to #line directives pointing at the original .cshtml. If we'd want breakpoint\n                // in the generated .cs code, we'd have to dump them somewhere on disk, and specify the path here.\n                var sourcePath = string.IsNullOrEmpty(host.PhysicalPath)\n                    ? host.VirtualPath // yay virtual paths, won't point at the original file\n                    : Path.ChangeExtension(host.PhysicalPath, \".roslynviewengine\");\n                return SyntaxFactory.ParseSyntaxTree(sourceText, path: sourcePath);\n            }\n        }\n\n        // we were getting OutOfMemory exceptions caused by MetadataReference.CreateFrom* creating\n        // System.Reflection.PortableExecutable.PEReader instances for the same assembly for each view being compiled\n        private static readonly ConcurrentDictionary<string, Lazy<MetadataReference>> ReferenceCache = new ConcurrentDictionary<string, Lazy<MetadataReference>>();\n        internal static MetadataReference ResolveReference(Assembly assembly)\n        {\n            var key = assembly.Location;\n            Uri uri;\n            if (Uri.TryCreate(assembly.CodeBase, UriKind.Absolute, out uri) && uri.IsFile)\n            {\n                key = uri.LocalPath;\n            }\n            return ReferenceCache.GetOrAdd(\n                key,\n                loc => new Lazy<MetadataReference>(\n                    () => MetadataReference.CreateFromFile(loc),\n                    LazyThreadSafetyMode.ExecutionAndPublication)).Value;\n        }\n\n        private static Assembly CompileToAssembly(WebPageRazorHost host, SyntaxTree syntaxTree, ICollection<ICompileModule> compilationModules)\n        {\n            var strArgs = new List<string>();\n            strArgs.Add(\"/target:library\");\n            strArgs.Add(host.DefaultDebugCompilation ? \"/o-\" : \"/o+\");\n            strArgs.Add(host.DefaultDebugCompilation ? \"/debug+\" : \"/debug-\");\n\n            var cscArgs = CSharpCommandLineParser.Default.Parse(strArgs, null, null);\n\n            var compilation = CSharpCompilation.Create(\n                \"RoslynRazor\", // Note: using a fixed assembly name, which doesn't matter as long as we don't expect cross references of generated assemblies\n                new[] { syntaxTree },\n                BuildManager.GetReferencedAssemblies().OfType<Assembly>().Select(ResolveReference),\n                cscArgs.CompilationOptions.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default));\n\n            compilation = Hacks.MakeValueTuplesWorkWhenRunningOn47RuntimeAndTargetingNet45Plus(compilation);\n            var diagnostics = new List<Diagnostic>();\n            var context = new CompileContext(compilationModules);\n            context.Before(new BeforeCompileContext\n            {\n                Arguments = cscArgs,\n                Compilation = compilation,\n                Diagnostics = diagnostics,\n            });\n            compilation = context.BeforeCompileContext.Compilation;\n\n            using (var dllStream = new MemoryStream())\n            using (var pdbStream = new MemoryStream())\n            {\n                EmitResult emitResult = compilation.Emit(dllStream, pdbStream);\n                diagnostics.AddRange(emitResult.Diagnostics);\n\n                if (!emitResult.Success)\n                {\n                    Diagnostic diagnostic = diagnostics.First(x => x.Severity == DiagnosticSeverity.Error);\n                    string message = diagnostic.ToString();\n                    LinePosition linePosition = diagnostic.Location.GetMappedLineSpan().StartLinePosition;\n\n                    throw new HttpParseException(message, null, host.VirtualPath, null, linePosition.Line + 1);\n                }\n\n                context.After(new AfterCompileContext\n                {\n                    Arguments = context.BeforeCompileContext.Arguments,\n                    AssemblyStream = dllStream,\n                    Compilation = compilation,\n                    Diagnostics = diagnostics,\n                    SymbolStream = pdbStream,\n                    XmlDocStream = null,\n                });\n\n                return Assembly.Load(dllStream.GetBuffer(), pdbStream.GetBuffer());\n            }\n        }\n\n        private static HttpParseException CreateExceptionFromParserError(RazorError error, string virtualPath, string sourceCode) =>\n            new HttpParseException(error.Message + Environment.NewLine, null, virtualPath, sourceCode, error.Location.LineIndex + 1);\n\n        /// <summary>\n        /// This is the equivalent of the <see cref=\"RazorBuildProvider.CompilingPath\"/> event, since <see cref=\"PrecompiledViewEngine\"/> bypasses <see cref=\"RazorBuildProvider\"/> completely.\n        /// </summary>\n        public static event EventHandler<CompilingPathEventArgs> CompilingPath;\n\n        /// <summary>\n        /// Raises the <see cref=\"CompilingPath\"/> event.\n        /// </summary>\n        /// <param name=\"args\"></param>\n        protected virtual void OnBeforeCompilePath(CompilingPathEventArgs args) =>\n            CompilingPath?.Invoke(this, args);\n\n        /// <summary>\n        /// This is the equivalent of the <see cref=\"RazorBuildProvider.CodeGenerationStarted\"/> event, since <see cref=\"PrecompiledViewEngine\"/> bypasses <see cref=\"RazorBuildProvider\"/> completely.\n        /// </summary>\n        public static event EventHandler CodeGenerationStarted;\n\n        private void OnCodeGenerationStarted() =>\n            CodeGenerationStarted?.Invoke(this, EventArgs.Empty);\n\n        /// <summary>\n        /// This is the equivalent of the <see cref=\"RazorBuildProvider.CodeGenerationCompleted\"/> event, since <see cref=\"PrecompiledViewEngine\"/> bypasses <see cref=\"RazorBuildProvider\"/> completely.\n        /// </summary>\n        public static event EventHandler<CodeGenerationCompleteEventArgs> CodeGenerationCompleted;\n\n        private void OnCodeGenerationCompleted(CodeCompileUnit codeCompileUnit, WebPageRazorHost host) =>\n           CodeGenerationCompleted?.Invoke(this, new CodeGenerationCompleteEventArgs(host.VirtualPath, host.PhysicalPath, codeCompileUnit));\n    }\n}\n\n"
  },
  {
    "path": "StackExhcange.Precompilation.MVC5/StackExchange.Precompilation.MVC5.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net462</TargetFramework>\n    <Description>Hooks into the ASP.NET MVC and StackExchange.Precompilation.Build pipeline to enable usage of C# 7.2, and views precompiled with StackExchange.Precompilation.Build</Description>\n    <IsPackable>true</IsPackable>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n  </PropertyGroup>\n  <ItemGroup>\n    <Reference Include=\"System.Web\" />\n    <PackageReference Include=\"Microsoft.AspNet.Mvc\" Version=\"5.2.7\" />\n    <ProjectReference Include=\"..\\StackExchange.Precompilation\\StackExchange.Precompilation.csproj\" />\n\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp.Workspaces\" Version=\"2.10.0\" PrivateAssets=\"all\" />\n    <ProjectReference Include=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.csproj\" IncludeAssets=\"compile\" PrivateAssets=\"all\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "Test.ConsoleApp/AliasTest.cs",
    "content": "﻿#if NET462\nextern alias aliastest;\n\nnamespace Test.ConsoleApp\n{\n    class AliasTest\n    {\n        public const string DataSet = nameof(aliastest::System.Data.DataSet);\n    }\n}\n#endif\n"
  },
  {
    "path": "Test.ConsoleApp/App.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n    <configSections>\n        <section name=\"stackExchange.precompiler\" type=\"StackExchange.Precompilation.PrecompilerSection, StackExchange.Precompilation\" />\n    </configSections>\n    <stackExchange.precompiler>\n        <modules>\n            <add type=\"Test.Module.TestCompileModule, Test.Module\" />\n        </modules>\n    </stackExchange.precompiler>\n    <startup>\n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6.2\" />\n    </startup>\n  <runtime>\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime.Extensions\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime.InteropServices\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Reflection\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Security.Cryptography.Algorithms\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.1.0\" newVersion=\"1.2.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\n      </dependentAssembly>\n    </assemblyBinding>\n  </runtime>\n</configuration>\n"
  },
  {
    "path": "Test.ConsoleApp/Program.cs",
    "content": "﻿using System;\nusing System.Runtime.CompilerServices;\nusing Test.Module;\n\nnamespace Test.ConsoleApp\n{\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            Console.WriteLine(PathMapTest().Dump());\n#if NET462\n            Console.WriteLine(typeof(AliasTest).FullName);\n#endif\n        }\n\n        // path mapping test, configured via <PathMap> property in the .csproj\n        static string PathMapTest([CallerFilePath] string path = null) =>\n            path.StartsWith(\"X:\\\\Test\\\\\")\n                ? path\n                : throw new InvalidOperationException($\"CallerFilePath was expected to start with X:\\\\Test\\\\ but was {path}.\");\n    }\n}\n"
  },
  {
    "path": "Test.ConsoleApp/Test.ConsoleApp.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>\n    <OutputType>Exe</OutputType>\n    <TargetFrameworks>net462;netcoreapp20</TargetFrameworks>\n    <RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>\n    <SEPrecompilerPath Condition=\"'$(SEPrecompilerPath)' == ''\">$(SolutionDir)StackExchange.Precompilation.Build\\bin\\$(Configuration)\\net462\\</SEPrecompilerPath>\n    <PathMap>$(SolutionDir)=X:\\Test\\</PathMap>\n    <DebugType>portable</DebugType>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\Test.Module\\Test.Module.csproj\">\n      <Project>{5fcaecc3-787b-473f-a372-783d0c235190}</Project>\n      <Name>Test.Module</Name>\n    </ProjectReference>\n  </ItemGroup>\n  <ItemGroup>\n    <Reference Include=\"System.Data\" Aliases=\"aliastest\" Condition=\"'$(TargetFramework)' == 'net462'\" />\n\n    <!-- Usually, this would be pulled in by the reference to StackExchange.Precompilation.Build nuget,\n         but since we don't have the package yet, msbuild complains about the .csproj not targeting netstandard,\n         so we're pulling it's references in manually.\n     -->\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp.Workspaces\" Version=\"2.10.0\" IncludeAssets=\"compile\" PrivateAssets=\"all\" />\n\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.0.0-beta-63127-02\" PrivateAssets=\"All\" />\n  </ItemGroup>\n  <Import Project=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.targets\" />\n</Project>"
  },
  {
    "path": "Test.Module/Test.Module.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFrameworks>net462;netstandard20</TargetFrameworks>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\StackExchange.Precompilation\\StackExchange.Precompilation.csproj\">\n      <Project>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Project>\n      <Name>StackExchange.Precompilation</Name>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "Test.Module/TestCompileModule.cs",
    "content": "﻿using System;\nusing System.Collections.Immutable;\nusing System.Linq;\nusing Microsoft.CodeAnalysis;\nusing Microsoft.CodeAnalysis.CSharp;\nusing StackExchange.Precompilation;\n\nnamespace Test.Module\n{\n    public class TestCompileModule : ICompileModule\n    {\n        public void BeforeCompile(BeforeCompileContext context)\n        {\n            // this can potentially run multiple times (for every view compiled at runtime) in RoslynRazorViewEngine;\n            if(context.Compilation.GetTypeByMetadataName(\"Test.Module.Extensions\") != null) return;\n\n            context.Diagnostics.Add(\n                Diagnostic.Create(\n                    new DiagnosticDescriptor(\"TEST\", \"TEST\", \"Hello meta programming world!\", \"TEST\", DiagnosticSeverity.Info, true),\n                    Location.None));\n\n            context.Compilation = context.Compilation.AddSyntaxTrees(\n                SyntaxFactory.ParseSyntaxTree(@\"\nnamespace Test.Module\n{\n    public static class Extensions\n    {\n        public static T Dump<T>(this T i)\n        {\n            if (i != null)\n            {\n                System.Console.WriteLine(i);\n            }\n            return i;\n        }\n    }\n}\n\", context.Arguments.ParseOptions));\n        }\n\n        public void AfterCompile(AfterCompileContext context)\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "Test.WebApp/Content/PartialExternalContent.cshtml",
    "content": "﻿Partial External Content"
  },
  {
    "path": "Test.WebApp/Controllers/HomeController.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Web.Mvc;\nusing StackExchange.Precompilation;\n\nnamespace Test.WebApp.Controllers\n{\n    public class HomeController : Controller\n    {\n        public ActionResult Index()\n        {\n            IEnumerable<string> viewPaths;\n#if DEBUG\n            viewPaths = new string[] { \"We don't keep track of the views in the RoslynRazorViewEngine.\" };\n#else\n            var viewEngine = ViewEngines.Engines.OfType<PrecompiledViewEngine>().Single();\n            viewPaths = viewEngine.ViewPaths;\n#endif\n\n            return View(new Models.SampleModel { ViewPaths = viewPaths });\n        }\n\n        public ActionResult IndexOverridden()\n        {\n            return new ViewResult\n            {\n                ViewName = \"~/Views/Home/Index.cshtml\",\n                MasterName = \"~/Views/Shared/_Layout.Overridden.cshtml\",\n                ViewData = new ViewDataDictionary(new Models.SampleModel { ViewPaths = new [] { \"OVERRIDDDDDEN\" } }),\n            };\n        }\n\n        public ActionResult ExcludedLayout() => View();\n    }\n}"
  },
  {
    "path": "Test.WebApp/Models/SampleModel.cs",
    "content": "﻿using System.Collections.Generic;\n\nnamespace Test.WebApp.Models\n{\n    public class SampleModel\n    {\n        public IEnumerable<string> ViewPaths { get; set; }\n    }\n}\n"
  },
  {
    "path": "Test.WebApp/MvcApplication.cs",
    "content": "using System.Web;\nusing System.Web.Mvc;\nusing System.Web.Routing;\nusing StackExchange.Precompilation;\nusing Test.WebApp.Controllers;\n\nnamespace Test.WebApp\n{\n    public static class MvcApplicationInitializer\n    {\n        public static void PreApplicationStart() =>\n            System.Web.UI.PageParser.DefaultApplicationBaseType = typeof(MvcApplication);\n    }\n\n    public class MvcApplication : HttpApplication\n    {\n        public static bool IsDebug =>\n#if DEBUG\n            true;\n#else\n                false;\n#endif\n\n        protected void Application_Start()\n        {\n            AreaRegistration.RegisterAllAreas();\n            GlobalFilters.Filters.Add(new HandleErrorAttribute());\n\n            RouteTable.Routes.IgnoreRoute(\"{resource}.axd/{*pathInfo}\");\n            RouteTable.Routes.MapRoute(\n                name: \"Default\",\n                url: \"{controller}/{action}/{id}\",\n                defaults: new { controller = \"Home\", action = \"Index\", id = UrlParameter.Optional }\n            );\n\n            ViewEngines.Engines.Clear();\n#if !DEBUG\n// use precompiled engine first (supports some C# 6),\n            ViewEngines.Engines.Add(new PrecompiledViewEngine(typeof(HomeController).Assembly, typeof(ExternalViews).Assembly));\n#endif\n            // fallback to RoslynRazorViewEngine (RazorViewEngine doesn't support C# 6).\n            ViewEngines.Engines.Add(new RoslynRazorViewEngine() { UseCompilationModules = true });\n        }\n    }\n}"
  },
  {
    "path": "Test.WebApp/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Web;\n\n// General Information about an assembly is controlled through the following\n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"Test.WebApp\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"Test.WebApp\")]\n[assembly: AssemblyCopyright(\"Copyright ©  2015\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible\n// to COM components.  If you need to access a type in this assembly from\n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n// The following GUID is for the ID of the typelib if this project is exposed to COM\n[assembly: Guid(\"09bb37e2-0d7e-472d-b74c-aa02018c89c6\")]\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version\n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Revision and Build Numbers\n// by using the '*' as shown below:\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n[assembly: PreApplicationStartMethod(typeof(Test.WebApp.MvcApplicationInitializer), nameof(Test.WebApp.MvcApplicationInitializer.PreApplicationStart))]\n\n"
  },
  {
    "path": "Test.WebApp/Test.WebApp.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\n  <PropertyGroup>\n    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\n    <ProductVersion>\n    </ProductVersion>\n    <SchemaVersion>2.0</SchemaVersion>\n    <ProjectGuid>{5B0105A4-256B-4A88-852C-6F5E9D185515}</ProjectGuid>\n    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>Test.WebApp</RootNamespace>\n    <AssemblyName>Test.WebApp</AssemblyName>\n    <TargetFramework>net462</TargetFramework>\n    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>\n    <MvcBuildViews>false</MvcBuildViews>\n    <UseIISExpress>true</UseIISExpress>\n    <IISExpressSSLPort />\n    <IISExpressAnonymousAuthentication />\n    <IISExpressWindowsAuthentication />\n    <IISExpressUseClassicPipelineMode />\n    <SolutionDir Condition=\"$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'\">..\\</SolutionDir>\n    <UseGlobalApplicationHostFile />\n    <TargetFrameworkProfile />\n    <RuntimeIdentifiers>win</RuntimeIdentifiers>\n    <DependsOnNETStandard>false</DependsOnNETStandard><!-- lies -->\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\n    <DebugSymbols>true</DebugSymbols>\n    <DebugType>full</DebugType>\n    <Optimize>false</Optimize>\n    <OutputPath>bin\\</OutputPath>\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\n    <DebugType>pdbonly</DebugType>\n    <Optimize>true</Optimize>\n    <OutputPath>bin\\</OutputPath>\n    <DefineConstants>TRACE</DefineConstants>\n    <ErrorReport>prompt</ErrorReport>\n    <WarningLevel>4</WarningLevel>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\StackExchange.Precompilation\\StackExchange.Precompilation.csproj\">\n      <Project>{3C0A90F1-B19E-4305-AB71-3CD31C7D0F4D}</Project>\n      <Name>StackExchange.Precompilation</Name>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\StackExhcange.Precompilation.MVC5\\StackExchange.Precompilation.MVC5.csproj\" />\n    <ProjectReference Include=\"..\\Test.WebApp.ExternalViews\\Test.WebApp.ExternalViews.csproj\">\n      <Project>{2ba24772-f7b0-4652-a430-2f4c2262e882}</Project>\n      <Name>Test.WebApp.ExternalViews</Name>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\Test.Module\\Test.Module.csproj\">\n      <Project>{5fcaecc3-787b-473f-a372-783d0c235190}</Project>\n      <Name>Test.Module</Name>\n    </ProjectReference>\n    <Reference Include=\"netstandard\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Compile Include=\"**\\*.cs\" Exclude=\"obj\\**\\*\" />\n    <Content Include=\"**\\*.cshtml\" Exclude=\"Views\\Home\\ExcludedLayout.cshtml\" />\n    <None Include=\"Web.config\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Reference Include=\"System.Web\" />\n    <Reference Include=\"Microsoft.CSharp\" />\n    <PackageReference Include=\"Microsoft.AspNet.Mvc\" Version=\"5.2.7\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"2.10.0\" />\n    <PackageReference Include=\"System.ValueTuple\" Version=\"4.5.0\" />\n    <PackageReference Include=\"MSBuild.Microsoft.VisualStudio.Web.targets\" Version=\"14.0.0.3\" />\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.0.0-beta-63127-02\" PrivateAssets=\"All\" />\n  </ItemGroup>\n  <Import Project=\"$(MSBuildBinPath)\\Microsoft.CSharp.targets\" />\n  <Target Name=\"MvcBuildViews\" AfterTargets=\"AfterBuild\" Condition=\"'$(MvcBuildViews)'=='true'\">\n    <AspNetCompiler VirtualPath=\"temp\" PhysicalPath=\"$(WebProjectOutputDir)\" />\n  </Target>\n  <ProjectExtensions>\n    <VisualStudio>\n      <FlavorProperties GUID=\"{349c5851-65df-11da-9384-00065b846f21}\">\n        <WebProjectProperties>\n          <SaveServerSettingsInUserFile>True</SaveServerSettingsInUserFile>\n        </WebProjectProperties>\n      </FlavorProperties>\n    </VisualStudio>\n  </ProjectExtensions>\n\n  <PropertyGroup>\n    <SEPrecompilerPath Condition=\"'$(SEPrecompilerPath)' == ''\">$(SolutionDir)StackExchange.Precompilation.Build\\bin\\$(Configuration)\\$(TargetFramework)\\</SEPrecompilerPath>\n    <!-- Using DEBUG build configuration to test RoslynRazorViewEngine in VS, SECompilerPath is set in the build script  -->\n    <SEPrecompilerIncludeRazor Condition=\"'$(Configuration)' == 'Release' or '(SECompilerPath)' != ''\">true</SEPrecompilerIncludeRazor>\n  </PropertyGroup>\n  <Import Project=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.targets\" />\n\n  <Target Name=\"Pack\">\n    <!-- this target is just a dummy to enable the pack target solution wide, since this is the only non-SDK project in the solution -->\n  </Target>\n</Project>"
  },
  {
    "path": "Test.WebApp/Views/Home/ExcludedLayout.cshtml",
    "content": "﻿\n@{\n    Layout = \"~/Views/Shared/_Layout.Excluded.cshtml\";\n}\n\n<h2>ExcludedLayout</h2>\n\n"
  },
  {
    "path": "Test.WebApp/Views/Home/Index.Mobile.cshtml",
    "content": "﻿@model SampleModel\n@{\n    ViewBag.Title = \"Test Page\";\n}\nMobile Precompiled View Paths:\n<ul>\n    @foreach (var path in Model.ViewPaths)\n    {\n        <li>@path</li>\n    }\n</ul>\n\n@Html.EditorForModel()\n\n@Helpers.Test()\n"
  },
  {
    "path": "Test.WebApp/Views/Home/Index.cshtml",
    "content": "﻿@model SampleModel\n@{\n    ViewBag.Title = \"Test Page\";\n}\nPrecompiled View Paths:\n<ul>\n    @foreach (var path in Model.ViewPaths)\n    {\n        <li>@path</li>\n    }\n</ul>\n\n@Html.EditorForModel()\n@Html.Partial(\"../Other/../Other/RelativePartial\")\n@Helpers.Test()\n\n@if (!MvcApplication.IsDebug)\n{\n    @Html.Partial(\"ExternalPartial\");\n}\n\n@{\n    // c# 7 features\n\n\n    (string title, string url) GetTitle() => (\"ValueTuple\", \"`2\");\n    @GetTitle().Item1\n}"
  },
  {
    "path": "Test.WebApp/Views/Other/RelativePartial.cshtml",
    "content": "﻿RelativePartial.cshtml\n@{\n    @*\n    code bellow is a repro case for a Razer parser errors, that were only caught\n    in RoslynRazorViewEngine but not during precompilation...\n\n    to repro use `@foreach` instead of `foreach`\n    *@\n\n    foreach(var x in new []{1,2,3})\n    {\n        @:@x,\n    }\n}"
  },
  {
    "path": "Test.WebApp/Views/Shared/EditorTemplates/SampleModel.Mobile.cshtml",
    "content": "﻿@model Test.WebApp.Models.SampleModel\n<hr/>\nEditorTemplates.Mobile\n@using (Html.BeginForm())\n{\n    @Html.AntiForgeryToken()\n    <div class=\"form-horizontal\">\n        @Html.ValidationSummary(true, \"\", new { @class = \"text-danger\" })\n        @Html.EditorFor(m => m.ViewPaths)\n        <div class=\"form-group\">\n            <div class=\"col-md-offset-2 col-md-10\">\n                <input type=\"submit\" value=\"Save\" disabled=\"disabled\" class=\"btn btn-default\" />\n            </div>\n        </div>\n    </div>\n}\n<hr/>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/EditorTemplates/SampleModel.cshtml",
    "content": "﻿@model Test.WebApp.Models.SampleModel\n<hr/>\nEditorTemplates\n@using (Html.BeginForm())\n{\n    @Html.AntiForgeryToken()\n    <div class=\"form-horizontal\">\n        @Html.ValidationSummary(true, \"\", new { @class = \"text-danger\" })\n        @Html.EditorFor(m => m.ViewPaths)\n        <div class=\"form-group\">\n            <div class=\"col-md-offset-2 col-md-10\">\n                <input type=\"submit\" value=\"Save\" disabled=\"disabled\" class=\"btn btn-default\" />\n            </div>\n        </div>\n    </div>\n}\n<hr/>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/EditorTemplates/String.cshtml",
    "content": "﻿@model System.String\n<div>\n    <input readonly=\"readonly\" disabled=\"disabled\" value=\"@Model\" />\n</div>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Footer.Mobile.cshtml",
    "content": "﻿@model DateTime\n<footer>\n    <p>&copy; @Model.Year Mobile Partial Footer</p>\n</footer>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Footer.cshtml",
    "content": "﻿@model DateTime\n<footer>\n    <p>&copy; @Model.Year Partial Footer</p>\n</footer>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Layout.Excluded.cshtml",
    "content": "﻿Layout\n\n@RenderBody()\n\n/Layout"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Layout.Mobile.cshtml",
    "content": "﻿<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\" />\n    <title>@ViewBag.Title - Test.WebApp - Mobile</title>\n</head>\n<body>\n    <h1>Mobile</h1>\n    <hr/>\n    <div class=\"body-content\">\n        @RenderBody()\n        <hr />\n    </div>\n    @Html.Partial(\"_Footer\", DateTime.Now)\n    @Html.Partial(\"~/Content/PartialExternalContent.cshtml\")\n</body>\n</html>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Layout.Overridden.cshtml",
    "content": "﻿<h1>OVERRIDDDDDEN</h1>\n<h2>@ViewBag.Title - Test.WebApp</h2>\n@RenderBody()\n<h1>/OVERRIDDDDDEN</h1>\n"
  },
  {
    "path": "Test.WebApp/Views/Shared/_Layout.cshtml",
    "content": "﻿<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\" />\n    <title>@ViewBag.Title - Test.WebApp</title>\n</head>\n<body>\n    <div class=\"body-content\">\n        @RenderBody()\n        <hr />\n    </div>\n    @Html.ActionLink(\"Overridden layout\", \"IndexOverridden\", new { controller = \"Home\".Dump() })\n    @Html.ActionLink(\"Excluded layout\", \"ExcludedLayout\", new { controller = \"Home\" })\n    @Html.Partial(\"_Footer\", DateTime.Now)\n    @Html.Partial(\"~/Content/PartialExternalContent.cshtml\")\n</body>\n</html>\n"
  },
  {
    "path": "Test.WebApp/Views/Web.config",
    "content": "﻿<?xml version=\"1.0\"?>\n\n<configuration>\n  <configSections>\n    <sectionGroup name=\"system.web.webPages.razor\" type=\"System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\">\n      <section name=\"host\" type=\"System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\n      <section name=\"pages\" type=\"System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\n    </sectionGroup>\n  </configSections>\n\n  <system.web.webPages.razor>\n    <host factoryType=\"System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" />\n    <pages pageBaseType=\"System.Web.Mvc.WebViewPage\">\n      <namespaces>\n        <add namespace=\"System.Web.Mvc\" />\n        <add namespace=\"System.Web.Mvc.Ajax\" />\n        <add namespace=\"System.Web.Mvc.Html\" />\n        <add namespace=\"System.Web.Routing\" />\n        <add namespace=\"Test.Module\" />\n        <add namespace=\"Test.WebApp\" />\n        <add namespace=\"Test.WebApp.Models\" />\n      </namespaces>\n    </pages>\n  </system.web.webPages.razor>\n\n  <appSettings>\n    <add key=\"webpages:Enabled\" value=\"false\" />\n  </appSettings>\n\n  <system.webServer>\n    <handlers>\n      <remove name=\"BlockViewHandler\"/>\n      <add name=\"BlockViewHandler\" path=\"*\" verb=\"*\" preCondition=\"integratedMode\" type=\"System.Web.HttpNotFoundHandler\" />\n    </handlers>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "Test.WebApp/Views/_ViewStart.cshtml",
    "content": "﻿@{\n    Layout = \"~/Views/Shared/_Layout.cshtml\";\n}\n_ViewStart\n<hr />\n"
  },
  {
    "path": "Test.WebApp/Web.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  For more information on how to configure your ASP.NET application, please visit\n  http://go.microsoft.com/fwlink/?LinkId=301880\n  -->\n<configuration>\n  <configSections>\n    <section name=\"stackExchange.precompiler\" type=\"StackExchange.Precompilation.PrecompilerSection, StackExchange.Precompilation\" />\n  </configSections>\n  <stackExchange.precompiler>\n    <modules>\n      <add type=\"Test.Module.TestCompileModule, Test.Module\" />\n    </modules>\n  </stackExchange.precompiler>\n  <appSettings>\n    <add key=\"owin:AutomaticAppStartup\" value=\"false\" />\n    <add key=\"webpages:Version\" value=\"3.0.0.0\" />\n    <add key=\"webpages:Enabled\" value=\"true\" />\n  </appSettings>\n  <!--\n    For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.\n\n    The following attributes can be set on the <httpRuntime> tag.\n      <system.Web>\n        <httpRuntime targetFramework=\"4.5.2\" />\n      </system.Web>\n  -->\n  <system.web>\n    <authentication mode=\"None\" />\n    <httpRuntime targetFramework=\"4.6.2\" />\n    <compilation debug=\"true\" targetFramework=\"4.6.2\">\n      <assemblies>\n        <add assembly=\"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n        <add assembly=\"System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\" />\n      </assemblies>\n    </compilation>\n  </system.web>\n  \n  <!-- /langversion needed for cshtml editor -->\n  <system.codedom>\n    <compilers>\n      <compiler language=\"c#;cs;csharp\" extension=\".cs\" type=\"Microsoft.CSharp.CSharpCodeProvider, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" warningLevel=\"4\" compilerOptions=\"/langversion:7 /nowarn:1659;1699;1701\" />\n    </compilers>\n  </system.codedom>\n\n  <runtime>\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Web.Helpers\" publicKeyToken=\"31bf3856ad364e35\" />\n        <bindingRedirect oldVersion=\"1.0.0.0-3.0.0.0\" newVersion=\"3.0.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Web.Mvc\" publicKeyToken=\"31bf3856ad364e35\" />\n        <bindingRedirect oldVersion=\"1.0.0.0-5.2.3.0\" newVersion=\"5.2.3.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Web.WebPages\" publicKeyToken=\"31bf3856ad364e35\" />\n        <bindingRedirect oldVersion=\"1.0.0.0-3.0.0.0\" newVersion=\"3.0.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime.Extensions\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Runtime.InteropServices\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Reflection\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.1.0\" newVersion=\"4.1.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Security.Cryptography.Algorithms\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.1.0\" newVersion=\"1.2.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\n      </dependentAssembly>\n      <dependentAssembly>\n        <assemblyIdentity name=\"System.ValueTuple\" culture=\"neutral\" publicKeyToken=\"cc7b13ffcd2ddd51\" />\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\n      </dependentAssembly>\n    </assemblyBinding>\n  </runtime>\n</configuration>"
  },
  {
    "path": "Test.WebApp.ExternalViews/App_Code/Helpers.cshtml",
    "content": "﻿@helper Test()\n{\n    <div>HELPERS</div>\n}\n"
  },
  {
    "path": "Test.WebApp.ExternalViews/ExternalViews.cs",
    "content": "﻿namespace Test.WebApp\n{\n    public class ExternalViews\n    {\n    }\n}\n"
  },
  {
    "path": "Test.WebApp.ExternalViews/Test.WebApp.ExternalViews.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <OutputType>Library</OutputType>\n    <AppDesignerFolder>Properties</AppDesignerFolder>\n    <RootNamespace>Test.WebApp</RootNamespace>\n    <TargetFramework>net462</TargetFramework>\n    <DebugType>portable</DebugType>\n  </PropertyGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.csproj\">\n      <Project>{31dfcccc-2f44-405e-a2d7-bb1ac718e7b9}</Project>\n      <Name>StackExchange.Precompilation.Build</Name>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\StackExchange.Precompilation\\StackExchange.Precompilation.csproj\">\n      <Project>{3c0a90f1-b19e-4305-ab71-3cd31c7d0f4d}</Project>\n      <Name>StackExchange.Precompilation</Name>\n    </ProjectReference>\n    <ProjectReference Include=\"..\\StackExhcange.Precompilation.MVC5\\StackExchange.Precompilation.MVC5.csproj\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Reference Include=\"System.Web\" />\n    <PackageReference Include=\"Microsoft.AspNet.Mvc\" Version=\"5.2.7\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"2.10.0\" />\n  </ItemGroup>\n  <PropertyGroup>\n    <SEPrecompilerPath Condition=\"'$(SEPrecompilerPath)' == ''\">$(SolutionDir)StackExchange.Precompilation.Build\\bin\\$(Configuration)\\$(TargetFramework)\\</SEPrecompilerPath>\n    <!-- Always precompile -->\n    <SEPrecompilerIncludeRazor>true</SEPrecompilerIncludeRazor>\n  </PropertyGroup>\n  <Import Project=\"..\\StackExchange.Precompilation.Build\\StackExchange.Precompilation.Build.targets\" />\n</Project>"
  },
  {
    "path": "Test.WebApp.ExternalViews/Views/Shared/ExternalPartial.cshtml",
    "content": "﻿ExternalPartial.cshtml\n"
  },
  {
    "path": "Test.WebApp.ExternalViews/Views/Shared/ExternalView.cshtml",
    "content": "﻿ExternalView.cshtml\n@{ Html.RenderPartial(\"ExternalPartial\"); }"
  },
  {
    "path": "Test.WebApp.ExternalViews/Views/Web.config",
    "content": "﻿<?xml version=\"1.0\"?>\n\n<configuration>\n  <configSections>\n    <sectionGroup name=\"system.web.webPages.razor\" type=\"System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\">\n      <section name=\"host\" type=\"System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\n      <section name=\"pages\" type=\"System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\n    </sectionGroup>\n  </configSections>\n\n  <system.web.webPages.razor>\n    <host factoryType=\"System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" />\n    <pages pageBaseType=\"System.Web.Mvc.WebViewPage\">\n      <namespaces>\n        <add namespace=\"System.Web.Mvc\" />\n        <add namespace=\"System.Web.Mvc.Ajax\" />\n        <add namespace=\"System.Web.Mvc.Html\" />\n        <add namespace=\"System.Web.Routing\" />\n      </namespaces>\n    </pages>\n  </system.web.webPages.razor>\n\n  <appSettings>\n    <add key=\"webpages:Enabled\" value=\"false\" />\n  </appSettings>\n\n  <system.webServer>\n    <handlers>\n      <remove name=\"BlockViewHandler\"/>\n      <add name=\"BlockViewHandler\" path=\"*\" verb=\"*\" preCondition=\"integratedMode\" type=\"System.Web.HttpNotFoundHandler\" />\n    </handlers>\n  </system.webServer>\n</configuration>\n"
  },
  {
    "path": "appveyor.yml",
    "content": "version: '{build}'\nimage: Visual Studio 2017\nassembly_info:\n  patch: true\n  file: '**\\AssemblyInfo.*'\n  assembly_version: $(semver)\n  assembly_file_version: $(semver).{build}\n  assembly_informational_version: '{version}'\ninit:\n  - git config --global core.autocrlf input\ninstall:\n- ps: >-\n    set -name semver -scope global -value (get-content .\\semver.txt)\n\n    $env:semver = $semver\n\n    if (\"$env:appveyor_repo_tag_name\" -ne \"releases/$semver\") {\n      $env:package_suffix = \"-alpha$env:appveyor_build_number\" }\n\n    update-appveyorbuild -Version \"$env:semver$env:package_suffix\"\nnuget:\n  disable_publish_on_pr: true\nbuild_script:\n- ps: .\\BuildAndPack.ps1 -VersionSuffix \"$env:package_suffix\" -GitCommitId \"$env:appveyor_repo_commit\" -MsBuildArgs @(, \"/logger:C:\\Program Files\\AppVeyor\\BuildAgent\\Appveyor.MSBuildLogger.dll\") -CIBuild\nskip_branch_with_pr: true\nskip_tags: false\nskip_commits:\n  files:\n    - '**/*.md'\nartifacts:\n- path: packages/obj/*.nupkg\ndeploy:\n- provider: NuGet\n  name: alpha\n  on:\n    branch: master\n  server: https://www.myget.org/F/stackoverflow/api/v2\n  api_key:\n    secure: P/UHxq2DEs0GI1SoDXDesHjRVsSVgdywz5vmsnhFQQY5aJgO3kP+QfhwfhXz19Rw\n  symbol_server: https://www.myget.org/F/stackoverflow/symbols/api/v2/package\n- provider: NuGet\n  name: release\n  on:\n    appveyor_repo_tag: true\n  server: https://www.myget.org/F/stackoverflow/api/v2\n  api_key:\n    secure: P/UHxq2DEs0GI1SoDXDesHjRVsSVgdywz5vmsnhFQQY5aJgO3kP+QfhwfhXz19Rw\n  symbol_server: https://www.myget.org/F/stackoverflow/symbols/api/v2/package\n"
  },
  {
    "path": "license.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Stack Exchange\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "semver.txt",
    "content": "5.1.0\n"
  }
]