Advertisement
Guest User

Untitled

a guest
Mar 21st, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.57 KB | None | 0 0
  1. // Copyright (C) 2019 Dmitry Yakimenko (detunized@gmail.com).
  2. // Licensed under the terms of the MIT license. See LICENCE for details.
  3.  
  4. using System;
  5. using System.IO;
  6. using System.Linq;
  7. using Microsoft.CodeAnalysis;
  8. using Microsoft.CodeAnalysis.CSharp;
  9. using Microsoft.CodeAnalysis.CSharp.Syntax;
  10.  
  11. namespace NunitToXunit
  12. {
  13. using static SyntaxFactory;
  14.  
  15. public static class Ast
  16. {
  17. private class Matcher
  18. {
  19. public bool Match(SyntaxNode code, SyntaxNode pattern)
  20. {
  21. // A placeholder matches anything
  22. if (IsPlaceholder(pattern))
  23. return true;
  24.  
  25. if (code.GetType() != pattern.GetType())
  26. return false;
  27.  
  28. switch (code)
  29. {
  30. case ArgumentSyntax c:
  31. {
  32. var p = (ArgumentSyntax)pattern;
  33. return Match(c.Expression, p.Expression);
  34. }
  35. case ArgumentListSyntax c:
  36. {
  37. var p = (ArgumentListSyntax)pattern;
  38. return Match(c.OpenParenToken, p.OpenParenToken)
  39. && Match(c.Arguments, p.Arguments)
  40. && Match(c.CloseParenToken, p.CloseParenToken);
  41. }
  42. case IdentifierNameSyntax c:
  43. {
  44. var p = (IdentifierNameSyntax)pattern;
  45. return Match(c.Identifier, p.Identifier);
  46. }
  47. case InvocationExpressionSyntax c:
  48. {
  49. var p = (InvocationExpressionSyntax)pattern;
  50. return Match(c.Expression, p.Expression)
  51. && Match(c.ArgumentList, p.ArgumentList);
  52. }
  53. case LiteralExpressionSyntax c:
  54. {
  55. var p = (LiteralExpressionSyntax)pattern;
  56. return Match(c.Token, p.Token);
  57. }
  58. case MemberAccessExpressionSyntax c:
  59. {
  60. var p = (MemberAccessExpressionSyntax)pattern;
  61. return Match(c.Expression, p.Expression)
  62. && Match(c.Name, p.Name);
  63. }
  64. case GenericNameSyntax c:
  65. {
  66. var p = (GenericNameSyntax)pattern;
  67. return Match(c.Identifier, p.Identifier)
  68. && Match(c.TypeArgumentList, p.TypeArgumentList);
  69. }
  70. case TypeArgumentListSyntax c:
  71. {
  72. var p = (TypeArgumentListSyntax)pattern;
  73. return Match(c.LessThanToken, p.LessThanToken)
  74. && Match(c.Arguments, p.Arguments)
  75. && Match(c.GreaterThanToken, p.GreaterThanToken);
  76. }
  77. default:
  78. return false;
  79. }
  80. }
  81.  
  82. //
  83. // Private
  84. //
  85.  
  86. private bool Match<T>(SeparatedSyntaxList<T> code, SeparatedSyntaxList<T> pattern) where T : SyntaxNode
  87. {
  88. if (code.Count != pattern.Count)
  89. return false;
  90.  
  91. for (var i = 0; i < code.Count; i++)
  92. if (!Match(code[i], pattern[i]))
  93. return false;
  94.  
  95. return true;
  96. }
  97.  
  98. private bool Match(SyntaxToken code, SyntaxToken pattern)
  99. {
  100. if (IsPlaceholder(pattern.Text))
  101. return true;
  102.  
  103. if (code.ValueText == pattern.ValueText)
  104. return true;
  105.  
  106. return false;
  107. }
  108.  
  109. private bool IsPlaceholder(SyntaxNode pattern)
  110. {
  111. return pattern is IdentifierNameSyntax i
  112. && IsPlaceholder(i.Identifier.Text);
  113. }
  114.  
  115. private bool IsPlaceholder(string name)
  116. {
  117. if (name == "_")
  118. return true;
  119.  
  120. return false;
  121. }
  122. }
  123.  
  124. public static ExpressionSyntax Parse(string pattern)
  125. {
  126. return ParseExpression(pattern);
  127. }
  128.  
  129. public static bool Match(SyntaxNode code, SyntaxNode pattern)
  130. {
  131. return new Matcher().Match(code, pattern);
  132. }
  133. }
  134.  
  135. static class Program
  136. {
  137. static void FindMatches(string filename, string pattern)
  138. {
  139. var sourceAst = CSharpSyntaxTree.ParseText(File.ReadAllText(filename));
  140. var patternAst = Ast.Parse(pattern);
  141. var nodes = sourceAst.GetRoot().DescendantNodes().OfType<ExpressionSyntax>();
  142.  
  143. foreach (var e in nodes)
  144. {
  145. if (Ast.Match(e, patternAst))
  146. {
  147. var line = e.GetLocation().GetLineSpan().StartLinePosition.Line;
  148. var code = e.NormalizeWhitespace();
  149. Console.WriteLine($" {line}: {code}");
  150. }
  151. }
  152. }
  153.  
  154. static void Main(string[] args)
  155. {
  156. if (args.Length < 2)
  157. {
  158. Console.WriteLine("USAGE: find-code pattern files...");
  159. return;
  160. }
  161.  
  162. var pattern = args[0];
  163. Console.WriteLine($"Looking for '{pattern}'");
  164.  
  165. foreach (var f in args.Skip(1))
  166. {
  167. Console.WriteLine(f);
  168. FindMatches(f, pattern);
  169. }
  170. }
  171. }
  172. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement