cli/src/Colorizer.cs
+112
-0
diff --git a/cli/src/Colorizer.cs b/cli/src/Colorizer.cs
new file mode 100644
index 0000000..e766f41
@@ -0,0 +1,112 @@
using System.Collections.Generic;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Cfa.Cli;
class Colorizer() : CSharpSyntaxWalker(SyntaxWalkerDepth.Token)
{
public static string ColorMember(ISymbol member)
{
if (member.ToString() is not string text)
{
return "";
}
var tree = CSharpSyntaxTree.ParseText(text);
var root = tree.GetCompilationUnitRoot();
var colorVisitor = new Colorizer();
root.Accept(colorVisitor);
return colorVisitor.ToString();
}
private StringBuilder sb = new();
private int accesses = 0;
private Stack<int> generics = [];
private IdentifierKind identifierKind = IdentifierKind.Top;
public override void VisitTypeArgumentList(TypeArgumentListSyntax node)
{
generics.Push(accesses);
accesses = 0;
var previousIdentifierKind = identifierKind;
identifierKind = IdentifierKind.TypeParameter;
base.VisitTypeArgumentList(node);
identifierKind = previousIdentifierKind;
accesses = generics.Pop();
}
public override void VisitArgumentList(ArgumentListSyntax node)
{
var previousIdentifierKind = identifierKind;
identifierKind = IdentifierKind.Parameter;
base.VisitArgumentList(node);
identifierKind = previousIdentifierKind;
}
public override void VisitMemberAccessExpression(MemberAccessExpressionSyntax node)
{
accesses++;
base.VisitMemberAccessExpression(node);
accesses--;
}
public override void VisitQualifiedName(QualifiedNameSyntax node)
{
accesses++;
base.VisitQualifiedName(node);
accesses--;
}
public override void VisitToken(SyntaxToken token)
{
switch (token.Kind())
{
case (SyntaxKind.DotToken) when identifierKind is not IdentifierKind.Top:
break;
case (SyntaxKind.LessThanToken or SyntaxKind.GreaterThanToken):
sb.Append($"\e[38;2;218;112;214m{token}\e[0m");
break;
case (SyntaxKind.OpenParenToken or SyntaxKind.CloseParenToken):
sb.Append($"\e[38;2;255;215;0m{token}\e[0m");
break;
case (SyntaxKind.IdentifierToken):
switch (identifierKind)
{
case (IdentifierKind.Top) when accesses <= 1:
sb.Append($"\e[38;2;210;168;255m{token}\e[0m");
break;
case (IdentifierKind.Top):
sb.Append($"\e[38;2;78;201;176m{token}\e[0m");
break;
case (IdentifierKind.Parameter) when accesses <= 1:
sb.Append($"\e[38;2;156;220;254m{token}\e[0m");
break;
case (IdentifierKind.TypeParameter) when accesses <= 1:
sb.Append($"\e[38;2;86;156;214m{token}\e[0m");
break;
}
break;
case SyntaxKind.CommaToken:
sb.Append(", ");
break;
case var k when (int)k is >= 8304 and <= 8319:
sb.Append($"\e[38;2;255;123;114m{token}\e[0m");
break;
default:
sb.Append(token);
break;
}
}
public override string ToString() => sb.ToString();
enum IdentifierKind
{
Top,
Parameter,
TypeParameter,
}
}
cli/src/ScanCommand.cs
+1
-1
diff --git a/cli/src/ScanCommand.cs b/cli/src/ScanCommand.cs
index e118777..5348f8c 100644
@@ -288,7 +288,7 @@ internal sealed class ScanCommand : Command
var column = start.Character + 1;
Console.Write($"\e]8;;file://{path}#{line}:{column}\e\\");
}
Console.Write(origin);
Console.Write(Colorizer.ColorMember(origin));
if (syntaxTree is not null)
{
Console.Write("\e]8;;\e\\");
core/src/packages.lock.json
+1
-2
diff --git a/core/src/packages.lock.json b/core/src/packages.lock.json
index 9a449f8..49304cf 100644
@@ -213,7 +213,6 @@
"System.Composition.Runtime": "10.0.1"
}
}
},
"net11.0/linux-x64": {}
}
}
}
\ No newline at end of file