strip-comments.test.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { describe, it, expect } from 'vitest';
  2. import { stripCommentsForRegex } from '../src/resolution/strip-comments';
  3. describe('stripCommentsForRegex', () => {
  4. it('python: strips line comments', () => {
  5. const src = "x = 1 # path('/fake/', View)\nreal = 2";
  6. const out = stripCommentsForRegex(src, 'python');
  7. expect(out).not.toMatch(/path\('\/fake\//);
  8. expect(out).toMatch(/real = 2/);
  9. });
  10. it('python: strips triple-quoted docstrings', () => {
  11. const src = `"""
  12. path('/in-docstring/', View)
  13. """
  14. real = 1
  15. `;
  16. const out = stripCommentsForRegex(src, 'python');
  17. expect(out).not.toMatch(/in-docstring/);
  18. expect(out).toMatch(/real = 1/);
  19. });
  20. it('python: keeps # inside strings', () => {
  21. const src = `path('#/fragment/', View)\n`;
  22. const out = stripCommentsForRegex(src, 'python');
  23. expect(out).toContain("'#/fragment/'");
  24. });
  25. it('python: handles triple-single-quoted docstrings', () => {
  26. const src = `'''\npath('/fake/')\n'''\nreal = 1\n`;
  27. const out = stripCommentsForRegex(src, 'python');
  28. expect(out).not.toMatch(/fake/);
  29. expect(out).toMatch(/real = 1/);
  30. });
  31. it('typescript: strips //, /* */', () => {
  32. const src =
  33. "// app.get('/fake', x)\n/* app.get('/also-fake', y) */\napp.get('/real', z)";
  34. const out = stripCommentsForRegex(src, 'typescript');
  35. expect(out).not.toMatch(/fake/);
  36. expect(out).toMatch(/'\/real'/);
  37. });
  38. it('typescript: keeps // inside strings', () => {
  39. const src = `const url = "https://example.com/path";\n`;
  40. const out = stripCommentsForRegex(src, 'typescript');
  41. expect(out).toContain('https://example.com/path');
  42. });
  43. it('php: strips //, #, and /* */', () => {
  44. const src =
  45. "// Route::get('/a', X::class)\n# Route::get('/b', Y::class)\n/* Route::get('/c', Z::class) */\nReal::go();";
  46. const out = stripCommentsForRegex(src, 'php');
  47. expect(out).not.toMatch(/'\/a'/);
  48. expect(out).not.toMatch(/'\/b'/);
  49. expect(out).not.toMatch(/'\/c'/);
  50. expect(out).toContain('Real::go();');
  51. });
  52. it('ruby: strips =begin/=end', () => {
  53. const src =
  54. "=begin\nget '/fake', to: 'x#y'\n=end\nget '/real', to: 'a#b'\n";
  55. const out = stripCommentsForRegex(src, 'ruby');
  56. expect(out).not.toMatch(/fake/);
  57. expect(out).toMatch(/'\/real'/);
  58. });
  59. it('ruby: strips # comments', () => {
  60. const src = "# get '/fake', to: 'x#y'\nget '/real', to: 'a#b'\n";
  61. const out = stripCommentsForRegex(src, 'ruby');
  62. expect(out).not.toMatch(/fake/);
  63. expect(out).toMatch(/'\/real'/);
  64. });
  65. it('rust: handles nested block comments', () => {
  66. const src =
  67. '/* outer /* inner */ still in outer */ .route("/real", get(h))';
  68. const out = stripCommentsForRegex(src, 'rust');
  69. expect(out).not.toMatch(/inner/);
  70. expect(out).toMatch(/\/real/);
  71. });
  72. it('go: keeps backtick raw strings intact, strips // comments', () => {
  73. const src = '// r.GET("/fake", h)\nr.GET(`/real`, h2)\n';
  74. const out = stripCommentsForRegex(src, 'go');
  75. expect(out).not.toMatch(/fake/);
  76. // backtick raw string contents preserved
  77. expect(out).toMatch(/`\/real`/);
  78. });
  79. it('go: strips block comments containing route-shaped text', () => {
  80. const src = '/* r.GET("/fake", h) */\nr.GET("/real", h2)\n';
  81. const out = stripCommentsForRegex(src, 'go');
  82. expect(out).not.toMatch(/fake/);
  83. expect(out).toMatch(/"\/real"/);
  84. });
  85. it('java: strips // and /* */ comments', () => {
  86. const src =
  87. '// @GetMapping("/fake")\n/* @PostMapping("/also-fake") */\n@GetMapping("/real")\n';
  88. const out = stripCommentsForRegex(src, 'java');
  89. expect(out).not.toMatch(/fake/);
  90. expect(out).toMatch(/"\/real"/);
  91. });
  92. it('csharp: strips // and /* */ comments', () => {
  93. const src =
  94. '// [HttpGet("/fake")]\n/* [HttpPost("/also-fake")] */\n[HttpGet("/real")]\n';
  95. const out = stripCommentsForRegex(src, 'csharp');
  96. expect(out).not.toMatch(/fake/);
  97. expect(out).toMatch(/"\/real"/);
  98. });
  99. it('swift: strips // and /* */ comments', () => {
  100. const src =
  101. '// app.get("fake", use: x)\n/* app.get("also-fake", use: y) */\napp.get("real", use: z)\n';
  102. const out = stripCommentsForRegex(src, 'swift');
  103. expect(out).not.toMatch(/fake/);
  104. expect(out).toMatch(/"real"/);
  105. });
  106. it('preserves line numbers (newlines retained)', () => {
  107. const src = "line1\n# comment with path('/fake/')\nline3";
  108. const out = stripCommentsForRegex(src, 'python');
  109. expect(out.split('\n').length).toBe(3);
  110. expect(out.split('\n')[2]).toBe('line3');
  111. });
  112. it('preserves overall length so source offsets stay valid', () => {
  113. const src = "x = 1 # path('/fake/', View)\nreal = 2";
  114. const out = stripCommentsForRegex(src, 'python');
  115. expect(out.length).toBe(src.length);
  116. });
  117. });