Skip to content

Commit 7deb75d

Browse files
authored
Merge e446e09 into 52cdc10
2 parents 52cdc10 + e446e09 commit 7deb75d

File tree

7 files changed

+208
-99
lines changed

7 files changed

+208
-99
lines changed

Confuser.Renamer/BAML/BAMLAnalyzer.cs

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ void ProcessElementBody(BamlElement root, BamlElement elem) {
428428
AddTypeSigReference(sig, reference);
429429
}
430430
else
431-
AnalyzePropertyPath(value);
431+
AnalyzePropertyPath(value, s => txt.Value = s);
432432
}
433433
}
434434
}
@@ -479,7 +479,7 @@ void ProcessConverter(PropertyWithConverterRecord rec, TypeDef type) {
479479
// Umm... Again nothing to do, DP already won't be renamed.
480480
}
481481
else if (converter.FullName == "System.Windows.PropertyPathConverter") {
482-
AnalyzePropertyPath(rec.Value);
482+
AnalyzePropertyPath(rec.Value, s => rec.Value = s);
483483
}
484484
else if (converter.FullName == "System.Windows.Markup.RoutedEventConverter") {
485485
;
@@ -501,7 +501,7 @@ void ProcessConverter(PropertyWithConverterRecord rec, TypeDef type) {
501501
attrName = attrInfo.Item2.Name;
502502

503503
if (attrName == "DisplayMemberPath") {
504-
AnalyzePropertyPath(rec.Value);
504+
AnalyzePropertyPath(rec.Value, s => rec.Value = s);
505505
}
506506
else if (attrName == "Source") {
507507
string declType = null;
@@ -581,52 +581,59 @@ Tuple<IDnlibDef, AttributeInfoRecord, TypeDef> AnalyzeAttributeReference(TypeDef
581581
return Tuple.Create(retDef, rec, retType == null ? null : retType.ResolveTypeDefThrow());
582582
}
583583

584-
void AnalyzePropertyPath(string path) {
585-
var parsedPath = PathParser.Parse(path);
586-
foreach (var part in parsedPath) {
587-
switch (part.type) {
584+
void AnalyzePropertyPath(string path, Action<string> updateAction) {
585+
var pathUpdater = new PropertyPathUpdater(path, updateAction);
586+
foreach (var part in pathUpdater) {
587+
switch (part.Type) {
588588
case SourceValueType.Property:
589-
// This is a property reference. This may be directly the name of a property or a reference by
590-
// with the type to the property
591-
// Simple Property: "TestProperty"
592-
// Property with Type: "(local:DataClass.TestProperty)"
593-
594-
var typeName = part.GetTypeName();
595-
var propertyName = part.GetPropertyName();
596-
if (!string.IsNullOrWhiteSpace(typeName)) {
597-
var sig = ResolveType(typeName, out var prefix);
598-
if (sig != null && context.Modules.Contains((ModuleDefMD)sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module)) {
599-
var reference = new BAMLPathTypeReference(xmlnsCtx, sig, part);
600-
AddTypeSigReference(sig, reference);
601-
break;
602-
}
603-
}
604-
605-
// Reaching this point means that the type reference was either not present or failed to
606-
// resolve. In this case every property with the matching name will be flagged so it does not
607-
// get renamed.
608-
if (properties.TryGetValue(propertyName, out var candidates))
609-
foreach (var property in candidates)
610-
service.SetCanRename(property, false);
611-
589+
AnalyzePropertyPathProperty(part);
612590
break;
613591
case SourceValueType.Indexer:
614592
// This is the indexer part of a property reference.
615-
foreach (var indexerArg in part.paramList) {
616-
if (!string.IsNullOrWhiteSpace(indexerArg.parenString)) {
617-
var sig = ResolveType(indexerArg.parenString, out var prefix);
618-
if (sig != null && context.Modules.Contains((ModuleDefMD)sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module)) {
619-
var reference = new BAMLPathTypeReference(xmlnsCtx, sig, part);
620-
AddTypeSigReference(sig, reference);
621-
break;
622-
}
623-
}
624-
}
593+
AnalyzePropertyPathIndexer(part);
625594
break;
626595
}
627596
}
628597
}
629598

599+
void AnalyzePropertyPathProperty(PropertyPathPartUpdater part) {
600+
// This is a property reference. This may be directly the name of a property or a reference by
601+
// with the type to the property
602+
// Simple Property: "TestProperty"
603+
// Property with Type: "(local:DataClass.TestProperty)"
604+
605+
var typeName = part.GetTypeName();
606+
var propertyName = part.GetPropertyName();
607+
if (!string.IsNullOrWhiteSpace(typeName)) {
608+
var sig = ResolveType(typeName, out var prefix);
609+
if (sig != null && context.Modules.Contains((ModuleDefMD) sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module)) {
610+
var reference = new BAMLPathTypeReference(xmlnsCtx, sig, part);
611+
AddTypeSigReference(sig, reference);
612+
return;
613+
}
614+
}
615+
616+
// Reaching this point means that the type reference was either not present or failed to
617+
// resolve. In this case every property with the matching name will be flagged so it does not
618+
// get renamed.
619+
if (properties.TryGetValue(propertyName, out var candidates))
620+
foreach (var property in candidates)
621+
service.SetCanRename(property, false);
622+
}
623+
624+
void AnalyzePropertyPathIndexer(PropertyPathPartUpdater part) {
625+
foreach (var indexerArg in part.ParamList) {
626+
if (!string.IsNullOrWhiteSpace(indexerArg.ParenString)) {
627+
var sig = ResolveType(indexerArg.ParenString, out var prefix);
628+
if (sig != null && context.Modules.Contains((ModuleDefMD) sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module)) {
629+
var reference = new BAMLPathTypeReference(xmlnsCtx, sig, indexerArg);
630+
AddTypeSigReference(sig, reference);
631+
break;
632+
}
633+
}
634+
}
635+
}
636+
630637
class DummyAssemblyRefFinder : IAssemblyRefFinder {
631638
readonly AssemblyDef assemblyDef;
632639

Confuser.Renamer/BAML/PropertyPathExtensions.cs

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
3+
namespace Confuser.Renamer.BAML {
4+
internal struct PropertyPathIndexUpdater {
5+
PropertyPathUpdater Parent { get; }
6+
int PathIndex { get; }
7+
int IndexerIndex { get; }
8+
IndexerParamInfo IndexInfo => Parent.PropertyPath[PathIndex].paramList[IndexerIndex];
9+
10+
internal string ParenString {
11+
get => IndexInfo.parenString;
12+
set => Parent.UpdateParenString(PathIndex, IndexerIndex, value);
13+
}
14+
15+
internal PropertyPathIndexUpdater(PropertyPathUpdater parent, int pathIndex, int indexerIndex) {
16+
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
17+
PathIndex = pathIndex;
18+
IndexerIndex = indexerIndex;
19+
}
20+
}
21+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace Confuser.Renamer.BAML {
6+
internal struct PropertyPathPartUpdater {
7+
PropertyPathUpdater Parent { get; }
8+
int PathIndex { get; }
9+
SourceValueInfo PathInfo => Parent.PropertyPath[PathIndex];
10+
11+
internal IEnumerable<PropertyPathIndexUpdater> ParamList {
12+
get {
13+
var parent = Parent;
14+
var pathIndex = PathIndex;
15+
return Enumerable.Range(0, PathInfo.paramList.Count).Select(i => new PropertyPathIndexUpdater(parent, pathIndex, i));
16+
}
17+
}
18+
19+
internal SourceValueType Type => PathInfo.type;
20+
21+
internal string Name {
22+
get => PathInfo.name;
23+
set => Parent.Update(PathIndex, value);
24+
}
25+
26+
internal PropertyPathPartUpdater(PropertyPathUpdater parent, int pathIndex) {
27+
Parent = parent ?? throw new ArgumentNullException(nameof(parent));
28+
PathIndex = pathIndex;
29+
}
30+
31+
internal string GetTypeName() {
32+
var propertyName = PathInfo.name?.Trim();
33+
if (propertyName != null && propertyName.StartsWith("(") && propertyName.EndsWith(")")) {
34+
var indexOfDot = propertyName.LastIndexOf('.');
35+
if (indexOfDot < 0) return null;
36+
return propertyName.Substring(1, indexOfDot - 1);
37+
}
38+
return null;
39+
}
40+
41+
internal string GetPropertyName() {
42+
switch (PathInfo.type) {
43+
case SourceValueType.Direct:
44+
return null;
45+
case SourceValueType.Property:
46+
var propertyName = PathInfo.name?.Trim();
47+
if (propertyName != null && propertyName.StartsWith("(") && propertyName.EndsWith(")")) {
48+
var indexOfDot = propertyName.LastIndexOf('.');
49+
if (indexOfDot < 0) return propertyName.Substring(1, propertyName.Length - 2);
50+
return propertyName.Substring(indexOfDot + 1, propertyName.Length - indexOfDot - 2);
51+
}
52+
return propertyName;
53+
case SourceValueType.Indexer:
54+
return "Item";
55+
default:
56+
throw new InvalidOperationException("Unexpected SourceValueType.");
57+
}
58+
}
59+
}
60+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
7+
namespace Confuser.Renamer.BAML {
8+
/// <summary>
9+
/// This class is used to update parts of an property path based on the references.
10+
/// </summary>
11+
internal sealed class PropertyPathUpdater : IEnumerable<PropertyPathPartUpdater> {
12+
internal SourceValueInfo[] PropertyPath { get; }
13+
Action<string> UpdateAction { get; }
14+
15+
internal PropertyPathUpdater(string path, Action<string> updateAction) {
16+
UpdateAction = updateAction ?? throw new ArgumentNullException(nameof(updateAction));
17+
var pathParser = new PropertyPathParser();
18+
PropertyPath = pathParser.Parse(path);
19+
}
20+
21+
internal void Update(int index, string value) {
22+
PropertyPath[index].name = value;
23+
RebuildAndUpdatePath();
24+
}
25+
26+
public void UpdateParenString(int pathIndex, int indexerIndex, string value) {
27+
var originalParams = PropertyPath[pathIndex].paramList;
28+
var newIndexParams = originalParams.ToArray();
29+
newIndexParams[indexerIndex].parenString = value;
30+
PropertyPath[pathIndex].paramList = newIndexParams;
31+
RebuildAndUpdatePath();
32+
}
33+
34+
private void RebuildAndUpdatePath() {
35+
var builder = new StringBuilder();
36+
foreach (var sourceValueInfo in PropertyPath) {
37+
if (builder.Length > 0) builder.Append('.');
38+
builder.Append(sourceValueInfo.name);
39+
if (sourceValueInfo.paramList?.Count > 0) {
40+
builder.Append('[');
41+
builder.Append(sourceValueInfo.paramList[0].parenString);
42+
builder.Append(sourceValueInfo.paramList[0].valueString);
43+
for (int i = 1; i < sourceValueInfo.paramList.Count; i++) {
44+
builder.Append(',');
45+
builder.Append(sourceValueInfo.paramList[i].parenString);
46+
builder.Append(sourceValueInfo.paramList[i].valueString);
47+
}
48+
builder.Append(']');
49+
}
50+
}
51+
52+
UpdateAction.Invoke(builder.ToString());
53+
}
54+
55+
/// <inheritdoc />
56+
public IEnumerator<PropertyPathPartUpdater> GetEnumerator() =>
57+
Enumerable.Range(0, PropertyPath.Length).Select(i => new PropertyPathPartUpdater(this, i)).GetEnumerator();
58+
59+
/// <inheritdoc />
60+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
61+
}
62+
}

Confuser.Renamer/References/BAMLPathTypeReference.cs

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,46 @@
11
using System;
2+
using System.Diagnostics;
23
using System.Globalization;
34
using Confuser.Core;
45
using Confuser.Renamer.BAML;
56
using dnlib.DotNet;
67

78
namespace Confuser.Renamer.References {
89
internal class BAMLPathTypeReference : INameReference<TypeDef> {
9-
private SourceValueInfo? propertyInfo;
10-
private IndexerParamInfo? indexerInfo;
10+
PropertyPathPartUpdater? PropertyInfo { get; }
11+
PropertyPathIndexUpdater? IndexerInfo { get; }
1112
private readonly TypeSig sig;
1213
private readonly BAMLAnalyzer.XmlNsContext xmlnsCtx;
1314

1415
private BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig) {
15-
if (xmlnsCtx == null) throw new ArgumentNullException(nameof(xmlnsCtx));
16-
if (sig == null) throw new ArgumentNullException(nameof(sig));
17-
18-
this.xmlnsCtx = xmlnsCtx;
19-
this.sig = sig;
16+
this.xmlnsCtx = xmlnsCtx ?? throw new ArgumentNullException(nameof(xmlnsCtx));
17+
this.sig = sig ?? throw new ArgumentNullException(nameof(sig));
2018
}
2119

22-
public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, IndexerParamInfo indexerInfo) : this(xmlnsCtx, sig) =>
23-
this.indexerInfo = indexerInfo;
20+
public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, PropertyPathIndexUpdater indexerInfo) : this(xmlnsCtx, sig) =>
21+
IndexerInfo = indexerInfo;
2422

25-
public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, SourceValueInfo propertyInfo) : this(xmlnsCtx, sig) =>
26-
this.propertyInfo = propertyInfo;
23+
public BAMLPathTypeReference(BAMLAnalyzer.XmlNsContext xmlnsCtx, TypeSig sig, PropertyPathPartUpdater propertyInfo) : this(xmlnsCtx, sig) =>
24+
PropertyInfo = propertyInfo;
2725

2826
public bool UpdateNameReference(ConfuserContext context, INameService service) {
2927
string name = sig.ReflectionName;
3028
string prefix = xmlnsCtx.GetPrefix(sig.ReflectionNamespace, sig.ToBasicTypeDefOrRef().ResolveTypeDefThrow().Module.Assembly);
3129
if (!string.IsNullOrEmpty(prefix))
3230
name = prefix + ":" + name;
3331

34-
if (indexerInfo != null) {
35-
var info = indexerInfo.Value;
36-
if (string.Equals(info.parenString, name, StringComparison.Ordinal)) return false;
37-
info.parenString = name;
38-
indexerInfo = info;
32+
if (IndexerInfo != null) {
33+
var info = IndexerInfo.Value;
34+
if (string.Equals(info.ParenString, name, StringComparison.Ordinal)) return false;
35+
info.ParenString = name;
3936
}
4037
else {
41-
var info = propertyInfo.Value;
38+
Debug.Assert(PropertyInfo != null, nameof(PropertyInfo) + " != null");
39+
var info = PropertyInfo.Value;
4240
var propertyName = info.GetPropertyName();
4341
var newName = string.Format(CultureInfo.InvariantCulture, "({0}.{1})", name, propertyName);
44-
if (string.Equals(info.name, newName, StringComparison.Ordinal)) return false;
45-
info.name = newName;
46-
propertyInfo = info;
42+
if (string.Equals(info.Name, newName, StringComparison.Ordinal)) return false;
43+
info.Name = newName;
4744
}
4845
return true;
4946
}

Tests/WpfRenaming/UserControl1Context.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System.Threading.Tasks;
66

77
namespace WpfRenaming {
8-
public class UserControl1Context {
8+
internal class UserControl1Context {
99
public string TestProperty => "This is from a property!";
1010

1111
public string[] TestListProperty => new string[] { "Index 1", "Index 2" };

0 commit comments

Comments
 (0)