Browse Source

Fully qualify ambiguous type names.

pull/124/head
Daniel Grunwald 14 years ago
parent
commit
6cb77e63e9
  1. 2
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 8
      ICSharpCode.Decompiler/Ast/DecompilerContext.cs
  3. 53
      ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
  4. 2
      ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
  5. 2
      ICSharpCode.Decompiler/Tests/TestRunner.cs
  6. 23
      ILSpy/CSharpLanguage.cs
  7. 2
      ILSpy/ILAstLanguage.cs

2
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.Ast
public class AstBuilder
{
DecompilerContext context = new DecompilerContext();
DecompilerContext context;
CompilationUnit astCompileUnit = new CompilationUnit();
Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
bool transformationsHaveRun;

8
ICSharpCode.Decompiler/Ast/DecompilerContext.cs

@ -10,11 +10,19 @@ namespace ICSharpCode.Decompiler @@ -10,11 +10,19 @@ namespace ICSharpCode.Decompiler
{
public class DecompilerContext
{
public ModuleDefinition CurrentModule;
public CancellationToken CancellationToken;
public TypeDefinition CurrentType;
public MethodDefinition CurrentMethod;
public DecompilerSettings Settings = new DecompilerSettings();
public DecompilerContext(ModuleDefinition currentModule)
{
if (currentModule == null)
throw new ArgumentNullException("currentModule");
this.CurrentModule = currentModule;
}
/// <summary>
/// Used to pass variable names from a method to its anonymous methods.
/// </summary>

53
ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs

@ -44,10 +44,22 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -44,10 +44,22 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, CompilationUnit.MemberRole);
}
// TODO: verify that the SimpleTypes refer to the correct type (no ambiguities)
FindAmbiguousTypeNames(context.CurrentModule, internalsVisible: true);
foreach (AssemblyNameReference r in context.CurrentModule.AssemblyReferences) {
AssemblyDefinition d = context.CurrentModule.AssemblyResolver.Resolve(r);
if (d != null)
FindAmbiguousTypeNames(d.MainModule, internalsVisible: false);
}
// verify that the SimpleTypes refer to the correct type (no ambiguities)
FullyQualifyAmbiguousTypeNames(compilationUnit);
}
readonly HashSet<string> declaredNamespaces = new HashSet<string>() { string.Empty };
readonly HashSet<string> importedNamespaces = new HashSet<string>();
readonly HashSet<string> availableTypeNames = new HashSet<string>();
readonly HashSet<string> ambiguousTypeNames = new HashSet<string>();
string currentNamespace;
bool IsParentOfCurrentNamespace(string ns)
@ -77,10 +89,49 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -77,10 +89,49 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
string oldNamespace = currentNamespace;
foreach (Identifier ident in namespaceDeclaration.Identifiers) {
currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name);
declaredNamespaces.Add(currentNamespace);
}
base.VisitNamespaceDeclaration(namespaceDeclaration, data);
currentNamespace = oldNamespace;
return null;
}
void FindAmbiguousTypeNames(ModuleDefinition module, bool internalsVisible)
{
foreach (TypeDefinition type in module.Types) {
if (internalsVisible || type.IsPublic) {
if (importedNamespaces.Contains(type.Namespace) || declaredNamespaces.Contains(type.Namespace)) {
if (!availableTypeNames.Add(type.Name))
ambiguousTypeNames.Add(type.Name);
}
}
}
}
void FullyQualifyAmbiguousTypeNames(AstNode compilationUnit)
{
foreach (SimpleType simpleType in compilationUnit.Descendants.OfType<SimpleType>()) {
TypeReference tr = simpleType.Annotation<TypeReference>();
if (tr != null && ambiguousTypeNames.Contains(tr.Name)) {
AstType ns;
if (string.IsNullOrEmpty(tr.Namespace)) {
ns = new SimpleType("global");
} else {
string[] parts = tr.Namespace.Split('.');
ns = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
ns = new MemberType { Target = ns, MemberName = parts[i] };
}
}
MemberType mt = new MemberType();
mt.Target = ns;
mt.IsDoubleColon = string.IsNullOrEmpty(tr.Namespace);
mt.MemberName = simpleType.Identifier;
mt.CopyAnnotationsFrom(simpleType);
simpleType.TypeArguments.MoveTo(mt.TypeArguments);
simpleType.ReplaceWith(mt);
}
}
}
}
}

