Browse Source

Escape invalid identifiers when decompiling whole assembly as project.

pull/728/head
Daniel Grunwald 10 years ago
parent
commit
5b947aad2f
  1. 53
      ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs
  2. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 27
      ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
  4. 3
      ICSharpCode.Decompiler/Tests/Helpers/Tester.cs
  5. 3
      ILSpy/Languages/CSharpLanguage.cs

53
ICSharpCode.Decompiler/CSharp/Transforms/EscapeInvalidIdentifiers.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.Decompiler.CSharp.Transforms
{
/// <summary>
/// Escape invalid identifiers.
/// </summary>
/// <remarks>
/// This transform is not enabled by default.
/// </remarks>
public class EscapeInvalidIdentifiers : IAstTransform
{
bool IsValid(char ch)
{
if (char.IsLetterOrDigit(ch))
return true;
if (ch == '_')
return true;
return false;
}
string ReplaceInvalid(string s)
{
return string.Concat(s.Select(ch => IsValid(ch) ? ch.ToString() : string.Format("_{0:0000X}", (int)ch)));
}
public void Run(AstNode rootNode, TransformContext context)
{
foreach (var ident in rootNode.DescendantsAndSelf.OfType<Identifier>()) {
ident.Name = ReplaceInvalid(ident.Name);
}
}
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -63,6 +63,7 @@ @@ -63,6 +63,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CSharp\Annotations.cs" />
<Compile Include="CSharp\Transforms\EscapeInvalidIdentifiers.cs" />
<Compile Include="CSharp\Transforms\IntroduceUsingDeclarations.cs" />
<Compile Include="CSharp\Transforms\TransformContext.cs" />
<Compile Include="CSharp\TranslatedExpression.cs" />

27
ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs

@ -35,31 +35,4 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -35,31 +35,4 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
rootNode.AcceptVisitor(this, null);
}
}
class EscapeGeneratedIdentifiers : DepthFirstAstVisitor
{
bool IsValid(char ch)
{
if (char.IsLetterOrDigit(ch))
return true;
if (ch == '_')
return true;
return false;
}
string ReplaceInvalid(string s)
{
return string.Concat(s.Select(ch => IsValid(ch) ? ch.ToString() : string.Format("_{0:0000X}", (int)ch)));
}
public override void VisitIdentifier(Identifier identifier)
{
identifier.Name = ReplaceInvalid(identifier.Name);
}
public void Run(AstNode node)
{
node.AcceptVisitor(this);
}
}
}

3
ICSharpCode.Decompiler/Tests/Helpers/Tester.cs

@ -7,6 +7,7 @@ using System.Linq; @@ -7,6 +7,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.NRefactory.CSharp;
using Microsoft.CSharp;
using Mono.Cecil;
@ -67,8 +68,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -67,8 +68,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var typeSystem = new DecompilerTypeSystem(ModuleDefinition.ReadModule(assemblyFileName));
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem);
decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute());
decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());
var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile();
new Helpers.EscapeGeneratedIdentifiers().Run(syntaxTree);
StringWriter output = new StringWriter();
var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop());

3
ILSpy/Languages/CSharpLanguage.cs

@ -28,6 +28,7 @@ using System.Threading.Tasks; @@ -28,6 +28,7 @@ using System.Threading.Tasks;
using System.Xml;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.CSharp;
@ -479,6 +480,7 @@ namespace ICSharpCode.ILSpy @@ -479,6 +480,7 @@ namespace ICSharpCode.ILSpy
using (LoadedAssembly.DisableAssemblyLoad())
{
CSharpDecompiler decompiler = new CSharpDecompiler(ts);
decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());
SyntaxTree syntaxTree = decompiler.DecompileModuleAndAssemblyAttributes();
string prop = "Properties";
@ -513,6 +515,7 @@ namespace ICSharpCode.ILSpy @@ -513,6 +515,7 @@ namespace ICSharpCode.ILSpy
delegate(IGrouping<string, TypeDefinition> file) {
using (StreamWriter w = new StreamWriter(Path.Combine(options.SaveAsProjectDirectory, file.Key))) {
CSharpDecompiler decompiler = new CSharpDecompiler(ts);
decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers());
foreach (TypeDefinition type in file) {
var syntaxTree = decompiler.Decompile(type);
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, options.DecompilerSettings.CSharpFormattingOptions));

Loading…
Cancel
Save