diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0c0cf4d13b..385845b466 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -21,7 +21,7 @@
-
+
diff --git a/eng/submodules/sdl b/eng/submodules/sdl
index b5c3eab6b4..5848e584a1 160000
--- a/eng/submodules/sdl
+++ b/eng/submodules/sdl
@@ -1 +1 @@
-Subproject commit b5c3eab6b447111d3c7879bb547b80fb4abd9063
+Subproject commit 5848e584a1b606de26e3dbd1c7e4ecbc34f807a6
diff --git a/sources/SDL/Native/build-linux-arm.sh b/sources/SDL/Native/build-linux-arm.sh
index 22d2ed4898..d066978d2b 100755
--- a/sources/SDL/Native/build-linux-arm.sh
+++ b/sources/SDL/Native/build-linux-arm.sh
@@ -6,13 +6,14 @@ fi
if [[ ! -z ${GITHUB_ACTIONS+x} ]]; then
../../../eng/native/buildsystem/download-zig.py
export PATH="$PATH:$(readlink -f "../../../eng/native/buildsystem/zig")"
+ # Dependency list is from https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies
sudo apt-get update
sudo apt-get install build-essential git make \
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \
- libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
- libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev \
+ libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
+ libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
- libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev \
+ libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev \
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
fi
rm -rf build
diff --git a/sources/SDL/Native/build-linux-arm64.sh b/sources/SDL/Native/build-linux-arm64.sh
index e39d9b3ada..cee2eddb7d 100755
--- a/sources/SDL/Native/build-linux-arm64.sh
+++ b/sources/SDL/Native/build-linux-arm64.sh
@@ -6,13 +6,14 @@ fi
if [[ ! -z ${GITHUB_ACTIONS+x} ]]; then
../../../eng/native/buildsystem/download-zig.py
export PATH="$PATH:$(readlink -f "../../../eng/native/buildsystem/zig")"
+ # Dependency list is from https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies
sudo apt-get update
sudo apt-get install build-essential git make \
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \
- libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
- libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev \
+ libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
+ libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
- libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev \
+ libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev \
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
fi
rm -rf build
diff --git a/sources/SDL/Native/build-linux-x64.sh b/sources/SDL/Native/build-linux-x64.sh
index eb6312105f..65f656a922 100755
--- a/sources/SDL/Native/build-linux-x64.sh
+++ b/sources/SDL/Native/build-linux-x64.sh
@@ -6,13 +6,14 @@ fi
if [[ ! -z ${GITHUB_ACTIONS+x} ]]; then
../../../eng/native/buildsystem/download-zig.py
export PATH="$PATH:$(readlink -f "../../../eng/native/buildsystem/zig")"
+ # Dependency list is from https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md#build-dependencies
sudo apt-get update
sudo apt-get install build-essential git make \
pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev \
- libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
- libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev \
+ libaudio-dev libfribidi-dev libjack-dev libsndio-dev libx11-dev libxext-dev \
+ libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev \
libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
- libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev \
+ libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libthai-dev \
libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev
fi
rm -rf build
diff --git a/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs b/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs
index 947b06a6d2..0df1ec07ea 100644
--- a/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/AddApiProfiles.cs
@@ -265,9 +265,7 @@ rewriter.Profile is null
logger.LogDebug("No profile identified for {}", path);
}
- ctx.SourceProject = doc.WithSyntaxRoot(
- rewriter.Visit(root).NormalizeWhitespace()
- ).Project;
+ ctx.SourceProject = doc.WithSyntaxRoot(rewriter.Visit(root)).Project;
rewriter.Profile = null;
}
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/AddOpaqueStructs.cs b/sources/SilkTouch/SilkTouch/Mods/AddOpaqueStructs.cs
index 34d4e13355..5d8cafcb0e 100644
--- a/sources/SilkTouch/SilkTouch/Mods/AddOpaqueStructs.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/AddOpaqueStructs.cs
@@ -72,11 +72,10 @@ public Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
{
var qualified = name.LastIndexOf('.');
var ns =
- qualified != -1
- ? ModUtils.NamespaceIntoIdentifierName(name.AsSpan()[..qualified])
- : _defaultNamespaces.TryGetValue(ctx.JobKey, out var def)
- ? ModUtils.NamespaceIntoIdentifierName(def)
- : null;
+ qualified != -1 ? ModUtils.NamespaceIntoIdentifierName(name.AsSpan()[..qualified])
+ : _defaultNamespaces.TryGetValue(ctx.JobKey, out var def)
+ ? ModUtils.NamespaceIntoIdentifierName(def)
+ : null;
if (ns is null)
{
logger.LogWarning(
@@ -107,8 +106,7 @@ public Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
)
)
)
- )
- .NormalizeWhitespace(),
+ ),
filePath: proj.FullPath(fname)
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/AddVTables.cs b/sources/SilkTouch/SilkTouch/Mods/AddVTables.cs
index e3d3326dfd..c2fc2b5c99 100644
--- a/sources/SilkTouch/SilkTouch/Mods/AddVTables.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/AddVTables.cs
@@ -1454,8 +1454,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
rw.Reset();
proj = doc.WithSyntaxRoot(
- rw.Visit(node)?.NormalizeWhitespace()
- ?? throw new InvalidOperationException("Visit returned null")
+ rw.Visit(node) ?? throw new InvalidOperationException("Visit returned null")
).Project;
if (rw.InterfacePartials.Count == 0)
{
@@ -1515,11 +1514,7 @@ rw.ClassName is not null
)
{
proj = proj
- ?.AddDocument(
- Path.GetFileName(fname),
- root.NormalizeWhitespace(),
- filePath: proj.FullPath(fname)
- )
+ ?.AddDocument(Path.GetFileName(fname), root, filePath: proj.FullPath(fname))
.Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/BakeSourceSets.cs b/sources/SilkTouch/SilkTouch/Mods/BakeSourceSets.cs
index 16885d4a3a..36f5d61732 100644
--- a/sources/SilkTouch/SilkTouch/Mods/BakeSourceSets.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/BakeSourceSets.cs
@@ -391,7 +391,7 @@ .. ctx
{
proj = proj.AddDocument(
Path.GetFileName(bakedPath),
- bakedRoot.NormalizeWhitespace(),
+ bakedRoot,
// we can forgive the below nulls because RelativePath checks them, and returns null if they're null.
filePath: proj.FullPath(bakedPath)
).Project;
diff --git a/sources/SilkTouch/SilkTouch/Mods/ChangeNamespace.cs b/sources/SilkTouch/SilkTouch/Mods/ChangeNamespace.cs
index 56edb5619f..ce19c5cca8 100644
--- a/sources/SilkTouch/SilkTouch/Mods/ChangeNamespace.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/ChangeNamespace.cs
@@ -59,7 +59,8 @@ public Task> BeforeScrapeAsync(string key, List
rsps[i] = rsp with
{
- GeneratorConfiguration = rsp.GeneratorConfiguration.ToWrapper() with {
+ GeneratorConfiguration = rsp.GeneratorConfiguration.ToWrapper() with
+ {
DefaultNamespace = def,
WithNamespaces = with,
},
@@ -91,7 +92,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj!.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
@@ -116,17 +117,16 @@ public Rewriter(
_usingsToAdd.Clear();
return base.VisitCompilationUnit(node) switch
{
- CompilationUnitSyntax syntax
- => syntax.AddUsings(
- _usingsToAdd
- .Select(x => UsingDirective(ModUtils.NamespaceIntoIdentifierName(x)))
- .Where(x =>
- syntax.Usings.All(y => x.Name?.ToString() != y.Name?.ToString())
- )
- .ToArray()
- ),
+ CompilationUnitSyntax syntax => syntax.AddUsings(
+ _usingsToAdd
+ .Select(x => UsingDirective(ModUtils.NamespaceIntoIdentifierName(x)))
+ .Where(x =>
+ syntax.Usings.All(y => x.Name?.ToString() != y.Name?.ToString())
+ )
+ .ToArray()
+ ),
{ } ret => ret,
- null => null
+ null => null,
};
}
@@ -140,10 +140,11 @@ CompilationUnitSyntax syntax
}
return base.VisitNamespaceDeclaration(node) switch
{
- NamespaceDeclarationSyntax syntax
- => syntax.WithName(ModUtils.NamespaceIntoIdentifierName(newNs)),
+ NamespaceDeclarationSyntax syntax => syntax.WithName(
+ ModUtils.NamespaceIntoIdentifierName(newNs)
+ ),
{ } ret => ret,
- null => null
+ null => null,
};
}
@@ -159,10 +160,11 @@ FileScopedNamespaceDeclarationSyntax node
}
return base.VisitFileScopedNamespaceDeclaration(node) switch
{
- FileScopedNamespaceDeclarationSyntax syntax
- => syntax.WithName(ModUtils.NamespaceIntoIdentifierName(newNs)),
+ FileScopedNamespaceDeclarationSyntax syntax => syntax.WithName(
+ ModUtils.NamespaceIntoIdentifierName(newNs)
+ ),
{ } ret => ret,
- null => null
+ null => null,
};
}
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs b/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs
index 793a0ed1c7..55bcbcf113 100644
--- a/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs
@@ -308,13 +308,8 @@ private static async Task ToNormalisedStringAsync(
CancellationToken ct = default
)
{
- var result = await CodeFormatter.FormatAsync(
- root.NormalizeWhitespace().SyntaxTree,
- _opts,
- ct
- );
- return !result.CompilationErrors.Any()
- ? result.Code
- : root.NormalizeWhitespace(eol: "\n").ToFullString();
+ var normalizedRoot = root.NormalizeWhitespace(eol: "\n");
+ var result = await CodeFormatter.FormatAsync(normalizedRoot.SyntaxTree, _opts, ct);
+ return !result.CompilationErrors.Any() ? result.Code : normalizedRoot.ToFullString();
}
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractHandles.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractHandles.cs
index d1018b9caf..f38e321042 100644
--- a/sources/SilkTouch/SilkTouch/Mods/ExtractHandles.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/ExtractHandles.cs
@@ -51,7 +51,7 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
project = project
.AddDocument(
Path.GetFileName(relativePath),
- node.NormalizeWhitespace(),
+ node,
filePath: project.FullPath(relativePath)
)
.Project;
diff --git a/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs b/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs
index e5073907e0..4d5ff5fb28 100644
--- a/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/ExtractNestedTyping.cs
@@ -86,7 +86,7 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
// This is also where extracted enums are processed.
rewriter.File = fname;
project = doc.WithSyntaxRoot(
- rewriter.Visit(node)?.NormalizeWhitespace()
+ rewriter.Visit(node)
?? throw new InvalidOperationException("Rewriter returned null")
).Project;
@@ -110,8 +110,7 @@ rewriter.Namespace is not null
)
)
: SingletonList(newStruct)
- )
- .NormalizeWhitespace(),
+ ),
filePath: project.FullPath(
$"{fname.AsSpan()[..fname.LastIndexOf('/')]}/{newStruct.Identifier}.gen.cs"
)
@@ -174,8 +173,7 @@ rewriter.Namespace is not null
.WithMembers(SingletonList(typeDecl))
)
: SingletonList(typeDecl)
- )
- .NormalizeWhitespace(),
+ ),
filePath: project.FullPath($"{dir}/{identifier}.gen.cs")
)
.Project;
diff --git a/sources/SilkTouch/SilkTouch/Mods/InterceptNativeFunctions.cs b/sources/SilkTouch/SilkTouch/Mods/InterceptNativeFunctions.cs
index cb563d3bf5..0c36df137a 100644
--- a/sources/SilkTouch/SilkTouch/Mods/InterceptNativeFunctions.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/InterceptNativeFunctions.cs
@@ -48,7 +48,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj!.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/IdentifierRenamingTransformer.cs b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/IdentifierRenamingTransformer.cs
index 3dcd4a281a..d2d459e11b 100644
--- a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/IdentifierRenamingTransformer.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/IdentifierRenamingTransformer.cs
@@ -14,19 +14,25 @@ public class IdentifierRenamingTransformer : LocationTransformer
{
private ISymbol symbol = null!;
- private readonly IReadOnlyDictionary> newNameLookup;
+ private readonly IReadOnlyDictionary<
+ string,
+ List<(ISymbol Symbol, string NewName)>
+ > newNameLookup;
///
/// Creates a new IdentifierRenamingTransformer.
///
/// The new names for each symbol
- public IdentifierRenamingTransformer(IEnumerable<(ISymbol Symbol, string NewName)> newNames) : this(CreateNameLookup(newNames)) {}
+ public IdentifierRenamingTransformer(IEnumerable<(ISymbol Symbol, string NewName)> newNames)
+ : this(CreateNameLookup(newNames)) { }
///
/// Creates a new IdentifierRenamingTransformer.
///
/// The new names for each symbol grouped by symbol name.
- public IdentifierRenamingTransformer(IReadOnlyDictionary> newNameLookup)
+ public IdentifierRenamingTransformer(
+ IReadOnlyDictionary> newNameLookup
+ )
{
this.newNameLookup = newNameLookup;
}
@@ -34,9 +40,14 @@ public IdentifierRenamingTransformer(IReadOnlyDictionary
/// Creates a name lookup dictionary designed for .
///
- public static IReadOnlyDictionary> CreateNameLookup(IEnumerable<(ISymbol Symbol, string NewName)> names)
+ public static IReadOnlyDictionary<
+ string,
+ List<(ISymbol Symbol, string NewName)>
+ > CreateNameLookup(IEnumerable<(ISymbol Symbol, string NewName)> names)
{
- return names.GroupBy(t => t.Symbol.Name).ToDictionary(group => group.Key, group => group.ToList());
+ return names
+ .GroupBy(t => t.Symbol.Name)
+ .ToDictionary(group => group.Key, group => group.ToList());
}
///
@@ -68,7 +79,7 @@ private SyntaxToken GetRenamed(ISymbol symbol, SyntaxToken currentNameIdentifier
return currentNameIdentifier;
}
- // ----- Types -----
+ // ----- Types -----
///
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
diff --git a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationRewriter.cs b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationRewriter.cs
index 47f48c8014..5253b0f935 100644
--- a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationRewriter.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationRewriter.cs
@@ -14,36 +14,74 @@ namespace Silk.NET.SilkTouch.Mods.LocationTransformation;
/// and modifies the nodes only when coming back up.
///
/// Modifying nodes cause them to be detached from the semantic model (meaning no symbol information),
-/// so this ensures that we gather all of the data we need before making changes.
+/// so this ensures that we gather all the data we need before making changes.
///
-/// Symbols to search for.
-/// Transformers to use on each found symbol reference.
-public class LocationTransformationRewriter(HashSet symbols, List transformers) : CSharpSyntaxRewriter
+public class LocationTransformationRewriter : CSharpSyntaxRewriter
{
// Symbols can also be referenced within XML doc, which are trivia nodes.
///
public override bool VisitIntoStructuredTrivia => true;
- private readonly Dictionary queuedTransformations = new();
+ private readonly Dictionary _queuedTransformations = new();
/// The symbol for the node.
/// The index of the transformer that should be used when continuing the transformation process.
private record struct QueuedTransformation(ISymbol Symbol, int TransformerIndex);
- private readonly List tempNodeList = new();
+ private readonly List _tempNodeList = new();
///
/// The semantic model of the currently processed document.
///
- private SemanticModel semanticModel = null!;
+ private SemanticModel _semanticModel = null!;
+
+ private readonly HashSet _symbols;
+ private readonly List _transformers;
+ private readonly HashSet _relevantIdentifiers;
+
+ /// Symbols to search for.
+ /// Transformers to use on each found symbol reference.
+ public LocationTransformationRewriter(
+ HashSet symbols,
+ List transformers
+ )
+ {
+ _symbols = symbols;
+ _transformers = transformers;
+
+ // Used to skip symbol lookups
+ // Does not handle the omission of the "-Attribute" suffix, but generally, we don't need to transform attributes
+ _relevantIdentifiers = new HashSet(_symbols.Count);
+ foreach (var symbol in _symbols)
+ {
+ _relevantIdentifiers.Add(symbol.Name);
+ }
+ }
+
+ private LocationTransformationRewriter(
+ HashSet symbols,
+ List transformers,
+ HashSet relevantIdentifiers
+ )
+ {
+ _symbols = symbols;
+ _transformers = transformers;
+ _relevantIdentifiers = relevantIdentifiers;
+ }
///
/// Initializes the renamer to work for a new document. Must be called before visiting any nodes.
///
- public void Initialize(SemanticModel semanticModel)
- {
- this.semanticModel = semanticModel;
- }
+ public void Initialize(SemanticModel semanticModel) => _semanticModel = semanticModel;
+
+ ///
+ /// Clone this rewriter for purposes of thread safety.
+ ///
+ ///
+ /// This is allowed to return the current instance and share data.
+ ///
+ public LocationTransformationRewriter GetThreadSafeCopy() =>
+ new(_symbols, [.. _transformers.Select(t => t.GetThreadSafeCopy())], _relevantIdentifiers);
///
[return: NotNullIfNotNull("unmodifiedNode")]
@@ -60,24 +98,25 @@ public void Initialize(SemanticModel semanticModel)
// Check for queued transformation
// To apply a transformation, we must be in the same level in the hierarchy as the selected node
// We also must apply transformations when going back up in the hierarchy so we don't overwrite previous transformations
- if (queuedTransformations.Remove(unmodifiedNode, out var transformation))
+ if (_queuedTransformations.Remove(unmodifiedNode, out var transformation))
{
if (transformation.TransformerIndex >= 0)
{
// Apply deferred transformer
- var deferredTransformer = transformers[transformation.TransformerIndex];
- modifiedNode = deferredTransformer.Visit(modifiedNode)
+ var deferredTransformer = _transformers[transformation.TransformerIndex];
+ modifiedNode = deferredTransformer
+ .Visit(modifiedNode)
.WithLeadingTrivia(unmodifiedNode.GetLeadingTrivia().Select(VisitTrivia))
.WithTrailingTrivia(unmodifiedNode.GetTrailingTrivia());
}
// Continue applying remaining transformers
- for (var i = transformation.TransformerIndex + 1; i < transformers.Count; i++)
+ for (var i = transformation.TransformerIndex + 1; i < _transformers.Count; i++)
{
- var transformer = transformers[i];
+ var transformer = _transformers[i];
// Calculate hierarchy
- var hierarchy = tempNodeList;
+ var hierarchy = _tempNodeList;
{
hierarchy.Clear();
@@ -105,13 +144,17 @@ public void Initialize(SemanticModel semanticModel)
{
// We can't directly transform the node since we are at the wrong place in the hierarchy
// Defer it so it is processed later
- queuedTransformations.Add(selectedNode, new QueuedTransformation(transformation.Symbol, i));
+ _queuedTransformations.Add(
+ selectedNode,
+ new QueuedTransformation(transformation.Symbol, i)
+ );
break;
}
// Transform the node
- modifiedNode = transformer.Visit(modifiedNode)
+ modifiedNode = transformer
+ .Visit(modifiedNode)
.WithLeadingTrivia(unmodifiedNode.GetLeadingTrivia().Select(VisitTrivia))
.WithTrailingTrivia(unmodifiedNode.GetTrailingTrivia());
}
@@ -122,12 +165,12 @@ public void Initialize(SemanticModel semanticModel)
private void ReportSymbol(SyntaxNode node, ISymbol? symbol)
{
- if (symbol == null || !symbols.Contains(symbol))
+ if (symbol == null || !_symbols.Contains(symbol))
{
return;
}
- queuedTransformations.Add(node, new QueuedTransformation(symbol, -1));
+ _queuedTransformations.Add(node, new QueuedTransformation(symbol, -1));
}
// ----- Types -----
@@ -135,7 +178,7 @@ private void ReportSymbol(SyntaxNode node, ISymbol? symbol)
///
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitClassDeclaration(node)!;
@@ -144,7 +187,7 @@ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
///
public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitStructDeclaration(node)!;
@@ -153,7 +196,7 @@ public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node)
///
public override SyntaxNode VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitInterfaceDeclaration(node)!;
@@ -162,7 +205,7 @@ public override SyntaxNode VisitInterfaceDeclaration(InterfaceDeclarationSyntax
///
public override SyntaxNode VisitRecordDeclaration(RecordDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitRecordDeclaration(node)!;
@@ -171,7 +214,7 @@ public override SyntaxNode VisitRecordDeclaration(RecordDeclarationSyntax node)
///
public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitDelegateDeclaration(node)!;
@@ -180,7 +223,7 @@ public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax no
///
public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitEnumDeclaration(node)!;
@@ -191,7 +234,7 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node)
///
public override SyntaxNode VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitEnumMemberDeclaration(node)!;
@@ -200,7 +243,7 @@ public override SyntaxNode VisitEnumMemberDeclaration(EnumMemberDeclarationSynta
///
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitPropertyDeclaration(node)!;
@@ -209,7 +252,7 @@ public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax no
///
public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitEventDeclaration(node)!;
@@ -218,7 +261,7 @@ public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node)
///
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitMethodDeclaration(node)!;
@@ -227,7 +270,7 @@ public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
///
public override SyntaxNode VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitConstructorDeclaration(node)!;
@@ -236,7 +279,7 @@ public override SyntaxNode VisitConstructorDeclaration(ConstructorDeclarationSyn
///
public override SyntaxNode VisitDestructorDeclaration(DestructorDeclarationSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitDestructorDeclaration(node)!;
@@ -247,7 +290,12 @@ public override SyntaxNode VisitDestructorDeclaration(DestructorDeclarationSynta
///
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
{
- var symbol = semanticModel.GetSymbolInfo(node).Symbol ?? semanticModel.GetTypeInfo(node).Type;
+ if (!_relevantIdentifiers.Contains(node.Identifier.Text))
+ {
+ return node;
+ }
+
+ var symbol = _semanticModel.GetSymbolInfo(node).Symbol;
ReportSymbol(node, symbol);
return base.VisitIdentifierName(node)!;
@@ -257,9 +305,14 @@ public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
///
public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
{
- var symbol = semanticModel.GetDeclaredSymbol(node);
+ var symbol = _semanticModel.GetDeclaredSymbol(node);
ReportSymbol(node, symbol);
return base.VisitVariableDeclarator(node)!;
}
+
+ // ----- Skipped nodes -----
+
+ ///
+ public override SyntaxNode VisitUsingDirective(UsingDirectiveSyntax node) => node;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationUtils.cs b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationUtils.cs
index 8ae9303d72..a2faa241f3 100644
--- a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationUtils.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformationUtils.cs
@@ -26,7 +26,8 @@ public static async Task ModifyAllReferencesAsync(
IEnumerable symbols,
IEnumerable transformers,
ILogger? logger = null,
- CancellationToken ct = default)
+ CancellationToken ct = default
+ )
{
var sourceProject = ctx.SourceProject;
if (sourceProject == null)
@@ -37,33 +38,42 @@ public static async Task ModifyAllReferencesAsync(
// We need to track both the original solution and modified solution
// The original is where we retrieve documents and semantic models
// The modified solution is where we place the results
- IReadOnlyList documentIds = [.. sourceProject.DocumentIds, .. ctx.TestProject?.DocumentIds ?? []];
+ IReadOnlyList documentIds =
+ [
+ .. sourceProject.DocumentIds,
+ .. ctx.TestProject?.DocumentIds ?? [],
+ ];
var originalSolution = sourceProject.Solution;
var newDocuments = new ConcurrentDictionary();
var symbolSet = new HashSet(symbols, SymbolEqualityComparer.Default);
- await Parallel.ForEachAsync(documentIds, ct, async (documentId, _) => {
- var originalDocument = originalSolution.GetDocument(documentId);
- if (originalDocument == null)
+ var baseRewriter = new LocationTransformationRewriter(symbolSet, transformers.ToList());
+ await Parallel.ForEachAsync(
+ documentIds,
+ ct,
+ async (documentId, _) =>
{
- return;
- }
+ var originalDocument = originalSolution.GetDocument(documentId);
+ if (originalDocument == null)
+ {
+ return;
+ }
- var originalRoot = await originalDocument.GetSyntaxRootAsync(ct);
- var semanticModel = await originalDocument.GetSemanticModelAsync(ct);
+ var originalRoot = await originalDocument.GetSyntaxRootAsync(ct);
+ var semanticModel = await originalDocument.GetSemanticModelAsync(ct);
+ if (originalRoot == null || semanticModel == null)
+ {
+ return;
+ }
- if (originalRoot == null || semanticModel == null)
- {
- return;
- }
-
- // Since this is multithreaded, each thread needs their own copy of the rewriter and transformers
- var rewriter = new LocationTransformationRewriter(symbolSet, [..transformers.Select(t => t.GetThreadSafeCopy())]);
- rewriter.Initialize(semanticModel);
+ // Since this is multithreaded, each thread needs their own copy of the rewriter and transformers
+ var rewriter = baseRewriter.GetThreadSafeCopy();
- var newRoot = rewriter.Visit(originalRoot);
- newDocuments.TryAdd(documentId, newRoot);
- });
+ rewriter.Initialize(semanticModel);
+ var newRoot = rewriter.Visit(originalRoot);
+ newDocuments.TryAdd(documentId, newRoot);
+ }
+ );
var modifiedSolution = sourceProject.Solution;
foreach (var (documentId, newRoot) in newDocuments)
diff --git a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformer.cs b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformer.cs
index 56c9884937..c1c466a171 100644
--- a/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformer.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/LocationTransformation/LocationTransformer.cs
@@ -24,12 +24,16 @@ public abstract class LocationTransformer : CSharpSyntaxRewriter
/// The node hierarchy as a reversed stack. Index 0 is the current node. Index 1 is its parent and so on.
/// The symbol that is associated with this node.
/// The given node, another node, or null.
- public abstract SyntaxNode? GetNodeToModify(IReadOnlyList hierarchy, ISymbol symbol);
+ public abstract SyntaxNode? GetNodeToModify(
+ IReadOnlyList hierarchy,
+ ISymbol symbol
+ );
///
/// Clone this location transformer for purposes of thread safety.
- /// If the location transformer is already thread safe, the location transformer
- /// does not need to be cloned.
///
+ ///
+ /// This is allowed to return the current instance and share data.
+ ///
public abstract LocationTransformer GetThreadSafeCopy();
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/MarkNativeNames.cs b/sources/SilkTouch/SilkTouch/Mods/MarkNativeNames.cs
index ebf68b4b0e..9f8aa554d1 100644
--- a/sources/SilkTouch/SilkTouch/Mods/MarkNativeNames.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/MarkNativeNames.cs
@@ -37,7 +37,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs b/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
index 98395e7517..5a48a038a4 100644
--- a/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/MixKhronosData.cs
@@ -363,7 +363,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter1.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter1.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
@@ -373,7 +373,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
{
proj = proj.AddDocument(
Path.GetFileName(filePath),
- node.NormalizeWhitespace(),
+ node,
filePath: proj.FullPath(filePath)
).Project;
}
@@ -385,7 +385,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter2.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter2.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
@@ -397,7 +397,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter3.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter3.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs b/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs
index 100f43ad25..afccdb95ab 100644
--- a/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/PrettifyNames.cs
@@ -195,9 +195,15 @@ await proj.GetCompilationAsync(ct)
// Change the filenames where appropriate.
proj = ctx.SourceProject;
+
var typeNames = newNames.GetValueOrDefault("", []);
var typeNamesLongestFirst = typeNames.OrderByDescending(x => x.Key.Length).ToArray();
+ var documentPaths = proj
+ .Documents.Select(d => d.RelativePath())
+ .Where(d => d != null)
+ .ToHashSet();
+
foreach (var docId in proj.DocumentIds)
{
var doc = proj.GetDocument(docId);
@@ -206,6 +212,7 @@ await proj.GetCompilationAsync(ct)
continue;
}
+ // Find best matching document for renamed types
var firstMatch = typeNamesLongestFirst.FirstOrDefault(x =>
doc.FilePath.Contains(x.Key) || doc.Name.Contains(x.Key)
);
@@ -214,43 +221,36 @@ await proj.GetCompilationAsync(ct)
continue;
}
- var originalName = doc.Name;
- doc = doc.ReplaceNameAndPath(oldName, newName);
-
- var found = false;
- if (doc.FilePath is not null)
+ // Save syntax tree so we can restore it later
+ // This is because modifying the document can cause it to be reparsed
+ // C# discord: https://discord.com/channels/143867839282020352/598678594750775301/1494176147351535687
+ var syntaxRoot = await doc.GetSyntaxRootAsync(ct);
+ if (syntaxRoot == null)
{
- foreach (var checkDocId in proj.DocumentIds)
- {
- if (checkDocId == docId)
- {
- continue;
- }
+ continue;
+ }
- var checkDoc = proj.GetDocument(checkDocId);
- if (checkDoc?.FilePath is null)
- {
- continue;
- }
+ // Rename doc and update path
+ var originalName = doc.Name;
+ var originalPath = doc.RelativePath();
+ doc = doc.ReplaceNameAndPath(oldName, newName);
+ var newPath = doc.RelativePath();
- if (checkDoc.FilePath == doc.FilePath)
- {
- found = true;
- break;
- }
- }
- }
+ // Restore syntax tree
+ doc = doc.WithSyntaxRoot(syntaxRoot);
- if (found)
+ // Check for path conflict
+ documentPaths.Remove(originalPath);
+ if (!documentPaths.Add(newPath))
{
logger.LogError(
- $"{originalName} -> {doc.Name} failed to rename file as a file already exists at {doc.FilePath}"
+ $"{originalName} -> {doc.Name} failed to rename file as a file already exists at {newPath}"
);
+
+ continue;
}
- else
- {
- proj = doc.Project;
- }
+
+ proj = doc.Project;
}
ctx.SourceProject = proj;
@@ -1132,17 +1132,6 @@ public void ProcessNames(NameProcessorContext context)
}
}
- // These collections are used later.
- // These keep track of method discriminators to determine whether we have incompatible overloads.
- // We keep track of the first original name so that we can add it to conflictingOriginalNames when we
- // do discover a conflict (along with the original name of the actual conflict).
- var methodDiscriminators =
- new Dictionary<
- string,
- (string? FirstOriginalName, List Methods)
- >();
- var conflictingOriginalNames = new HashSet();
-
// This loop cannot be part of the loop below because it modifies the primaries
foreach (var (scope, members) in context.Names)
{
@@ -1208,6 +1197,17 @@ d is not MethodDeclarationSyntax
}
}
+ // These collections are used later.
+ // These keep track of method discriminators to determine whether we have incompatible overloads.
+ // We keep track of the first original name so that we can add it to conflictingOriginalNames when we
+ // do discover a conflict (along with the original name of the actual conflict).
+ var methodDiscriminators =
+ new Dictionary<
+ string,
+ (string? FirstOriginalName, List Methods)
+ >();
+ var conflictingOriginalNames = new HashSet();
+
foreach (var (scope, members) in context.Names)
{
nameData.Names.TryGetValue(scope, out var scopeData);
diff --git a/sources/SilkTouch/SilkTouch/Mods/StripAttributes.cs b/sources/SilkTouch/SilkTouch/Mods/StripAttributes.cs
index 9bf511bf3b..c043f71293 100644
--- a/sources/SilkTouch/SilkTouch/Mods/StripAttributes.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/StripAttributes.cs
@@ -48,7 +48,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/TransformEnums.cs b/sources/SilkTouch/SilkTouch/Mods/TransformEnums.cs
index e3fa94640f..e5ee37046e 100644
--- a/sources/SilkTouch/SilkTouch/Mods/TransformEnums.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/TransformEnums.cs
@@ -190,7 +190,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
var doc =
proj.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
proj = doc.WithSyntaxRoot(
- rewriter.Visit(await doc.GetSyntaxRootAsync(ct))?.NormalizeWhitespace()
+ rewriter.Visit(await doc.GetSyntaxRootAsync(ct))
?? throw new InvalidOperationException("Visit returned null.")
).Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/TransformFunctions.cs b/sources/SilkTouch/SilkTouch/Mods/TransformFunctions.cs
index 222c974af8..1d97c3a230 100644
--- a/sources/SilkTouch/SilkTouch/Mods/TransformFunctions.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/TransformFunctions.cs
@@ -60,7 +60,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
proj!.GetDocument(docId) ?? throw new InvalidOperationException("Document missing");
if (await doc.GetSyntaxRootAsync(ct) is { } root)
{
- proj = doc.WithSyntaxRoot(Visit(root).NormalizeWhitespace()).Project;
+ proj = doc.WithSyntaxRoot(Visit(root)).Project;
}
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs b/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs
index 04feaa8cd0..c2011b0ba4 100644
--- a/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/TransformHandles.cs
@@ -86,8 +86,8 @@ public override async Task ExecuteAsync(IModContext ctx, CancellationToken ct =
}
}
- // Do the two following transformation to all references of the handle types:
- // 2. Reduce pointer dimensions
+ // Reduce pointer dimensions
+ // The -Handle suffix will be applied later by PrettifyNames if the user configures it to do so
ctx.SourceProject = project;
await LocationTransformationUtils.ModifyAllReferencesAsync(
ctx,
@@ -115,9 +115,7 @@ [new PointerDimensionReductionTransformer()],
var syntaxRoot = await syntaxTree.GetRootAsync(ct);
// Rewrite handle struct to include handle members
- document = document.WithSyntaxRoot(
- handleTypeRewriter.Visit(syntaxRoot).NormalizeWhitespace()
- );
+ document = document.WithSyntaxRoot(handleTypeRewriter.Visit(syntaxRoot));
project = document.Project;
}
diff --git a/sources/SilkTouch/SilkTouch/Mods/TransformProperties.cs b/sources/SilkTouch/SilkTouch/Mods/TransformProperties.cs
index bed5366d8a..4ce2a40291 100644
--- a/sources/SilkTouch/SilkTouch/Mods/TransformProperties.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/TransformProperties.cs
@@ -58,7 +58,7 @@ is GenericNameSyntax
&& lit.IsKind(SyntaxKind.Utf8StringLiteralExpression)
)
{
- node = node.WithType(IdentifierName("Utf8String")).NormalizeWhitespace();
+ node = node.WithType(IdentifierName("Utf8String"));
}
return base.VisitPropertyDeclaration(node);
diff --git a/sources/SilkTouch/SilkTouch/Mods/Transformation/FunctionTransformer.cs b/sources/SilkTouch/SilkTouch/Mods/Transformation/FunctionTransformer.cs
index ba663df169..9ce3347aac 100644
--- a/sources/SilkTouch/SilkTouch/Mods/Transformation/FunctionTransformer.cs
+++ b/sources/SilkTouch/SilkTouch/Mods/Transformation/FunctionTransformer.cs
@@ -117,7 +117,6 @@ meth.Body.Statements[0] as ExpressionStatementSyntax
.WithBody(null)
.WithExpressionBody(null)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))
- .NormalizeWhitespace(eol: "\n")
.ToFullString()
);
continue;
diff --git a/sources/SilkTouch/SilkTouch/Profiling/ProfilingScope.cs b/sources/SilkTouch/SilkTouch/Profiling/ProfilingScope.cs
new file mode 100644
index 0000000000..03989bda03
--- /dev/null
+++ b/sources/SilkTouch/SilkTouch/Profiling/ProfilingScope.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics;
+
+namespace Silk.NET.SilkTouch.Profiling;
+
+///
+/// Lightweight way to profile a section of code.
+///
+internal readonly struct ProfilingScope : IDisposable
+{
+ private readonly string _name;
+ private readonly long _timestamp;
+
+ public ProfilingScope(string name)
+ {
+ _name = name;
+ _timestamp = Stopwatch.GetTimestamp();
+ }
+
+ public void Dispose()
+ {
+ var elapsed = Stopwatch.GetElapsedTime(_timestamp);
+ Console.WriteLine(
+ "Elapsed time for scope \"{0}\": {1:F3} ms",
+ _name,
+ elapsed.TotalMilliseconds
+ );
+ }
+}