| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
				@@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.CSharp.Transforms; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.DebugInfo; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.Metadata; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.Semantics; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.Solution; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.TypeSystem; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					using ICSharpCode.Decompiler.Util; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -206,58 +207,99 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
				@@ -206,58 +207,99 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var metadata = module.Metadata; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									delegate (TypeDefinitionHandle h) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										var type = metadata.GetTypeDefinition(h); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										string ns = metadata.GetString(type.Namespace); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										if (string.IsNullOrEmpty(ns)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											return file; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											string dir = Settings.UseNestedDirectoriesForNamespaces ? CleanUpPath(ns) : CleanUpDirectoryName(ns); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											if (directories.Add(dir)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												Directory.CreateDirectory(Path.Combine(TargetDirectory, dir)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											return Path.Combine(dir, file); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									}, StringComparer.OrdinalIgnoreCase).ToList(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var progressReporter = ProgressIndicator; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var progress = new DecompilationProgress { TotalUnits = files.Count, Title = "Exporting project..." }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								Parallel.ForEach( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									Partitioner.Create(files, loadBalance: true), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									new ParallelOptions { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										CancellationToken = cancellationToken | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									}, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									delegate (IGrouping<string, TypeDefinitionHandle> file) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										using (StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key))) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											try | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var workList = new HashSet<TypeDefinitionHandle>(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								var processedTypes = new HashSet<TypeDefinitionHandle>(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								ProcessFiles(files); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								while (workList.Count > 0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									var additionalFiles = workList | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									workList.Clear(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									ProcessFiles(additionalFiles); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									files.AddRange(additionalFiles); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									progress.TotalUnits = files.Count; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								string GetFileFileNameForHandle(TypeDefinitionHandle h) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									var type = metadata.GetTypeDefinition(h); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									string ns = metadata.GetString(type.Namespace); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									if (string.IsNullOrEmpty(ns)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										return file; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									else | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										string dir = Settings.UseNestedDirectoriesForNamespaces ? CleanUpPath(ns) : CleanUpDirectoryName(ns); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										if (directories.Add(dir)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											Directory.CreateDirectory(Path.Combine(TargetDirectory, dir)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										return Path.Combine(dir, file); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								void ProcessFiles(List<IGrouping<string, TypeDefinitionHandle>> files) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									processedTypes.AddRange(files.SelectMany(f => f)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									Parallel.ForEach( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										Partitioner.Create(files, loadBalance: true), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										new ParallelOptions { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											CancellationToken = cancellationToken | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										}, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										delegate (IGrouping<string, TypeDefinitionHandle> file) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											using (StreamWriter w = new StreamWriter(Path.Combine(TargetDirectory, file.Key))) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												CSharpDecompiler decompiler = CreateDecompiler(ts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												try | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													CSharpDecompiler decompiler = CreateDecompiler(ts); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												foreach (var partialType in partialTypes) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													foreach (var partialType in partialTypes) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														decompiler.AddPartialTypeDefinition(partialType); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													decompiler.CancellationToken = cancellationToken; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													var declaredTypes = file.ToArray(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													var syntaxTree = decompiler.DecompileTypes(declaredTypes); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													foreach (var node in syntaxTree.Descendants) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														var td = (node.GetResolveResult() as TypeResolveResult)?.Type.GetDefinition(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														if (td?.ParentModule != ts.MainModule) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
															continue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														while (td?.DeclaringTypeDefinition != null) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
															td = td.DeclaringTypeDefinition; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														if (td != null && td.MetadataToken is { IsNil: false } token && !processedTypes.Contains((TypeDefinitionHandle)token)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
															lock (workList) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
															{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
																workList.Add((TypeDefinitionHandle)token); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
															} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
														} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													decompiler.AddPartialTypeDefinition(partialType); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												decompiler.CancellationToken = cancellationToken; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												var syntaxTree = decompiler.DecompileTypes(file.ToArray()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										progress.Status = file.Key; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										Interlocked.Increment(ref progress.UnitsCompleted); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										progressReporter?.Report(progress); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									}); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											progress.Status = file.Key; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											Interlocked.Increment(ref progress.UnitsCompleted); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											progressReporter?.Report(progress); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										}); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							#endregion
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				 | 
				
					
 
				 
					 |