Skip to content

Commit 2ea8c3b

Browse files
committed
More refactorings
1 parent eeba9b4 commit 2ea8c3b

File tree

2 files changed

+88
-73
lines changed

2 files changed

+88
-73
lines changed

src/Cli/dotnet/Commands/Solution/Add/SolutionAddCommand.cs

Lines changed: 76 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -52,67 +52,17 @@ public override int Execute()
5252
throw new GracefulException(CliStrings.SpecifyAtLeastOneProjectToAdd);
5353
}
5454

55-
try
56-
{
57-
PathUtility.EnsureAllPathsExist(_projects, CliStrings.CouldNotFindProjectOrDirectory, true);
58-
IEnumerable<string> fullProjectPaths = _projects.Select(project =>
59-
{
60-
var fullPath = Path.GetFullPath(project);
61-
return Directory.Exists(fullPath) ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath;
62-
});
63-
AddProjectsToSolutionAsync(fullProjectPaths, CancellationToken.None).GetAwaiter().GetResult();
64-
return 0;
65-
}
66-
catch (Exception ex) when (ex is not GracefulException)
67-
{
68-
{
69-
if (ex is SolutionException || ex.InnerException is SolutionException)
70-
{
71-
throw new GracefulException(CliStrings.InvalidSolutionFormatString, _solutionFileFullPath, ex.Message);
72-
}
73-
throw new GracefulException(ex.Message, ex);
74-
}
75-
}
76-
}
55+
// Get project paths from the command line arguments
56+
PathUtility.EnsureAllPathsExist(_projects, CliStrings.CouldNotFindProjectOrDirectory, true);
7757

78-
private async Task AddProjectsToSolutionAsync(IEnumerable<string> projectPaths, CancellationToken cancellationToken)
79-
{
80-
SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(_solutionFileFullPath);
81-
ISolutionSerializer serializer = solution.SerializerExtension.Serializer;
82-
83-
// set UTF8 BOM encoding for .sln
84-
if (serializer is ISolutionSerializer<SlnV12SerializerSettings> v12Serializer)
58+
IEnumerable<string> fullProjectPaths = _projects.Select(project =>
8559
{
86-
solution.SerializerExtension = v12Serializer.CreateModelExtension(new()
87-
{
88-
Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)
89-
});
90-
91-
// Set default configurations and platforms for sln file
92-
SlnFileFactory.DefaultPlatforms.ToList().ForEach(solution.AddPlatform);
93-
SlnFileFactory.DefaultBuildTypes.ToList().ForEach(solution.AddBuildType);
94-
}
95-
96-
97-
foreach (var projectPath in projectPaths)
98-
{
99-
string relativePath = Path.GetRelativePath(Path.GetDirectoryName(_solutionFileFullPath), projectPath);
60+
var fullPath = Path.GetFullPath(project);
61+
return Directory.Exists(fullPath) ? MsbuildProject.GetProjectFileFromDirectory(fullPath).FullName : fullPath;
62+
});
10063

101-
try
102-
{
103-
AddProject(solution, relativePath, projectPath, serializer);
104-
}
105-
catch (InvalidProjectFileException ex)
106-
{
107-
Reporter.Error.WriteLine(string.Format(CliStrings.InvalidProjectWithExceptionMessage, projectPath, ex.Message));
108-
}
109-
catch (SolutionArgumentException ex) when (ex.Type == SolutionErrorType.DuplicateProjectName || solution.FindProject(relativePath) is not null)
110-
{
111-
Reporter.Output.WriteLine(CliStrings.SolutionAlreadyContainsProject, _solutionFileFullPath, relativePath);
112-
}
113-
}
114-
115-
await serializer.SaveAsync(_solutionFileFullPath, solution, cancellationToken);
64+
AddProjectsToSolutionAsync(fullProjectPaths, CancellationToken.None).GetAwaiter().GetResult();
65+
return 0;
11666
}
11767

11868
private SolutionFolderModel? GenerateIntermediateSolutionFoldersForProjectPath(SolutionModel solution, string relativeProjectPath)
@@ -152,30 +102,73 @@ private async Task AddProjectsToSolutionAsync(IEnumerable<string> projectPaths,
152102
: solution.AddFolder(GetSolutionFolderPathWithForwardSlashes(relativeSolutionFolderPath));
153103
}
154104

