python-quoted-annotation.test.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /**
  2. * A quoted (forward-reference) parameter annotation names a receiver type too
  3. * (#1684): `def f(o: "Alpha")` resolves `o.render()` exactly like `def f(o:
  4. * Alpha)`. Quoted annotations are ordinary Python — forward references, and
  5. * everything under `from __future__ import annotations`.
  6. */
  7. import { describe, it, expect, beforeAll, afterAll } from 'vitest';
  8. import * as fs from 'fs';
  9. import * as os from 'os';
  10. import * as path from 'path';
  11. import { CodeGraph } from '../src';
  12. import { initGrammars, loadAllGrammars } from '../src/extraction/grammars';
  13. let dir: string;
  14. let cg: CodeGraph;
  15. beforeAll(async () => {
  16. await initGrammars();
  17. await loadAllGrammars();
  18. dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-1684-'));
  19. fs.mkdirSync(path.join(dir, 'pkg'));
  20. fs.writeFileSync(path.join(dir, 'pkg', '__init__.py'), '');
  21. fs.writeFileSync(
  22. path.join(dir, 'pkg', 'a.py'),
  23. 'def render(x):\n return x\n\nclass Alpha:\n def render(self):\n return "a"\n\nclass Beta:\n def render(self):\n return "b"\n'
  24. );
  25. fs.writeFileSync(
  26. path.join(dir, 'pkg', 'b.py'),
  27. 'from __future__ import annotations\nfrom pkg.a import Alpha, Beta\n\n' +
  28. 'def quoted(o: "Alpha"):\n return o.render()\n\n' +
  29. "def single_quoted(o: 'Beta'):\n return o.render()\n\n" +
  30. 'def unquoted(o: Alpha):\n return o.render()\n'
  31. );
  32. cg = CodeGraph.initSync(dir);
  33. await cg.indexAll();
  34. });
  35. afterAll(() => {
  36. cg.destroy();
  37. fs.rmSync(dir, { recursive: true, force: true });
  38. });
  39. const calleeOf = (fn: string): string[] =>
  40. cg
  41. .getCallees(cg.getNodesByName(fn).find((n) => n.kind === 'function')!.id)
  42. .map(({ node }) => node.qualifiedName)
  43. .sort();
  44. describe('quoted forward-reference annotations (#1684)', () => {
  45. it('resolves the method on the quoted type, the same as the unquoted annotation', () => {
  46. expect(calleeOf('unquoted')).toEqual(['Alpha::render']);
  47. expect(calleeOf('quoted')).toEqual(['Alpha::render']);
  48. expect(calleeOf('single_quoted')).toEqual(['Beta::render']);
  49. });
  50. });