22using System . Collections . Generic ;
33using System . IO ;
44using System . Linq ;
5- using System . Text . RegularExpressions ;
65using System . Threading ;
7- using ICSharpCode . CodeConverter . CSharp ;
86using ICSharpCode . CodeConverter . Util ;
97using Microsoft . CodeAnalysis ;
8+ using System . IO . Abstractions ;
109
1110namespace ICSharpCode . CodeConverter . Shared
1211{
@@ -18,32 +17,58 @@ public class SolutionConverter
1817 private readonly List < ( string Find , string Replace , bool FirstOnly ) > _projectReferenceReplacements ;
1918 private readonly IProgress < ConversionProgress > _progress ;
2019 private readonly ILanguageConversion _languageConversion ;
20+ private readonly SolutionFileTextEditor _solutionFileTextEditor ;
2121 private readonly CancellationToken _cancellationToken ;
2222
23+ public static IFileSystem FileSystem { get ; set ; } = new FileSystem ( ) ;
24+
25+ public static SolutionConverter CreateFor < TLanguageConversion > ( IReadOnlyCollection < Project > projectsToConvert , string sourceSolutionContents )
26+ where TLanguageConversion : ILanguageConversion , new ( )
27+ {
28+ return CreateFor < TLanguageConversion > ( projectsToConvert , solutionContents : sourceSolutionContents ) ;
29+ }
30+
2331 public static SolutionConverter CreateFor < TLanguageConversion > ( IReadOnlyCollection < Project > projectsToConvert ,
2432 ConversionOptions conversionOptions = default ,
2533 IProgress < ConversionProgress > progress = null ,
26- CancellationToken cancellationToken = default ) where TLanguageConversion : ILanguageConversion , new ( )
34+ CancellationToken cancellationToken = default ,
35+ string solutionContents = "" ) where TLanguageConversion : ILanguageConversion , new ( )
2736 {
2837 var conversion = new TLanguageConversion { ConversionOptions = conversionOptions } ;
29- return CreateFor ( conversion , projectsToConvert , progress , cancellationToken ) ;
38+ return CreateFor ( conversion , projectsToConvert , progress , cancellationToken , solutionContents ) ;
3039 }
3140
3241 public static SolutionConverter CreateFor ( ILanguageConversion languageConversion , IReadOnlyCollection < Project > projectsToConvert ,
3342 IProgress < ConversionProgress > progress ,
34- CancellationToken cancellationToken )
43+ CancellationToken cancellationToken , string solutionContents = "" )
3544 {
3645 languageConversion . ConversionOptions ??= new ConversionOptions ( ) ;
3746 var solutionFilePath = projectsToConvert . First ( ) . Solution . FilePath ;
38- var sourceSolutionContents = File . Exists ( solutionFilePath ) ? File . ReadAllText ( solutionFilePath ) : "" ;
39- var projectReferenceReplacements = GetProjectReferenceReplacements ( projectsToConvert , sourceSolutionContents ) ;
40- return new SolutionConverter ( solutionFilePath , sourceSolutionContents , projectsToConvert , projectReferenceReplacements , progress ?? new Progress < ConversionProgress > ( ) , cancellationToken , languageConversion ) ;
47+ var sourceSolutionContents = File . Exists ( solutionFilePath )
48+ ? FileSystem . File . ReadAllText ( solutionFilePath )
49+ : solutionContents ;
50+
51+ var projTuples = projectsToConvert . Select ( proj =>
52+ {
53+ var relativeProjPath = PathConverter . GetRelativePath ( solutionFilePath , proj . FilePath ) ;
54+ var projContents = FileSystem . File . ReadAllText ( proj . FilePath ) ;
55+
56+ return ( proj . Name , RelativeProjPath : relativeProjPath , ProjContents : projContents ) ;
57+ } ) ;
58+
59+ var solutionFileTextEditor = new SolutionFileTextEditor ( ) ;
60+ var projectReferenceReplacements = solutionFileTextEditor . GetProjectFileProjectReferenceReplacements ( projTuples , sourceSolutionContents ) ;
61+
62+ return new SolutionConverter ( solutionFilePath , sourceSolutionContents , projectsToConvert , projectReferenceReplacements ,
63+ progress ?? new Progress < ConversionProgress > ( ) , cancellationToken , languageConversion , solutionFileTextEditor ) ;
4164 }
4265
4366 private SolutionConverter ( string solutionFilePath ,
4467 string sourceSolutionContents , IReadOnlyCollection < Project > projectsToConvert ,
45- List < ( string Find , string Replace , bool FirstOnly ) > projectReferenceReplacements , IProgress < ConversionProgress > showProgressMessage ,
46- CancellationToken cancellationToken , ILanguageConversion languageConversion )
68+ List < ( string Find , string Replace , bool FirstOnly ) > projectReferenceReplacements ,
69+ IProgress < ConversionProgress > showProgressMessage ,
70+ CancellationToken cancellationToken , ILanguageConversion languageConversion ,
71+ SolutionFileTextEditor solutionFileTextEditor )
4772 {
4873 _solutionFilePath = solutionFilePath ;
4974 _sourceSolutionContents = sourceSolutionContents ;
@@ -52,6 +77,7 @@ private SolutionConverter(string solutionFilePath,
5277 _progress = showProgressMessage ;
5378 _languageConversion = languageConversion ;
5479 _cancellationToken = cancellationToken ;
80+ _solutionFileTextEditor = solutionFileTextEditor ;
5581 }
5682
5783 public IAsyncEnumerable < ConversionResult > Convert ( )
@@ -76,34 +102,32 @@ private IAsyncEnumerable<ConversionResult> ConvertProject(Project project)
76102
77103 private IEnumerable < ConversionResult > UpdateProjectReferences ( IEnumerable < Project > projectsToUpdateReferencesOnly )
78104 {
79- return projectsToUpdateReferencesOnly
80- . Where ( p => p . FilePath != null ) //Some project types like Websites don't have a project file
81- . Select ( project => {
105+ var conversionResults = projectsToUpdateReferencesOnly
106+ . Where ( p => p . FilePath != null ) //Some project types like Websites don't have a project file
107+ . Select ( project => {
82108 var withReferencesReplaced =
83109 new FileInfo ( project . FilePath ) . ConversionResultFromReplacements ( _projectReferenceReplacements ) ;
84110 withReferencesReplaced . TargetPathOrNull = withReferencesReplaced . SourcePathOrNull ;
85111 return withReferencesReplaced ;
86- } ) . Where ( c => ! c . IsIdentity ) ;
87- }
112+ } ) ;
88113
89- private static List < ( string Find , string Replace , bool FirstOnly ) > GetProjectReferenceReplacements ( IReadOnlyCollection < Project > projectsToConvert , string sourceSolutionContents ) =>
90- SolutionFileTextEditor . GetProjectReferenceReplacements ( projectsToConvert . Select ( p => ( FilePath : p . FilePath , DirectoryPath : p . GetDirectoryPath ( ) ) ) , sourceSolutionContents ) . ToList ( ) ;
114+ return conversionResults . Where ( c => ! c . IsIdentity ) ;
115+ }
91116
92- private ConversionResult ConvertSolutionFile ( )
117+ public ConversionResult ConvertSolutionFile ( )
93118 {
94119 var projectTypeGuidMappings = _languageConversion . GetProjectTypeGuidMappings ( ) ;
95- var projectTypeReplacements = _projectsToConvert . SelectMany ( project => GetProjectTypeReplacement ( project , projectTypeGuidMappings ) ) . ToList ( ) ;
120+ var relativeProjPaths = _projectsToConvert . Select ( proj =>
121+ ( proj . Name , RelativeProjPath : PathConverter . GetRelativePath ( _solutionFilePath , proj . FilePath ) ) ) ;
122+
123+ var slnProjectReferenceReplacements = _solutionFileTextEditor . GetSolutionFileProjectReferenceReplacements ( relativeProjPaths ,
124+ _sourceSolutionContents , projectTypeGuidMappings ) ;
96125
97- var convertedSolutionContents = _sourceSolutionContents . Replace ( _projectReferenceReplacements . Concat ( projectTypeReplacements ) ) ;
126+ var convertedSolutionContents = _sourceSolutionContents . Replace ( slnProjectReferenceReplacements ) ;
98127 return new ConversionResult ( convertedSolutionContents ) {
99128 SourcePathOrNull = _solutionFilePath ,
100129 TargetPathOrNull = _solutionFilePath
101130 } ;
102131 }
103-
104- private IEnumerable < ( string , string , bool ) > GetProjectTypeReplacement ( Project project , IReadOnlyCollection < ( string , string ) > typeGuidMappings )
105- {
106- return typeGuidMappings . Select ( guidReplacement => ( $@ "Project\s*\(\s*""{ guidReplacement . Item1 } ""\s*\)\s*=\s*""{ project . Name } """, $@" Project( "" { guidReplacement . Item2 } "") = " "{project.Name}" "" , false ) ) ;
107- }
108132 }
109133}
0 commit comments