ether-code 0.9.2 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/ether.js +1 -1
- package/generators/php-generator.js +175 -28
- package/package.json +1 -1
- package/parsers/ether-parser-php.js +3 -1
package/cli/ether.js
CHANGED
|
@@ -134,7 +134,6 @@ class PHPGenerator {
|
|
|
134
134
|
'formater nombre': 'number_format',
|
|
135
135
|
'date': 'date',
|
|
136
136
|
'temps': 'time',
|
|
137
|
-
'maintenant': 'time',
|
|
138
137
|
'creer date': 'mktime',
|
|
139
138
|
'date vers temps': 'strtotime',
|
|
140
139
|
'formater date': 'date_format',
|
|
@@ -305,9 +304,33 @@ class PHPGenerator {
|
|
|
305
304
|
return this.keywordMap[normalized] || word
|
|
306
305
|
}
|
|
307
306
|
|
|
307
|
+
translateMethodName(word) {
|
|
308
|
+
if (!word) return word
|
|
309
|
+
const normalized = this.normalizeAccents(word)
|
|
310
|
+
const magicMethods = {
|
|
311
|
+
'constructeur': '__construct',
|
|
312
|
+
'destructeur': '__destruct',
|
|
313
|
+
'obtenir': '__get',
|
|
314
|
+
'definir': '__set',
|
|
315
|
+
'appeler': '__call',
|
|
316
|
+
'vers chaine': '__toString',
|
|
317
|
+
'invoquer': '__invoke',
|
|
318
|
+
'cloner': '__clone',
|
|
319
|
+
'serialiser': '__serialize',
|
|
320
|
+
'deserialiser': '__unserialize',
|
|
321
|
+
'deboguer': '__debugInfo'
|
|
322
|
+
}
|
|
323
|
+
return magicMethods[normalized] || word
|
|
324
|
+
}
|
|
325
|
+
|
|
308
326
|
extractTypeName(typeNode) {
|
|
309
327
|
if (!typeNode) return ''
|
|
310
328
|
if (typeof typeNode === 'string') return this.translateKeyword(typeNode)
|
|
329
|
+
if (typeNode.type === 'TypeHint') {
|
|
330
|
+
const types = (typeNode.types || []).map(t => this.translateKeyword(t))
|
|
331
|
+
const result = types.join('|')
|
|
332
|
+
return typeNode.nullable ? '?' + result : result
|
|
333
|
+
}
|
|
311
334
|
if (typeNode.name) return this.translateKeyword(typeNode.name)
|
|
312
335
|
if (typeNode.type === 'Identifier') return this.translateKeyword(typeNode.name || typeNode.value || '')
|
|
313
336
|
if (typeNode.value) return this.translateKeyword(typeNode.value)
|
|
@@ -317,6 +340,9 @@ class PHPGenerator {
|
|
|
317
340
|
generate(ast) {
|
|
318
341
|
this.output = ''
|
|
319
342
|
this.indent = 0
|
|
343
|
+
this.closureVariables = new Set()
|
|
344
|
+
|
|
345
|
+
this.collectClosureVariables(ast)
|
|
320
346
|
|
|
321
347
|
if (ast.phpTag !== false) {
|
|
322
348
|
this.output = '<?php\n'
|
|
@@ -341,6 +367,32 @@ class PHPGenerator {
|
|
|
341
367
|
return this.output.trim()
|
|
342
368
|
}
|
|
343
369
|
|
|
370
|
+
collectClosureVariables(ast) {
|
|
371
|
+
const nodes = Array.isArray(ast) ? ast : (ast?.body || [ast])
|
|
372
|
+
|
|
373
|
+
for (const node of nodes) {
|
|
374
|
+
if (!node) continue
|
|
375
|
+
|
|
376
|
+
if (node.type === 'VariableDeclaration') {
|
|
377
|
+
const init = node.init || node.value
|
|
378
|
+
if (init && (init.type === 'ArrowFunctionExpression' || init.type === 'FunctionExpression' || init.type === 'ClosureExpression')) {
|
|
379
|
+
const name = node.name || node.id?.name
|
|
380
|
+
if (name) this.closureVariables.add(name)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (node.body) {
|
|
385
|
+
this.collectClosureVariables(node.body)
|
|
386
|
+
}
|
|
387
|
+
if (node.consequent) {
|
|
388
|
+
this.collectClosureVariables(Array.isArray(node.consequent) ? node.consequent : [node.consequent])
|
|
389
|
+
}
|
|
390
|
+
if (node.alternate) {
|
|
391
|
+
this.collectClosureVariables(Array.isArray(node.alternate) ? node.alternate : [node.alternate])
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
344
396
|
generateNode(node) {
|
|
345
397
|
if (!node) return ''
|
|
346
398
|
|
|
@@ -376,6 +428,8 @@ class PHPGenerator {
|
|
|
376
428
|
return this.generateForStatement(node)
|
|
377
429
|
case 'ForEachStatement':
|
|
378
430
|
return this.generateForEachStatement(node)
|
|
431
|
+
case 'ForeachStatement':
|
|
432
|
+
return this.generateForEachStatement(node)
|
|
379
433
|
case 'WhileStatement':
|
|
380
434
|
return this.generateWhileStatement(node)
|
|
381
435
|
case 'DoWhileStatement':
|
|
@@ -474,9 +528,19 @@ class PHPGenerator {
|
|
|
474
528
|
}
|
|
475
529
|
|
|
476
530
|
generateUseStatement(node) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
531
|
+
if (node.imports && node.imports.length > 0) {
|
|
532
|
+
for (const imp of node.imports) {
|
|
533
|
+
const name = imp.path || imp.name
|
|
534
|
+
const alias = imp.alias ? ` as ${imp.alias}` : ''
|
|
535
|
+
const useType = node.useType ? `${node.useType} ` : ''
|
|
536
|
+
this.writeLine(`use ${useType}${name}${alias};`)
|
|
537
|
+
}
|
|
538
|
+
} else {
|
|
539
|
+
const name = node.name || node.source
|
|
540
|
+
const alias = node.alias ? ` as ${node.alias}` : ''
|
|
541
|
+
const useType = node.useType ? `${node.useType} ` : ''
|
|
542
|
+
this.writeLine(`use ${useType}${name}${alias};`)
|
|
543
|
+
}
|
|
480
544
|
return ''
|
|
481
545
|
}
|
|
482
546
|
|
|
@@ -619,7 +683,7 @@ class PHPGenerator {
|
|
|
619
683
|
this.writeLine(`${visibility} ${isStatic}${isReadonly}${typeHint}${name}${value};`)
|
|
620
684
|
} else if (node.type === 'Method' || node.kind === 'method' || node.type === 'MethodDeclaration') {
|
|
621
685
|
const name = node.name || node.key?.name || ''
|
|
622
|
-
const translatedName = this.
|
|
686
|
+
const translatedName = this.translateMethodName(name)
|
|
623
687
|
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
624
688
|
let returnType = ''
|
|
625
689
|
|
|
@@ -673,7 +737,7 @@ class PHPGenerator {
|
|
|
673
737
|
|
|
674
738
|
const visibility = 'public'
|
|
675
739
|
const name = node.name || node.key?.name || ''
|
|
676
|
-
const translatedName = this.
|
|
740
|
+
const translatedName = this.translateMethodName(name)
|
|
677
741
|
const params = (node.params || []).map(p => this.generateParam(p)).join(', ')
|
|
678
742
|
let returnType = ''
|
|
679
743
|
|
|
@@ -705,7 +769,8 @@ class PHPGenerator {
|
|
|
705
769
|
let declaration = 'enum ' + (node.name || '')
|
|
706
770
|
|
|
707
771
|
if (node.backingType) {
|
|
708
|
-
|
|
772
|
+
const type = this.extractTypeName(node.backingType)
|
|
773
|
+
if (type) declaration += ': ' + type
|
|
709
774
|
}
|
|
710
775
|
|
|
711
776
|
this.writeLine(declaration + ' {')
|
|
@@ -855,21 +920,26 @@ class PHPGenerator {
|
|
|
855
920
|
this.generateBody(node.block)
|
|
856
921
|
this.indent--
|
|
857
922
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
const
|
|
861
|
-
|
|
923
|
+
const catches = node.catches || (node.handler ? [node.handler] : [])
|
|
924
|
+
for (const catchClause of catches) {
|
|
925
|
+
const types = catchClause.types || []
|
|
926
|
+
const exceptionType = types.length > 0
|
|
927
|
+
? types.join('|')
|
|
928
|
+
: (catchClause.exceptionType || catchClause.type || 'Exception')
|
|
929
|
+
const param = catchClause.param
|
|
930
|
+
? this.generateVariable(catchClause.param)
|
|
862
931
|
: '$e'
|
|
863
932
|
this.writeLine(`} catch (${exceptionType} ${param}) {`)
|
|
864
933
|
this.indent++
|
|
865
|
-
this.generateBody(
|
|
934
|
+
this.generateBody(catchClause.body)
|
|
866
935
|
this.indent--
|
|
867
936
|
}
|
|
868
937
|
|
|
869
|
-
|
|
938
|
+
const finallyBlock = node.finally || node.finalizer
|
|
939
|
+
if (finallyBlock) {
|
|
870
940
|
this.writeLine('} finally {')
|
|
871
941
|
this.indent++
|
|
872
|
-
this.generateBody(
|
|
942
|
+
this.generateBody(finallyBlock)
|
|
873
943
|
this.indent--
|
|
874
944
|
}
|
|
875
945
|
|
|
@@ -916,19 +986,82 @@ class PHPGenerator {
|
|
|
916
986
|
|
|
917
987
|
generateCallExpression(node) {
|
|
918
988
|
let callee
|
|
989
|
+
let originalName = ''
|
|
919
990
|
|
|
920
991
|
if (typeof node.callee === 'string') {
|
|
921
|
-
|
|
992
|
+
originalName = node.callee
|
|
993
|
+
if (this.closureVariables && this.closureVariables.has(node.callee)) {
|
|
994
|
+
callee = '$' + node.callee
|
|
995
|
+
} else {
|
|
996
|
+
callee = this.translateFunction(node.callee)
|
|
997
|
+
}
|
|
922
998
|
} else if (node.callee.type === 'Identifier') {
|
|
923
|
-
|
|
999
|
+
originalName = node.callee.name
|
|
1000
|
+
if (this.closureVariables && this.closureVariables.has(node.callee.name)) {
|
|
1001
|
+
callee = '$' + node.callee.name
|
|
1002
|
+
} else {
|
|
1003
|
+
callee = this.translateFunction(node.callee.name)
|
|
1004
|
+
}
|
|
1005
|
+
} else if (node.callee.type === 'Variable') {
|
|
1006
|
+
callee = this.generateVariable(node.callee)
|
|
924
1007
|
} else if (node.callee.type === 'MemberExpression' || node.callee.type === 'StaticMemberExpression') {
|
|
925
1008
|
callee = this.generateNode(node.callee)
|
|
926
1009
|
} else {
|
|
927
1010
|
callee = this.generateNode(node.callee)
|
|
928
1011
|
}
|
|
929
1012
|
|
|
930
|
-
|
|
931
|
-
|
|
1013
|
+
let args = (node.arguments || []).map(a => this.generateNode(a))
|
|
1014
|
+
|
|
1015
|
+
args = this.reorderArguments(callee, args, originalName)
|
|
1016
|
+
args = this.addDefaultArguments(callee, args)
|
|
1017
|
+
|
|
1018
|
+
return `${callee}(${args.join(', ')})`
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
reorderArguments(func, args, originalName) {
|
|
1022
|
+
const normalized = this.normalizeAccents(originalName)
|
|
1023
|
+
|
|
1024
|
+
if ((func === 'str_replace' || normalized === 'remplacer') && args.length === 3) {
|
|
1025
|
+
return [args[1], args[2], args[0]]
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if ((func === 'array_map' || normalized === 'mapper' || normalized === 'mapper tableau' || normalized === 'transformer') && args.length === 2) {
|
|
1029
|
+
return [args[1], args[0]]
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return args
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
addDefaultArguments(func, args) {
|
|
1036
|
+
if (func === 'password_hash' && args.length === 1) {
|
|
1037
|
+
return [...args, 'PASSWORD_DEFAULT']
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
return args
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
isNativeFunction(name) {
|
|
1044
|
+
const natives = [
|
|
1045
|
+
'echo', 'print', 'var_dump', 'print_r', 'die', 'exit',
|
|
1046
|
+
'strlen', 'substr', 'strpos', 'str_replace', 'strtoupper', 'strtolower',
|
|
1047
|
+
'trim', 'ltrim', 'rtrim', 'explode', 'implode', 'sprintf', 'printf',
|
|
1048
|
+
'count', 'array_push', 'array_pop', 'array_shift', 'array_unshift',
|
|
1049
|
+
'array_merge', 'array_filter', 'array_map', 'array_reduce', 'array_keys',
|
|
1050
|
+
'array_values', 'array_sum', 'array_unique', 'array_reverse', 'sort',
|
|
1051
|
+
'in_array', 'array_key_exists', 'array_search',
|
|
1052
|
+
'is_array', 'is_string', 'is_int', 'is_float', 'is_bool', 'is_null',
|
|
1053
|
+
'is_numeric', 'is_object', 'is_callable', 'isset', 'empty', 'gettype',
|
|
1054
|
+
'intval', 'floatval', 'strval', 'boolval', 'settype',
|
|
1055
|
+
'abs', 'ceil', 'floor', 'round', 'sqrt', 'pow', 'rand', 'max', 'min', 'pi',
|
|
1056
|
+
'date', 'time', 'strtotime', 'mktime',
|
|
1057
|
+
'file_exists', 'file_get_contents', 'file_put_contents', 'fopen', 'fclose', 'fread', 'fwrite',
|
|
1058
|
+
'json_encode', 'json_decode', 'preg_match', 'preg_match_all', 'preg_replace',
|
|
1059
|
+
'header', 'session_start', 'session_destroy', 'password_hash', 'password_verify',
|
|
1060
|
+
'include', 'include_once', 'require', 'require_once',
|
|
1061
|
+
'class_exists', 'function_exists', 'method_exists', 'defined', 'define', 'constant',
|
|
1062
|
+
'new', 'throw'
|
|
1063
|
+
]
|
|
1064
|
+
return natives.includes(name)
|
|
932
1065
|
}
|
|
933
1066
|
|
|
934
1067
|
generateMemberExpression(node) {
|
|
@@ -936,9 +1069,9 @@ class PHPGenerator {
|
|
|
936
1069
|
let property
|
|
937
1070
|
|
|
938
1071
|
if (typeof node.property === 'string') {
|
|
939
|
-
property = node.property
|
|
1072
|
+
property = this.translateMemberProperty(node.property)
|
|
940
1073
|
} else if (node.property.type === 'Identifier') {
|
|
941
|
-
property = this.
|
|
1074
|
+
property = this.translateMemberProperty(node.property.name)
|
|
942
1075
|
} else {
|
|
943
1076
|
property = this.generateNode(node.property)
|
|
944
1077
|
}
|
|
@@ -951,6 +1084,26 @@ class PHPGenerator {
|
|
|
951
1084
|
return `${object}${operator}${property}`
|
|
952
1085
|
}
|
|
953
1086
|
|
|
1087
|
+
translateMemberProperty(name) {
|
|
1088
|
+
const translations = {
|
|
1089
|
+
'valeur': 'value',
|
|
1090
|
+
'nom': 'name',
|
|
1091
|
+
'message': 'message',
|
|
1092
|
+
'code': 'code',
|
|
1093
|
+
'fichier': 'file',
|
|
1094
|
+
'ligne': 'line',
|
|
1095
|
+
'precedent': 'previous',
|
|
1096
|
+
'trace': 'trace',
|
|
1097
|
+
'formater': 'format',
|
|
1098
|
+
'ajouter': 'add',
|
|
1099
|
+
'modifier': 'modify',
|
|
1100
|
+
'obtenir': 'get',
|
|
1101
|
+
'definir': 'set'
|
|
1102
|
+
}
|
|
1103
|
+
const normalized = this.normalizeAccents(name)
|
|
1104
|
+
return translations[normalized] || name
|
|
1105
|
+
}
|
|
1106
|
+
|
|
954
1107
|
generateStaticMemberExpression(node) {
|
|
955
1108
|
const cls = node.class?.name || this.generateNode(node.class)
|
|
956
1109
|
let member = node.member?.name || this.generateNode(node.member)
|
|
@@ -1044,12 +1197,6 @@ class PHPGenerator {
|
|
|
1044
1197
|
const name = node.name || node
|
|
1045
1198
|
if (typeof name !== 'string') return '$var'
|
|
1046
1199
|
|
|
1047
|
-
const normalized = this.normalizeAccents(name)
|
|
1048
|
-
|
|
1049
|
-
if (this.functionMap[normalized]) {
|
|
1050
|
-
return this.functionMap[normalized]
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
1200
|
const translated = this.translateKeyword(name)
|
|
1054
1201
|
|
|
1055
1202
|
if (translated.startsWith('$')) return translated
|
|
@@ -1057,11 +1204,11 @@ class PHPGenerator {
|
|
|
1057
1204
|
return translated
|
|
1058
1205
|
}
|
|
1059
1206
|
if (/^[A-Z]/.test(translated)) return translated
|
|
1060
|
-
if (
|
|
1207
|
+
if (!name.startsWith('$')) {
|
|
1061
1208
|
return '$' + name
|
|
1062
1209
|
}
|
|
1063
1210
|
|
|
1064
|
-
return
|
|
1211
|
+
return name
|
|
1065
1212
|
}
|
|
1066
1213
|
|
|
1067
1214
|
generateVariable(node) {
|
package/package.json
CHANGED
|
@@ -159,7 +159,6 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
159
159
|
'json decoder': 'json_decode',
|
|
160
160
|
'date': 'date',
|
|
161
161
|
'temps': 'time',
|
|
162
|
-
'maintenant': 'time',
|
|
163
162
|
'demarrer session': 'session_start',
|
|
164
163
|
'detruire session': 'session_destroy',
|
|
165
164
|
'definir cookie': 'setcookie',
|
|
@@ -635,6 +634,9 @@ class EtherParserPHP extends EtherParserBase {
|
|
|
635
634
|
type: 'ClassDeclaration',
|
|
636
635
|
name: name,
|
|
637
636
|
modifiers: modifiers,
|
|
637
|
+
abstract: modifiers.includes('abstract'),
|
|
638
|
+
final: modifiers.includes('final'),
|
|
639
|
+
readonly: modifiers.includes('readonly'),
|
|
638
640
|
superClass: superClass,
|
|
639
641
|
interfaces: interfaces,
|
|
640
642
|
body: body
|