mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-02 09:45:39 +08:00
fix(astro): the component name heuristic applies to .astro files only (#2245)
Astro components are used in Astro markup; a .ts / .d.ts type name sharing a component's name (Playwright's Page, a declaration file's Image) is no component. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
000c986276
commit
b2afa75f08
@@ -14,6 +14,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
### Fixes
|
||||
|
||||
- In Astro projects, the component-name convention now applies only inside `.astro` files, where components are used. Before, a TypeScript type with a component's name was linked to that component: astrowind's `image?: Image` and `callToAction?: CallToAction` in its type declarations, and starlight's Playwright `page: Page` in its tests.
|
||||
- In JavaScript and TypeScript, the Express conventions for middleware (`validate…`, `auth`, `logger`, …), controllers and services now pick only the calling file's own declaration. Another file's is reached only through an `import` or `require`. Before, SvelteKit's remote functions linked `validate(arg)` to its config loader's `validate` in another package, and Express's examples linked `logger('dev')` to one example's `logger`.
|
||||
- An Objective-C class that conforms to a protocol of its own name now links to that protocol instead of to itself. Swift's naming conventions for views, models and controllers also no longer apply to Objective-C code. Before, every one of SDWebImage's `@interface SDDiskCache : NSObject <SDDiskCache>`-style classes implemented itself.
|
||||
- In Solidity, a call to an overloaded function now reaches the overload whose parameter count it fits, as in the other languages with overloading. Before, OpenZeppelin's `_checkRole(role, _msgSender())` inside the one-argument `_checkRole(bytes32 role)` was linked to itself.
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* An Astro component is used in Astro markup, so the component name
|
||||
* heuristic applies to `.astro` files only: astrowind's `types.d.ts`
|
||||
* (`image?: Image`, `callToAction?: CallToAction`) and starlight's
|
||||
* Playwright `page: Page` went to `Image.astro`, `CallToAction.astro` and
|
||||
* `Page.astro`.
|
||||
*/
|
||||
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { CodeGraph } from '../src';
|
||||
|
||||
let root = '';
|
||||
let cg: CodeGraph;
|
||||
|
||||
beforeAll(async () => {
|
||||
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-astro-markup-'));
|
||||
const files: Record<string, string> = {
|
||||
'package.json': JSON.stringify({ name: 'site', private: true, dependencies: { astro: '^5.0.0' }, devDependencies: { '@playwright/test': '^1.0.0' } }),
|
||||
'astro.config.mjs': 'export default {};\n',
|
||||
'src/components/Page.astro': `---
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
<main>{title}</main>
|
||||
`,
|
||||
'tests/test-utils.ts': `import { type Page } from '@playwright/test';
|
||||
|
||||
export class StarlightPage {
|
||||
private readonly page: Page;
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
}
|
||||
`,
|
||||
};
|
||||
for (const [rel, content] of Object.entries(files)) {
|
||||
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
|
||||
fs.writeFileSync(path.join(root, rel), content);
|
||||
}
|
||||
cg = await CodeGraph.init(root, { index: true });
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
cg?.close();
|
||||
if (root) fs.rmSync(root, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('Astro components', () => {
|
||||
it('are never what a TypeScript type name means', () => {
|
||||
const ids = cg.getNodesInFile('tests/test-utils.ts').map((n) => n.id);
|
||||
const targets = cg.getOutgoingEdgesFrom(ids).filter((e) => e.kind !== 'contains').map((e) => cg.getNode(e.target)!.filePath);
|
||||
expect(targets).not.toContain('src/components/Page.astro');
|
||||
});
|
||||
});
|
||||
@@ -74,7 +74,10 @@ export const astroResolver: FrameworkResolver = {
|
||||
// Pattern 3: Component references (PascalCase) — resolve to component
|
||||
// nodes. Template tags arrive as `references`, frontmatter expression
|
||||
// usages as `calls`.
|
||||
// Only from Astro markup: a `.ts` file's `Page` (Playwright's) or a
|
||||
// declaration file's `image?: Image` is no `Page.astro` / `Image.astro`.
|
||||
if (
|
||||
ref.filePath.endsWith('.astro') &&
|
||||
isPascalCase(ref.referenceName) &&
|
||||
(ref.referenceKind === 'references' || ref.referenceKind === 'calls')
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user