Browse Source

Fix hyperlinks in decompiled output.

pull/832/head
Siegfried Pammer 8 years ago
parent
commit
7bf0ed79d4
  1. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 79
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  4. 9
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  5. 1
      ILSpy/ILSpy.csproj
  6. 13
      ILSpy/Languages/CSharpLanguage.cs

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -137,6 +137,8 @@ namespace ICSharpCode.Decompiler.CSharp
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
public IDecompilerTypeSystem TypeSystem => typeSystem;
/// <summary> /// <summary>
/// IL transforms. /// IL transforms.
/// </summary> /// </summary>

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -291,6 +291,7 @@
<Compile Include="IL\Transforms\AssignVariableNames.cs" /> <Compile Include="IL\Transforms\AssignVariableNames.cs" />
<Compile Include="IL\Transforms\NullCoalescingTransform.cs" /> <Compile Include="IL\Transforms\NullCoalescingTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" /> <Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="Util\UnicodeNewline.cs" /> <Compile Include="Util\UnicodeNewline.cs" />
<Compile Include="FlowAnalysis\ControlFlowNode.cs" /> <Compile Include="FlowAnalysis\ControlFlowNode.cs" />
<Compile Include="FlowAnalysis\DataFlowVisitor.cs" /> <Compile Include="FlowAnalysis\DataFlowVisitor.cs" />

