This repository was archived by the owner on May 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 164
Expand file tree
/
Copy pathConverter.cs
More file actions
110 lines (96 loc) · 5.14 KB
/
Copy pathConverter.cs
File metadata and controls
110 lines (96 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using MSBuild.Abstractions;
namespace MSBuild.Conversion.Project
{
public class Converter
{
private readonly UnconfiguredProject _project;
private readonly BaselineProject _sdkBaselineProject;
private readonly IProjectRootElement _projectRootElement;
private readonly bool _noBackup;
private readonly bool _forceRemoveCustomImports;
private readonly ImmutableDictionary<string, Differ> _differs;
public Converter(UnconfiguredProject project, BaselineProject sdkBaselineProject,
IProjectRootElement projectRootElement, bool noBackup, bool forceRemoveCustomImports)
{
_project = project ?? throw new ArgumentNullException(nameof(project));
_sdkBaselineProject = sdkBaselineProject;
_projectRootElement = projectRootElement ?? throw new ArgumentNullException(nameof(projectRootElement));
_noBackup = noBackup;
_forceRemoveCustomImports = forceRemoveCustomImports;
_differs = GetDiffers();
}
public void Convert(string outputPath)
{
ConvertProjectFile();
CleanUpProjectFile(outputPath);
}
internal IProjectRootElement? ConvertProjectFile()
{
return _projectRootElement
// Let's convert packages first, since that's what you should do manually anyways
.ConvertAndAddPackages(_sdkBaselineProject.ProjectStyle, _sdkBaselineProject.TargetTFM, removePackagesConfig: _noBackup)
// Now we can convert the project over
.ChangeImportsAndAddSdkAttribute(_sdkBaselineProject, _forceRemoveCustomImports)
.AddCsWinRTReferenceAndComponentProperty(_sdkBaselineProject)
.UpdateOutputTypeProperty(_sdkBaselineProject)
.RemoveDefaultedProperties(_sdkBaselineProject, _differs)
.RemoveUnnecessaryPropertiesNotInSDKByDefault(_sdkBaselineProject.ProjectStyle)
.AddTargetFrameworkProperty(_sdkBaselineProject, _sdkBaselineProject.TargetTFM)
.AddGenerateAssemblyInfoAsFalse(_sdkBaselineProject.ProjectStyle)
.AddDesktopProperties(_sdkBaselineProject)
.AddCommonPropertiesToTopLevelPropertyGroup()
.RemoveOrUpdateItems(_differs, _sdkBaselineProject, _sdkBaselineProject.TargetTFM)
.AddItemRemovesForIntroducedItems(_differs)
.RemoveUnnecessaryTargetsIfTheyExist()
.RemoveWebExtensions(_sdkBaselineProject.ProjectStyle)
.ModifyProjectElement();
}
internal ImmutableDictionary<string, Differ> GetDiffers() =>
_project.ConfiguredProjects.Select(p => (p.Key, new Differ(p.Value, _sdkBaselineProject.Project.ConfiguredProjects[p.Key]))).ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Item2);
private void CleanUpProjectFile(string outputPath)
{
var projectXml = _projectRootElement.Xml;
// remove all use of xmlns attributes
projectXml.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();
foreach (var element in projectXml.Descendants())
{
if (element is null)
{
continue;
}
// Appears to be a nullability bug?
// Also the diagnostic doesn't show in the editor
element.Name = element.Name.LocalName!;
}
// remove all use of ProductVersion
// this is a property that is used by VS to detect which version of
// Visual Studio opened this project last and is no longer needed
projectXml.Descendants().Elements().Where(x => x.Name == "ProductVersion").Remove();
projectXml.Descendants().Elements().Where(x => x.Name == "FileUpgradeFlags").Remove();
projectXml.Descendants().Elements().Where(x => x.Name == "UpgradeBackupLocation").Remove();
// Remove properties that do nothing if they are not set
projectXml.Descendants().Elements().Where(x => x.Name == "ApplicationIcon" && string.IsNullOrEmpty(x.Value)).Remove();
projectXml.Descendants().Elements().Where(x => x.Name == "PreBuildEvent" && string.IsNullOrEmpty(x.Value)).Remove();
projectXml.Descendants().Elements().Where(x => x.Name == "PostBuildEvent" && string.IsNullOrEmpty(x.Value)).Remove();
// Do not keep comments as the entire file is changing
var readerSettings = new XmlReaderSettings()
{
IgnoreComments = true
};
projectXml = XDocument.Load(XmlReader.Create(projectXml.CreateReader(), readerSettings));
// do not write out xml declaration header
var writerSettings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true,
};
using var writer = XmlWriter.Create(outputPath, writerSettings);
projectXml.Save(writer);
}
}
}