Spaces:
Sleeping
Sleeping
File size: 4,342 Bytes
1ae2e8e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace RobloxCS
{
public sealed class DebugTransformer : BaseTransformer
{
public DebugTransformer(SyntaxTree tree, ConfigData config)
: base(tree, config)
{
}
public override SyntaxNode? VisitInvocationExpression(InvocationExpressionSyntax node)
{
if (node.Expression is IdentifierNameSyntax || node.Expression is MemberAccessExpressionSyntax)
{
{
if (node.Expression is MemberAccessExpressionSyntax memberAccess)
{
if (Utility.GetNamesFromNode(memberAccess.Expression).LastOrDefault() != "Globals")
{
goto DoNothing;
}
}
}
{
var name = GetName(node.Expression is MemberAccessExpressionSyntax memberAccess ? memberAccess.Name : node.Expression);
HashSet<string> concatMethodNames = ["error"];
HashSet<string> extraArgNames = ["print", "warn"];
var newNode = node;
if (concatMethodNames.Contains(name))
{
newNode = ConcatenateFileInfoToMessageArgument(node);
}
else if (extraArgNames.Contains(name))
{
newNode = PrependFileInfoArgument(node);
}
return base.VisitInvocationExpression(node.Expression is MemberAccessExpressionSyntax _memberAccess ? newNode.WithExpression(_memberAccess.Name) : newNode);
}
}
DoNothing:
return base.VisitInvocationExpression(node);
}
private InvocationExpressionSyntax ConcatenateFileInfoToMessageArgument(InvocationExpressionSyntax node)
{
var messageArgument = node.ArgumentList.Arguments.First().Expression;
var fileInfoLiteral = GetFileInfoLiteral(node, addSpace: true);
var emptyTrivia = SyntaxFactory.TriviaList();
var plusToken = SyntaxFactory.Token(emptyTrivia, SyntaxKind.PlusToken, "+", "", emptyTrivia);
var binaryExpression = SyntaxFactory.BinaryExpression(SyntaxKind.AddExpression, fileInfoLiteral, plusToken, messageArgument);
var newArgument = SyntaxFactory.Argument(binaryExpression);
var newArguments = SeparatedSyntaxList.Create(new ReadOnlySpan<ArgumentSyntax>(ref newArgument));
var newArgumentListNode = node.ArgumentList.WithArguments(newArguments);
return node.WithArgumentList(newArgumentListNode);
}
private InvocationExpressionSyntax PrependFileInfoArgument(InvocationExpressionSyntax node)
{
var fileInfoLiteral = GetFileInfoLiteral(node, addSpace: false);
var argument = SyntaxFactory.Argument(fileInfoLiteral);
var newArguments = SeparatedSyntaxList.Create(new ReadOnlySpan<ArgumentSyntax>(new List<ArgumentSyntax> { argument }.Concat(node.ArgumentList.Arguments).ToArray())); // good lord why do they make that so convoluted
var newArgumentListNode = node.ArgumentList.WithArguments(newArguments);
return node.WithArgumentList(newArgumentListNode);
}
private LiteralExpressionSyntax GetFileInfoLiteral(SyntaxNode node, bool addSpace)
{
var fileLocation = FormatLocation(node);
var infoText = $"[{fileLocation}]:" + (addSpace ? " " : "");
var emptyTrivia = SyntaxFactory.TriviaList();
var token = SyntaxFactory.Token(emptyTrivia, SyntaxKind.StringLiteralToken, infoText, infoText, emptyTrivia); // why is trivia required bruh
return SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, token);
}
private string FormatLocation(SyntaxNode node)
{
var location = Utility.FormatLocation(node.GetLocation().GetLineSpan())
.Replace(_config.SourceFolder + "/", "")
.Replace("..", "./")
.Replace("./", "");
return location;
}
}
} |