public ImmutableDictionary <string, ImmutableDictionary <string, string> > DetermineConfigurations(IProjectRootElement projectRootElement) { var builder = ImmutableDictionary.CreateBuilder <string, ImmutableDictionary <string, string> >(); foreach (var propertyGroup in projectRootElement.PropertyGroups) { if (MSBuildHelpers.ConditionToDimensionValues(propertyGroup.Condition, out var dimensionValues)) { var name = MSBuildHelpers.GetConfigurationName(dimensionValues); builder.Add(name, dimensionValues.ToImmutableDictionary()); } } return(builder.ToImmutable()); }
public MSBuildWorkspace(ImmutableArray <string> paths, bool noBackup) { var items = ImmutableArray.CreateBuilder <MSBuildWorkspaceItem>(); var globalProperties = ImmutableDictionary <string, string> .Empty; using var collection = new ProjectCollection(); foreach (var path in paths) { var fileExtension = Path.GetExtension(path); if ((StringComparer.OrdinalIgnoreCase.Compare(fileExtension, ".fsproj") != 0) && (StringComparer.OrdinalIgnoreCase.Compare(fileExtension, ".csproj") != 0) && (StringComparer.OrdinalIgnoreCase.Compare(fileExtension, ".vbproj") != 0)) { Console.WriteLine($"'{path}' is not a .NET project, skipping it."); continue; } var root = new MSBuildProjectRootElement(ProjectRootElement.Open(path, collection, preserveFormatting: true)); if (IsSupportedProjectType(root)) { if (!noBackup) { File.Copy(path, path + ".old"); } // Let them know about System.Web if (MSBuildHelpers.IsProjectReferencingSystemWeb(root)) { Console.WriteLine($"'{root.FullPath}' references System.Web, which is unsupported on .NET Core. You may have significant work remaining after conversion."); } var configurations = DetermineConfigurations(root); var unconfiguredProject = new UnconfiguredProject(configurations); unconfiguredProject.LoadProjects(collection, globalProperties, path); var baseline = CreateSdkBaselineProject(path, unconfiguredProject.FirstConfiguredProject, root, configurations); root.Reload(throwIfUnsavedChanges: false, preserveFormatting: true); var item = new MSBuildWorkspaceItem(root, unconfiguredProject, baseline); items.Add(item); } } WorkspaceItems = items.ToImmutable(); }
/// <summary> /// Clear out the project's construction model and add a simple SDK-based project to get a baseline. /// We need to use the same name as the original csproj and same path so that all the default that derive /// from name\path get the right values (there are a lot of them). /// </summary> private BaselineProject CreateSdkBaselineProject(string projectFilePath, IProject project, IProjectRootElement root, ImmutableDictionary <string, ImmutableDictionary <string, string> > configurations) { var projectStyle = GetProjectStyle(root); var rootElement = ProjectRootElement.Open(projectFilePath); rootElement.RemoveAllChildren(); switch (projectStyle) { case ProjectStyle.Default: case ProjectStyle.DefaultSubset: rootElement.Sdk = MSBuildFacts.DefaultSDKAttribute; break; case ProjectStyle.WindowsDesktop: rootElement.Sdk = DesktopFacts.WinSDKAttribute; break; case ProjectStyle.DefaultWithCustomTargets: var imports = root.Imports; void CopyImport(ProjectImportElement import) { var newImport = rootElement.AddImport(import.Project); newImport.Condition = import.Condition; } CopyImport(imports.First()); CopyImport(imports.Last()); break; default: throw new NotSupportedException("This project has custom imports in a manner that's not supported."); } var propGroup = rootElement.AddPropertyGroup(); propGroup.AddProperty(MSBuildFacts.TargetFrameworkNodeName, project.GetTargetFramework()); propGroup.AddProperty(MSBuildFacts.OutputTypeNodeName, project.GetPropertyValue(MSBuildFacts.OutputTypeNodeName) ?? throw new InvalidOperationException("OutputType is not set!")); if (projectStyle == ProjectStyle.WindowsDesktop) { if (MSBuildHelpers.IsWinForms(root)) { MSBuildHelpers.AddUseWinForms(propGroup); } if (MSBuildHelpers.IsWPF(root)) { MSBuildHelpers.AddUseWPF(propGroup); } // User is referencing WindowsBase only if (MSBuildHelpers.IsDesktop(root) && !MSBuildHelpers.HasWPFOrWinForms(propGroup)) { MSBuildHelpers.AddUseWinForms(propGroup); } } // Create a new collection because a project with this name has already been loaded into the global collection. using var pc = new ProjectCollection(); var newProject = new UnconfiguredProject(configurations); newProject.LoadProjects(pc, rootElement); // If the original project had the TargetFramework property don't touch it during conversion. var propertiesInTheBaseline = ImmutableArray.Create(MSBuildFacts.OutputTypeNodeName); if (project.GetProperty(MSBuildFacts.TargetFrameworkNodeName) is { })
/// <summary> /// Checks if an item is an explicit System.ValueTuple and if the given TFM correspondes with an in-box System.ValueTuple type. /// </summary> public static bool IsExplicitValueTupleReferenceThatCanBeRemoved(ProjectItemElement item, string tfm) => item.ElementName.Equals(MSBuildFacts.MSBuildReferenceName, StringComparison.OrdinalIgnoreCase) && item.Include.Equals(MSBuildFacts.SystemValueTupleName, StringComparison.OrdinalIgnoreCase) && MSBuildHelpers.FrameworkHasAValueTuple(tfm);