Browse Source

Improve tooltips and highlighting of local functions

pull/2077/head
Siegfried Pammer 5 years ago
parent
commit
67b2a45292
  1. 3
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  2. 63
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  3. 3
      ILSpy/Languages/CSharpLanguage.cs

3
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -24,6 +24,7 @@ using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{ {
@ -103,7 +104,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (symbol is ITypeDefinition) if (symbol is ITypeDefinition)
WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy); WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy);
else if (symbol is IMember) else if (symbol is IMember && !(symbol is LocalFunctionMethod))
WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy); WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy);
else else
writer.WriteIdentifier(Identifier.Create(symbol.Name)); writer.WriteIdentifier(Identifier.Create(symbol.Name));

63
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Resolver;
@ -26,6 +27,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
@ -39,7 +41,7 @@ namespace ICSharpCode.Decompiler
bool inDocumentationComment = false; bool inDocumentationComment = false;
bool firstUsingDeclaration; bool firstUsingDeclaration;
bool lastUsingDeclaration; bool lastUsingDeclaration;
public TextTokenWriter(ITextOutput output, DecompilerSettings settings, IDecompilerTypeSystem typeSystem) public TextTokenWriter(ITextOutput output, DecompilerSettings settings, IDecompilerTypeSystem typeSystem)
{ {
if (output == null) if (output == null)
@ -52,13 +54,13 @@ namespace ICSharpCode.Decompiler
this.settings = settings; this.settings = settings;
this.typeSystem = typeSystem; this.typeSystem = typeSystem;
} }
public override void WriteIdentifier(Identifier identifier) public override void WriteIdentifier(Identifier identifier)
{ {
if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) {
output.Write('@'); output.Write('@');
} }
var definition = GetCurrentDefinition(); var definition = GetCurrentDefinition();
string name = TextWriterTokenWriter.EscapeIdentifier(identifier.Name); string name = TextWriterTokenWriter.EscapeIdentifier(identifier.Name);
switch (definition) { switch (definition) {
@ -69,7 +71,7 @@ namespace ICSharpCode.Decompiler
output.WriteReference(m, name, true); output.WriteReference(m, name, true);
return; return;
} }
var member = GetCurrentMemberReference(); var member = GetCurrentMemberReference();
switch (member) { switch (member) {
case IType t: case IType t:
@ -110,6 +112,7 @@ namespace ICSharpCode.Decompiler
if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) { if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) {
symbol = node.Parent.GetSymbol(); symbol = node.Parent.GetSymbol();
} }
if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) {
var declaringType = member.DeclaringType; var declaringType = member.DeclaringType;
if (declaringType != null && declaringType.Kind == TypeKind.Delegate) if (declaringType != null && declaringType.Kind == TypeKind.Delegate)
@ -123,10 +126,8 @@ namespace ICSharpCode.Decompiler
if (symbol == null) if (symbol == null)
return null; return null;
//if (settings.AutomaticEvents && member is FieldDefinition) { if (symbol is LocalFunctionMethod)
// var field = (FieldDefinition)member; return null;
// return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? member;
//}
return symbol; return symbol;
} }
@ -142,14 +143,18 @@ namespace ICSharpCode.Decompiler
if (letClauseVariable != null) if (letClauseVariable != null)
return letClauseVariable; return letClauseVariable;
var gotoStatement = node as GotoStatement; if (node is GotoStatement gotoStatement) {
if (gotoStatement != null)
{
var method = nodeStack.Select(nd => nd.GetSymbol() as IMethod).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 + gotoStatement.Label; return method + gotoStatement.Label;
} }
if (node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) {
var symbol = node.Parent.GetSymbol();
if (symbol is LocalFunctionMethod)
return symbol;
}
return null; return null;
} }
@ -177,29 +182,29 @@ namespace ICSharpCode.Decompiler
return method + label.Label; return method + label.Label;
} }
if (node is LocalFunctionDeclarationStatement) { if (node is MethodDeclaration && node.Parent is LocalFunctionDeclarationStatement) {
var localFunction = node.GetResolveResult() as MemberResolveResult; var localFunction = node.Parent.GetResolveResult() as MemberResolveResult;
if (localFunction != null) if (localFunction != null)
return localFunction.Member; return localFunction.Member;
} }
return null; return null;
} }
ISymbol GetCurrentDefinition() ISymbol GetCurrentDefinition()
{ {
if (nodeStack == null || nodeStack.Count == 0) if (nodeStack == null || nodeStack.Count == 0)
return null; return null;
var node = nodeStack.Peek(); var node = nodeStack.Peek();
if (node is Identifier) if (node is Identifier)
node = node.Parent; node = node.Parent;
if (IsDefinition(ref node)) if (IsDefinition(ref node))
return node.GetSymbol(); return node.GetSymbol();
return null; return null;
} }
public override void WriteKeyword(Role role, string keyword) public override void WriteKeyword(Role role, string keyword)
{ {
//To make reference for 'this' and 'base' keywords in the ClassName():this() expression //To make reference for 'this' and 'base' keywords in the ClassName():this() expression
@ -211,7 +216,7 @@ namespace ICSharpCode.Decompiler
} }
output.Write(keyword); output.Write(keyword);
} }
public override void WriteToken(Role role, string token) public override void WriteToken(Role role, string token)
{ {
switch (token) { switch (token) {
@ -253,22 +258,22 @@ namespace ICSharpCode.Decompiler
break; break;
} }
} }
public override void Space() public override void Space()
{ {
output.Write(' '); output.Write(' ');
} }
public override void Indent() public override void Indent()
{ {
output.Indent(); output.Indent();
} }
public override void Unindent() public override void Unindent()
{ {
output.Unindent(); output.Unindent();
} }
public override void NewLine() public override void NewLine()
{ {
if (!firstUsingDeclaration && lastUsingDeclaration) { if (!firstUsingDeclaration && lastUsingDeclaration) {
@ -277,7 +282,7 @@ namespace ICSharpCode.Decompiler
} }
output.WriteLine(); output.WriteLine();
} }
public override void WriteComment(CommentType commentType, string content) public override void WriteComment(CommentType commentType, string content)
{ {
switch (commentType) { switch (commentType) {
@ -309,7 +314,7 @@ namespace ICSharpCode.Decompiler
break; break;
} }
} }
public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument) public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument)
{ {
// pre-processor directive must start on its own line // pre-processor directive must start on its own line
@ -321,7 +326,7 @@ namespace ICSharpCode.Decompiler
} }
output.WriteLine(); output.WriteLine();
} }
public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None) public override void WritePrimitiveValue(object value, LiteralFormat format = LiteralFormat.None)
{ {
new TextWriterTokenWriter(new TextOutputWriter(output)).WritePrimitiveValue(value, format); new TextWriterTokenWriter(new TextOutputWriter(output)).WritePrimitiveValue(value, format);
@ -376,7 +381,7 @@ namespace ICSharpCode.Decompiler
break; break;
} }
} }
public override void StartNode(AstNode node) public override void StartNode(AstNode node)
{ {
if (nodeStack.Count == 0) { if (nodeStack.Count == 0) {
@ -390,7 +395,7 @@ namespace ICSharpCode.Decompiler
} }
nodeStack.Push(node); nodeStack.Push(node);
} }
private bool IsUsingDeclaration(AstNode node) private bool IsUsingDeclaration(AstNode node)
{ {
return node is UsingDeclaration || node is UsingAliasDeclaration; return node is UsingDeclaration || node is UsingAliasDeclaration;
@ -401,10 +406,10 @@ namespace ICSharpCode.Decompiler
if (nodeStack.Pop() != node) if (nodeStack.Pop() != node)
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
public static bool IsDefinition(ref AstNode node) public static bool IsDefinition(ref AstNode node)
{ {
if (node is EntityDeclaration) if (node is EntityDeclaration && !(node.Parent is LocalFunctionDeclarationStatement))
return true; return true;
if (node is VariableInitializer && node.Parent is FieldDeclaration) { if (node is VariableInitializer && node.Parent is FieldDeclaration) {
node = node.Parent; node = node.Parent;

3
ILSpy/Languages/CSharpLanguage.cs

@ -648,6 +648,9 @@ namespace ICSharpCode.ILSpy
if (!settings.LiftNullables) { if (!settings.LiftNullables) {
flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes; flags &= ~ConversionFlags.UseNullableSpecifierForValueTypes;
} }
if (entity is IMethod m && m.IsLocalFunction) {
writer.WriteIdentifier(Identifier.Create("(local)"));
}
new CSharpAmbience() { new CSharpAmbience() {
ConversionFlags = flags, ConversionFlags = flags,
}.ConvertSymbol(entity, writer, settings.CSharpFormattingOptions); }.ConvertSymbol(entity, writer, settings.CSharpFormattingOptions);

Loading…
Cancel
Save