Skip to content

Commit 31bbcf4

Browse files
Fix handling of file extensions in project export.
1 parent 292c21d commit 31bbcf4

File tree

7 files changed

+22
-18
lines changed

7 files changed

+22
-18
lines changed

ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System;
2020
using System.Collections.Concurrent;
2121
using System.Collections.Generic;
22+
using System.Diagnostics;
2223
using System.IO;
2324
using System.Linq;
2425
using System.Reflection.Metadata;
@@ -135,7 +136,7 @@ protected WholeProjectDecompiler(
135136

136137
public void DecompileProject(MetadataFile file, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken))
137138
{
138-
string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(file.Name) + ".csproj");
139+
string projectFileName = Path.Combine(targetDirectory, CleanUpFileName(file.Name, ".csproj"));
139140
using (var writer = new StreamWriter(projectFileName))
140141
{
141142
DecompileProject(file, targetDirectory, writer, cancellationToken);
@@ -238,7 +239,7 @@ IEnumerable<ProjectItemInfo> WriteCodeFilesInProject(MetadataFile module, IList<
238239
string GetFileFileNameForHandle(TypeDefinitionHandle h)
239240
{
240241
var type = metadata.GetTypeDefinition(h);
241-
string file = CleanUpFileName(metadata.GetString(type.Name) + ".cs");
242+
string file = CleanUpFileName(metadata.GetString(type.Name), ".cs");
242243
string ns = metadata.GetString(type.Namespace);
243244
if (string.IsNullOrEmpty(ns))
244245
{
@@ -339,8 +340,7 @@ protected virtual IEnumerable<ProjectItemInfo> WriteResourceFilesInProject(Metad
339340
{
340341
foreach (var (name, value) in resourcesFile)
341342
{
342-
string fileName = SanitizeFileName(name)
343-
.Replace('/', Path.DirectorySeparatorChar);
343+
string fileName = SanitizeFileName(name);
344344
string dirName = Path.GetDirectoryName(fileName);
345345
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName))
346346
{
@@ -609,9 +609,14 @@ static string CleanUpApplicationManifest(byte[] appManifest)
609609
/// <summary>
610610
/// Cleans up a node name for use as a file name.
611611
/// </summary>
612-
public static string CleanUpFileName(string text)
612+
public static string CleanUpFileName(string text, string extension)
613613
{
614-
return CleanUpName(text, separateAtDots: false, treatAsFileName: false);
614+
Debug.Assert(!string.IsNullOrEmpty(extension));
615+
if (!extension.StartsWith("."))
616+
extension = "." + extension;
617+
text = text + extension;
618+
619+
return CleanUpName(text, separateAtDots: false, treatAsFileName: !string.IsNullOrEmpty(extension), treatAsPath: false);
615620
}
616621

617622
/// <summary>
@@ -620,7 +625,7 @@ public static string CleanUpFileName(string text)
620625
/// </summary>
621626
public static string SanitizeFileName(string fileName)
622627
{
623-
return CleanUpName(fileName, separateAtDots: false, treatAsFileName: true);
628+
return CleanUpName(fileName, separateAtDots: false, treatAsFileName: true, treatAsPath: true);
624629
}
625630

626631
/// <summary>
@@ -629,7 +634,7 @@ public static string SanitizeFileName(string fileName)
629634
/// If <paramref name="treatAsFileName"/> is active, we check for file a extension and try to preserve it,
630635
/// if it's valid.
631636
/// </summary>
632-
static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName)
637+
static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName, bool treatAsPath)
633638
{
634639
// Remove anything that could be confused with a rooted path.
635640
int pos = text.IndexOf(':');
@@ -692,7 +697,7 @@ static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName
692697
if (separateAtDots)
693698
currentSegmentLength = 0;
694699
}
695-
else if (treatAsFileName && (c is '/' or '\\') && currentSegmentLength > 1)
700+
else if (treatAsPath && (c is '/' or '\\') && currentSegmentLength > 1)
696701
{
697702
// if we treat this as a file name, we've started a new segment
698703
b.Append(Path.DirectorySeparatorChar);
@@ -732,13 +737,12 @@ static string CleanUpName(string text, bool separateAtDots, bool treatAsFileName
732737
/// </summary>
733738
public static string CleanUpDirectoryName(string text)
734739
{
735-
return CleanUpName(text, separateAtDots: false, treatAsFileName: false);
740+
return CleanUpName(text, separateAtDots: false, treatAsFileName: false, treatAsPath: false);
736741
}
737742

738743
public static string CleanUpPath(string text)
739744
{
740-
return CleanUpName(text, separateAtDots: true, treatAsFileName: false)
741-
.Replace('.', Path.DirectorySeparatorChar);
745+
return CleanUpName(text, separateAtDots: true, treatAsFileName: true, treatAsPath: true);
742746
}
743747

744748
static bool IsReservedFileSystemName(string name)

ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ string BuildFileNameFromTypeName(TypeDefinitionHandle handle)
9292
string ns = settings.UseNestedDirectoriesForNamespaces
9393
? WholeProjectDecompiler.CleanUpPath(typeName.Namespace)
9494
: WholeProjectDecompiler.CleanUpDirectoryName(typeName.Namespace);
95-
return Path.Combine(ns, WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
95+
return Path.Combine(ns, WholeProjectDecompiler.CleanUpFileName(typeName.Name, ".cs"));
9696
}
9797

9898
var sourceFiles = reader.GetTopLevelTypeDefinitions().Where(t => IncludeTypeWhenGeneratingPdb(file, t, settings)).GroupBy(BuildFileNameFromTypeName).ToList();

ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stre
6262
var typeDefinition = result.TypeName.HasValue ? typeSystem.MainModule.GetTypeDefinition(result.TypeName.Value.TopLevelTypeName) : null;
6363
if (typeDefinition != null)
6464
{
65-
fileName = WholeProjectDecompiler.CleanUpPath(typeDefinition.ReflectionName) + ".xaml";
65+
fileName = WholeProjectDecompiler.CleanUpPath(typeDefinition.ReflectionName + ".xaml");
6666
var partialTypeInfo = new PartialTypeInfo(typeDefinition);
6767
foreach (var member in result.GeneratedMembers)
6868
{

ILSpy/Commands/GeneratePdbContextMenuEntry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ internal static void GeneratePdbForAssembly(LoadedAssembly assembly, LanguageSer
7171
return;
7272
}
7373
SaveFileDialog dlg = new SaveFileDialog();
74-
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(assembly.ShortName) + ".pdb";
74+
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(assembly.ShortName, ".pdb");
7575
dlg.Filter = Resources.PortablePDBPdbAllFiles;
7676
dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName);
7777
if (dlg.ShowDialog() != true)

ILSpy/Commands/SelectPdbContextMenuEntry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public async void Execute(TextViewContext context)
3838
if (assembly == null)
3939
return;
4040
OpenFileDialog dlg = new OpenFileDialog();
41-
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(assembly.ShortName) + ".pdb";
41+
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(assembly.ShortName, ".pdb");
4242
dlg.Filter = Resources.PortablePDBPdbAllFiles;
4343
dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName);
4444
if (dlg.ShowDialog() != true)

ILSpy/TextView/DecompilerTextView.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ public void SaveToDisk(ILSpy.Language language, IEnumerable<ILSpyTreeNode> treeN
10911091
SaveFileDialog dlg = new SaveFileDialog();
10921092
dlg.DefaultExt = language.FileExtension;
10931093
dlg.Filter = language.Name + "|*" + language.FileExtension + Properties.Resources.AllFiles;
1094-
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(treeNodes.First().ToString()) + language.FileExtension;
1094+
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(treeNodes.First().ToString(), language.FileExtension);
10951095
if (dlg.ShowDialog() == true)
10961096
{
10971097
SaveToDisk(new DecompilationContext(language, treeNodes.ToArray(), options), dlg.FileName);

ILSpy/TreeNodes/AssemblyTreeNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ public override bool Save(TabPageModel tabPage)
475475
if (string.IsNullOrEmpty(language.ProjectFileExtension))
476476
return false;
477477
SaveFileDialog dlg = new SaveFileDialog();
478-
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(LoadedAssembly.ShortName) + language.ProjectFileExtension;
478+
dlg.FileName = WholeProjectDecompiler.CleanUpFileName(LoadedAssembly.ShortName, language.ProjectFileExtension);
479479
dlg.Filter = language.Name + " project|*" + language.ProjectFileExtension + "|" + language.Name + " single file|*" + language.FileExtension + "|All files|*.*";
480480
if (dlg.ShowDialog() == true)
481481
{

0 commit comments

Comments
 (0)