PageRenderTime 202ms CodeModel.GetById 22ms RepoModel.GetById 2ms app.codeStats 1ms

/test/System.Web.Razor.Test/Parser/CSharp/CSharpToMarkupSwitchTest.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 491 lines | 467 code | 20 blank | 4 comment | 0 complexity | dc43ab775d237d90526df360ddc4afa9 MD5 | raw file
  1. using System.Web.Razor.Editor;
  2. using System.Web.Razor.Parser;
  3. using System.Web.Razor.Parser.SyntaxTree;
  4. using System.Web.Razor.Resources;
  5. using System.Web.Razor.Test.Framework;
  6. using System.Web.Razor.Tokenizer.Symbols;
  7. using Xunit;
  8. namespace System.Web.Razor.Test.Parser.CSharp
  9. {
  10. public class CSharpToMarkupSwitchTest : CsHtmlCodeParserTestBase
  11. {
  12. [Fact]
  13. public void SingleAngleBracketDoesNotCauseSwitchIfOuterBlockIsTerminated()
  14. {
  15. ParseBlockTest("{ List< }",
  16. new StatementBlock(
  17. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  18. Factory.Code(" List< ").AsStatement(),
  19. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  20. }
  21. [Fact]
  22. public void ParseBlockGivesSpacesToCodeOnAtTagTemplateTransitionInDesignTimeMode()
  23. {
  24. ParseBlockTest(@"Foo( @<p>Foo</p> )",
  25. new ExpressionBlock(
  26. Factory.Code(@"Foo( ")
  27. .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
  28. .Accepts(AcceptedCharacters.Any),
  29. new TemplateBlock(
  30. new MarkupBlock(
  31. Factory.MarkupTransition(),
  32. Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
  33. )
  34. ),
  35. Factory.Code(@" )")
  36. .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
  37. .Accepts(AcceptedCharacters.NonWhiteSpace)
  38. ), designTimeParser: true);
  39. }
  40. [Fact]
  41. public void ParseBlockGivesSpacesToCodeOnAtColonTemplateTransitionInDesignTimeMode()
  42. {
  43. ParseBlockTest(@"Foo(
  44. @:<p>Foo</p>
  45. )",
  46. new ExpressionBlock(
  47. Factory.Code("Foo( \r\n").AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
  48. new TemplateBlock(
  49. new MarkupBlock(
  50. Factory.MarkupTransition(),
  51. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  52. Factory.Markup("<p>Foo</p> \r\n")
  53. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  54. )
  55. ),
  56. Factory.Code(@")")
  57. .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
  58. .Accepts(AcceptedCharacters.NonWhiteSpace)
  59. ), designTimeParser: true);
  60. }
  61. [Fact]
  62. public void ParseBlockGivesSpacesToCodeOnTagTransitionInDesignTimeMode()
  63. {
  64. ParseBlockTest(@"{
  65. <p>Foo</p>
  66. }",
  67. new StatementBlock(
  68. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  69. Factory.Code("\r\n ").AsStatement(),
  70. new MarkupBlock(
  71. Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
  72. ),
  73. Factory.Code(" \r\n").AsStatement(),
  74. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
  75. ), designTimeParser: true);
  76. }
  77. [Fact]
  78. public void ParseBlockGivesSpacesToCodeOnInvalidAtTagTransitionInDesignTimeMode()
  79. {
  80. ParseBlockTest(@"{
  81. @<p>Foo</p>
  82. }",
  83. new StatementBlock(
  84. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  85. Factory.Code("\r\n ").AsStatement(),
  86. new MarkupBlock(
  87. Factory.MarkupTransition(),
  88. Factory.Markup("<p>Foo</p>").Accepts(AcceptedCharacters.None)
  89. ),
  90. Factory.Code(" \r\n").AsStatement(),
  91. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
  92. ), true,
  93. new RazorError(RazorResources.ParseError_AtInCode_Must_Be_Followed_By_Colon_Paren_Or_Identifier_Start, 7, 1, 4));
  94. }
  95. [Fact]
  96. public void ParseBlockGivesSpacesToCodeOnAtColonTransitionInDesignTimeMode()
  97. {
  98. ParseBlockTest(@"{
  99. @:<p>Foo</p>
  100. }",
  101. new StatementBlock(
  102. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  103. Factory.Code("\r\n ").AsStatement(),
  104. new MarkupBlock(
  105. Factory.MarkupTransition(),
  106. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  107. Factory.Markup("<p>Foo</p> \r\n")
  108. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  109. ),
  110. Factory.EmptyCSharp().AsStatement(),
  111. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
  112. ), designTimeParser: true);
  113. }
  114. [Fact]
  115. public void ParseBlockShouldSupportSingleLineMarkupContainingStatementBlock()
  116. {
  117. ParseBlockTest(@"Repeat(10,
  118. @: @{}
  119. )",
  120. new ExpressionBlock(
  121. Factory.Code("Repeat(10,\r\n ")
  122. .AsImplicitExpression(CSharpCodeParser.DefaultKeywords),
  123. new TemplateBlock(
  124. new MarkupBlock(
  125. Factory.MarkupTransition(),
  126. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  127. Factory.Markup(" ")
  128. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString)),
  129. new StatementBlock(
  130. Factory.CodeTransition(),
  131. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  132. Factory.EmptyCSharp().AsStatement(),
  133. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
  134. ),
  135. Factory.Markup("\r\n")
  136. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  137. )
  138. ),
  139. Factory.Code(")")
  140. .AsImplicitExpression(CSharpCodeParser.DefaultKeywords)
  141. .Accepts(AcceptedCharacters.NonWhiteSpace)
  142. ));
  143. }
  144. [Fact]
  145. public void ParseBlockShouldSupportMarkupWithoutPreceedingWhitespace()
  146. {
  147. ParseBlockTest(@"foreach(var file in files){
  148. @:Baz
  149. <br/>
  150. <a>Foo</a>
  151. @:Bar
  152. }",
  153. new StatementBlock(
  154. Factory.Code("foreach(var file in files){\r\n\r\n\r\n").AsStatement(),
  155. new MarkupBlock(
  156. Factory.MarkupTransition(),
  157. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  158. Factory.Markup("Baz\r\n")
  159. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  160. ),
  161. new MarkupBlock(
  162. Factory.Markup("<br/>\r\n")
  163. .Accepts(AcceptedCharacters.None)
  164. ),
  165. new MarkupBlock(
  166. Factory.Markup("<a>Foo</a>\r\n")
  167. .Accepts(AcceptedCharacters.None)
  168. ),
  169. new MarkupBlock(
  170. Factory.MarkupTransition(),
  171. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  172. Factory.Markup("Bar\r\n")
  173. .With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  174. ),
  175. Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
  176. ));
  177. }
  178. [Fact]
  179. public void ParseBlockGivesAllWhitespaceOnSameLineExcludingPreceedingNewlineButIncludingTrailingNewLineToMarkup()
  180. {
  181. ParseBlockTest(@"if(foo) {
  182. var foo = ""After this statement there are 10 spaces"";
  183. <p>
  184. Foo
  185. @bar
  186. </p>
  187. @:Hello!
  188. var biz = boz;
  189. }",
  190. new StatementBlock(
  191. Factory.Code("if(foo) {\r\n var foo = \"After this statement there are 10 spaces\"; \r\n").AsStatement(),
  192. new MarkupBlock(
  193. Factory.Markup(" <p>\r\n Foo\r\n"),
  194. new ExpressionBlock(
  195. Factory.Code(" ").AsStatement(),
  196. Factory.CodeTransition(),
  197. Factory.Code(@"bar").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
  198. ),
  199. Factory.Markup("\r\n </p>\r\n").Accepts(AcceptedCharacters.None)
  200. ),
  201. new MarkupBlock(
  202. Factory.Markup(@" "),
  203. Factory.MarkupTransition(),
  204. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  205. Factory.Markup("Hello!\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  206. ),
  207. Factory.Code(" var biz = boz;\r\n}").AsStatement()));
  208. }
  209. [Fact]
  210. public void ParseBlockAllowsMarkupInIfBodyWithBraces()
  211. {
  212. ParseBlockTest("if(foo) { <p>Bar</p> } else if(bar) { <p>Baz</p> } else { <p>Boz</p> }",
  213. new StatementBlock(
  214. Factory.Code("if(foo) {").AsStatement(),
  215. new MarkupBlock(
  216. Factory.Markup(" <p>Bar</p> ").Accepts(AcceptedCharacters.None)
  217. ),
  218. Factory.Code("} else if(bar) {").AsStatement(),
  219. new MarkupBlock(
  220. Factory.Markup(" <p>Baz</p> ").Accepts(AcceptedCharacters.None)
  221. ),
  222. Factory.Code("} else {").AsStatement(),
  223. new MarkupBlock(
  224. Factory.Markup(" <p>Boz</p> ").Accepts(AcceptedCharacters.None)
  225. ),
  226. Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
  227. ));
  228. }
  229. [Fact]
  230. public void ParseBlockAllowsMarkupInIfBodyWithBracesWithinCodeBlock()
  231. {
  232. ParseBlockTest("{ if(foo) { <p>Bar</p> } else if(bar) { <p>Baz</p> } else { <p>Boz</p> } }",
  233. new StatementBlock(
  234. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  235. Factory.Code(" if(foo) {").AsStatement(),
  236. new MarkupBlock(
  237. Factory.Markup(" <p>Bar</p> ").Accepts(AcceptedCharacters.None)
  238. ),
  239. Factory.Code("} else if(bar) {").AsStatement(),
  240. new MarkupBlock(
  241. Factory.Markup(" <p>Baz</p> ").Accepts(AcceptedCharacters.None)
  242. ),
  243. Factory.Code("} else {").AsStatement(),
  244. new MarkupBlock(
  245. Factory.Markup(" <p>Boz</p> ").Accepts(AcceptedCharacters.None)
  246. ),
  247. Factory.Code("} ").AsStatement(),
  248. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)
  249. ));
  250. }
  251. [Fact]
  252. public void ParseBlockSupportsMarkupInCaseAndDefaultBranchesOfSwitch()
  253. {
  254. // Arrange
  255. ParseBlockTest(@"switch(foo) {
  256. case 0:
  257. <p>Foo</p>
  258. break;
  259. case 1:
  260. <p>Bar</p>
  261. return;
  262. case 2:
  263. {
  264. <p>Baz</p>
  265. <p>Boz</p>
  266. }
  267. default:
  268. <p>Biz</p>
  269. }",
  270. new StatementBlock(
  271. Factory.Code("switch(foo) {\r\n case 0:\r\n").AsStatement(),
  272. new MarkupBlock(
  273. Factory.Markup(" <p>Foo</p>\r\n").Accepts(AcceptedCharacters.None)
  274. ),
  275. Factory.Code(" break;\r\n case 1:\r\n").AsStatement(),
  276. new MarkupBlock(
  277. Factory.Markup(" <p>Bar</p>\r\n").Accepts(AcceptedCharacters.None)
  278. ),
  279. Factory.Code(" return;\r\n case 2:\r\n {\r\n").AsStatement(),
  280. new MarkupBlock(
  281. Factory.Markup(" <p>Baz</p>\r\n").Accepts(AcceptedCharacters.None)
  282. ),
  283. new MarkupBlock(
  284. Factory.Markup(" <p>Boz</p>\r\n").Accepts(AcceptedCharacters.None)
  285. ),
  286. Factory.Code(" }\r\n default:\r\n").AsStatement(),
  287. new MarkupBlock(
  288. Factory.Markup(" <p>Biz</p>\r\n").Accepts(AcceptedCharacters.None)
  289. ),
  290. Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)));
  291. }
  292. [Fact]
  293. public void ParseBlockSupportsMarkupInCaseAndDefaultBranchesOfSwitchInCodeBlock()
  294. {
  295. // Arrange
  296. ParseBlockTest(@"{ switch(foo) {
  297. case 0:
  298. <p>Foo</p>
  299. break;
  300. case 1:
  301. <p>Bar</p>
  302. return;
  303. case 2:
  304. {
  305. <p>Baz</p>
  306. <p>Boz</p>
  307. }
  308. default:
  309. <p>Biz</p>
  310. } }",
  311. new StatementBlock(
  312. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  313. Factory.Code(" switch(foo) {\r\n case 0:\r\n").AsStatement(),
  314. new MarkupBlock(
  315. Factory.Markup(" <p>Foo</p>\r\n").Accepts(AcceptedCharacters.None)
  316. ),
  317. Factory.Code(" break;\r\n case 1:\r\n").AsStatement(),
  318. new MarkupBlock(
  319. Factory.Markup(" <p>Bar</p>\r\n").Accepts(AcceptedCharacters.None)
  320. ),
  321. Factory.Code(" return;\r\n case 2:\r\n {\r\n").AsStatement(),
  322. new MarkupBlock(
  323. Factory.Markup(" <p>Baz</p>\r\n").Accepts(AcceptedCharacters.None)
  324. ),
  325. new MarkupBlock(
  326. Factory.Markup(" <p>Boz</p>\r\n").Accepts(AcceptedCharacters.None)
  327. ),
  328. Factory.Code(" }\r\n default:\r\n").AsStatement(),
  329. new MarkupBlock(
  330. Factory.Markup(" <p>Biz</p>\r\n").Accepts(AcceptedCharacters.None)
  331. ),
  332. Factory.Code("} ").AsStatement(),
  333. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  334. }
  335. [Fact]
  336. public void ParseBlockParsesMarkupStatementOnOpenAngleBracket()
  337. {
  338. ParseBlockTest("for(int i = 0; i < 10; i++) { <p>Foo</p> }",
  339. new StatementBlock(
  340. Factory.Code("for(int i = 0; i < 10; i++) {").AsStatement(),
  341. new MarkupBlock(
  342. Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
  343. ),
  344. Factory.Code("}").AsStatement().Accepts(AcceptedCharacters.None)
  345. ));
  346. }
  347. [Fact]
  348. public void ParseBlockParsesMarkupStatementOnOpenAngleBracketInCodeBlock()
  349. {
  350. ParseBlockTest("{ for(int i = 0; i < 10; i++) { <p>Foo</p> } }",
  351. new StatementBlock(
  352. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  353. Factory.Code(" for(int i = 0; i < 10; i++) {").AsStatement(),
  354. new MarkupBlock(
  355. Factory.Markup(" <p>Foo</p> ").Accepts(AcceptedCharacters.None)
  356. ),
  357. Factory.Code("} ").AsStatement(),
  358. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  359. }
  360. [Fact]
  361. public void ParseBlockParsesMarkupStatementOnSwitchCharacterFollowedByColon()
  362. {
  363. // Arrange
  364. ParseBlockTest(@"if(foo) { @:Bar
  365. } zoop",
  366. new StatementBlock(
  367. Factory.Code("if(foo) {").AsStatement(),
  368. new MarkupBlock(
  369. Factory.Markup(" "),
  370. Factory.MarkupTransition(),
  371. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  372. Factory.Markup("Bar\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  373. ),
  374. Factory.Code("}").AsStatement()));
  375. }
  376. [Fact]
  377. public void ParseBlockParsesMarkupStatementOnSwitchCharacterFollowedByColonInCodeBlock()
  378. {
  379. // Arrange
  380. ParseBlockTest(@"{ if(foo) { @:Bar
  381. } } zoop",
  382. new StatementBlock(
  383. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  384. Factory.Code(" if(foo) {").AsStatement(),
  385. new MarkupBlock(
  386. Factory.Markup(" "),
  387. Factory.MarkupTransition(),
  388. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  389. Factory.Markup("Bar\r\n").Accepts(AcceptedCharacters.None)
  390. ),
  391. Factory.Code("} ").AsStatement(),
  392. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  393. }
  394. [Fact]
  395. public void ParseBlockCorrectlyReturnsFromMarkupBlockWithPseudoTag()
  396. {
  397. ParseBlockTest(@"if (i > 0) { <text>;</text> }",
  398. new StatementBlock(
  399. Factory.Code(@"if (i > 0) {").AsStatement(),
  400. new MarkupBlock(
  401. Factory.Markup(" "),
  402. Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
  403. Factory.Markup(";"),
  404. Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
  405. Factory.Markup(" ").Accepts(AcceptedCharacters.None)
  406. ),
  407. Factory.Code(@"}").AsStatement()));
  408. }
  409. [Fact]
  410. public void ParseBlockCorrectlyReturnsFromMarkupBlockWithPseudoTagInCodeBlock()
  411. {
  412. ParseBlockTest(@"{ if (i > 0) { <text>;</text> } }",
  413. new StatementBlock(
  414. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  415. Factory.Code(@" if (i > 0) {").AsStatement(),
  416. new MarkupBlock(
  417. Factory.Markup(" "),
  418. Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
  419. Factory.Markup(";"),
  420. Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
  421. Factory.Markup(" ").Accepts(AcceptedCharacters.None)
  422. ),
  423. Factory.Code(@"} ").AsStatement(),
  424. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  425. }
  426. [Fact]
  427. public void ParseBlockSupportsAllKindsOfImplicitMarkupInCodeBlock()
  428. {
  429. ParseBlockTest(@"{
  430. if(true) {
  431. @:Single Line Markup
  432. }
  433. foreach (var p in Enumerable.Range(1, 10)) {
  434. <text>The number is @p</text>
  435. }
  436. if(!false) {
  437. <p>A real tag!</p>
  438. }
  439. }",
  440. new StatementBlock(
  441. Factory.MetaCode("{").Accepts(AcceptedCharacters.None),
  442. Factory.Code("\r\n if(true) {\r\n").AsStatement(),
  443. new MarkupBlock(
  444. Factory.Markup(" "),
  445. Factory.MarkupTransition(),
  446. Factory.MetaMarkup(":", HtmlSymbolType.Colon),
  447. Factory.Markup("Single Line Markup\r\n").With(new SingleLineMarkupEditHandler(CSharpLanguageCharacteristics.Instance.TokenizeString, AcceptedCharacters.None))
  448. ),
  449. Factory.Code(" }\r\n foreach (var p in Enumerable.Range(1, 10)) {\r\n").AsStatement(),
  450. new MarkupBlock(
  451. Factory.Markup(@" "),
  452. Factory.MarkupTransition("<text>").Accepts(AcceptedCharacters.None),
  453. Factory.Markup("The number is "),
  454. new ExpressionBlock(
  455. Factory.CodeTransition(),
  456. Factory.Code("p").AsImplicitExpression(CSharpCodeParser.DefaultKeywords).Accepts(AcceptedCharacters.NonWhiteSpace)
  457. ),
  458. Factory.MarkupTransition("</text>").Accepts(AcceptedCharacters.None),
  459. Factory.Markup("\r\n").Accepts(AcceptedCharacters.None)
  460. ),
  461. Factory.Code(" }\r\n if(!false) {\r\n").AsStatement(),
  462. new MarkupBlock(
  463. Factory.Markup(" <p>A real tag!</p>\r\n").Accepts(AcceptedCharacters.None)
  464. ),
  465. Factory.Code(" }\r\n").AsStatement(),
  466. Factory.MetaCode("}").Accepts(AcceptedCharacters.None)));
  467. }
  468. }
  469. }