diff --git a/README.md b/README.md index 5d53bf5..50cd336 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,19 @@ Please see the blog [Enabling the .NET Compiler Platform (“Roslyn”) in ASP.N for an introduction to Microsoft.CodeDom.Providers.DotNetCompilerPlatform. ## Updates ++ #### Version 4.1.0 (preview1) + - #### Refreshed current compilers + In keeping with the new versioning scheme for this project, the version has been revved to 4.1 to match the version of the compilers included. + + - #### No more old compilers + Stop carrying old versions of compilers. If you upgrade to get new compilers, you get new compilers. The old compilers that might carry references to binaries that get flagged in security scans even though the binaries don't get copied to the ouput directory... they just won't be included in the package anymore. + + - #### .Net >= 4.7.2 + As a result of not keeping older compilers packaged in this project, we can no longer support versions before 4.7.2 because compiler versions 3.0 and newer only support 4.7.2+. + + - #### Drop install.ps1, Rely more on msbuild + Nuget has moved on from install.ps1. We had one foot in the msbuild camp before, and one foot still in the install.ps1 camp. Time to just jump in with both feet. See the 'RoslynRegisterInConfig' setting description below. + + #### Version 3.11.0 (preview1) - #### Refreshed compilers In keeping with the new versioning scheme for this project, the version has been revved to 3.11 to match the version of the compilers included. @@ -46,13 +59,28 @@ for an introduction to Microsoft.CodeDom.Providers.DotNetCompilerPlatform. Generally, command-line options for the codedom compilers can be specified using the `compilerOptions` attribute of the compiler when it is registered in configuration. There are however, a handful of options for controlling some behaviors of this package that are not command-line options. These options fall into two broad categories and can be set as follows: ### Build-time Options -+ **Specify the path to copy Roslyn compiler at build time** - When building projects, target files included by the Microsoft.CodeDom.Providers.DotNetCompilerPlatform nupkg will copy appropriate Roslyn compiler into bin\roslyn folder. With this setting, you can specify a custom path from which the build process will copy the Roslyn compiler, rather than using one of the pre-packaged Roslyn compilers. ++ **(V2) Specify the path to copy Roslyn compiler at build time** - When building projects, target files included by the Microsoft.CodeDom.Providers.DotNetCompilerPlatform nupkg will copy appropriate Roslyn compiler into bin\roslyn folder. With this setting, you can specify a custom path from which the build process will copy the Roslyn compiler, rather than using one of the pre-packaged Roslyn compilers. **Setting name** - RoslynToolPath **How to use it** - ```msbuild mysolution.sln /t:build /p:RoslynToolPath="[Roslyn compiler folder full path]"``` **Use case** - In 2.0.0 version, Microsoft.CodeDom.Providers.DotNetCompilerPlatform nupkg removes the dependency on Microsoft.Net.Compilers nupkg. Instead, it embeds one version of Roslyn compiler inside the nupkg. It's possible that the embeded version of Roslyn compiler is not the one you want, so through this setting you can specify a version of Roslyn compiler at build time which will be copied to bin\roslyn folder. + ++ **(V4) Skip copying Roslyn compiler at build time** - When building projects, target files will copy the appropriate binaries specified by the 'RoslynToolPath' setting described above and copy them into the project output for runtime use. This copy step can be skipped by using this project setting. + + **Setting name** - RoslynCopyToOutDir + + **How to use it** - ```msbuild mysolution.sln /t:build /p:RoslynCopyToOutDir="[true|false]"``` + ++ **(V4) Don't modify config at build time** - CodeDom providers are not magically picked up from referenced assemblies. They must be explicitly registered in config in order to be used. Prior to the Version 4 update, all modifications to config were performed via powershell scripts included in the nuget package. This powershell method worked with 'packages.config' apps, but does not work with 'PackageReference' apps. As more applications move towards the preferred 'PackageReference' way of doing things, we have updated our method of config registration to be an msbuild task instead of a powershell install script. We take care not to stomp over existing settings. But this step gets checked/performed on every build now instead of just on package install. Use this setting to skip the config update. + + **Setting name** - RoslynRegisterInConfig + + **How to use it** - ```msbuild mysolution.sln /t:build /p:RoslynRegisterInConfig="[true|false]"``` + + **Use case** - This config-manipulation step happens on ever build. (Even designer builds.) We take care to be as non-invasive as possible, but if you want us to stay entirely hands-off and update your config registrations manually, this setting enables that. + ### Run-time Options + **Specify the path to load Roslyn compiler at runtime** - When asp.net compiles the views at runtime or precompile time(using aspnet_compiler to precompile the web app), Microsoft.CodeDom.Providers.DotNetCompilerPlatform needs a path to load Roslyn compiler. This setting can be used to specify this loading path. diff --git a/RoslynCodeProviderTest/CommonCodeDomProviderTests.cs b/RoslynCodeProviderTest/CommonCodeDomProviderTests.cs index 6f25153..17239ff 100644 --- a/RoslynCodeProviderTest/CommonCodeDomProviderTests.cs +++ b/RoslynCodeProviderTest/CommonCodeDomProviderTests.cs @@ -19,8 +19,8 @@ public void AssemblyVersion(CodeDomProvider provider) { var ver = provider.GetType().Assembly.GetName().Version; - Assert.Equal(3, ver.Major); - Assert.Equal(11, ver.Minor); + Assert.Equal(4, ver.Major); + Assert.Equal(1, ver.Minor); } public void FileExtension(CodeDomProvider provider, string extension) { diff --git a/src/DotNetCompilerPlatformTasks/UpdateCompilerConfigRecord.cs b/src/DotNetCompilerPlatformTasks/UpdateCompilerConfigRecord.cs new file mode 100644 index 0000000..08b6d70 --- /dev/null +++ b/src/DotNetCompilerPlatformTasks/UpdateCompilerConfigRecord.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Xml; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace DotNetCompilerPlatformTasks +{ + public class UpdateCompilerConfigRecord : Task + { + [Required] + public string ConfigFile { get; set; } + [Required] + public string Extension { get; set; } + [Required] + public string Language { get; set; } + [Required] + public string WarningLevel { get; set; } + [Required] + public string Options { get; set; } + [Required] + public string CompilerType { get; set; } + + private readonly string singleTab = " "; + + + public override bool Execute() + { + try + { + XmlDocument config = new XmlDocument() { PreserveWhitespace = true }; + config.Load(ConfigFile); + + // Look for existing 'compiler' record first. Keying on 'extension' is a little dubious since that attribute can + // technically be a ';' separated list of extensions... but it's what we always seemed to do in the past. + XmlNode compiler = config.SelectSingleNode($"/configuration/system.codedom/compilers/compiler[@extension='{Extension}']"); + + // Create the 'compiler' record if not found. + if (compiler == null) + { + string indent = ""; + XmlElement e = CreateElement(config, "system.codedom/compilers", "compiler", ref indent); + e.SetAttribute("language", Language); + e.SetAttribute("extension", Extension); + e.SetAttribute("warningLevel", WarningLevel); + e.SetAttribute("compilerOptions", Options); + e.SetAttribute("type", CompilerType); + + // Add a 'providerOption' to not do ASP.Net "magic" within the codedom provider if not working on web.config + if (!ConfigFile.EndsWith("web.config", System.StringComparison.InvariantCultureIgnoreCase)) + { + XmlElement pOpt = CreateIndentedElement(e, "providerOption", indent + singleTab); + pOpt.SetAttribute("name", "UseAspNetSettings"); + pOpt.SetAttribute("value", "false"); + } + + config.Save(ConfigFile); + return true; + } + + // Otherwise, leave the existing compiler alone - including any 'providerOptions' - except... + // Ensure the 'type' value is current. + var typeAttr = compiler.Attributes["type"]; + if (typeAttr == null || string.Compare(typeAttr.Value, CompilerType, System.StringComparison.InvariantCultureIgnoreCase) != 0) + { + typeAttr = config.CreateAttribute("type"); + typeAttr.Value = CompilerType; + compiler.Attributes.SetNamedItem(typeAttr); + config.Save(ConfigFile); + } + } + catch (Exception e) + { + Log.LogErrorFromException(e); + return false; + } + + return true; + } + + private XmlElement CreateElement(XmlDocument doc, string path, string name, ref string indent) + { + XmlElement current = doc.DocumentElement; + + foreach (var partName in path.Trim('/').Split('/')) + { + if (string.IsNullOrWhiteSpace(partName)) + continue; + + current = (current.SelectSingleNode(partName) as XmlElement) ?? CreateIndentedElement(current, partName, indent); + indent += singleTab; + } + + return CreateIndentedElement(current, name, indent); + } + + private XmlElement CreateIndentedElement(XmlNode parent, string name, string indent) + { + if (!parent.HasChildNodes) + parent.AppendChild(parent.OwnerDocument.CreateWhitespace(Environment.NewLine + indent + singleTab)); + else + parent.AppendChild(parent.OwnerDocument.CreateWhitespace(singleTab)); + + XmlElement e = parent.AppendChild(parent.OwnerDocument.CreateElement(name)) as XmlElement; + parent.AppendChild(parent.OwnerDocument.CreateWhitespace(Environment.NewLine + indent)); + return e; + } + } +} diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.nuproj b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.nuproj index 5e4b9a8..a2881e0 100644 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.nuproj +++ b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.nuproj @@ -10,15 +10,15 @@ $(AssemblyPath) - lib\net462 + lib\net472 $(OutputPath) - lib\net462 + lib\net472 $(OutputPath) - lib\net462 + lib\net472 @@ -29,72 +29,17 @@ $(OutputPath) tasks - - content\net462\app.config.install.xdt - - - content\net462\web.config.install.xdt - - - content\net462\app.config.uninstall.xdt - - - content\net462\web.config.uninstall.xdt - - - content\net472\app.config.install.xdt - - - content\net472\web.config.install.xdt - - - content\net472\app.config.uninstall.xdt - - - content\net472\web.config.uninstall.xdt - - - build\net472 - - - build\net462 - - - build\net462 - - + build\net472 - - tools - - - tools - - - tools\$(LocalRoslyn46FolderName) - - - tools\$(LocalRoslyn472FolderName) + + tools\$(LocalRoslynFolderName) icons - - - - - - - - Microsoft400 - - - - $(PackageOutputDir) diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.targets b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.targets index 7ebe80e..a6cf880 100644 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.targets +++ b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.targets @@ -1,11 +1,12 @@ - true + true + $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\$roslynToolPath$')) - - + + @@ -37,14 +38,29 @@ - + - + + + + + + + + @@ -60,5 +76,6 @@ + \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net46/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net46/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets deleted file mode 100644 index 7dd5012..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net46/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets +++ /dev/null @@ -1,9 +0,0 @@ - - - - - $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\tools\roslyn46')) - - - - \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net472/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net472/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets deleted file mode 100644 index 3d1c7d0..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/build/net472/Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Extensions.targets +++ /dev/null @@ -1,9 +0,0 @@ - - - - - $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\..\tools\roslyn472')) - - - - \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.install.xdt b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.install.xdt deleted file mode 100644 index 8bdd7c4..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.install.xdt +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.uninstall.xdt b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.uninstall.xdt deleted file mode 100644 index 8dee510..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/content/config.uninstall.xdt +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/common.ps1 b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/common.ps1 deleted file mode 100644 index 962f5d0..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/common.ps1 +++ /dev/null @@ -1,251 +0,0 @@ -# Copyright (c) .NET Foundation. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - - -## -## Assigning a "DefaultValue" to a ParameterDescription will result in emitting this parameter when -## writing out a default compiler declaration. -## -## Setting IsRequired to $true will require the attribute to be set on all declarations in config. -## -Add-Type @" - using System; - - public class CompilerParameterDescription { - public string Name; - public string DefaultValue; - public bool IsRequired; - public bool IsProviderOption; - } - - public class CodeDomProviderDescription { - public string TypeName; - public string Assembly; - public string Version; - public string FileExtension; - public CompilerParameterDescription[] Parameters; - } -"@ - -function InstallCodeDomProvider($providerDescription) { - ##### Update/Rehydrate config declarations ##### - $config = ReadConfigFile - $rehydratedCount = RehydrateOldDeclarations $config $providerDescription - $updatedCount = UpdateDeclarations $config $providerDescription - - ##### Add the default provider if it wasn't rehydrated above - $defaultProvider = $config.xml.configuration["system.codedom"].compilers.compiler | where { $_.extension -eq $providerDescription.FileExtension } - if ($defaultProvider -eq $null) { AddDefaultDeclaration $config $providerDescription } - SaveConfigFile $config | Out-Null -} - -function UninstallCodeDomProvider($providerType) { - ##### Dehydrate config declarations ##### - $config = ReadConfigFile - DehydrateDeclarations $config $providerType | Out-Null - SaveConfigFile $config | Out-Null -} - -function GetConfigFileName() { - # Try web.config first. Then fall back to app.config. - $configFile = $project.ProjectItems | where { $_.Name -ieq "web.config" } - if ($configFile -eq $null) { $configFile = $project.ProjectItems | where { $_.Name -ieq "app.config" } } - $configPath = $configFile.Properties | where { $_.Name -ieq "LocalPath" } - if ($configPath -eq $null) { $configPath = $configFile.Properties | where { $_.Name -ieq "FullPath" } } - return $configPath.Value -} - -function GetTempFileName() { - $uname = $project.UniqueName - if ([io.path]::IsPathRooted($uname)) { $uname = $project.Name } - return [io.path]::Combine($env:TEMP, "Microsoft.CodeDom.Providers.DotNetCompilerPlatform.Temp", $uname + ".xml") -} - -function ReadConfigFile() { - $configFile = GetConfigFileName - $configObj = @{ fileName = $configFile; xml = (Select-Xml -Path "$configFile" -XPath /).Node } - $configObj.xml.PreserveWhitespace = $true - return $configObj -} - -function DehydrateDeclarations($config, $typeName) { - $tempFile = GetTempFileName - $count = 0 - - if ([io.file]::Exists($tempFile)) { - $xml = (Select-Xml -Path "$tempFile" -XPath /).Node - $xml.PreserveWhitespace = $true - } else { - $xml = New-Object System.Xml.XmlDocument - $xml.PreserveWhitespace = $true - $xml.AppendChild($xml.CreateElement("driedDeclarations")) | Out-Null - } - - foreach ($rec in $config.xml.configuration["system.codedom"].compilers.compiler | where { IsSameType $_.type $typeName }) { - # Remove records from config. - $config.xml.configuration["system.codedom"].compilers.RemoveChild($rec) | Out-Null - - # Add the record to the temp stash. Don't worry about duplicates. - AppendChildNode $xml.ImportNode($rec, $true) $xml.DocumentElement | Out-Null - $count++ - } - - # Save the dehydrated declarations - $tmpFolder = Split-Path $tempFile - md -Force $tmpFolder | Out-Null - $xml.Save($tempFile) | Out-Null - return $count -} - -function RehydrateOldDeclarations($config, $providerDescription) { - $tempFile = GetTempFileName - if (![io.file]::Exists($tempFile)) { return 0 } - - $count = 0 - $xml = (Select-Xml -Path "$tempFile" -XPath /).Node - $xml.PreserveWhitespace = $true - - foreach($rec in $xml.driedDeclarations.compiler | where { IsSameType $_.type ($providerDescription.TypeName + "," + $providerDescription.Assembly) }) { - # Remove records that match type, even if we don't end up rehydrating them. - $xml.driedDeclarations.RemoveChild($rec) | Out-Null - - # Skip if an existing record of the same file extension already exists. - $existingRecord = $config.xml.configuration["system.codedom"].compilers.compiler | where { $_.extension -eq $rec.extension } - if ($existingRecord -ne $null) { continue } - - # Bring the record back to life - AppendChildNode $config.xml.ImportNode($rec, $true) $config.xml.configuration["system.codedom"]["compilers"] | Out-Null - $count++ - Write-Host "Restored system.codedom compiler for extension '$($rec.extension)'." - } - - # Make dried record removal permanent - $xml.Save($tempFile) | Out-Null - - return $count -} - -function UpdateDeclarations($config, $providerDescription) { - $count = 0 - - foreach ($provider in $config.xml.configuration["system.codedom"].compilers.compiler | where { IsSameType $_.type ($providerDescription.TypeName + "," + $providerDescription.Assembly) }) { - - $failed = $false - - # Add default attributes if they are required and not already present - foreach ($p in $providerDescription.Parameters | where { ($_.IsRequired -eq $true) -and ($_.IsProviderOption -eq $false) }) { - if ($provider.($p.Name) -eq $null) { - if ($p.DefaultValue -eq $null) { - Write-Warning "Failed to add parameter to '$($provider.name)' codeDom provider: '$($p.Name)' is required, but does not have a default value." - $failed = $true - } - $attr = $config.xml.CreateAttribute($p.Name) - $attr.Value = $p.DefaultValue - $provider.Attributes.InsertBefore($attr, $provider.Attributes["type"]) | Out-Null - } - } - - # Do the same thing for default providerOptions if not already present - foreach ($p in $providerDescription.Parameters | where { ($_.IsRequired -eq $true) -and ($_.IsProviderOption -eq $true)}) { - $existing = $provider.providerOption | where { $_.name -eq $p.Name } - if ($existing -eq $null) { - if ($p.DefaultValue -eq $null) { - Write-Warning "Failed to add providerOption to '$($provider.name)' codeDom provider: '$($p.Name)' is required, but does not have a default value." - $failed = $true - } - $po = $config.xml.CreateElement("providerOption") - $po.SetAttribute("name", $p.Name) | Out-Null - $po.SetAttribute("value", $p.DefaultValue) | Out-Null - AppendChildNode $po $provider 4 | Out-Null - } - } - - # Finally, update type. And do so with remove/add so the 'type' parameter gets put at the end - $provider.RemoveAttribute("type") | Out-Null - $provider.SetAttribute("type", "$($providerDescription.TypeName), $($providerDescription.Assembly), Version=$($providerDescription.Version), Culture=neutral, PublicKeyToken=31bf3856ad364e35") | Out-Null - - if ($failed -ne $true) { $count++ } - } - - return $count -} - -function AddDefaultDeclaration($config, $providerDescription) { - $dd = $config.xml.CreateElement("compiler") - - # file extension first - $dd.SetAttribute("extension", $providerDescription.FileExtension) | Out-Null - - # everything else in the middle - foreach ($p in $providerDescription.Parameters) { - if ($p.IsRequired -and ($p.DefaultValue -eq $null)) { - Write-Host "Failed to add default declaration for code dom extension '$($providerDescription.FileExtension)': '$($p.Name)' is required, but does not have a default value." - return - } - - if ($p.DefaultValue -ne $null) { - if ($p.IsProviderOption -eq $true) { - $po = $config.xml.CreateElement("providerOption") - $po.SetAttribute("name", $p.Name) | Out-Null - $po.SetAttribute("value", $p.DefaultValue) | Out-Null - AppendChildNode $po $dd 4 | Out-Null - } else { - $dd.SetAttribute($p.Name, $p.DefaultValue) | Out-Null - } - } - } - - # type last - $dd.SetAttribute("type", "$($providerDescription.TypeName), $($providerDescription.Assembly), Version=$($providerDescription.Version), Culture=neutral, PublicKeyToken=31bf3856ad364e35") | Out-Null - - AppendChildNode $dd $config.xml.configuration["system.codedom"]["compilers"] | Out-Null - Write-Host "Added system.codedom compiler for extension '$($dd.extension)'." -} - -function AppendChildNode($provider, $parent, $indentLevel = 3) { - $lastSibling = $parent.ChildNodes | where { $_ -isnot [System.Xml.XmlWhitespace] } | select -Last 1 - if ($lastSibling -ne $null) { - # If not the first child, then copy the whitespace convention of the existing child - $ws = ""; - $prev = $lastSibling.PreviousSibling | where { $_ -is [System.Xml.XmlWhitespace] } - while ($prev -ne $null) { - $ws = $prev.data + $ws - $prev = $prev.PreviousSibling | where { $_ -is [System.Xml.XmlWhitespace] } - } - $parent.InsertAfter($provider, $lastSibling) | Out-Null - if ($ws.length -gt 0) { $parent.InsertAfter($parent.OwnerDocument.CreateWhitespace($ws), $lastSibling) | Out-Null } - return - } - - # Add on a new line with indents. Make sure there is no existing whitespace mucking this up. - foreach ($exws in $parent.ChildNodes | where { $_ -is [System.Xml.XmlWhitespace] }) { $parent.RemoveChild($exws) | Out-Null } - $parent.AppendChild($parent.OwnerDocument.CreateWhitespace("`r`n")) | Out-Null - $parent.AppendChild($parent.OwnerDocument.CreateWhitespace(" " * $indentLevel)) | Out-Null - $parent.AppendChild($provider) | Out-Null - $parent.AppendChild($parent.OwnerDocument.CreateWhitespace("`r`n")) | Out-Null - $parent.AppendChild($parent.OwnerDocument.CreateWhitespace(" " * ($indentLevel - 1))) | Out-Null -} - -function SaveConfigFile($config) { - $config.xml.Save($config.fileName) | Out-Null -} - -function IsSameType($typeString1, $typeString2) { - - if (($typeString1 -eq $null) -or ($typeString2 -eq $null)) { return $false } - - # First check the type - $t1 = $typeString1.Split(',')[0].Trim() - $t2 = $typeString2.Split(',')[0].Trim() - if ($t1 -cne $t2) { return $false } - - # Then check for assembly match if possible - $a1 = $typeString1.Split(',')[1] - $a2 = $typeString2.Split(',')[1] - if (($a1 -ne $null) -and ($a2 -ne $null)) { - return ($a1.Trim() -eq $a2.Trim()) - } - - # Don't care about assembly. Match is good. - return $true -} diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/install.ps1 b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/install.ps1 deleted file mode 100644 index f9e071e..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/install.ps1 +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (c) .NET Foundation. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -##################################################################################################### -## Although the NuGet package includes msbuild targets that does this same work, the ps1 files are # -## kept for use in web site projects # -##################################################################################################### - -param($installPath, $toolsPath, $package, $project) - -$assemblyVersion = '3.11.0.0' -$roslynSubFolder = 'roslyn' - -if ($project -eq $null) { - $project = Get-Project -} - -$libDirectory = Join-Path $installPath 'lib\net462' -$projectRoot = $project.Properties.Item('FullPath').Value -$projectTargetFramework = $project.Properties.Item('TargetFrameworkMoniker').Value -$binDirectory = Join-Path $projectRoot 'bin' - -# -# Some things vary depending on which framework version you target. If you target an -# older framework, (4.5-4.7.1) then we need to change some of these. -# -$compilerVersion = $package.Version -if($package.Versions -ne $null) { $compilerVersion = @($package.Versions)[0] } -$packageDirectory = Split-Path $installPath -$compilerPackageFolderName = $package.Id + "." + $compilerVersion -$compilerPackageDirectory = Join-Path $packageDirectory $compilerPackageFolderName -$compilerPackageToolsDirectory = Join-Path $compilerPackageDirectory 'tools\roslyn472' -$csLanguageVersion = '7.3' -$vbLanguageVersion = 'default' -if (($projectTargetFramework -match 'v4\.6') -or ($projectTargetFramework -match 'v4\.7[^\.]') -or ($projectTargetFramework -match 'v4\.7\.[01]')) -{ - $compilerPackageToolsDirectory = Join-Path $compilerPackageDirectory 'tools\roslyn46' - $csLanguageVersion = '7.0' # This was 'default' which is 7.0 for this version of ms.net.compilers - $vbLanguageVersion = 'default' # Is 15 for this ms.net.compilers... but will leave as 'default' for upgrades since that is still valid in .Net 4.8 -} - - -# Fill out the config entries for these code dom providers here. Using powershell to do -# this allows us to cache and restore customized attribute values from previous versions of -# this package in the upgrade scenario. -. "$PSScriptRoot\common.ps1" -$csCodeDomProvider = [CodeDomProviderDescription]@{ - TypeName="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider"; - Assembly="Microsoft.CodeDom.Providers.DotNetCompilerPlatform"; - Version=$assemblyVersion; - FileExtension=".cs"; - Parameters=@( - [CompilerParameterDescription]@{ Name="language"; DefaultValue="c#;cs;csharp"; IsRequired=$true; IsProviderOption=$false }, - [CompilerParameterDescription]@{ Name="warningLevel"; DefaultValue="4"; IsRequired=$true; IsProviderOption=$false }, - [CompilerParameterDescription]@{ Name="compilerOptions"; DefaultValue="/langversion:" + $csLanguageVersion + " /nowarn:1659;1699;1701;612;618"; IsRequired=$false; IsProviderOption=$false }); -} -InstallCodeDomProvider $csCodeDomProvider -$vbCodeDomProvider = [CodeDomProviderDescription]@{ - TypeName="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider"; - Assembly="Microsoft.CodeDom.Providers.DotNetCompilerPlatform"; - Version=$assemblyVersion; - FileExtension=".vb"; - Parameters=@( - [CompilerParameterDescription]@{ Name="language"; DefaultValue="vb;vbs;visualbasic;vbscript"; IsRequired=$true; IsProviderOption=$false }, - [CompilerParameterDescription]@{ Name="warningLevel"; DefaultValue="4"; IsRequired=$true; IsProviderOption=$false }, - [CompilerParameterDescription]@{ Name="compilerOptions"; DefaultValue="/langversion:" + $vbLanguageVersion + " /nowarn:41008,40000,40008 /define:_MYTYPE=\""Web\"" /optionInfer+"; IsRequired=$false; IsProviderOption=$false }); -} -InstallCodeDomProvider $vbCodeDomProvider - - -# For Web Site, we need to copy the Roslyn toolset into -# the applicaiton's bin folder. -# For Web Applicaiton project, this is done in csproj. -if ($project.Type -eq 'Web Site') { - - # We need to copy the provider assembly into the bin\ folder, otherwise - # Microsoft.VisualStudio.Web.Host.exe cannot find the assembly. - # However, users will see the error after they clean solutions. - New-Item $binDirectory -type directory -force | Out-Null - Copy-Item $libDirectory\* $binDirectory -force | Out-Null - - if ((Get-Item $compilerPackageDirectory) -isnot [System.IO.DirectoryInfo]) - { - Write-Host "The install.ps1 cannot find the installation location of package $compilerPackageName, or the pakcage is not installed correctly." - Write-Host 'The install.ps1 did not complete.' - break - } - - $roslynSubDirectory = Join-Path $binDirectory $roslynSubFolder - New-Item $roslynSubDirectory -type directory -force | Out-Null - Copy-Item $compilerPackageToolsDirectory\* $roslynSubDirectory -force | Out-Null - - # Generate a .refresh file for each dll/exe file. - Push-Location - Set-Location $projectRoot - $relativeAssemblySource = Resolve-Path -relative $compilerPackageToolsDirectory - Pop-Location - - Get-ChildItem -Path $roslynSubDirectory | ` - Foreach-Object { - if (($_.Extension -eq ".dll") -or ($_.Extension -eq ".exe")) { - $refreshFile = $_.FullName - $refreshFile += ".refresh" - $refreshContent = Join-Path $relativeAssemblySource $_.Name - Set-Content $refreshFile $refreshContent - } - } -} \ No newline at end of file diff --git a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/uninstall.ps1 b/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/uninstall.ps1 deleted file mode 100644 index 6d0072a..0000000 --- a/src/Packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/tools/uninstall.ps1 +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) .NET Foundation. All rights reserved. -# Licensed under the MIT license. See LICENSE file in the project root for full license information. - -##################################################################################################### -## Although the NuGet package includes msbuild targets that does this same work, the ps1 files are # -## kept for use in web site projects # -##################################################################################################### - -param($installPath, $toolsPath, $package, $project) - - -# First save the code dom compiler declarations off to a temp file so they can be restored -# in the event that this is a package upgrade scenario. -. "$PSScriptRoot\common.ps1" -UninstallCodeDomProvider "Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform" -UninstallCodeDomProvider "Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform" - - -# Then remove the compiler bits from the bin directory -$roslynSubFolder = 'roslyn' - -if ($project -eq $null) { - $project = Get-Project -} - -$projectRoot = $project.Properties.Item('FullPath').Value -$binDirectory = Join-Path $projectRoot 'bin' -$targetDirectory = Join-Path $binDirectory $roslynSubFolder - -if (Test-Path $targetDirectory) { - Get-Process -Name "VBCSCompiler" -ErrorAction SilentlyContinue | Stop-Process -Force -PassThru -ErrorAction SilentlyContinue | Wait-Process - Remove-Item $targetDirectory -Force -Recurse -ErrorAction SilentlyContinue -} \ No newline at end of file diff --git a/src/Packages/Packages.csproj b/src/Packages/Packages.csproj index a55592c..fbe52a6 100644 --- a/src/Packages/Packages.csproj +++ b/src/Packages/Packages.csproj @@ -28,11 +28,9 @@ - - - - - + + + diff --git a/tools/RoslynCodeProvider.Extensions.targets b/tools/RoslynCodeProvider.Extensions.targets index 22d4f55..3aa7815 100644 --- a/tools/RoslynCodeProvider.Extensions.targets +++ b/tools/RoslynCodeProvider.Extensions.targets @@ -1,17 +1,14 @@ $(RepositoryRoot)src\Packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform\tools\ - Roslyn46 - Roslyn472 + Roslyn-$(MSNetCompilersNuGetPackageVersion) - - - - + + @@ -28,9 +25,9 @@ var roslynNugetBaseUri = "https://api.nuget.org/packages/microsoft.net.compilers.{0}.nupkg"; var roslynPackageName = "microsoft.net.compilers.{0}.nupkg"; - var targetFilePath = Path.Combine(Path.GetTempPath(), string.Format(roslynPackageName, ReferenceRoslyn46NupkgVersion)); - var targetExtractPath = Path.Combine(Path.GetTempPath(), LocalRoslyn46FolderName); - var packageToolsPath = Path.Combine(NupkgToolPath, LocalRoslyn46FolderName); + var targetFilePath = Path.Combine(Path.GetTempPath(), string.Format(roslynPackageName, ReferenceRoslynNupkgVersion)); + var targetExtractPath = Path.Combine(Path.GetTempPath(), LocalRoslynFolderName); + var packageToolsPath = Path.Combine(NupkgToolPath, LocalRoslynFolderName); if (Directory.Exists(targetExtractPath)) { Directory.Delete(targetExtractPath, true); @@ -40,31 +37,8 @@ Directory.Delete(packageToolsPath, true); } - wc.DownloadFile(string.Format(roslynNugetBaseUri, ReferenceRoslyn46NupkgVersion), targetFilePath); - Log.LogMessage("Microsoft.Net.Compilers.{0}.nupkg is downloaded", ReferenceRoslyn46NupkgVersion); - - ZipFile.ExtractToDirectory(targetFilePath, targetExtractPath); - Directory.CreateDirectory(packageToolsPath); - foreach (var file in Directory.GetFiles(Path.Combine(targetExtractPath, "tools"))) - { - var fi = new FileInfo(file); - File.Copy(file, Path.Combine(packageToolsPath, fi.Name)); - } - - targetFilePath = Path.Combine(Path.GetTempPath(), string.Format(roslynPackageName, ReferenceRoslyn472NupkgVersion)); - targetExtractPath = Path.Combine(Path.GetTempPath(), LocalRoslyn472FolderName); - packageToolsPath = Path.Combine(NupkgToolPath, LocalRoslyn472FolderName); - if (Directory.Exists(targetExtractPath)) - { - Directory.Delete(targetExtractPath, true); - } - if (Directory.Exists(packageToolsPath)) - { - Directory.Delete(packageToolsPath, true); - } - - wc.DownloadFile(string.Format(roslynNugetBaseUri, ReferenceRoslyn472NupkgVersion), targetFilePath); - Log.LogMessage("Microsoft.Net.Compilers.{0}.nupkg is downloaded", ReferenceRoslyn472NupkgVersion); + wc.DownloadFile(string.Format(roslynNugetBaseUri, ReferenceRoslynNupkgVersion), targetFilePath); + Log.LogMessage("Microsoft.Net.Compilers.{0}.nupkg is downloaded", ReferenceRoslynNupkgVersion); ZipFile.ExtractToDirectory(targetFilePath, targetExtractPath); Directory.CreateDirectory(packageToolsPath); @@ -85,4 +59,42 @@ + + + + + + + + + + + + + properties = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); // Nuget .pp transforms are case insensitive + foreach (var p in PropertyCollection) { properties.TryAdd(p.GetMetadata("Identity"), p.GetMetadata("Value")); } + foreach (var inFile in Files) { + string filename = inFile.ItemSpec; + if (!File.Exists(filename)) { Log.LogError("File to preprocess does not exist: {0}", filename); return false; } + if (!Directory.Exists(OutputDir)) { Directory.CreateDirectory(OutputDir); } + using (StreamReader sr = new StreamReader(filename)) + using (StreamWriter sw = new StreamWriter(Path.Combine(OutputDir, Path.GetFileName(filename)), false)) + { + while ((line = sr.ReadLine()) != null) { + line = Regex.Replace(line, tokenPattern, (m) => { + string key = m.Groups[1].Value; + if (properties.ContainsKey(key)) { return properties[key]; } + return m.Groups[0].Value; + }); + sw.WriteLine(line); + } + } + } + ]]> + + + diff --git a/tools/RoslynCodeProvider.settings.targets b/tools/RoslynCodeProvider.settings.targets index 84a81ee..958a15d 100644 --- a/tools/RoslynCodeProvider.settings.targets +++ b/tools/RoslynCodeProvider.settings.targets @@ -12,16 +12,15 @@ rtm 2022 - 3 - 11 + 4 + 1 0 0 $([MSBuild]::Add(1, $([MSBuild]::Subtract($([System.DateTime]::Now.Year), $(VersionStartYear)))))$([System.DateTime]::Now.ToString("MMdd")) - 2.10.0 - 3.11.0 + 4.1.0 diff --git a/tools/RoslynCodeProvider.targets b/tools/RoslynCodeProvider.targets index a548e1c..7cac6b9 100644 --- a/tools/RoslynCodeProvider.targets +++ b/tools/RoslynCodeProvider.targets @@ -30,10 +30,33 @@ - + + + $(MSBuildProjectDirectory)\build + + + + + tools\roslyn-$(MSNetCompilersNuGetPackageVersion) + + + + Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=$(AssemblyVersion), Culture=neutral, PublicKeyToken=31bf3856ad364e35 + + + + + + + + + + + - +