Skip to content

Commit eb0f7f5

Browse files
committed
support typedef
1 parent eff1cc9 commit eb0f7f5

File tree

17 files changed

+448
-14
lines changed

17 files changed

+448
-14
lines changed

src/generator.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ function resolveDependencies(lang, config, ast) {
7070
let client_name = default_client_name;
7171
let model_dir = default_model_dir;
7272
let lang_config = !meta[lang] ? {} : meta[lang];
73+
let typedef = {};
7374
if (lang_config.package) {
7475
package_name = lang_config.package;
7576
}
@@ -79,6 +80,17 @@ function resolveDependencies(lang, config, ast) {
7980
if (lang_config.modelDirName) {
8081
model_dir = lang_config.modelDirName;
8182
}
83+
if (lang_config.typedef) {
84+
const moduleTypedef = lang_config.typedef;
85+
Object.keys(moduleTypedef || {}).forEach((types) => {
86+
if (!typedef[types]) {
87+
typedef[types] = {};
88+
}
89+
typedef[types].import = moduleTypedef[types].import;
90+
typedef[types].type = moduleTypedef[types].type;
91+
typedef[types].package = moduleTypedef[types].package;
92+
});
93+
}
8294
// check package name duplication
8395
if (package_sets.indexOf(package_name.toLowerCase()) > 0) {
8496
debug.stack(`The package name (${package_name}) has been defined in ${aliasId} dara package.`);
@@ -99,7 +111,8 @@ function resolveDependencies(lang, config, ast) {
99111
package_name,
100112
client_name,
101113
client_alias,
102-
model_dir
114+
model_dir,
115+
typedef
103116
};
104117
});
105118
return dependencies;
@@ -199,12 +212,14 @@ class Generator {
199212
dir: meta.outputDir,
200213
};
201214
const meta_lang_config = !meta[lang] ? {} : meta[lang];
215+
const typedef = meta[lang] && meta[lang].typedef ? meta[lang].typedef : {};
202216
this.config = _assignObject(
203217
config,
204218
common_config,
205219
lang_config,
206220
meta,
207-
meta_lang_config
221+
meta_lang_config,
222+
typedef
208223
);
209224
}
210225

src/langs/common/combinator.js

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class BaseCombinator {
3232

3333
this.config = config;
3434
this.dependencies = dependencies;
35+
this.typedef = config.typedef;
3536

3637
_config(this.config);
3738
}
@@ -88,6 +89,8 @@ class BaseCombinator {
8889
path_name = this.addModelInclude(path_name.substr(1));
8990
} else if (path_name.indexOf('$') === 0) { // System : Tea Core Class
9091
path_name = this.addInclude(path_name);
92+
} else if (path_name.indexOf('%') === 0) { // Typedef
93+
path_name = this.addTypedefInclude(path_name.substr(1));
9194
}
9295
}
9396
return _name(path_name, avoidKeyword);

src/langs/php/combinator.js

+52-11
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,39 @@ class Combinator extends CombinatorBase {
169169
return last;
170170
}
171171

