1
0

cpp-raw-string-delimiter-haserror.test.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import { beforeAll, describe, expect, it } from 'vitest';
  2. import { extractFromSource } from '../src/extraction';
  3. import { getParser, initGrammars, loadGrammarsForLanguages } from '../src/extraction/grammars';
  4. function rawStringSource(delimiter: string): string {
  5. return `const char* kTemplate = R"${delimiter}(
  6. struct Ignored { int v; };
  7. )${delimiter}";
  8. int after_the_raw_string(int x) {
  9. return x + 1;
  10. }
  11. `;
  12. }
  13. describe('C++ raw-string delimiter parse collapse (#1522)', () => {
  14. beforeAll(async () => {
  15. await initGrammars();
  16. await loadGrammarsForLanguages(['cpp', 'c']);
  17. });
  18. it('warns when a legal 16-character delimiter swallows every symbol', () => {
  19. const result = extractFromSource('min.cpp', rawStringSource('FILE_TEMPLATE_V1'));
  20. // The vendored tree-sitter-cpp scanner currently rejects the standard's
  21. // maximum delimiter length, consuming the following function as ERROR.
  22. expect(result.nodes.filter((n) => n.kind === 'function')).toEqual([]);
  23. expect(result.nodes.map((n) => n.kind)).toEqual(['file']);
  24. expect(result.errors).toEqual([
  25. {
  26. message:
  27. 'min.cpp: parse produced no symbols (tree has errors) — ' +
  28. 'the file is indexed but contributes nothing to the graph',
  29. severity: 'warning',
  30. code: 'parse_error',
  31. },
  32. ]);
  33. });
  34. it('extracts the function after a 15-character delimiter without warning', () => {
  35. const result = extractFromSource('min.cpp', rawStringSource('FILE_TEMPLATE_V'));
  36. expect(result.nodes.filter((n) => n.kind === 'function').map((n) => n.name))
  37. .toEqual(['after_the_raw_string']);
  38. expect(result.errors).toEqual([]);
  39. });
  40. it.each(['min.cpp', 'min.c', 'min.h'])('does not warn on a healthy include-only %s', (filePath) => {
  41. const result = extractFromSource(filePath, '#include <stdio.h>\n#include <stdlib.h>\n');
  42. expect(result.nodes.filter((n) => n.kind !== 'file' && n.kind !== 'import')).toEqual([]);
  43. expect(result.errors).toEqual([]);
  44. });
  45. it('does not warn on a healthy empty file with zero symbols', () => {
  46. const result = extractFromSource('empty.cpp', '');
  47. expect(result.nodes.map((n) => n.kind)).toEqual(['file']);
  48. expect(result.errors).toEqual([]);
  49. });
  50. it('does not warn on parse errors when a function survives', () => {
  51. const source = 'int before_the_raw_string() { return 0; }\n' + rawStringSource('FILE_TEMPLATE_V1');
  52. const tree = getParser('cpp')!.parse(source)!;
  53. try {
  54. expect(tree.rootNode.hasError).toBe(true);
  55. } finally {
  56. tree.delete();
  57. }
  58. const result = extractFromSource('min.cpp', source);
  59. expect(result.nodes.filter((n) => n.kind === 'function').map((n) => n.name))
  60. .toEqual(['before_the_raw_string']);
  61. expect(result.errors).toEqual([]);
  62. });
  63. });