155-
private void AddProject(SolutionModel solution, string solutionRelativeProjectPath, string fullProjectPath, ISolutionSerializer serializer = null)
105+
private async Task AddProjectsToSolutionAsync(IEnumerable<string> projectPaths, CancellationToken cancellationToken)
156106
{
107+
SolutionModel solution = SlnFileFactory.CreateFromFileOrDirectory(_solutionFileFullPath);
108+
ISolutionSerializer serializer = solution.SerializerExtension.Serializer;
109+
110+
// set UTF8 BOM encoding for .sln
111+
if (serializer is ISolutionSerializer<SlnV12SerializerSettings> v12Serializer)
112+
{
113+
solution.SerializerExtension = v12Serializer.CreateModelExtension(new()
114+
{
115+
Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)
116+
});
117+
118+
// Set default configurations and platforms for sln file
119+
SlnFileFactory.DefaultPlatforms.ToList().ForEach(solution.AddPlatform);
120+
SlnFileFactory.DefaultBuildTypes.ToList().ForEach(solution.AddBuildType);
121+
}
122+
123+
124+
foreach (var projectPath in projectPaths)
125+
{
126+
// TODO: Remove this when we have a better way to handle this
127+
string solutionRelativeProjectPath = Path.GetRelativePath(Path.GetDirectoryName(_solutionFileFullPath), projectPath);
128+
// Generate the solution folder path based on the project path
129+
SolutionFolderModel? solutionFolder = GenerateIntermediateSolutionFoldersForProjectPath(solution, solutionRelativeProjectPath);
130+
AddProject(solution, projectPath, solutionFolder, serializer);
131+
}
132+
133+
await serializer.SaveAsync(_solutionFileFullPath, solution, cancellationToken);
134+
}
135+
136+
private void AddProject(SolutionModel solution, string fullProjectPath, SolutionFolderModel solutionFolder, ISolutionSerializer serializer = null)
137+
{
138+
string solutionRelativeProjectPath = Path.GetRelativePath(Path.GetDirectoryName(_solutionFileFullPath), fullProjectPath);
139+
157140
// Open project instance to see if it is a valid project
158-
ProjectRootElement projectRootElement = ProjectRootElement.Open(fullProjectPath);
141+
ProjectRootElement projectRootElement;
142+
try
143+
{
144+
projectRootElement = ProjectRootElement.Open(fullProjectPath);
145+
}
146+
catch (InvalidProjectFileException ex)
147+
{
148+
Reporter.Error.WriteLine(string.Format(CliStrings.InvalidProjectWithExceptionMessage, fullProjectPath, ex.Message));
149+
return;
150+
}
151+
159152
ProjectInstance projectInstance = new ProjectInstance(projectRootElement);
160153
SolutionProjectModel project;
161154

162-
// Generate the solution folder path based on the project path
163-
SolutionFolderModel? solutionFolder = GenerateIntermediateSolutionFoldersForProjectPath(solution, solutionRelativeProjectPath);
155+
// Handle guid
156+
string projectTypeGuid = solution.ProjectTypes.FirstOrDefault(t => t.Extension == Path.GetExtension(fullProjectPath))?.ProjectTypeId.ToString()
157+
?? projectRootElement.GetProjectTypeGuid() ?? projectInstance.GetDefaultProjectTypeGuid();
164158

165159
try
166160
{
167-
project = solution.AddProject(solutionRelativeProjectPath, null, solutionFolder);
161+
project = solution.AddProject(solutionRelativeProjectPath, projectTypeGuid, solutionFolder);
168162
}
169163
catch (SolutionArgumentException ex) when (ex.Type == SolutionErrorType.InvalidProjectTypeReference)
170164
{
171-
// If guid is not identified by vs-solutionpersistence, check in project element itself
172-
var guid = projectRootElement.GetProjectTypeGuid() ?? projectInstance.GetDefaultProjectTypeGuid();
173-
if (string.IsNullOrEmpty(guid))
174-
{
175-
Reporter.Error.WriteLine(CliStrings.UnsupportedProjectType, fullProjectPath);
176-
return;
177-
}
178-
project = solution.AddProject(solutionRelativeProjectPath, guid, solutionFolder);
165+
Reporter.Error.WriteLine(CliStrings.UnsupportedProjectType, fullProjectPath);
166+
return;
167+
}
168+
catch (SolutionArgumentException ex) when (ex.Type == SolutionErrorType.DuplicateProjectName || solution.FindProject(solutionRelativeProjectPath) is not null)
169+
{
170+
Reporter.Output.WriteLine(CliStrings.SolutionAlreadyContainsProject, _solutionFileFullPath, solutionRelativeProjectPath);
171+
return;
179172
}
180173

181174
// Add settings based on existing project instance
@@ -203,6 +196,18 @@ private void AddProject(SolutionModel solution, string solutionRelativeProjectPa
203196
project.AddProjectConfigurationRule(new ConfigurationRule(BuildDimension.BuildType, solutionBuildType, "*", projectBuildType));
204197
}
205198

199+
// Get referencedprojects from the project instance
200+
//var referencedProjectsFullPaths = projectInstance.EvaluatedItemElements
201+
// .Where(item => item.ItemType == "ProjectReference")
202+
// .Select(item => item.Include)
203+
// .Select(item => Path.GetFullPath(item, Path.GetDirectoryName(fullProjectPath)))
204+
// .ToList();
205+
206+
//foreach (var referencedProjectFullPath in referencedProjectsFullPaths)
207+
//{
208+
// var referencedProjectRelativePath = Path.GetRelativePath(_solutionFileFullPath, referencedProjectFullPath);
209+
//}
210+
206211
Reporter.Output.WriteLine(CliStrings.ProjectAddedToTheSolution, solutionRelativeProjectPath);
207212
}
208213
}

src/Cli/dotnet/SlnFileFactory.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Text.Json;
56
using Microsoft.DotNet.Cli.Utils;
67
using Microsoft.VisualStudio.SolutionPersistence;
@@ -66,11 +67,20 @@ public static SolutionModel CreateFromFileOrDirectory(string fileOrDirectory, bo
6667
{
6768
return CreateFromFilteredSolutionFile(solutionPath);
6869
}
69-
ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(solutionPath) ?? throw new GracefulException(
70+
try
71+
{
72+
ISolutionSerializer serializer = SolutionSerializers.GetSerializerByMoniker(solutionPath) ?? throw new GracefulException(
7073
CliStrings.CouldNotFindSolutionOrDirectory,
7174
solutionPath);
7275

73-
return serializer.OpenAsync(solutionPath, CancellationToken.None).Result;
76+
return serializer.OpenAsync(solutionPath, CancellationToken.None).Result;
77+
}
78+
catch (SolutionException ex)
79+
{
80+
throw new GracefulException(
81+
CliStrings.InvalidSolutionFormatString,
82+
solutionPath, ex.Message);
83+
}
7484
}
7585

7686
public static SolutionModel CreateFromFilteredSolutionFile(string filteredSolutionPath)

0 commit comments

Comments
 (0)