2
ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.Tests
static string RoundtripCode(string code)
{
AssemblyDefinition assembly = Compile(code);
AstBuilder decompiler = new AstBuilder(new DecompilerContext());
AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
decompiler.AddAssembly(assembly);
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
StringWriter output = new StringWriter();

2
ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -98,7 +98,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -98,7 +98,7 @@ namespace ICSharpCode.Decompiler.Tests
{
string code = File.ReadAllText(fileName);
AssemblyDefinition assembly = Compile(code);
AstBuilder decompiler = new AstBuilder(new DecompilerContext());
AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
decompiler.AddAssembly(assembly);
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
StringWriter output = new StringWriter();

23
ILSpy/CSharpLanguage.cs

@ -51,8 +51,9 @@ namespace ICSharpCode.ILSpy @@ -51,8 +51,9 @@ namespace ICSharpCode.ILSpy
#if DEBUG
internal static IEnumerable<CSharpLanguage> GetDebugLanguages()
{
DecompilerContext context = new DecompilerContext(ModuleDefinition.CreateModule("dummy", ModuleKind.Dll));
string lastTransformName = "no transforms";
foreach (Type _transformType in TransformationPipeline.CreatePipeline(new DecompilerContext()).Select(v => v.GetType()).Distinct()) {
foreach (Type _transformType in TransformationPipeline.CreatePipeline(context).Select(v => v.GetType()).Distinct()) {
Type transformType = _transformType; // copy for lambda
yield return new CSharpLanguage {
transformAbortCondition = v => transformType.IsInstanceOfType(v),
@ -83,7 +84,7 @@ namespace ICSharpCode.ILSpy @@ -83,7 +84,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, method.DeclaringType);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType);
codeDomBuilder.AddMethod(method);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -92,7 +93,7 @@ namespace ICSharpCode.ILSpy @@ -92,7 +93,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, property.DeclaringType);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: property.DeclaringType);
codeDomBuilder.AddProperty(property);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -101,7 +102,7 @@ namespace ICSharpCode.ILSpy @@ -101,7 +102,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, field.DeclaringType);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: field.DeclaringType);
codeDomBuilder.AddField(field);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -110,7 +111,7 @@ namespace ICSharpCode.ILSpy @@ -110,7 +111,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, ev.DeclaringType);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: ev.DeclaringType);
codeDomBuilder.AddEvent(ev);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -118,7 +119,7 @@ namespace ICSharpCode.ILSpy @@ -118,7 +119,7 @@ namespace ICSharpCode.ILSpy
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = CreateAstBuilder(options, type);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
codeDomBuilder.AddType(type);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -133,7 +134,7 @@ namespace ICSharpCode.ILSpy @@ -133,7 +134,7 @@ namespace ICSharpCode.ILSpy
WriteProjectFile(new TextOutputWriter(output), files, assembly.MainModule);
} else {
base.DecompileAssembly(assembly, fileName, output, options);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: null);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.MainModule);
codeDomBuilder.AddAssembly(assembly, onlyAssemblyLevel: !options.FullDecompilation);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
@ -296,7 +297,7 @@ namespace ICSharpCode.ILSpy @@ -296,7 +297,7 @@ namespace ICSharpCode.ILSpy
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
delegate (IGrouping<string, TypeDefinition> file) {
using (StreamWriter w = new StreamWriter(Path.Combine(options.SaveAsProjectDirectory, file.Key))) {
AstBuilder codeDomBuilder = CreateAstBuilder(options, null);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: assembly.MainModule);
foreach (TypeDefinition type in file) {
codeDomBuilder.AddType(type);
}
@ -383,10 +384,12 @@ namespace ICSharpCode.ILSpy @@ -383,10 +384,12 @@ namespace ICSharpCode.ILSpy
}
#endregion
AstBuilder CreateAstBuilder(DecompilationOptions options, TypeDefinition currentType)
AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null)
{
if (currentModule == null)
currentModule = currentType.Module;
return new AstBuilder(
new DecompilerContext {
new DecompilerContext(currentModule) {
CancellationToken = options.CancellationToken,
CurrentType = currentType,
Settings = options.DecompilerSettings

2
ILSpy/ILAstLanguage.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy @@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy
ilMethod.Body = astBuilder.Build(method, inlineVariables);
if (abortBeforeStep != null) {
DecompilerContext context = new DecompilerContext { CurrentType = method.DeclaringType, CurrentMethod = method };
DecompilerContext context = new DecompilerContext(method.Module) { CurrentType = method.DeclaringType, CurrentMethod = method };
new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value);
}

Loading…
Cancel
Save