/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxAnnotationTests.cs

https://gitlab.com/sharadag/TestProject2 · C# · 872 lines · 863 code · 4 blank · 5 comment · 0 complexity · cf4352b920189e13ec7d22de794ff230 MD5 · raw file

  1. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Microsoft.CodeAnalysis.CSharp.Syntax;
  6. using Roslyn.Test.Utilities;
  7. using Xunit;
  8. namespace Microsoft.CodeAnalysis.CSharp.UnitTests
  9. {
  10. public class SyntaxAnnotationTests
  11. {
  12. #region Boundary Tests
  13. [Fact]
  14. public void TestEmpty()
  15. {
  16. var code = @"";
  17. var tree = SyntaxFactory.ParseSyntaxTree(code);
  18. TestAnnotation(tree);
  19. }
  20. [Fact]
  21. public void TestAddAnnotationToNullSyntaxToken()
  22. {
  23. SyntaxAnnotation annotation = new SyntaxAnnotation();
  24. var oldToken = default(SyntaxToken);
  25. var newToken = oldToken.WithAdditionalAnnotations(annotation);
  26. Assert.False(newToken.ContainsAnnotations);
  27. }
  28. [Fact]
  29. public void TestAddAnnotationToNullSyntaxTrivia()
  30. {
  31. SyntaxAnnotation annotation = new SyntaxAnnotation();
  32. var oldTrivia = default(SyntaxTrivia);
  33. var newTrivia = oldTrivia.WithAdditionalAnnotations(annotation);
  34. Assert.False(newTrivia.ContainsAnnotations);
  35. }
  36. [Fact]
  37. public void TestCopyAnnotationToNullSyntaxNode()
  38. {
  39. var fromNode = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot();
  40. var toNode = default(SyntaxNode);
  41. var annotatedNode = fromNode.CopyAnnotationsTo(toNode);
  42. Assert.Null(annotatedNode);
  43. }
  44. [Fact]
  45. public void TestCopyAnnotationOfZeroLengthToSyntaxNode()
  46. {
  47. var fromNode = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot();
  48. var toNode = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot();
  49. var annotatedNode = fromNode.CopyAnnotationsTo(toNode);
  50. Assert.Equal(annotatedNode, toNode); // Reference Equal
  51. }
  52. [Fact]
  53. public void TestCopyAnnotationFromNullSyntaxToken()
  54. {
  55. var fromToken = default(SyntaxToken);
  56. var toToken = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot().DescendantTokens().First();
  57. var annotatedToken = fromToken.CopyAnnotationsTo(toToken);
  58. Assert.True(annotatedToken.IsEquivalentTo(toToken));
  59. }
  60. [Fact]
  61. public void TestCopyAnnotationToNullSyntaxToken()
  62. {
  63. var fromToken = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot().DescendantTokens().First();
  64. var toToken = default(SyntaxToken);
  65. var annotatedToken = fromToken.CopyAnnotationsTo(toToken);
  66. Assert.True(annotatedToken.IsEquivalentTo(default(SyntaxToken)));
  67. }
  68. [Fact]
  69. public void TestCopyAnnotationOfZeroLengthToSyntaxToken()
  70. {
  71. var fromToken = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot().DescendantTokens().First();
  72. var toToken = SyntaxFactory.ParseSyntaxTree(_helloWorldCode).GetCompilationUnitRoot().DescendantTokens().First();
  73. var annotatedToken = fromToken.CopyAnnotationsTo(toToken);
  74. Assert.Equal(annotatedToken, toToken); // Reference Equal
  75. }
  76. [Fact]
  77. public void TestCopyAnnotationFromNullSyntaxTrivia()
  78. {
  79. var fromTrivia = default(SyntaxTrivia);
  80. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  81. var toTrivia = GetAllTrivia(tree.GetCompilationUnitRoot()).FirstOrDefault();
  82. var annotatedTrivia = fromTrivia.CopyAnnotationsTo(toTrivia);
  83. Assert.True(toTrivia.IsEquivalentTo(annotatedTrivia));
  84. }
  85. [Fact]
  86. public void TestCopyAnnotationToNullSyntaxTrivia()
  87. {
  88. var toTrivia = default(SyntaxTrivia);
  89. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  90. var fromTrivia = GetAllTrivia(tree.GetCompilationUnitRoot()).FirstOrDefault();
  91. var annotatedTrivia = fromTrivia.CopyAnnotationsTo(toTrivia);
  92. Assert.True(default(SyntaxTrivia).IsEquivalentTo(annotatedTrivia));
  93. }
  94. [Fact]
  95. public void TestCopyAnnotationOfZeroLengthToSyntaxTrivia()
  96. {
  97. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  98. var fromTrivia = GetAllTrivia(tree.GetCompilationUnitRoot()).FirstOrDefault();
  99. var toTrivia = GetAllTrivia(tree.GetCompilationUnitRoot()).FirstOrDefault();
  100. var annotatedTrivia = fromTrivia.CopyAnnotationsTo(toTrivia);
  101. Assert.Equal(annotatedTrivia, toTrivia); // Reference Equal
  102. }
  103. #endregion
  104. #region Negative Tests
  105. [Fact]
  106. public void TestMissingAnnotationsOnNodesOrTokens()
  107. {
  108. SyntaxAnnotation annotation = new SyntaxAnnotation();
  109. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  110. var matchingNodesOrTokens = tree.GetCompilationUnitRoot().GetAnnotatedNodesAndTokens(annotation);
  111. Assert.Empty(matchingNodesOrTokens);
  112. }
  113. [Fact]
  114. public void TestMissingAnnotationsOnTrivia()
  115. {
  116. SyntaxAnnotation annotation = new SyntaxAnnotation();
  117. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  118. var matchingTrivia = tree.GetCompilationUnitRoot().GetAnnotatedTrivia(annotation);
  119. Assert.Empty(matchingTrivia);
  120. }
  121. #endregion
  122. #region Other Functional Tests
  123. [Fact]
  124. public void TestSimpleMultipleAnnotationsOnNode()
  125. {
  126. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  127. SyntaxAnnotation annotation1 = new SyntaxAnnotation();
  128. SyntaxAnnotation annotation2 = new SyntaxAnnotation();
  129. // Pick the first node from tree
  130. var node = GetAllNodesAndTokens(tree.GetCompilationUnitRoot()).First(t => t.IsNode).AsNode();
  131. // Annotate it
  132. var annotatedNode = node.WithAdditionalAnnotations(annotation1);
  133. var newRoot = tree.GetCompilationUnitRoot().ReplaceNode(node, annotatedNode);
  134. // Verify if annotation Exists
  135. TestAnnotation(annotation1, newRoot, node);
  136. // Pick the annotated node from the new tree
  137. var node2 = newRoot.GetAnnotatedNodesAndTokens(annotation1).Single().AsNode();
  138. // Annotate it again
  139. var twiceAnnotatedNode = node2.WithAdditionalAnnotations(annotation2);
  140. var twiceAnnotatedRoot = newRoot.ReplaceNode(node2, twiceAnnotatedNode);
  141. // Verify the recent annotation
  142. TestAnnotation(annotation2, twiceAnnotatedRoot, node2);
  143. // Verify both annotations exist in the newTree
  144. TestAnnotation(annotation1, twiceAnnotatedRoot, node);
  145. TestAnnotation(annotation2, twiceAnnotatedRoot, node);
  146. }
  147. [Fact]
  148. public void TestSimpleMultipleAnnotationsOnToken()
  149. {
  150. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  151. SyntaxAnnotation annotation1 = new SyntaxAnnotation();
  152. SyntaxAnnotation annotation2 = new SyntaxAnnotation();
  153. // Pick the first node from tree
  154. var token = GetAllNodesAndTokens(tree.GetCompilationUnitRoot()).First(t => t.IsToken).AsToken();
  155. // Annotate it
  156. var annotatedToken = token.WithAdditionalAnnotations(annotation1);
  157. var newRoot = tree.GetCompilationUnitRoot().ReplaceToken(token, annotatedToken);
  158. // Verify if annotation Exists
  159. TestAnnotation(annotation1, newRoot, token);
  160. // Pick the annotated node from the new tree
  161. var token2 = newRoot.GetAnnotatedNodesAndTokens(annotation1).Single().AsToken();
  162. // Annotate it again
  163. var twiceAnnotatedToken = token2.WithAdditionalAnnotations(annotation2);
  164. var twiceAnnotatedRoot = newRoot.ReplaceToken(token2, twiceAnnotatedToken);
  165. // Verify the recent annotation
  166. TestAnnotation(annotation2, twiceAnnotatedRoot, token2);
  167. // Verify both annotations exist in the newTree
  168. TestAnnotation(annotation1, twiceAnnotatedRoot, token);
  169. TestAnnotation(annotation2, twiceAnnotatedRoot, token);
  170. }
  171. [Fact]
  172. public void TestSimpleMultipleAnnotationsOnTrivia()
  173. {
  174. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  175. SyntaxAnnotation annotation1 = new SyntaxAnnotation();
  176. SyntaxAnnotation annotation2 = new SyntaxAnnotation();
  177. // Pick the first node from tree
  178. var trivia = GetAllTrivia(tree.GetCompilationUnitRoot()).First();
  179. // Annotate it
  180. var annotatedTrivia = trivia.WithAdditionalAnnotations(annotation1);
  181. var newRoot = tree.GetCompilationUnitRoot().ReplaceTrivia(trivia, annotatedTrivia);
  182. // Verify if annotation Exists
  183. TestAnnotation(annotation1, newRoot, trivia);
  184. // Pick the annotated node from the new tree
  185. var trivia2 = newRoot.GetAnnotatedTrivia(annotation1).Single();
  186. // Annotate it again
  187. var twiceAnnotatedTrivia = trivia2.WithAdditionalAnnotations(annotation2);
  188. var twiceAnnotatedRoot = newRoot.ReplaceTrivia(trivia2, twiceAnnotatedTrivia);
  189. // Verify the recent annotation
  190. TestAnnotation(annotation2, twiceAnnotatedRoot, trivia2);
  191. // Verify both annotations exist in the newTree
  192. TestAnnotation(annotation1, twiceAnnotatedRoot, trivia);
  193. TestAnnotation(annotation2, twiceAnnotatedRoot, trivia);
  194. }
  195. [Fact]
  196. public void TestMultipleAnnotationsOnAllNodesTokensAndTrivia()
  197. {
  198. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  199. SyntaxNode newRoot = tree.GetCompilationUnitRoot();
  200. var annotations = new List<SyntaxAnnotation>(Enumerable.Range(0, 3).Select(_ => new SyntaxAnnotation()));
  201. // add annotation one by one to every single node, token, trivia
  202. foreach (var annotation in annotations)
  203. {
  204. var rewriter = new InjectAnnotationRewriter(annotation);
  205. newRoot = rewriter.Visit(newRoot);
  206. }
  207. // Verify that all annotations are present in whichever places they were added
  208. TestMultipleAnnotationsInTree(tree.GetCompilationUnitRoot(), newRoot, annotations);
  209. }
  210. [Fact]
  211. public void TestAnnotationOnEveryNodeTokenTriviaOfHelloWorld()
  212. {
  213. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  214. TestAnnotation(tree);
  215. TestTriviaAnnotation(tree);
  216. }
  217. [Fact]
  218. public void TestIfNodeHasAnnotations()
  219. {
  220. var tree = SyntaxFactory.ParseSyntaxTree(_helloWorldCode);
  221. SyntaxAnnotation annotation1 = new SyntaxAnnotation();
  222. // Pick the first node from tree
  223. var firstNode = GetAllNodesAndTokens(tree.GetCompilationUnitRoot()).First(t => t.IsNode).AsNode();
  224. var children = firstNode.ChildNodesAndTokens();
  225. var lastChildOfFirstNode = children.Last(t => t.IsNode).AsNode();
  226. var annotatedNode = lastChildOfFirstNode.WithAdditionalAnnotations(annotation1);
  227. var newRoot = tree.GetCompilationUnitRoot().ReplaceNode(lastChildOfFirstNode, annotatedNode);
  228. // Verify if annotation Exists
  229. TestAnnotation(annotation1, newRoot, lastChildOfFirstNode);
  230. // Pick the first node from new tree and see if any of its children is annotated
  231. var firstNodeInNewTree = GetAllNodesAndTokens(newRoot).First(t => t.IsNode).AsNode();
  232. Assert.True(firstNodeInNewTree.ContainsAnnotations);
  233. // Pick the node which was annotated and see if it has the annotation
  234. var rightNode = firstNodeInNewTree.ChildNodesAndTokens().Last(t => t.IsNode).AsNode();
  235. Assert.NotNull(rightNode.GetAnnotations().Single());
  236. }
  237. [Fact]
  238. public void TestCSharpAllInOne()
  239. {
  240. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  241. TestAnnotation(tree);
  242. }
  243. [Fact]
  244. public void TestCSharpAllInOneRandom()
  245. {
  246. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  247. TestRandomAnnotations(tree);
  248. }
  249. [Fact]
  250. public void TestCSharpAllInOneManyRandom()
  251. {
  252. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  253. TestManyRandomAnnotations(tree);
  254. }
  255. [Fact]
  256. public void TestCSharpAllInOneTrivia()
  257. {
  258. var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  259. TestTriviaAnnotation(tree);
  260. }
  261. [Fact]
  262. public void TestCopyAnnotations1()
  263. {
  264. var tree1 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  265. var tree2 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular);
  266. TestCopyAnnotations(tree1, tree2);
  267. }
  268. #endregion
  269. private void TestMultipleAnnotationsInTree(SyntaxNode oldRoot, SyntaxNode newRoot, List<SyntaxAnnotation> annotations)
  270. {
  271. foreach (var annotation in annotations)
  272. {
  273. // Verify annotations in Nodes or Tokens
  274. var annotatedNodesOrTokens = newRoot.GetAnnotatedNodesAndTokens(annotation).OrderBy(t => t.SpanStart).ToList();
  275. var actualNodesOrTokens = GetAllNodesAndTokens(oldRoot).OrderBy(t => t.SpanStart).ToList();
  276. Assert.Equal(actualNodesOrTokens.Count, annotatedNodesOrTokens.Count);
  277. for (int i = 0; i < actualNodesOrTokens.Count(); i++)
  278. {
  279. var oldNode = actualNodesOrTokens.ElementAt(i);
  280. var annotatedNode = annotatedNodesOrTokens.ElementAt(i);
  281. Assert.Equal(oldNode.FullSpan, annotatedNode.FullSpan);
  282. Assert.Equal(oldNode.Span, annotatedNode.Span);
  283. Assert.True(oldNode.IsEquivalentTo(annotatedNode));
  284. }
  285. // Verify annotations in Trivia
  286. var annotatedTrivia = newRoot.GetAnnotatedTrivia(annotation).OrderBy(t => t.SpanStart);
  287. var actualTrivia = GetAllTrivia(oldRoot).OrderBy(t => t.SpanStart);
  288. Assert.Equal(annotatedTrivia.Count(), actualTrivia.Count());
  289. for (int i = 0; i < actualTrivia.Count(); i++)
  290. {
  291. var oldTrivia = actualTrivia.ElementAt(i);
  292. var newTrivia = annotatedTrivia.ElementAt(i);
  293. Assert.Equal(oldTrivia.FullSpan, newTrivia.FullSpan);
  294. Assert.Equal(oldTrivia.Span, newTrivia.Span);
  295. Assert.True(oldTrivia.IsEquivalentTo(newTrivia));
  296. }
  297. }
  298. }
  299. private void TestCopyAnnotations(SyntaxTree tree1, SyntaxTree tree2)
  300. {
  301. // create 10 annotations
  302. var annotations = new List<SyntaxAnnotation>(Enumerable.Range(0, 10).Select(_ => new SyntaxAnnotation()));
  303. // add a random annotation to every single node, token, trivia
  304. var rewriter = new InjectRandomAnnotationsRewriter(annotations);
  305. var sourceTreeRoot = rewriter.Visit(tree1.GetCompilationUnitRoot());
  306. var destTreeRoot = CopyAnnotationsTo(sourceTreeRoot, tree2.GetCompilationUnitRoot());
  307. // now we have two tree with same annotation everywhere
  308. // verify that
  309. foreach (var annotation in annotations)
  310. {
  311. // verify annotation at nodes and tokens
  312. var sourceNodeOrTokens = sourceTreeRoot.GetAnnotatedNodesAndTokens(annotation);
  313. var sourceNodeOrTokenEnumerator = sourceNodeOrTokens.GetEnumerator();
  314. var destNodeOrTokens = destTreeRoot.GetAnnotatedNodesAndTokens(annotation);
  315. var destNodeOrTokenEnumerator = destNodeOrTokens.GetEnumerator();
  316. Assert.Equal(sourceNodeOrTokens.Count(), destNodeOrTokens.Count());
  317. while (sourceNodeOrTokenEnumerator.MoveNext() && destNodeOrTokenEnumerator.MoveNext())
  318. {
  319. Assert.True(sourceNodeOrTokenEnumerator.Current.IsEquivalentTo(destNodeOrTokenEnumerator.Current));
  320. }
  321. // verify annotation at trivia
  322. var sourceTrivia = sourceTreeRoot.GetAnnotatedTrivia(annotation);
  323. var destTrivia = destTreeRoot.GetAnnotatedTrivia(annotation);
  324. var sourceTriviaEnumerator = sourceTrivia.GetEnumerator();
  325. var destTriviaEnumerator = destTrivia.GetEnumerator();
  326. Assert.Equal(sourceTrivia.Count(), destTrivia.Count());
  327. while (sourceTriviaEnumerator.MoveNext() && destTriviaEnumerator.MoveNext())
  328. {
  329. Assert.True(sourceTriviaEnumerator.Current.IsEquivalentTo(destTriviaEnumerator.Current));
  330. }
  331. }
  332. }
  333. private SyntaxNode CopyAnnotationsTo(SyntaxNode sourceTreeRoot, SyntaxNode destTreeRoot)
  334. {
  335. // now I have a tree that has annotation at every node/token/trivia
  336. // copy all those annotation to tree2 and create map from old one to new one
  337. var sourceTreeNodeOrTokenEnumerator = GetAllNodesAndTokens(sourceTreeRoot).GetEnumerator();
  338. var destTreeNodeOrTokenEnumerator = GetAllNodesAndTokens(destTreeRoot).GetEnumerator();
  339. var nodeOrTokenMap = new Dictionary<SyntaxNodeOrToken, SyntaxNodeOrToken>();
  340. while (sourceTreeNodeOrTokenEnumerator.MoveNext() && destTreeNodeOrTokenEnumerator.MoveNext())
  341. {
  342. if (sourceTreeNodeOrTokenEnumerator.Current.IsNode)
  343. {
  344. var oldNode = destTreeNodeOrTokenEnumerator.Current.AsNode();
  345. var newNode = sourceTreeNodeOrTokenEnumerator.Current.AsNode().CopyAnnotationsTo(oldNode);
  346. nodeOrTokenMap.Add(oldNode, newNode);
  347. }
  348. else if (sourceTreeNodeOrTokenEnumerator.Current.IsToken)
  349. {
  350. var oldToken = destTreeNodeOrTokenEnumerator.Current.AsToken();
  351. var newToken = sourceTreeNodeOrTokenEnumerator.Current.AsToken().CopyAnnotationsTo(oldToken);
  352. nodeOrTokenMap.Add(oldToken, newToken);
  353. }
  354. }
  355. // copy annotations at trivia
  356. var sourceTreeTriviaEnumerator = GetAllTrivia(sourceTreeRoot).GetEnumerator();
  357. var destTreeTriviaEnumerator = GetAllTrivia(destTreeRoot).GetEnumerator();
  358. var triviaMap = new Dictionary<SyntaxTrivia, SyntaxTrivia>();
  359. while (sourceTreeTriviaEnumerator.MoveNext() && destTreeTriviaEnumerator.MoveNext())
  360. {
  361. var oldTrivia = destTreeTriviaEnumerator.Current;
  362. var newTrivia = sourceTreeTriviaEnumerator.Current.CopyAnnotationsTo(oldTrivia);
  363. triviaMap.Add(oldTrivia, newTrivia);
  364. }
  365. var copier = new CopyAnnotationRewriter(nodeOrTokenMap, triviaMap);
  366. return copier.Visit(destTreeRoot);
  367. }
  368. private void TestManyRandomAnnotations(SyntaxTree syntaxTree)
  369. {
  370. // inject annotations in random places and see whether it is preserved after tree transformation
  371. var annotations = new List<Tuple<SyntaxAnnotation, SyntaxNodeOrToken>>();
  372. // we give constant seed so that we get exact same sequence every time.
  373. var randomGenerator = new Random(0);
  374. var currentRoot = syntaxTree.GetCompilationUnitRoot();
  375. var count = GetAllNodesAndTokens(currentRoot).Count;
  376. // add one in root
  377. var rootAnnotation = new SyntaxAnnotation();
  378. annotations.Add(Tuple.Create(rootAnnotation, new SyntaxNodeOrToken(currentRoot)));
  379. var rootAnnotated = AddAnnotationTo(rootAnnotation, currentRoot);
  380. currentRoot = Replace(currentRoot, currentRoot, rootAnnotated);
  381. for (int i = 0; i < 20; i++)
  382. {
  383. var annotation = new SyntaxAnnotation();
  384. var item = GetAllNodesAndTokens(currentRoot)[randomGenerator.Next(count - 1)];
  385. // save it
  386. annotations.Add(Tuple.Create(annotation, item));
  387. var annotated = AddAnnotationTo(annotation, item);
  388. currentRoot = Replace(currentRoot, item, annotated);
  389. TestAnnotations(annotations, currentRoot);
  390. }
  391. }
  392. private void TestRandomAnnotations(SyntaxTree syntaxTree)
  393. {
  394. // inject annotations in random places and see whether it is preserved after tree transformation
  395. var firstAnnotation = new SyntaxAnnotation();
  396. var secondAnnotation = new SyntaxAnnotation();
  397. var candidatePool = GetAllNodesAndTokens(syntaxTree.GetCompilationUnitRoot());
  398. var numberOfCandidates = candidatePool.Count;
  399. // we give constant seed so that we get exact same sequence every time.
  400. var randomGenerator = new Random(100);
  401. for (int i = 0; i < 20; i++)
  402. {
  403. var firstItem = candidatePool[randomGenerator.Next(numberOfCandidates - 1)];
  404. var firstAnnotated = AddAnnotationTo(firstAnnotation, firstItem);
  405. var newRoot = Replace(syntaxTree.GetCompilationUnitRoot(), firstItem, firstAnnotated);
  406. // check the first annotation
  407. TestAnnotation(firstAnnotation, newRoot, firstItem);
  408. var secondItem = GetAllNodesAndTokens(newRoot)[randomGenerator.Next(numberOfCandidates - 1)];
  409. var secondAnnotated = AddAnnotationTo(secondAnnotation, secondItem);
  410. // transform the tree again
  411. newRoot = Replace(newRoot, secondItem, secondAnnotated);
  412. // make sure both annotation are in the tree
  413. TestAnnotation(firstAnnotation, newRoot, firstItem);
  414. TestAnnotation(secondAnnotation, newRoot, secondItem);
  415. }
  416. }
  417. public TRoot Replace<TRoot>(TRoot root, SyntaxNodeOrToken oldNodeOrToken, SyntaxNodeOrToken newNodeOrToken) where TRoot : SyntaxNode
  418. {
  419. if (oldNodeOrToken.IsToken)
  420. {
  421. return root.ReplaceToken(oldNodeOrToken.AsToken(), newNodeOrToken.AsToken());
  422. }
  423. return root.ReplaceNode(oldNodeOrToken.AsNode(), newNodeOrToken.AsNode());
  424. }
  425. public SyntaxNodeOrToken AddAnnotationTo(SyntaxAnnotation annotation, SyntaxNodeOrToken nodeOrToken)
  426. {
  427. return nodeOrToken.WithAdditionalAnnotations(annotation);
  428. }
  429. private void TestAnnotations(List<Tuple<SyntaxAnnotation, SyntaxNodeOrToken>> annotations, SyntaxNode currentRoot)
  430. {
  431. // check every annotations
  432. foreach (var pair in annotations)
  433. {
  434. var annotation = pair.Item1;
  435. var nodeOrToken = pair.Item2;
  436. TestAnnotation(annotation, currentRoot, nodeOrToken);
  437. }
  438. }
  439. private void TestTriviaAnnotation(SyntaxTree syntaxTree)
  440. {
  441. var annotation = new SyntaxAnnotation();
  442. foreach (var trivia in GetAllTrivia(syntaxTree.GetCompilationUnitRoot()))
  443. {
  444. // add one annotation and test its existence
  445. var newTrivia = trivia.WithAdditionalAnnotations(annotation);
  446. var newRoot = syntaxTree.GetCompilationUnitRoot().ReplaceTrivia(trivia, newTrivia);
  447. TestAnnotation(annotation, newRoot, trivia);
  448. }
  449. }
  450. private void TestAnnotation(SyntaxTree syntaxTree)
  451. {
  452. var annotation = new SyntaxAnnotation();
  453. var allNodesAndTokens = GetAllNodesAndTokens(syntaxTree.GetCompilationUnitRoot());
  454. for (int i = 0; i < allNodesAndTokens.Count; i++)
  455. {
  456. var nodeOrToken = allNodesAndTokens[i];
  457. SyntaxNode newRoot;
  458. // add one annotation and test its existence
  459. if (nodeOrToken.IsToken)
  460. {
  461. var newToken = nodeOrToken.AsToken().WithAdditionalAnnotations(annotation);
  462. newRoot = syntaxTree.GetCompilationUnitRoot().ReplaceToken(nodeOrToken.AsToken(), newToken);
  463. }
  464. else
  465. {
  466. var newNode = nodeOrToken.AsNode().WithAdditionalAnnotations(annotation);
  467. newRoot = syntaxTree.GetCompilationUnitRoot().ReplaceNode(nodeOrToken.AsNode(), newNode);
  468. }
  469. TestAnnotation(annotation, newRoot, nodeOrToken);
  470. }
  471. }
  472. private void TestAnnotation(SyntaxAnnotation annotation, SyntaxNode root, SyntaxNodeOrToken oldNodeOrToken)
  473. {
  474. // Test for existence of exactly one annotation
  475. if (oldNodeOrToken.IsToken)
  476. {
  477. TestAnnotation(annotation, root, oldNodeOrToken.AsToken());
  478. return;
  479. }
  480. TestAnnotation(annotation, root, oldNodeOrToken.AsNode());
  481. }
  482. private void TestAnnotation(SyntaxAnnotation annotation, SyntaxNode root, SyntaxNode oldNode)
  483. {
  484. var results = root.GetAnnotatedNodesAndTokens(annotation);
  485. Assert.Equal(1, results.Count());
  486. var annotatedNode = results.Single().AsNode();
  487. // try to check whether it is same node as old node.
  488. Assert.Equal(oldNode.FullSpan, annotatedNode.FullSpan);
  489. Assert.Equal(oldNode.Span, annotatedNode.Span);
  490. Assert.True(oldNode.IsEquivalentTo(annotatedNode));
  491. }
  492. private void TestAnnotation(SyntaxAnnotation annotation, SyntaxNode root, SyntaxToken oldToken)
  493. {
  494. var results = root.GetAnnotatedNodesAndTokens(annotation);
  495. Assert.Equal(1, results.Count());
  496. var annotatedToken = results.Single().AsToken();
  497. // try to check whether it is same token as old token.
  498. Assert.Equal(oldToken.FullSpan, annotatedToken.FullSpan);
  499. Assert.Equal(oldToken.Span, annotatedToken.Span);
  500. Assert.True(oldToken.IsEquivalentTo(annotatedToken));
  501. }
  502. private void TestAnnotation(SyntaxAnnotation annotation, SyntaxNode root, SyntaxTrivia oldTrivia)
  503. {
  504. var results = root.GetAnnotatedTrivia(annotation);
  505. Assert.Equal(1, results.Count());
  506. var annotatedTrivia = results.Single();
  507. // try to check whether it is same token as old token.
  508. Assert.Equal(oldTrivia.FullSpan, annotatedTrivia.FullSpan);
  509. Assert.Equal(oldTrivia.Span, annotatedTrivia.Span);
  510. Assert.True(oldTrivia.IsEquivalentTo(annotatedTrivia));
  511. }
  512. private List<SyntaxTrivia> GetAllTrivia(SyntaxNode root)
  513. {
  514. var collector = new Collector();
  515. collector.Visit(root);
  516. return collector.Trivia;
  517. }
  518. private List<SyntaxNodeOrToken> GetAllNodesAndTokens(SyntaxNode root)
  519. {
  520. return root.DescendantNodesAndTokensAndSelf(descendIntoTrivia: true).Select(n => (SyntaxNodeOrToken)n).ToList();
  521. }
  522. private class Collector : CSharpSyntaxWalker
  523. {
  524. public List<SyntaxNodeOrToken> NodeOrTokens { get; }
  525. public List<SyntaxTrivia> Trivia { get; }
  526. public Collector()
  527. : base(SyntaxWalkerDepth.StructuredTrivia)
  528. {
  529. this.NodeOrTokens = new List<SyntaxNodeOrToken>();
  530. this.Trivia = new List<SyntaxTrivia>();
  531. }
  532. public override void Visit(SyntaxNode node)
  533. {
  534. if (node != null)
  535. {
  536. this.NodeOrTokens.Add(node);
  537. }
  538. base.Visit(node);
  539. }
  540. public override void VisitToken(SyntaxToken token)
  541. {
  542. if (!token.IsKind(SyntaxKind.None))
  543. {
  544. this.NodeOrTokens.Add(token);
  545. }
  546. base.VisitToken(token);
  547. }
  548. public override void VisitTrivia(SyntaxTrivia trivia)
  549. {
  550. if (!trivia.IsKind(SyntaxKind.None))
  551. {
  552. this.Trivia.Add(trivia);
  553. }
  554. base.VisitTrivia(trivia);
  555. }
  556. }
  557. private class InjectAnnotationRewriter : CSharpSyntaxRewriter
  558. {
  559. private readonly SyntaxAnnotation _annotation;
  560. public InjectAnnotationRewriter(SyntaxAnnotation annotation) :
  561. base(visitIntoStructuredTrivia: true)
  562. {
  563. _annotation = annotation;
  564. }
  565. public override SyntaxNode Visit(SyntaxNode node)
  566. {
  567. if (node == null)
  568. {
  569. return node;
  570. }
  571. return base.Visit(node).WithAdditionalAnnotations(_annotation);
  572. }
  573. public override SyntaxToken VisitToken(SyntaxToken token)
  574. {
  575. if (token.IsKind(SyntaxKind.None))
  576. {
  577. return token;
  578. }
  579. return base.VisitToken(token).WithAdditionalAnnotations(_annotation);
  580. }
  581. public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
  582. {
  583. if (trivia.IsKind(SyntaxKind.None))
  584. {
  585. return trivia;
  586. }
  587. if (trivia.HasStructure)
  588. {
  589. return base.VisitTrivia(trivia);
  590. }
  591. return base.VisitTrivia(trivia).WithAdditionalAnnotations(_annotation);
  592. }
  593. }
  594. private class InjectRandomAnnotationsRewriter : CSharpSyntaxRewriter
  595. {
  596. private readonly List<SyntaxAnnotation> _annotations;
  597. private readonly Random _random;
  598. public InjectRandomAnnotationsRewriter(List<SyntaxAnnotation> annotations) :
  599. base(visitIntoStructuredTrivia: true)
  600. {
  601. _annotations = annotations;
  602. _random = new Random(10);
  603. }
  604. public override SyntaxNode Visit(SyntaxNode node)
  605. {
  606. if (node == null)
  607. {
  608. return node;
  609. }
  610. var annotation = _annotations[_random.Next(0, _annotations.Count - 1)];
  611. return base.Visit(node).WithAdditionalAnnotations(annotation);
  612. }
  613. public override SyntaxToken VisitToken(SyntaxToken token)
  614. {
  615. if (token.Kind() == SyntaxKind.None)
  616. {
  617. return token;
  618. }
  619. var annotation = _annotations[_random.Next(0, _annotations.Count - 1)];
  620. return base.VisitToken(token).WithAdditionalAnnotations(annotation);
  621. }
  622. public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
  623. {
  624. if (trivia.IsKind(SyntaxKind.None))
  625. {
  626. return trivia;
  627. }
  628. // annotation will be set by actual structure trivia
  629. if (trivia.HasStructure)
  630. {
  631. return base.VisitTrivia(trivia);
  632. }
  633. var annotation = _annotations[_random.Next(0, _annotations.Count - 1)];
  634. return base.VisitTrivia(trivia).WithAdditionalAnnotations(annotation);
  635. }
  636. }
  637. private class CopyAnnotationRewriter : CSharpSyntaxRewriter
  638. {
  639. private readonly Dictionary<SyntaxNodeOrToken, SyntaxNodeOrToken> _nodeOrTokenMap;
  640. private readonly Dictionary<SyntaxTrivia, SyntaxTrivia> _triviaMap;
  641. public CopyAnnotationRewriter(Dictionary<SyntaxNodeOrToken, SyntaxNodeOrToken> nodeOrTokenMap, Dictionary<SyntaxTrivia, SyntaxTrivia> triviaMap) :
  642. base(visitIntoStructuredTrivia: true)
  643. {
  644. _nodeOrTokenMap = nodeOrTokenMap;
  645. _triviaMap = triviaMap;
  646. }
  647. public override SyntaxNode Visit(SyntaxNode node)
  648. {
  649. if (node == null)
  650. {
  651. return node;
  652. }
  653. return _nodeOrTokenMap[node].AsNode().CopyAnnotationsTo(base.Visit(node));
  654. }
  655. public override SyntaxToken VisitToken(SyntaxToken token)
  656. {
  657. if (token.IsKind(SyntaxKind.None))
  658. {
  659. return token;
  660. }
  661. return _nodeOrTokenMap[token].AsToken().CopyAnnotationsTo(base.VisitToken(token));
  662. }
  663. public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
  664. {
  665. if (trivia.IsKind(SyntaxKind.None))
  666. {
  667. return trivia;
  668. }
  669. // annotation will be set by actual structure trivia
  670. if (trivia.HasStructure)
  671. {
  672. return base.VisitTrivia(trivia);
  673. }
  674. return _triviaMap[trivia].CopyAnnotationsTo(base.VisitTrivia(trivia));
  675. }
  676. }
  677. private readonly string _helloWorldCode = @"using System;
  678. using System.Collections.Generic;
  679. using System.Linq;
  680. /// <summary>
  681. /// Sample Documentation
  682. /// </summary>
  683. class Program
  684. {
  685. static void Main(string[] args)
  686. {
  687. // User Comments
  688. Console.WriteLine(""Hello World!"");
  689. }
  690. }";
  691. private readonly string _allInOneCSharpCode = TestResource.AllInOneCSharpCode;
  692. }
  693. }