Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/codegen-core/src/__tests__/planner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const createMockNode = (args: {
},
exported: true,
language,
meta: {},
name: ref(name) as INode['name'],
scope: 'value',
symbol,
Expand Down Expand Up @@ -146,6 +147,7 @@ describe('Planner imports deduplication', () => {
},
exported: true,
language: 'typescript',
meta: {},
name: ref('Consumer') as INode['name'],
scope: 'value',
symbol: consumerSymbol,
Expand Down Expand Up @@ -195,6 +197,7 @@ describe('Planner imports deduplication', () => {
},
exported: true,
language: 'typescript',
meta: {},
name: ref('Consumer') as INode['name'],
scope: 'value',
symbol: consumerSymbol,
Expand Down Expand Up @@ -252,6 +255,7 @@ describe('Planner imports deduplication', () => {
},
exported: true,
language: 'typescript',
meta: {},
name: ref('Consumer') as INode['name'],
scope: 'value',
symbol: consumerSymbol,
Expand Down
7 changes: 5 additions & 2 deletions packages/codegen-core/src/nodes/node.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AnyString } from '@hey-api/types';

import type { IProjectMeta } from '../extensions';
import type { File } from '../files/file';
import type { Language } from '../languages/types';
import type { IAnalysisContext } from '../planner/types';
Expand All @@ -16,7 +17,7 @@ export type NodeRelationship = 'container' | 'reference';

export type NodeScope = 'type' | 'value';

export interface INode<T = unknown> {
export interface INode<T = unknown, L extends Language = Language> {
/** Perform semantic analysis. */
analyze(ctx: IAnalysisContext): void;
/** Create a shallow copy of this node. */
Expand All @@ -26,7 +27,9 @@ export interface INode<T = unknown> {
/** The file this node belongs to. */
file?: File;
/** The programming language associated with this node */
language: Language;
language: L;
/** Arbitrary language metadata. */
meta: IProjectMeta[L];
/** The display name of this node. */
readonly name: Ref<NodeName> & {
set(value: NodeName): void;
Expand Down
16 changes: 9 additions & 7 deletions packages/codegen-core/src/planner/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ import { createScope, registerChildName } from './scope';
import type { IAnalysisContext, Input } from './types';

export class AnalysisContext implements IAnalysisContext {
/** Arbitrary project metadata. */
private meta: IProjectMeta;
/**
* Stack of parent nodes during analysis.
*
* The top of the stack is the current semantic container.
*/
private _parentStack: Array<INode> = [];
private parentStack: Array<INode> = [];

/** Arbitrary project metadata. */
meta: IProjectMeta;
scope: Scope;
scopes: Scope = createScope();
symbol?: Symbol;

constructor(node: INode, meta: IProjectMeta) {
this._parentStack.push(node);
this.parentStack.push(node);
this.meta = meta;
this.scope = this.scopes;
this.symbol = node.symbol;
Expand All @@ -33,7 +33,7 @@ export class AnalysisContext implements IAnalysisContext {
* Get the current semantic parent (top of stack).
*/
get currentParent(): INode | undefined {
return this._parentStack[this._parentStack.length - 1];
return this.parentStack[this.parentStack.length - 1];
}

/**
Expand Down Expand Up @@ -73,6 +73,7 @@ export class AnalysisContext implements IAnalysisContext {
const node = fromRef(value);
this.addChild(node, 'container');
this.pushParent(node);
node.meta = this.meta[node.language] ?? {};
node.analyze(this);
this.popParent();
}
Expand Down Expand Up @@ -116,7 +117,7 @@ export class AnalysisContext implements IAnalysisContext {
* Call this when exiting a container node.
*/
popParent(): void {
this._parentStack.pop();
this.parentStack.pop();
}

popScope(): void {
Expand All @@ -127,7 +128,7 @@ export class AnalysisContext implements IAnalysisContext {
* Push a node as the current semantic parent.
*/
pushParent(node: INode): void {
this._parentStack.push(node);
this.parentStack.push(node);
}

pushScope(): void {
Expand Down Expand Up @@ -165,6 +166,7 @@ export class Analyzer {
if (cached) return cached;

node.root = true;
node.meta = this.meta[node.language] ?? {};
const ctx = new AnalysisContext(node, this.meta);
node.analyze(ctx);

Expand Down
3 changes: 0 additions & 3 deletions packages/codegen-core/src/planner/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { IProjectMeta } from '../extensions';
import type { Ref } from '../refs/types';
import type { Symbol } from '../symbols/symbol';
import type { NameScopes, Scope } from './scope';
Expand All @@ -21,8 +20,6 @@ export interface IAnalysisContext {
injectChildren(input: Input): void;
/** Get local names in the current scope. */
localNames(scope: Scope): NameScopes;
/** Arbitrary project metadata. */
meta: IProjectMeta;
/** Pop the current local scope. */
popScope(): void;
/** Push a new local scope. */
Expand Down
8 changes: 2 additions & 6 deletions packages/codegen-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ import type { INode } from './nodes/node';
import type { IProject } from './project/types';

export interface RenderContext<Node extends INode = INode> {
/**
* The current file.
*/
/** The current file. */
file: File<Node>;
/**
* The project the file belongs to.
*/
/** The project the file belongs to. */
project: IProject;
}

Expand Down
9 changes: 7 additions & 2 deletions packages/openapi-python/src/py-dsl/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
NodeNameSanitizer,
NodeRelationship,
NodeScope,
ProjectMeta,
Ref,
Symbol,
} from '@hey-api/codegen-core';
Expand All @@ -18,7 +19,10 @@ import type { AnyString } from '@hey-api/types';
import { py } from '../py-compiler';
import type { AccessOptions } from './utils/context';

export abstract class PyDsl<T extends py.Node = py.Node> implements Node<T> {
export abstract class PyDsl<
T extends py.Node = py.Node,
L extends Language = 'python',
> implements Node<T, L> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
analyze(_: AnalysisContext): void {}
clone(): this {
Expand All @@ -41,7 +45,8 @@ export abstract class PyDsl<T extends py.Node = py.Node> implements Node<T> {
} as Node['name'];
}
readonly nameSanitizer?: NodeNameSanitizer;
language: Language = 'python';
language: L = 'python' as L;
meta: Required<ProjectMeta>[L] = {} as Required<ProjectMeta>[L];
parent?: Node;
root: boolean = false;
scope?: NodeScope = 'value';
Expand Down
9 changes: 7 additions & 2 deletions packages/openapi-ts/src/ts-dsl/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
NodeNameSanitizer,
NodeRelationship,
NodeScope,
ProjectMeta,
Ref,
Symbol,
} from '@hey-api/codegen-core';
Expand All @@ -18,7 +19,10 @@ import ts from 'typescript';

import type { AccessOptions } from './utils/context';

export abstract class TsDsl<T extends ts.Node = ts.Node> implements Node<T> {
export abstract class TsDsl<
T extends ts.Node = ts.Node,
L extends Language = 'typescript',
> implements Node<T> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
analyze(_: AnalysisContext): void {}
clone(): this {
Expand All @@ -41,7 +45,8 @@ export abstract class TsDsl<T extends ts.Node = ts.Node> implements Node<T> {
} as Node['name'];
}
readonly nameSanitizer?: NodeNameSanitizer;
language: Language = 'typescript';
language: L = 'typescript' as L;
meta: Required<ProjectMeta>[L] = {} as Required<ProjectMeta>[L];
parent?: Node;
root: boolean = false;
scope?: NodeScope = 'value';
Expand Down
Loading