79
ILSpy/Languages/TextTokenWriter.cs → ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -24,14 +24,16 @@ using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.ILSpy namespace ICSharpCode.Decompiler
{ {
public class TextTokenWriter : TokenWriter public class TextTokenWriter : TokenWriter
{ {
readonly ITextOutput output; readonly ITextOutput output;
readonly DecompilerSettings settings; readonly DecompilerSettings settings;
readonly IDecompilerTypeSystem typeSystem;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>(); readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
int braceLevelWithinType = -1; int braceLevelWithinType = -1;
bool inDocumentationComment = false; bool inDocumentationComment = false;
@ -42,14 +44,17 @@ namespace ICSharpCode.ILSpy
public bool FoldBraces = false; public bool FoldBraces = false;
public TextTokenWriter(ITextOutput output, DecompilerSettings settings) public TextTokenWriter(ITextOutput output, DecompilerSettings settings, IDecompilerTypeSystem typeSystem)
{ {
if (output == null) if (output == null)
throw new ArgumentNullException(nameof(output)); throw new ArgumentNullException(nameof(output));
if (settings == null) if (settings == null)
throw new ArgumentNullException(nameof(settings)); throw new ArgumentNullException(nameof(settings));
if (typeSystem == null)
throw new ArgumentNullException(nameof(typeSystem));
this.output = output; this.output = output;
this.settings = settings; this.settings = settings;
this.typeSystem = typeSystem;
} }
public override void WriteIdentifier(Identifier identifier) public override void WriteIdentifier(Identifier identifier)
@ -64,11 +69,21 @@ namespace ICSharpCode.ILSpy
return; return;
} }
object memberRef = GetCurrentMemberReference(); var member = GetCurrentMemberReference();
if (memberRef != null) { if (member != null) {
output.WriteReference(identifier.Name, memberRef); MemberReference cecil;
return; if (member is IType type) {
cecil = typeSystem.GetCecil(type.GetDefinition());
} else if (member is IMember) {
cecil = typeSystem.GetCecil((IMember)member);
} else {
cecil = null;
}
if (cecil != null) {
output.WriteReference(identifier.Name, cecil);
return;
}
} }
definition = GetCurrentLocalDefinition(); definition = GetCurrentLocalDefinition();
@ -77,7 +92,7 @@ namespace ICSharpCode.ILSpy
return; return;
} }
memberRef = GetCurrentLocalReference(); var memberRef = GetCurrentLocalReference();
if (memberRef != null) { if (memberRef != null) {
output.WriteReference(identifier.Name, memberRef, true); output.WriteReference(identifier.Name, memberRef, true);
return; return;
@ -91,32 +106,32 @@ namespace ICSharpCode.ILSpy
output.Write(identifier.Name); output.Write(identifier.Name);
} }
MemberReference GetCurrentMemberReference() ISymbol GetCurrentMemberReference()
{ {
AstNode node = nodeStack.Peek(); AstNode node = nodeStack.Peek();
MemberReference memberRef = node.Annotation<MemberReference>(); var symbol = node.GetSymbol();
if (memberRef == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) { if (symbol == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) {
memberRef = node.Parent.Annotation<MemberReference>(); symbol = node.Parent.GetSymbol();
} }
if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && memberRef != null) { if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) {
var declaringType = memberRef.DeclaringType.Resolve(); var declaringType = member.DeclaringType;
if (declaringType != null && declaringType.IsDelegate()) if (declaringType != null && declaringType.Kind == TypeKind.Delegate)
return null; return null;
} }
return FilterMemberReference(memberRef); return FilterMember(symbol);
} }
MemberReference FilterMemberReference(MemberReference memberRef) ISymbol FilterMember(ISymbol symbol)
{ {
if (memberRef == null) if (symbol == null)
return null; return null;
if (settings.AutomaticEvents && memberRef is FieldDefinition) { //if (settings.AutomaticEvents && member is FieldDefinition) {
var field = (FieldDefinition)memberRef; // var field = (FieldDefinition)member;
return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? memberRef; // return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? member;
} //}
return memberRef; return symbol;
} }
object GetCurrentLocalReference() object GetCurrentLocalReference()
@ -129,9 +144,9 @@ namespace ICSharpCode.ILSpy
var gotoStatement = node as GotoStatement; var gotoStatement = node as GotoStatement;
if (gotoStatement != null) if (gotoStatement != null)
{ {
var method = nodeStack.Select(nd => nd.Annotation<MethodReference>()).FirstOrDefault(mr => mr != null); var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).FirstOrDefault(mr => mr != null);
if (method != null) if (method != null)
return method.ToString() + gotoStatement.Label; return method + gotoStatement.Label;
} }
return null; return null;
@ -151,9 +166,9 @@ namespace ICSharpCode.ILSpy
var label = node as LabelStatement; var label = node as LabelStatement;
if (label != null) { if (label != null) {
var method = nodeStack.Select(nd => nd.Annotation<MethodReference>()).FirstOrDefault(mr => mr != null); var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).FirstOrDefault(mr => mr != null);
if (method != null) if (method != null)
return method.ToString() + label.Label; return method + label.Label;
} }
return null; return null;
@ -168,7 +183,7 @@ namespace ICSharpCode.ILSpy
if (node is Identifier) if (node is Identifier)
node = node.Parent; node = node.Parent;
if (IsDefinition(node)) if (IsDefinition(node))
return node.Annotation<MemberReference>(); return node.GetSymbol();
return null; return null;
} }
@ -181,10 +196,10 @@ namespace ICSharpCode.ILSpy
public override void WriteToken(Role role, string token) public override void WriteToken(Role role, string token)
{ {
// Attach member reference to token only if there's no identifier in the current node. // Attach member reference to token only if there's no identifier in the current node.
MemberReference memberRef = GetCurrentMemberReference(); var member = GetCurrentMemberReference();
var node = nodeStack.Peek(); var node = nodeStack.Peek();
if (memberRef != null && node.GetChildByRole(Roles.Identifier).IsNull) if (member != null && node.GetChildByRole(Roles.Identifier).IsNull)
output.WriteReference(token, memberRef); output.WriteReference(token, member);
else else
output.Write(token); output.Write(token);
} }
@ -310,8 +325,8 @@ namespace ICSharpCode.ILSpy
nodeStack.Push(node); nodeStack.Push(node);
// startLocations.Push(output.Location); // startLocations.Push(output.Location);
if (node is EntityDeclaration && node.Annotation<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull) // if (node is EntityDeclaration && node.GetSymbol() != null && node.GetChildByRole(Roles.Identifier).IsNull)
output.WriteDefinition("", node.Annotation<MemberReference>(), false); // output.WriteDefinition("", node.GetSymbol(), false);
// if (node.Annotation<MethodDebugSymbols>() != null) { // if (node.Annotation<MethodDebugSymbols>() != null) {
// symbolsStack.Push(node.Annotation<MethodDebugSymbols>()); // symbolsStack.Push(node.Annotation<MethodDebugSymbols>());

