1
1
// Licensed to the .NET Foundation under one or more agreements.
2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
4
+ using System . Text . Json ;
4
5
using Microsoft . DotNet . Cli . Utils ;
5
6
using Microsoft . VisualStudio . SolutionPersistence ;
6
7
using Microsoft . VisualStudio . SolutionPersistence . Model ;
@@ -10,6 +11,40 @@ namespace Microsoft.DotNet.Tools.Common
10
11
{
11
12
public static class SlnFileFactory
12
13
{
14
+ public static string GetSolutionFileFullPath ( string slnFileOrDirectory , bool includeSolutionFilterFiles = false , bool includeSolutionXmlFiles = true )
15
+ {
16
+ // Throw error if slnFileOrDirectory is an invalid path
17
+ if ( string . IsNullOrWhiteSpace ( slnFileOrDirectory ) || slnFileOrDirectory . IndexOfAny ( Path . GetInvalidPathChars ( ) ) != - 1 )
18
+ {
19
+ throw new GracefulException ( CommonLocalizableStrings . CouldNotFindSolutionOrDirectory ) ;
20
+ }
21
+ if ( File . Exists ( slnFileOrDirectory ) )
22
+ {
23
+ return Path . GetFullPath ( slnFileOrDirectory ) ;
24
+ }
25
+ if ( Directory . Exists ( slnFileOrDirectory ) )
26
+ {
27
+ string [ ] files = ListSolutionFilesInDirectory ( slnFileOrDirectory , includeSolutionFilterFiles , includeSolutionXmlFiles ) ;
28
+ if ( files . Length == 0 )
29
+ {
30
+ throw new GracefulException (
31
+ CommonLocalizableStrings . CouldNotFindSolutionIn ,
32
+ slnFileOrDirectory ) ;
33
+ }
34
+ if ( files . Length > 1 )
35
+ {
36
+ throw new GracefulException (
37
+ CommonLocalizableStrings . MoreThanOneSolutionInDirectory ,
38
+ slnFileOrDirectory ) ;
39
+ }
40
+ return Path . GetFullPath ( files . Single ( ) ) ;
41
+ }
42
+ throw new GracefulException (
43
+ CommonLocalizableStrings . CouldNotFindSolutionOrDirectory ,
44
+ slnFileOrDirectory ) ;
45
+ }
46
+
47
+
13
48
public static string [ ] ListSolutionFilesInDirectory ( string directory , bool includeSolutionFilterFiles = false , bool includeSolutionXmlFiles = true )
14
49
{
15
50
return [
@@ -19,87 +54,77 @@ public static string[] ListSolutionFilesInDirectory(string directory, bool inclu
19
54
] ;
20
55
}
21
56
22
- public static SolutionModel CreateFromFileOrDirectory ( string fileOrDirectory , bool includeSolutionXmlFiles = true )
57
+ public static SolutionModel CreateFromFileOrDirectory ( string fileOrDirectory , bool includeSolutionFilterFiles = false , bool includeSolutionXmlFiles = true )
23
58
{
24
- if ( File . Exists ( fileOrDirectory ) )
25
- {
26
- return FromFile ( fileOrDirectory ) ;
27
- }
28
- else
29
- {
30
- return FromDirectory ( fileOrDirectory , includeSolutionXmlFiles ) ;
31
- }
32
- }
59
+ string solutionPath = GetSolutionFileFullPath ( fileOrDirectory , includeSolutionFilterFiles , includeSolutionXmlFiles ) ;
33
60
34
- private static SolutionModel FromFile ( string solutionPath )
35
- {
36
- SolutionModel slnFile = null ;
37
- try
61
+ if ( solutionPath . HasExtension ( ".slnf" ) )
38
62
{
39
- ISolutionSerializer serializer = SolutionSerializers . GetSerializerByMoniker ( solutionPath ) ?? throw new GracefulException (
63
+ return CreateFromFilteredSolutionFile ( solutionPath ) ;
64
+ }
65
+ ISolutionSerializer serializer = SolutionSerializers . GetSerializerByMoniker ( solutionPath ) ?? throw new GracefulException (
40
66
CommonLocalizableStrings . CouldNotFindSolutionOrDirectory ,
41
67
solutionPath ) ;
42
68
43
- slnFile = serializer . OpenAsync ( solutionPath , CancellationToken . None ) . Result ;
44
- }
45
- catch ( SolutionException e )
46
- {
47
- throw new GracefulException (
48
- CommonLocalizableStrings . InvalidSolutionFormatString ,
49
- solutionPath ,
50
- e . Message ) ;
51
- }
52
- return slnFile ;
69
+ return serializer . OpenAsync ( solutionPath , CancellationToken . None ) . Result ;
53
70
}
54
71
55
- private static SolutionModel FromDirectory ( string solutionDirectory , bool includeSolutionXmlFiles )
72
+ public static SolutionModel CreateFromFilteredSolutionFile ( string filteredSolutionPath )
56
73
{
57
- DirectoryInfo dir ;
74
+ JsonDocument jsonDocument ;
75
+ JsonElement jsonElement ;
76
+ JsonElement filteredSolutionJsonElement ;
77
+ string originalSolutionPath ;
78
+ string originalSolutionPathAbsolute ;
79
+ string [ ] filteredSolutionProjectPaths ;
80
+
58
81
try
59
82
{
60
- dir = new DirectoryInfo ( solutionDirectory ) ;
61
- if ( ! dir . Exists )
83
+ jsonDocument = JsonDocument . Parse ( File . ReadAllText ( filteredSolutionPath ) ) ;
84
+ jsonElement = jsonDocument . RootElement ;
85
+ filteredSolutionJsonElement = jsonElement . GetProperty ( "solution" ) ;
86
+ originalSolutionPath = filteredSolutionJsonElement . GetProperty ( "path" ) . GetString ( ) ;
87
+ originalSolutionPathAbsolute = Path . GetFullPath ( originalSolutionPath , Path . GetDirectoryName ( filteredSolutionPath ) ) ;
88
+ if ( ! File . Exists ( originalSolutionPathAbsolute ) )
62
89
{
63
- throw new GracefulException (
64
- CommonLocalizableStrings . CouldNotFindSolutionOrDirectory ,
65
- solutionDirectory ) ;
90
+ throw new Exception ( ) ;
66
91
}
92
+ filteredSolutionProjectPaths = filteredSolutionJsonElement . GetProperty ( "projects" )
93
+ . EnumerateArray ( )
94
+ . Select ( project => project . GetString ( ) )
95
+ . ToArray ( ) ;
67
96
}
68
- catch ( ArgumentException )
69
- {
97
+ catch ( Exception ex ) {
70
98
throw new GracefulException (
71
- CommonLocalizableStrings . CouldNotFindSolutionOrDirectory ,
72
- solutionDirectory ) ;
99
+ CommonLocalizableStrings . InvalidSolutionFormatString ,
100
+ filteredSolutionPath , ex . Message ) ;
73
101
}
74
102
75
- FileInfo [ ] files = [
76
- ..dir . GetFiles ( "*.sln" ) ,
77
- ..( includeSolutionXmlFiles ? dir . GetFiles ( ".slnx" ) : [ ] )
78
- ] ;
103
+ SolutionModel filteredSolution = new SolutionModel ( ) ;
104
+ SolutionModel originalSolution = CreateFromFileOrDirectory ( originalSolutionPathAbsolute ) ;
79
105
80
- if ( files . Length == 0 )
106
+ foreach ( var platform in originalSolution . Platforms )
81
107
{
82
- throw new GracefulException (
83
- CommonLocalizableStrings . CouldNotFindSolutionIn ,
84
- solutionDirectory ) ;
108
+ filteredSolution . AddPlatform ( platform ) ;
85
109
}
86
-
87
- if ( files . Length > 1 )
110
+ foreach ( var buildType in originalSolution . BuildTypes )
88
111
{
89
- throw new GracefulException (
90
- CommonLocalizableStrings . MoreThanOneSolutionInDirectory ,
91
- solutionDirectory ) ;
112
+ filteredSolution . AddBuildType ( buildType ) ;
92
113
}
93
114
94
- FileInfo solutionFile = files . Single ( ) ;
95
- if ( ! solutionFile . Exists )
115
+ foreach ( string path in filteredSolutionProjectPaths )
96
116
{
97
- throw new GracefulException (
98
- CommonLocalizableStrings . CouldNotFindSolutionIn ,
99
- solutionDirectory ) ;
117
+ // Normalize path to use correct directory separator
118
+ string normalizedPath = path . Replace ( '\\ ' , Path . DirectorySeparatorChar ) ;
119
+
120
+ SolutionProjectModel project = originalSolution . FindProject ( normalizedPath ) ?? throw new GracefulException (
121
+ CommonLocalizableStrings . ProjectNotFoundInTheSolution ,
122
+ normalizedPath ,
123
+ originalSolutionPath ) ;
124
+ filteredSolution . AddProject ( project . FilePath , project . Type , project . Parent is null ? null : filteredSolution . AddFolder ( project . Parent . Path ) ) ;
100
125
}
101
126
102
- return FromFile ( solutionFile . FullName ) ;
127
+ return filteredSolution ;
103
128
}
104
129
}
105
130
}
0 commit comments