Skip to content

Commit f220227

Browse files
authored
fix: import (#7)
1 parent c2be42c commit f220227

File tree

7 files changed

+168
-22
lines changed

7 files changed

+168
-22
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
],
3030
"license": "MIT",
3131
"devDependencies": {
32-
"@types/node": "^14.0.11",
33-
"@types/jest": "^26.0.22",
3432
"@midwayjs/cli": "^1.0.0",
33+
"@types/jest": "^26.0.22",
34+
"@types/node": "^14.0.11",
3535
"mwts": "^1.0.5"
3636
},
3737
"dependencies": {

src/compiler/index.ts

+83-19
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ import './handlebars/method-generate-helper';
2020

2121
import { IGenOptions } from '../types';
2222

23+
function formatImport(item: string) {
24+
const prefix = /^\./.test(item) ? '' : './';
25+
const arr = item.split('/');
26+
const filename = arr[arr.length - 1];
27+
return prefix + filename.replace('.proto', '');
28+
}
29+
2330
/** Set Compiler */
2431
export class Compiler {
2532
constructor(private readonly options: IGenOptions) {}
33+
private protoFiles: string[] = [];
34+
private protoInfo = {};
2635

2736
private resolveRootPath(root: Root): void {
2837
const paths = this.options.path;
@@ -105,7 +114,7 @@ export class Compiler {
105114
}
106115
}
107116

108-
private output(file: string, pkg: string, tmpl: string): void {
117+
private output(file: string, tmpl: string): void {
109118
const root = new Root();
110119

111120
this.resolveRootPath(root);
@@ -119,7 +128,37 @@ export class Compiler {
119128

120129
this.walkTree(root);
121130

122-
const results = compile(tmpl)(root);
131+
let results = compile(tmpl)(root);
132+
const packageArr = [];
133+
134+
// 处理继承问题
135+
results = results.replace("'@midwayjs/grpc';", matched => {
136+
return [matched]
137+
.concat(
138+
this.protoInfo[file].imports.map(item => {
139+
packageArr.push(this.findPackage(item));
140+
return `import { ${this.findPackage(item)} } from '${formatImport(
141+
item
142+
)}';`;
143+
})
144+
)
145+
.join('\n');
146+
});
147+
148+
// 移除继承的代码
149+
for (const name of packageArr) {
150+
const regexp = new RegExp(
151+
`\\/\\*.+package ${name} start[\\s\\S]*${name} end \\*\\/`,
152+
'gm'
153+
);
154+
results = results.replace(regexp, '');
155+
}
156+
157+
// 清理空导入
158+
results = results.replace(/import { {2}} from '.+';\n/, '');
159+
160+
// 清理最后的换行
161+
results = results.replace(/\n+$/, '\n');
123162

124163
const outputFile = this.options.output
125164
? join(this.options.output, basename(file))
@@ -132,22 +171,6 @@ export class Compiler {
132171
outputFileSync(outputPath, results, 'utf8');
133172
}
134173

135-
private generate(path: string, pkg: string): void {
136-
const hbTemplate = resolve(__dirname, '../../template.hbs');
137-
138-
if (!existsSync(hbTemplate)) {
139-
throw new Error(`Template ${hbTemplate} is not found`);
140-
}
141-
142-
const tmpl = readFileSync(hbTemplate, 'utf8');
143-
144-
if (this.options.verbose) {
145-
console.log(chalk.blueBright('-- found: ') + chalk.gray(path));
146-
}
147-
148-
this.output(path, pkg, tmpl);
149-
}
150-
151174
private getProtoFiles(pkg: string): void {
152175
if (!existsSync(pkg)) {
153176
throw new Error(`Directory ${pkg} is not exist`);
@@ -166,7 +189,10 @@ export class Compiler {
166189
if (stat.isDirectory()) {
167190
this.getProtoFiles(filename);
168191
} else if (filename.indexOf(this.options.target.join()) > -1) {
169-
this.generate(filename, pkg);
192+
if (this.options.verbose) {
193+
console.log(chalk.blueBright('-- found: ') + chalk.gray(filename));
194+
}
195+
this.protoFiles.push(filename);
170196
}
171197
}
172198
}
@@ -177,5 +203,43 @@ export class Compiler {
177203
this.getProtoFiles(pkg);
178204
}
179205
});
206+
207+
// 提前分析 package 和导入的情况
208+
for (const filename of this.protoFiles) {
209+
this.protoInfo[filename] = {};
210+
const originFile = readFileSync(filename, 'utf8');
211+
const regex1 = /import\s"(.+)";/g;
212+
let array1;
213+
const result = [];
214+
while ((array1 = regex1.exec(originFile)) !== null) {
215+
result.push(array1[1]);
216+
}
217+
const packageRegexp = /package\s+(.+);/;
218+
const arr = packageRegexp.exec(originFile);
219+
this.protoInfo[filename] = {
220+
packageName: arr[1],
221+
imports: result,
222+
};
223+
}
224+
225+
const hbTemplate = resolve(__dirname, '../../template.hbs');
226+
if (!existsSync(hbTemplate)) {
227+
throw new Error(`Template ${hbTemplate} is not found`);
228+
}
229+
const tmpl = readFileSync(hbTemplate, 'utf8');
230+
231+
for (const filename of this.protoFiles) {
232+
this.output(filename, tmpl);
233+
}
234+
}
235+
236+
findPackage(p: string): string {
237+
p = p.replace(/\.+\//g, '');
238+
for (const key of Object.keys(this.protoInfo)) {
239+
if (key.lastIndexOf(p) !== -1) {
240+
return this.protoInfo[key].packageName;
241+
}
242+
}
243+
return '';
180244
}
181245
}

template.hbs

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ import * as grpc from '@midwayjs/grpc';
2424
{{#if comment}}
2525
{{comment}}
2626
{{/if}}
27+
/* package {{@key}} start */
2728
export namespace {{@key}} {
2829
{{> selector }}
2930
}
30-
{{/inline}}
31+
/* package {{@key}} end */
3132

33+
{{/inline}}
3234
{{#*inline "service"}}
3335
{{#each methods}}
3436
{{else}}

test/fixtures/issue999/base.proto

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
syntax="proto3";
2+
package base; //协议包名
3+
4+
option go_package = "base";
5+
6+
import "proto/gogo/gogo.proto";
7+
import "abc.proto";
8+
9+
option (gogoproto.goproto_enum_prefix_all) = false;
10+
message Void {
11+
12+
}

test/fixtures/issue999/liveroom.proto

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
syntax = "proto3";
2+
package liveroom; //协议包名
3+
option go_package = "liveroom";
4+
import "base.proto";
5+
import "proto/gogo/gogo.proto";
6+
service LiveRoomService {
7+
// 玩家离开房间
8+
rpc LeaveRoom (GetRoomReq) returns (base.Void) {
9+
option (kitproto.id) = 4;
10+
}
11+
12+
rpc AddRoom (GetRoomReq) returns (gogo.HelloReply) {
13+
option (kitproto.id) = 4;
14+
}
15+
}
16+
17+
message GetRoomReq {
18+
optional string id = 1[(gogoproto.nullable) = false];
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
syntax = "proto3";
2+
package gogo; //协议包名
3+
4+
// The greeting service definition.
5+
service Greeter {
6+
// Sends a greeting
7+
rpc SayHello (HelloRequest) returns (HelloReply) {}
8+
}
9+
10+
// The request message containing the user's name.
11+
message HelloRequest {
12+
string name = 1;
13+
}
14+
15+
// The response message containing the greetings
16+
message HelloReply {
17+
string message = 1;
18+
}

test/index.test.ts

+31
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,35 @@ describe('/test/index.test.ts', () => {
7272

7373
await remove(join(__dirname, './fixtures/keep_case/domain'));
7474
});
75+
76+
it('test fix issue 999', async () => {
77+
const compiler = new Compiler({
78+
path: ['test/fixtures/issue999'],
79+
target: ['.proto'],
80+
ignore: ['node_modules', 'dist'],
81+
output: 'test/fixtures/issue999/domain',
82+
keepCase: true,
83+
});
84+
85+
compiler.compile();
86+
expect(existsSync(join(__dirname, './fixtures/issue999/domain/base.ts'))).toBeTruthy();
87+
expect(existsSync(join(__dirname, './fixtures/issue999/domain/gogo.ts'))).toBeTruthy();
88+
expect(existsSync(join(__dirname, './fixtures/issue999/domain/liveroom.ts'))).toBeTruthy();
89+
90+
let content = readFileSync(join(__dirname, './fixtures/issue999/domain/base.ts'), 'utf8');
91+
expect(content.includes('export namespace base {')).toBeTruthy();
92+
expect(content.includes('import { gogo } from \'./gogo\';')).toBeTruthy();
93+
expect(!content.includes('namespace gogo')).toBeTruthy();
94+
95+
content = readFileSync(join(__dirname, './fixtures/issue999/domain/gogo.ts'), 'utf8');
96+
expect(content.includes('sayHello(data: HelloRequest): Promise<HelloReply>;')).toBeTruthy();
97+
98+
content = readFileSync(join(__dirname, './fixtures/issue999/domain/liveroom.ts'), 'utf8');
99+
expect(content.includes('import { gogo } from \'./gogo\';')).toBeTruthy();
100+
expect(content.includes('import { base } from \'./base\';')).toBeTruthy();
101+
expect(!content.includes('namespace base')).toBeTruthy();
102+
expect(!content.includes('namespace gogo')).toBeTruthy();
103+
104+
await remove(join(__dirname, './fixtures/issue999/domain'));
105+
});
75106
});

0 commit comments

Comments
 (0)