172+
addTypedefInclude(typeName) {
173+
let accessPath = typeName.split('.');
174+
let importName = '';
175+
let fromName = '';
176+
let typedefModule = {};
177+
if (accessPath.length === 2) {
178+
if (this.dependencies[accessPath[0]]
179+
&& this.dependencies[accessPath[0]].typedef
180+
&& this.dependencies[accessPath[0]].typedef[accessPath[1]]) {
181+
typedefModule = this.dependencies[accessPath[0]].typedef[accessPath[1]];
182+
}
183+
} else if (accessPath.length === 1 && this.typedef[accessPath[0]]) {
184+
typedefModule = this.typedef[accessPath[0]];
185+
}
186+
if (typedefModule.import || typedefModule.package) {
187+
if (typedefModule.import) {
188+
fromName = typedefModule.import;
189+
}
190+
if (typedefModule.type) {
191+
importName = typedefModule.type;
192+
}
193+
}
194+
195+
let existResult = this.includeList.some(item => item.import === importName && item.from === fromName);
196+
if (!existResult) {
197+
this.includeList.push({
198+
import: fromName && importName ? `${fromName}\\${importName}` : fromName ? fromName : importName ? importName : null,
199+
alias: null,
200+
});
201+
}
202+
return typedefModule.type || typeName;
203+
}
204+
172205
combine(objectArr = []) {
173206
if (this.config.packageInfo) {
174207
const packageInfo = new PackageInfo(this.config, this.dependencies);
@@ -466,7 +499,11 @@ class Combinator extends CombinatorBase {
466499
} else if (prop.type instanceof TypeBase || prop.type instanceof TypeBytes || prop.type instanceof TypeStream) {
467500
emitter.emitln(`$res['${name}'] = $this->${prop.name};`, this.level);
468501
} else {
469-
emitter.emitln(`$res['${name}'] = null !== $this->${prop.name} ? $this->${prop.name}->toMap() : null;`, this.level);
502+
if (prop.type.objectName.indexOf('%') === 0) {
503+
emitter.emitln(`$res['${name}'] = $this->${prop.name};`, this.level);
504+
} else {
505+
emitter.emitln(`$res['${name}'] = null !== $this->${prop.name} ? $this->${prop.name}->toMap() : null;`, this.level);
506+
}
470507
}
471508
this.levelDown();
472509
emitter.emitln('}', this.level);
@@ -516,7 +553,7 @@ class Combinator extends CombinatorBase {
516553
}
517554
this.levelDown();
518555
emitter.emitln('}', this.level);
519-
} else if (prop.type instanceof TypeObject) {
556+
} else if (prop.type instanceof TypeObject && prop.type.objectName.indexOf('%') !== 0) {
520557
emitter.emitln(`$model->${prop.name} = ${this.resolveName(prop.type.objectName)}::fromMap(${mapVal});`, this.level);
521558
} else {
522559
emitter.emitln(`$model->${prop.name} = ${mapVal};`, this.level);
@@ -724,24 +761,28 @@ class Combinator extends CombinatorBase {
724761
let importClass;
725762
if (include.import === this.config.tea.exception.name) {
726763
importClass = include.import;
727-
} else {
764+
} else if (include.import) {
728765
importClass = include.import.split('\\').filter(str => str.length > 0).join('\\');
729766
}
730-
let emitContent = include.alias ? `use ${importClass} as ${include.alias.split('->').join('')};` : `use ${importClass};`;
731-
if (emitSet.indexOf(emitContent) === -1) {
732-
emitter.emitln(emitContent);
733-
emitSet.push(emitContent);
767+
if (importClass) {
768+
let emitContent = include.alias ? `use ${importClass} as ${include.alias.split('->').join('')};` : `use ${importClass};`;
769+
if (emitSet.indexOf(emitContent) === -1) {
770+
emitter.emitln(emitContent);
771+
emitSet.push(emitContent);
772+
}
734773
}
735774
});
736775
if (this.includeList.length) {
737776
emitter.emitln();
738777
}
739778
this.includeModelList.forEach(include => {
740779
const importClass = include.import.split('\\').filter(str => str.length > 0).join('\\');
741-
let emitContent = include.alias ? `use ${importClass} as ${include.alias};` : `use ${importClass};`;
742-
if (emitSet.indexOf(emitContent) === -1) {
743-
emitter.emitln(emitContent);
744-
emitSet.push(emitContent);
780+
if (importClass) {
781+
let emitContent = include.alias ? `use ${importClass} as ${include.alias};` : `use ${importClass};`;
782+
if (emitSet.indexOf(emitContent) === -1) {
783+
emitter.emitln(emitContent);
784+
emitSet.push(emitContent);
785+
}
745786
}
746787
});
747788
if (this.includeModelList.length) {

src/langs/php/package_info.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,18 @@ class PackageInfo extends BasePackageInfo {
9999
// extra require
100100
let json = JSON.parse(content);
101101
Object.keys(dependencies).forEach(key => {
102-
const item = dependencies[key].meta;
102+
Object.keys(dependencies[key].typedef).forEach((types) => {
103+
if (dependencies[key].typedef[types].package) {
104+
let [pack, version] = dependencies[key].typedef[types].package.split(':');
105+
if (version && version[0] && version[0] !== '^') {
106+
version = '^' + version;
107+
}
108+
json.require[pack] = version;
109+
}
110+
});
103111
let name;
104112
let version = '*';
113+
const item = dependencies[key].meta;
105114
if (item.releases && item.releases.php) {
106115
let [p, v] = item.releases.php.split(':');
107116
name = p;
@@ -124,6 +133,17 @@ class PackageInfo extends BasePackageInfo {
124133
}
125134
json.require[name] = version;
126135
});
136+
if (config.typedef) {
137+
Object.keys(config.typedef).forEach((types) => {
138+
if (config.typedef[types].package) {
139+
let [pack, version] = config.typedef[types].package.split(':');
140+
if (version && version[0] && version[0] !== '^') {
141+
version = '^' + version;
142+
}
143+
json.require[pack] = version;
144+
}
145+
});
146+
}
127147
if (config.maintainers) {
128148
json.authors = [];
129149
config.maintainers.forEach(maintainer => {

src/resolver/base.js

+15
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ class BaseResolver {
140140
return new TypeObject(`#${typeNode.lexeme}`);
141141
} else if (typeNode.idType === 'module') {
142142
return new TypeObject(`^${typeNode.lexeme}`);
143+
} else if (typeNode.idType === 'typedef') {
144+
return new TypeObject(`%${typeNode.lexeme}`);
143145
} else if (typeNode.idType === 'builtin_model') {
144146
return new TypeObject(`^${typeNode.lexeme}`);
145147
}
@@ -149,6 +151,8 @@ class BaseResolver {
149151
if (typeNode.fieldType.idType) {
150152
if (typeNode.fieldType.idType === 'module') {
151153
return new TypeObject(`^${typeNode.fieldType.lexeme}`);
154+
} else if (typeNode.fieldType.idType === 'typedef') {
155+
return new TypeObject(`%${typeNode.fieldType.lexeme}`);
152156
}
153157
return new TypeObject(`#${typeNode.fieldType.lexeme}`);
154158
}
@@ -183,6 +187,17 @@ class BaseResolver {
183187
tmp.push(item.lexeme);
184188
});
185189
return new TypeObject(`#${tmp.join('.')}`);
190+
} else if (typeNode.type === 'moduleTypedef') {
191+
let tmp = [];
192+
typeNode.path.forEach(item => {
193+
tmp.push(item.lexeme);
194+
});
195+
return new TypeObject(`%${tmp.join('.')}`);
196+
} else if (typeNode.type === 'typedef') {
197+
if (typeNode.moduleName) {
198+
return new TypeObject(`%${typeNode.moduleName}.${typeNode.name}`);
199+
}
200+
return new TypeObject(`%${typeNode.name}`);
186201
} else if (typeNode.type === 'subModel' || typeNode.type === 'subModel_or_moduleModel') {
187202
// subModel_or_moduleModel is retained for compatibility with older parser.
188203
let tmp = [];

tests/expected/typedef/.gitignore

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
composer.phar
2+
/vendor/
3+
4+
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
5+
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
6+
composer.lock
7+
8+
.vscode/
9+
.idea
10+
.DS_Store
11+
12+
cache/
13+
*.cache
14+
runtime/
15+
.php_cs.cache

tests/expected/typedef/.php_cs.dist

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/*
3+
* This document has been generated with
4+
* https://mlocati.github.io/php-cs-fixer-configurator/#version:2.15|configurator
5+
* you can change this configuration by importing this file.
6+
*/
7+
8+
return PhpCsFixer\Config::create()
9+
->setRiskyAllowed(true)
10+
->setIndent(' ')
11+
->setRules([
12+
'@PSR2' => true,
13+
'@PhpCsFixer' => true,
14+
'@Symfony:risky' => true,
15+
'concat_space' => ['spacing' => 'one'],
16+
'array_syntax' => ['syntax' => 'short'],
17+
'array_indentation' => true,
18+
'combine_consecutive_unsets' => true,
19+
'method_separation' => true,
20+
'single_quote' => true,
21+
'declare_equal_normalize' => true,
22+
'function_typehint_space' => true,
23+
'hash_to_slash_comment' => true,
24+
'include' => true,
25+
'lowercase_cast' => true,
26+
'no_multiline_whitespace_before_semicolons' => true,
27+
'no_leading_import_slash' => true,
28+
'no_multiline_whitespace_around_double_arrow' => true,
29+
'no_spaces_around_offset' => true,
30+
'no_unneeded_control_parentheses' => true,
31+
'no_unused_imports' => true,
32+
'no_whitespace_before_comma_in_array' => true,
33+
'no_whitespace_in_blank_line' => true,
34+
'object_operator_without_whitespace' => true,
35+
'single_blank_line_before_namespace' => true,
36+
'single_class_element_per_statement' => true,
37+
'space_after_semicolon' => true,
38+
'standardize_not_equals' => true,
39+
'ternary_operator_spaces' => true,
40+
'trailing_comma_in_multiline_array' => true,
41+
'trim_array_spaces' => true,
42+
'unary_operator_spaces' => true,
43+
'whitespace_after_comma_in_array' => true,
44+
'no_extra_consecutive_blank_lines' => [
45+
'curly_brace_block',
46+
'extra',
47+
'parenthesis_brace_block',
48+
'square_brace_block',
49+
'throw',
50+
'use',
51+
],
52+
'binary_operator_spaces' => [
53+
'align_double_arrow' => true,
54+
'align_equals' => true,
55+
],
56+
'braces' => [
57+
'allow_single_line_closure' => true,
58+
],
59+
])
60+
->setFinder(
61+
PhpCsFixer\Finder::create()
62+
->exclude('vendor')
63+
->exclude('tests')
64+
->in(__DIR__)
65+
);

tests/expected/typedef/autoload.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
if (file_exists(__DIR__ . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'autoload.php')) {
4+
require_once __DIR__ . \DIRECTORY_SEPARATOR . 'vendor' . \DIRECTORY_SEPARATOR . 'autoload.php';
5+
}
6+
7+
spl_autoload_register(function ($class) {
8+
$name = str_replace('Darabonba\\Tests\\', '', $class);
9+
$file = __DIR__ . \DIRECTORY_SEPARATOR . 'src' . \DIRECTORY_SEPARATOR . str_replace('\\', \DIRECTORY_SEPARATOR, $name) . '.php';
10+
if (file_exists($file)) {
11+
require_once $file;
12+
return true;
13+
}
14+
return false;
15+
});

tests/expected/typedef/composer.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "darabonba/tests",
3+
"description": "Darabonba Tests",
4+
"type": "library",
5+
"license": "Apache-2.0",
6+
"authors": [],
7+
"require": {
8+
"php": ">5.5",
9+
"guzzlehttp/psr7": "^1.8.5 || ^2.2.1",
10+
"source": "^*",
11+
"alibabacloud/tea": "^3.1.23",
12+
"guzzlehttp/guzzle": "^6.5.6 || ^7.4.3"
13+
},
14+
"autoload": {
15+
"psr-4": {
16+
"Darabonba\\Tests\\": "src"
17+
}
18+
},
19+
"scripts": {
20+
"fixer": "php-cs-fixer fix ./"
21+
},
22+
"config": {
23+
"sort-packages": true,
24+
"preferred-install": "dist",
25+
"optimize-autoloader": true
26+
},
27+
"prefer-stable": true
28+
}

0 commit comments

Comments
 (0)