Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Copyright (C) 2019 Dmitry Yakimenko (detunized@gmail.com).
- // Licensed under the terms of the MIT license. See LICENCE for details.
- using System;
- using System.IO;
- using System.Linq;
- using Microsoft.CodeAnalysis;
- using Microsoft.CodeAnalysis.CSharp;
- using Microsoft.CodeAnalysis.CSharp.Syntax;
- namespace NunitToXunit
- {
- using static SyntaxFactory;
- public static class Ast
- {
- private class Matcher
- {
- public bool Match(SyntaxNode code, SyntaxNode pattern)
- {
- // A placeholder matches anything
- if (IsPlaceholder(pattern))
- return true;
- if (code.GetType() != pattern.GetType())
- return false;
- switch (code)
- {
- case ArgumentSyntax c:
- {
- var p = (ArgumentSyntax)pattern;
- return Match(c.Expression, p.Expression);
- }
- case ArgumentListSyntax c:
- {
- var p = (ArgumentListSyntax)pattern;
- return Match(c.OpenParenToken, p.OpenParenToken)
- && Match(c.Arguments, p.Arguments)
- && Match(c.CloseParenToken, p.CloseParenToken);
- }
- case IdentifierNameSyntax c:
- {
- var p = (IdentifierNameSyntax)pattern;
- return Match(c.Identifier, p.Identifier);
- }
- case InvocationExpressionSyntax c:
- {
- var p = (InvocationExpressionSyntax)pattern;
- return Match(c.Expression, p.Expression)
- && Match(c.ArgumentList, p.ArgumentList);
- }
- case LiteralExpressionSyntax c:
- {
- var p = (LiteralExpressionSyntax)pattern;
- return Match(c.Token, p.Token);
- }
- case MemberAccessExpressionSyntax c:
- {
- var p = (MemberAccessExpressionSyntax)pattern;
- return Match(c.Expression, p.Expression)
- && Match(c.Name, p.Name);
- }
- case GenericNameSyntax c:
- {
- var p = (GenericNameSyntax)pattern;
- return Match(c.Identifier, p.Identifier)
- && Match(c.TypeArgumentList, p.TypeArgumentList);
- }
- case TypeArgumentListSyntax c:
- {
- var p = (TypeArgumentListSyntax)pattern;
- return Match(c.LessThanToken, p.LessThanToken)
- && Match(c.Arguments, p.Arguments)
- && Match(c.GreaterThanToken, p.GreaterThanToken);
- }
- default:
- return false;
- }
- }
- //
- // Private
- //
- private bool Match<T>(SeparatedSyntaxList<T> code, SeparatedSyntaxList<T> pattern) where T : SyntaxNode
- {
- if (code.Count != pattern.Count)
- return false;
- for (var i = 0; i < code.Count; i++)
- if (!Match(code[i], pattern[i]))
- return false;
- return true;
- }
- private bool Match(SyntaxToken code, SyntaxToken pattern)
- {
- if (IsPlaceholder(pattern.Text))
- return true;
- if (code.ValueText == pattern.ValueText)
- return true;
- return false;
- }
- private bool IsPlaceholder(SyntaxNode pattern)
- {
- return pattern is IdentifierNameSyntax i
- && IsPlaceholder(i.Identifier.Text);
- }
- private bool IsPlaceholder(string name)
- {
- if (name == "_")
- return true;
- return false;
- }
- }
- public static ExpressionSyntax Parse(string pattern)
- {
- return ParseExpression(pattern);
- }
- public static bool Match(SyntaxNode code, SyntaxNode pattern)
- {
- return new Matcher().Match(code, pattern);
- }
- }
- static class Program
- {
- static void FindMatches(string filename, string pattern)
- {
- var sourceAst = CSharpSyntaxTree.ParseText(File.ReadAllText(filename));
- var patternAst = Ast.Parse(pattern);
- var nodes = sourceAst.GetRoot().DescendantNodes().OfType<ExpressionSyntax>();
- foreach (var e in nodes)
- {
- if (Ast.Match(e, patternAst))
- {
- var line = e.GetLocation().GetLineSpan().StartLinePosition.Line;
- var code = e.NormalizeWhitespace();
- Console.WriteLine($" {line}: {code}");
- }
- }
- }
- static void Main(string[] args)
- {
- if (args.Length < 2)
- {
- Console.WriteLine("USAGE: find-code pattern files...");
- return;
- }
- var pattern = args[0];
- Console.WriteLine($"Looking for '{pattern}'");
- foreach (var f in args.Skip(1))
- {
- Console.WriteLine(f);
- FindMatches(f, pattern);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement