11import { For , Show , childrenArray , computed } from "@alloy-js/core" ;
2+ import { snakeCase } from "change-case" ;
23import { dataclassesModule } from "../builtins/python.js" ;
34import { usePythonScope } from "../symbols/scopes.js" ;
45import { Atom } from "./Atom.jsx" ;
@@ -30,13 +31,9 @@ function validateDataclassMemberConflicts(kwargs: DataclassDecoratorKwargs) {
3031 if ( ! owner ) return ;
3132
3233 const hasMemberNamed = ( name : string ) : boolean => {
33- for ( const sym of owner . instanceMembers as Iterable < any > ) {
34- if ( sym . originalName === name ) return true ;
35- }
36- for ( const sym of owner . staticMembers as Iterable < any > ) {
37- if ( sym . originalName === name ) return true ;
38- }
39- return false ;
34+ const instanceNames : Set < string > | undefined = ( owner . instanceMembers as any ) ?. symbolNames ;
35+ const staticNames : Set < string > | undefined = ( owner . staticMembers as any ) ?. symbolNames ;
36+ return Boolean ( instanceNames ?. has ( name ) || staticNames ?. has ( name ) ) ;
4037 } ;
4138
4239 if ( kwargs . order === true ) {
@@ -100,6 +97,9 @@ export const dataclassDecoratorKeys = [
10097 "slots" ,
10198 "weakrefSlot" ,
10299] as const ;
100+ export const dataclassDecoratorKeySet = new Set < string > (
101+ dataclassDecoratorKeys as unknown as string [ ] ,
102+ ) ;
103103export type DataclassDecoratorKey = ( typeof dataclassDecoratorKeys ) [ number ] ;
104104export type DataclassDecoratorKwargs = Partial <
105105 Record < DataclassDecoratorKey , boolean >
@@ -110,7 +110,7 @@ export interface DataclassDeclarationProps
110110 DataclassDecoratorKwargs { }
111111
112112/**
113- * Renders a Python dataclass. Uses ClassDeclaration component internally.
113+ * Renders a Python dataclass.
114114 *
115115 * Example:
116116 * ```tsx
@@ -138,38 +138,20 @@ export interface DataclassDeclarationProps
138138 * ```
139139 */
140140export function DataclassDeclaration ( props : DataclassDeclarationProps ) {
141- const decoratorKeys : ( keyof DataclassDecoratorKwargs ) [ ] = [
142- ...dataclassDecoratorKeys ,
143- ] ;
144- const validKeySet = new Set < string > ( decoratorKeys as unknown as string [ ] ) ;
145141 // Collect flags from props in the order they appear (preserves emission order)
146- const orderedKwargs : Array < [ keyof DataclassDecoratorKwargs , any ] > = [ ] ;
142+ const decoratorEntries : Array < [ string , any ] > = [ ] ;
143+ const kwargs = { } as DataclassDecoratorKwargs ;
147144 for ( const key of Object . keys ( props ) ) {
148145 // Only include known flags; skip undefined values
149- if ( validKeySet . has ( key ) ) {
146+ if ( dataclassDecoratorKeySet . has ( key ) ) {
150147 const value = ( props as any ) [ key ] ;
151- if ( value !== undefined )
152- orderedKwargs . push ( [ key as keyof DataclassDecoratorKwargs , value ] ) ;
148+ if ( value !== undefined ) {
149+ ( kwargs as any ) [ key ] = value ;
150+ decoratorEntries . push ( [ snakeCase ( key ) , value ] ) ;
151+ }
153152 }
154153 }
155- // Materialize ordered entries into an object for validation/rendering
156- const kwargs = orderedKwargs . reduce ( ( acc , [ k , v ] ) => {
157- ( acc as any ) [ k ] = v ;
158- return acc ;
159- } , { } as DataclassDecoratorKwargs ) ;
160- const hasDecoratorArgs = orderedKwargs . length > 0 ;
161- const toSnakeCase = ( s : string ) : string =>
162- s
163- . replace ( / ( [ a - z \d ] ) ( [ A - Z ] ) / g, "$1_$2" )
164- . replace ( / ( [ A - Z ] + ) ( [ A - Z ] [ a - z ] ) / g, "$1_$2" )
165- . toLowerCase ( ) ;
166- const decoratorEntries = orderedKwargs . map ( ( [ k , v ] ) => {
167- const pyKey = toSnakeCase ( k as unknown as string ) ;
168- return [ pyKey , v ] as const ;
169- } ) ;
170- const hasBodyChildren = computed ( ( ) =>
171- childrenArray ( ( ) => props . children ) . some ( Boolean ) ,
172- ) ;
154+ const hasDecoratorArgs = decoratorEntries . length > 0 ;
173155
174156 if ( hasDecoratorArgs ) {
175157 validateDataclassDecoratorArgs ( kwargs ) ;
@@ -180,14 +162,6 @@ export function DataclassDeclaration(props: DataclassDeclarationProps) {
180162 return null ;
181163 }
182164
183- const classBody =
184- hasBodyChildren . value ?
185- < >
186- < StatementList > { props . children } </ StatementList >
187- < RunSymbolValidation />
188- </ >
189- : undefined ;
190-
191165 return (
192166 < >
193167 { "@" }
@@ -205,7 +179,8 @@ export function DataclassDeclaration(props: DataclassDeclarationProps) {
205179 </ Show >
206180 < hbr />
207181 < ClassDeclaration name = { props . name } bases = { props . bases } doc = { props . doc } >
208- { classBody }
182+ < StatementList > { props . children } </ StatementList >
183+ < RunSymbolValidation />
209184 </ ClassDeclaration >
210185 </ >
211186 ) ;
0 commit comments