9
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly CecilLoader typeReferenceCecilLoader = new CecilLoader(); readonly CecilLoader typeReferenceCecilLoader = new CecilLoader();
/// <summary> /// <summary>
/// Dictionary for NRefactory->Cecil lookup. Only contains entities from the main module. /// Dictionary for NRefactory->Cecil lookup.
/// May only be accessed within lock(entityDict) /// May only be accessed within lock(entityDict)
/// </summary> /// </summary>
Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>(); Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>();
@ -41,15 +41,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (moduleDefinition == null) if (moduleDefinition == null)
throw new ArgumentNullException(nameof(moduleDefinition)); throw new ArgumentNullException(nameof(moduleDefinition));
this.moduleDefinition = moduleDefinition; this.moduleDefinition = moduleDefinition;
CecilLoader mainAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false }; CecilLoader cecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false };
CecilLoader referencedAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, ShortenInterfaceImplNames = false };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); typeReferenceCecilLoader.SetCurrentModule(moduleDefinition);
IUnresolvedAssembly mainAssembly = mainAssemblyCecilLoader.LoadModule(moduleDefinition); IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition);
var referencedAssemblies = new List<IUnresolvedAssembly>(); var referencedAssemblies = new List<IUnresolvedAssembly>();
foreach (var asmRef in moduleDefinition.AssemblyReferences) { foreach (var asmRef in moduleDefinition.AssemblyReferences) {
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef); var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null) if (asm != null)
referencedAssemblies.Add(referencedAssemblyCecilLoader.LoadAssembly(asm)); referencedAssemblies.Add(cecilLoader.LoadAssembly(asm));
} }
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
context = new SimpleTypeResolveContext(compilation.MainAssembly); context = new SimpleTypeResolveContext(compilation.MainAssembly);

1
ILSpy/ILSpy.csproj

@ -173,7 +173,6 @@
<Compile Include="Languages\IResourceFileHandler.cs" /> <Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" /> <Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" /> <Compile Include="Languages\Languages.cs" />
<Compile Include="Languages\TextTokenWriter.cs" />
<Compile Include="LoadedAssembly.cs" /> <Compile Include="LoadedAssembly.cs" />
<Compile Include="NativeMethods.cs" /> <Compile Include="NativeMethods.cs" />
<Compile Include="NavigationHistory.cs" /> <Compile Include="NavigationHistory.cs" />

13
ILSpy/Languages/CSharpLanguage.cs

@ -30,6 +30,7 @@ using Mono.Cecil;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -93,10 +94,10 @@ namespace ICSharpCode.ILSpy
return decompiler; return decompiler;
} }
void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree) void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{ {
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
var outputFormatter = new TextTokenWriter(output, settings) { FoldBraces = settings.FoldBraces }; var outputFormatter = new TextTokenWriter(output, settings, typeSystem) { FoldBraces = settings.FoldBraces };
var formattingPolicy = settings.CSharpFormattingOptions; var formattingPolicy = settings.CSharpFormattingOptions;
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy)); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
} }
@ -105,7 +106,7 @@ namespace ICSharpCode.ILSpy
{ {
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(method.Module, options); CSharpDecompiler decompiler = CreateDecompiler(method.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method)); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method), decompiler.TypeSystem);
/* /*
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true); AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true);
if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) { if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) {
@ -160,7 +161,7 @@ namespace ICSharpCode.ILSpy
{ {
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true)); WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(property.Module, options); CSharpDecompiler decompiler = CreateDecompiler(property.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property)); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property), decompiler.TypeSystem);
} }
/* /*
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
@ -215,14 +216,14 @@ namespace ICSharpCode.ILSpy
{ {
WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true)); WriteCommentLine(output, TypeToString(ev.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(ev.Module, options); CSharpDecompiler decompiler = CreateDecompiler(ev.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(ev)); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(ev), decompiler.TypeSystem);
} }
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, TypeToString(type, includeNamespace: true)); WriteCommentLine(output, TypeToString(type, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(type.Module, options); CSharpDecompiler decompiler = CreateDecompiler(type.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type)); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type), decompiler.TypeSystem);
} }
/* /*

Loading…
Cancel
Save