From 4ebb101bf83ecb4c81167f767b13751cdf498c76 Mon Sep 17 00:00:00 2001 From: peze <954152927@qq.com> Date: Thu, 7 Aug 2025 19:05:58 +0800 Subject: [PATCH] fix for sse --- lib/builtin.js | 15 ++++++++--- lib/generator.js | 25 ++++++++++++------- lib/helper.js | 7 ++++++ .../builtin/tea_python_tests/client.py | 2 +- .../complex/tea_python_tests/client.py | 8 +++--- tests/fixtures/complex/libraries/import.dara | 11 ++++++++ tests/fixtures/complex/main.dara | 4 +-- 7 files changed, 53 insertions(+), 19 deletions(-) diff --git a/lib/builtin.js b/lib/builtin.js index a4d3068..8707b7a 100644 --- a/lib/builtin.js +++ b/lib/builtin.js @@ -148,13 +148,22 @@ class URL extends Builtin { class Stream extends Builtin { constructor(generator) { - const methods = ['readAsBytes', 'readAsJSON', 'readAsString', 'readAsSSE']; + const methods = ['readAsBytes', 'readAsJSON', 'readAsString']; super(generator, `${CORE}Stream`, methods); } + readAsSSE(ast, level, async) { + this.generator.imports.push(_getImport(this.module)); + this.generator.emit(`${this.module}.read_as_sse`); + if(async) { + this.generator.emit('_async'); + } + this.generator.visitArgs(ast.args, level); + } + write(ast, level, async) { if(async) { - this.emit('awiat '); + this.emit('await '); } this.generator.emit(`${_snakeCase(ast.left.id.lexeme)}.write${async ? '_async' : ''}(`); this.generator.visitExpr(ast.args[0], level); @@ -431,7 +440,7 @@ class Func { sleep(ast, level, async) { const clientName = this.getClientName(); if(async) { - this.generator.emit('awiat '); + this.generator.emit('await '); } this.generator.emit(`${clientName}.sleep`); if(async) { diff --git a/lib/generator.js b/lib/generator.js index 97ab1b9..8d15b40 100644 --- a/lib/generator.js +++ b/lib/generator.js @@ -1741,17 +1741,19 @@ setup( assert.equal(ast.left.type, 'method_call'); const name = _name(ast.left.id); const functionName = _avoidKeywords(_snakeCase(name)); + const sse = ast.notes && ast.notes.find(note => note.note.lexeme === '@sse'); + const isSSE = sse && sse.arg.value; if (name.startsWith('$') && this.builtin[name]) { const method = name.replace('$', ''); this.builtin[name][method](ast, level, ast.isAsync && this.isAsyncFunction); return; - } else if (this.isStaticFunction === false && this.isAsyncFunction && ast.isAsync) { - this.emit(`await self.${functionName}_async`); + } else if (this.isStaticFunction === false && this.isAsyncFunction && ast.isAsync){ + this.emit(`${isSSE ? '' : 'await '}self.${functionName}_async`); } else if (this.isStaticFunction === false) { this.emit(`self.${functionName}`); } else if (ast.isAsync && this.isAsyncFunction) { - this.emit(`await ${this.className}.${functionName}_async`); - } else { + this.emit(`${isSSE ? '' : 'await '}${this.className}.${functionName}_async`); + } else { const functionName = _snakeCase(name); this.emit(`${this.className}.${functionName}`); } @@ -1763,7 +1765,9 @@ setup( assert.equal(ast.left.type, 'instance_call'); const method = _name(ast.left.propertyPath[0]); const async = ast.isAsync && this.isAsyncFunction; - if (async) { + const sse = ast.notes && ast.notes.find(note => note.note.lexeme === '@sse'); + const isSSE = sse && sse.arg.value; + if (async && !isSSE) { this.emit('await '); } if (ast.builtinModule && this.builtin[ast.builtinModule] && this.builtin[ast.builtinModule][method]) { @@ -1796,8 +1800,10 @@ setup( const functionName = _avoidKeywords(_snakeCase(_name(ast.left.propertyPath[0]))); + const sse = ast.notes && ast.notes.find(note => note.note.lexeme === '@sse'); + const isSSE = sse && sse.arg.value; if (ast.isAsync && this.isAsyncFunction) { - this.emit(`await ${clientName}.${functionName}_async`); + this.emit(`${isSSE ? '' : 'await '}${clientName}.${functionName}_async`); } else { this.emit(`${clientName}.${functionName}`); } @@ -2465,7 +2471,8 @@ setup( // if (ast.annotation) { // this.emit(`${_anno(ast.annotation.value)}\n`, level); // } - + const sse = ast.notes.find(note => note.note.lexeme === '@sse'); + const isSSE = sse && sse.arg.value; this.visitAnnotation(ast.annotation, level); let comments = DSL.comment.getFrontComments(this.comments, ast.tokenRange[0]); this.visitComments(comments, level); @@ -2488,7 +2495,7 @@ setup( this.visitAPIBody(ast.apiBody, secondLevel); } this.emit(`_last_request = ${REQUEST}\n`, secondLevel); - this.emit(`${RESPONSE} = ${CORE}Core.do_action(${REQUEST}`, secondLevel); + this.emit(`${RESPONSE} = ${CORE}Core.${isSSE ? 'do_sse_action' : 'do_action'}(${REQUEST}`, secondLevel); if (ast.runtimeBody) { this.emit(', _runtime'); } @@ -2521,7 +2528,7 @@ setup( // temp level this.visitAPIBody(ast.apiBody, secondLevel); this.emit(`_last_request = ${REQUEST}\n`, secondLevel); - this.emit(`${RESPONSE} = await ${CORE}Core.async_do_action(${REQUEST}`, secondLevel); + this.emit(`${RESPONSE} = await ${CORE}Core.${isSSE ? 'async_do_sse_action' : 'async_do_action'}(${REQUEST}`, secondLevel); if (ast.runtimeBody) { this.emit(', _runtime'); } diff --git a/lib/helper.js b/lib/helper.js index c09f9e4..77eef6f 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -35,6 +35,8 @@ const builtinModels = [ '$ResponseError', '$FileField' ]; +const words = ['SSE']; + const CORE = 'Dara'; const REQUEST = '_request'; const RESPONSE = '_response'; @@ -219,6 +221,11 @@ function _snakeCase(str) { } let res = ''; let tmp = ''; + words.forEach(word => { + // 只匹配驼峰词前缀,不破坏开头 + const regex = new RegExp(word + '(?=[A-Z0-9])', 'g'); + str = str.replace(regex, _upperFirst(word.toLowerCase())); + }); for (const c of str) { if (/[A-Z|0-9]/.test(c)) { tmp += c; diff --git a/tests/expected/builtin/tea_python_tests/client.py b/tests/expected/builtin/tea_python_tests/client.py index fd55b77..cc63c1a 100644 --- a/tests/expected/builtin/tea_python_tests/client.py +++ b/tests/expected/builtin/tea_python_tests/client.py @@ -677,7 +677,7 @@ async def main_async( if not DaraCore.is_null(data): ws.write(data) - awiat DaraCore.sleep_async(a) + await DaraCore.sleep_async(a) default_val = args[0] or args[1] if default_val == b: return diff --git a/tests/expected/complex/tea_python_tests/client.py b/tests/expected/complex/tea_python_tests/client.py index 35246f1..5533e4c 100644 --- a/tests/expected/complex/tea_python_tests/client.py +++ b/tests/expected/complex/tea_python_tests/client.py @@ -227,7 +227,7 @@ def complex_1( return elif SourceClient.judge_str('test') or False: return source_models.RuntimeObject() - source_client.print_data(DaraCore.to_map(request), '1') + source_client.print_data_async(DaraCore.to_map(request), '1') self.hello(DaraCore.to_map(request), [ '1', '2' @@ -442,7 +442,7 @@ async def complex_1_async( return elif SourceClient.judge_str('test') or False: return source_models.RuntimeObject() - source_client.print_data(DaraCore.to_map(request), '1') + await source_client.print_data_async_async(DaraCore.to_map(request), '1') await self.hello_async(DaraCore.to_map(request), [ '1', '2' @@ -477,7 +477,7 @@ def complex_2( config_array = [ config ] - source_client.print_data(DaraCore.to_map(request), '1') + source_client.print_data_sse(DaraCore.to_map(request), '1') _request.protocol = 'HTTP' _request.port = 80 _request.method = 'GET' @@ -504,7 +504,7 @@ async def complex_2_async( config_array = [ config ] - source_client.print_data(DaraCore.to_map(request), '1') + source_client.print_data_sse_async(DaraCore.to_map(request), '1') _request.protocol = 'HTTP' _request.port = 80 _request.method = 'GET' diff --git a/tests/fixtures/complex/libraries/import.dara b/tests/fixtures/complex/libraries/import.dara index cb879ac..14edb83 100644 --- a/tests/fixtures/complex/libraries/import.dara +++ b/tests/fixtures/complex/libraries/import.dara @@ -5,10 +5,21 @@ type @pathname = string init(config: Config); model Config = {} + function printData(runtime: object, str: string): void { return; } +async function printDataAsync(runtime: object, str: string): void { + return; +} + +@sse(true) +async function printDataSSE(runtime: object, str: string): void { + return; +} + + static function judgeStr(a: string): boolean { return true; } diff --git a/tests/fixtures/complex/main.dara b/tests/fixtures/complex/main.dara index 155b0dc..d64f5ec 100644 --- a/tests/fixtures/complex/main.dara +++ b/tests/fixtures/complex/main.dara @@ -247,7 +247,7 @@ api Complex1(request: ComplexRequest, sourceClient: Source): Source.RuntimeObjec } else if(Source.judgeStr("test") || false){ return new Source.RuntimeObject{}; } - sourceClient.printData(request, '1'); + sourceClient.printDataAsync(request, '1'); hello(request, ["1","2"], null); hello(null, null, null); return {}; @@ -262,7 +262,7 @@ api Complex2(request: ComplexRequest, str: [ string ], val: map[string]string): var config = new Source.Config{}; var sourceClient = new Source(config); var configArray : [Source.Config] = [config]; - sourceClient.printData(request, '1'); + sourceClient.printDataSSE(request, '1'); __request.protocol = 'HTTP'; __request.port = 80; __request.method = 'GET';