Dnspy/dnSpy/dnSpy.Decompiler/MSBuild/FilenameCreator.cs

174 lines
5.3 KiB
C#
Raw Permalink Normal View History

2021-09-20 18:20:01 +02:00
/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using dnlib.DotNet;
namespace dnSpy.Decompiler.MSBuild {
sealed class FilenameCreator {
// Max length of a filename, excluding extension
const int MaxNameLength = 60;
// Max length of a directory name part
const int MaxDirNameLength = 40;
public string DefaultNamespace => defaultNamespace;
readonly string defaultNamespace;
readonly HashSet<string> usedNames;
readonly string baseDir;
public FilenameCreator(string baseDir) {
Debug.Assert(Path.IsPathRooted(baseDir));
this.baseDir = baseDir;
defaultNamespace = string.Empty;
usedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
public FilenameCreator(string baseDir, string defaultNamespace) {
Debug.Assert(Path.IsPathRooted(baseDir));
this.baseDir = baseDir;
this.defaultNamespace = defaultNamespace;
usedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
public string Create(string fileExt, string fullName) {
Debug2.Assert(fileExt is not null && fileExt.Length > 1 && fileExt[0] == '.');
string name = StripDefaultNamespace(fullName);
if (string.IsNullOrEmpty(name))
name = fullName;
return Create(name.Split('.'), fileExt);
}
public string CreateFromNamespaceName(string fileExt, string ns, string name) {
Debug2.Assert(fileExt is not null && fileExt.Length > 1 && fileExt[0] == '.');
var list = GetNamespaceParts(ns);
list.Add(name);
return Create(list.ToArray(), fileExt);
}
List<string> GetNamespaceParts(string ns) {
ns = StripDefaultNamespace(ns);
var list = new List<string>();
if (!string.IsNullOrEmpty(ns))
list.AddRange(ns.Split('.'));
return list;
}
string StripDefaultNamespace(string name) {
if (defaultNamespace.Equals(name))
return string.Empty;
if (name.StartsWith(defaultNamespace + "."))
return name.Substring(defaultNamespace.Length + 1);
return name;
}
public string CreateFromRelativePath(string relPath, string fileExt) {
relPath = relPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
return Create(relPath.Split(Path.DirectorySeparatorChar), fileExt);
}
string Create(string[] parts, string fileExt) {
fileExt = FilenameUtils.CleanName(fileExt);
string tempName = string.Empty;
for (int i = 0; i < parts.Length; i++) {
var part = parts[i];
int maxLen = i == parts.Length - 1 ? MaxNameLength : MaxDirNameLength;
tempName = Path.Combine(tempName, FixLongName(FilenameUtils.CleanName(part), maxLen));
}
tempName = Path.Combine(baseDir, tempName);
var newName = tempName + fileExt;
if (usedNames.Contains(newName)) {
for (int i = 2; ; i++) {
newName = tempName + "." + i.ToString() + fileExt;
if (!usedNames.Contains(newName))
break;
}
}
usedNames.Add(newName);
return newName;
}
public string Create(ModuleDef module) {
string name;
var asm = module.Assembly;
if (asm is not null && module.IsManifestModule)
name = module.Assembly.Name;
else
name = FileUtils.GetFilename(module.Name);
return Create(name);
}
string Create(string name) {
name = Path.Combine(baseDir, FixLongName(FilenameUtils.CleanName(name), MaxNameLength));
if (usedNames.Contains(name)) {
var tempName = name;
for (int i = 2; ; i++) {
name = tempName + "." + i.ToString();
if (!usedNames.Contains(name))
break;
}
}
usedNames.Add(name);
return name;
}
static string FixLongName(string name, int maxLen) {
if (name.Length <= maxLen)
return name;
return name.Substring(0, maxLen);
}
public string CreateFromNamespaceFilename(string @namespace, string filename) {
var fileExt = FileUtils.GetExtension(filename);
var relPath = filename.Substring(0, filename.Length - fileExt.Length);
ExtractNamespace(relPath, out string ns, out string filenameNoExt);
if (!string.IsNullOrEmpty(ns)) {
if (string.IsNullOrEmpty(@namespace))
@namespace = ns;
else
@namespace += "." + ns;
}
var parts = GetNamespaceParts(@namespace);
parts.Add(FileUtils.GetFileNameWithoutExtension(filenameNoExt));
return Create(parts.ToArray(), fileExt);
}
static void ExtractNamespace(string relPath, out string ns, out string name) {
int i = relPath.LastIndexOf('.');
if (i < 0) {
ns = string.Empty;
name = relPath;
}
else {
ns = relPath.Substring(0, i);
name = relPath.Substring(i + 1);
}
}
public string CreateName(string nameOnly) {
string fileExt = FileUtils.GetExtension(nameOnly);
var parts = new string[] { FileUtils.GetFileNameWithoutExtension(nameOnly) };
return Create(parts, fileExt);
}
}
}