Rename interface methods alongside their implementations and async state machines#273
Open
AlpinePastoralist wants to merge 1 commit into
Open
Rename interface methods alongside their implementations and async state machines#273AlpinePastoralist wants to merge 1 commit into
AlpinePastoralist wants to merge 1 commit into
Conversation
…ions and rename async state machines
The previous implementation skipped every method with IsVirtual=true, which
meant the entire public surface of services and repositories (every implicit
interface implementation in C# is virtual at IL level) kept its original
name. The original method name also leaked through compiler-generated async
state-machine types named "<MethodName>d__N".
This change:
1. Adds a pre-pass that collects each interface method in the current
obfuscation scope, reserves one random name per method, and applies the
same name to every matching implementation that is also in scope. The
contract between interface and implementation stays consistent.
2. After renaming a method, looks for nested compiler-generated types whose
name embeds the original method name ("<originalName>d__N" or
"<originalName>b__N_M") and renames them too. This closes the most
common stack-trace leak for async methods and closures.
3. Refines the virtual-method skip in the standard rename loop:
- IsVirtual && !IsNewSlot is kept as skip (true override; the name is
bound to the base class method).
- IsVirtual && IsNewSlot && IsFinal is added as skip (implicit
implementation of an interface that lives outside the current module;
renaming would break the contract and trigger TypeLoadException at
load time).
4. Replaces the in-line loops for method/type/field rename with iteration
over pre-collected lists so the helpers can be called safely while the
underlying collections are still in use.
The original behaviour is preserved for type and field renames.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rename interface methods together with their implementations and rename async state machines
The previous implementation skipped every method with IsVirtual=true, which meant the entire public surface of services and repositories (every implicit interface implementation in C# is virtual at IL level) kept its original name. The original method name also leaked through compiler-generated async state-machine types named "d__N".
This change:
Adds a pre-pass that collects each interface method in the current obfuscation scope, reserves one random name per method, and applies the same name to every matching implementation that is also in scope. The contract between interface and implementation stays consistent.
After renaming a method, looks for nested compiler-generated types whose name embeds the original method name ("d__N" or "b__N_M") and renames them too. This closes the most common stack-trace leak for async methods and closures.
Refines the virtual-method skip in the standard rename loop:
Replaces the in-line loops for method/type/field rename with iteration over pre-collected lists so the helpers can be called safely while the underlying collections are still in use.
The original behaviour is preserved for type and field renames.