From c076b0f5f0c88a15c939da9e2ac2f7efb05ba071 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Tue, 22 Apr 2025 18:16:03 +0300 Subject: [PATCH 001/747] Add 'version' option to options.yaml Issue: #IC36OU Signed-off-by: Vyacheslav Cherkashin --- ets2panda/util/options.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index 332845801b..af06d0bf4a 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -22,6 +22,11 @@ options: default: false description: Print this message and exit +- name: version + type: bool + default: false + description: Print version and exit + - name: arktsconfig type: std::string default: $ORIGIN/arktsconfig.json -- Gitee From bf064c061653368371b02e9bf0668f86fcfb9b48 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Sun, 27 Apr 2025 14:45:59 +0800 Subject: [PATCH 002/747] [SDK-API]update for sdk-constructor-funcs Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC4C09 Test scenarios:new tests add to the linter Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 62 +++++- .../test/sdkwhite/sdk_constructor_funcs.ets | 28 ++- .../sdk_constructor_funcs.ets.arkts2.json | 196 +++++++++++++++++- .../sdkwhite/sdk_constructor_funcs.ets.json | 43 +++- 4 files changed, 306 insertions(+), 23 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index bb89621028..79dce7bc89 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -159,6 +159,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { static missingAttributeSet: Set; static literalAsPropertyNameTypeSet: Set; private localApiListItem: ApiListItem | undefined = undefined; + static constructorFuncsSet: Set; static initGlobals(): void { TypeScriptLinter.sharedModulesCache = new Map(); @@ -234,6 +235,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private static addSdkConstructorFuncsSetData(item: ApiListItem): void { + if (item.api_info.problem === SdkProblem.ConstructorFuncs) { + TypeScriptLinter.constructorFuncsSet.add(item); + } + } + private static addGlobalApiInfosCollocetionData(item: ApiListItem): void { const problemType = item.api_info.problem; const isGlobal = item.is_global; @@ -249,6 +256,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private static initSdkWhitelist(): void { TypeScriptLinter.indexedTypeSet = new Set(); TypeScriptLinter.literalAsPropertyNameTypeSet = new Set(); + TypeScriptLinter.constructorFuncsSet = new Set(); const list: ApiList = new ApiList(apiWhiteList); if (list?.api_list?.length > 0) { for (const item of list.api_list) { @@ -260,6 +268,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { }); TypeScriptLinter.addSdkIndexedTypeSetData(item); TypeScriptLinter.addSdkliteralAsPropertyNameTypeSetData(item); + TypeScriptLinter.addSdkConstructorFuncsSetData(item); TypeScriptLinter.addGlobalApiInfosCollocetionData(item); } } @@ -4881,6 +4890,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } this.checkNoEnumProp(typeRef); + if (ts.isQualifiedName(typeRef.typeName)) { + this.handleSdkForConstructorFuncs(typeRef.typeName); + } } private checkNoEnumProp(typeRef: ts.TypeReferenceNode): void { @@ -6899,21 +6911,49 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isFunctionExpression(node); } - private handleSdkForConstructorFuncs(node: ts.PropertyAccessExpression): void { - if (!this.options.arkts2 || !node) { - return; + private static isThirdPartyBySymbol(symbol: ts.Symbol | undefined, apiList: ApiListItem): boolean { + if (!symbol) { + return false; } - const sdkInfos = this.interfaceMap.get(node.expression.getText()); - if (!sdkInfos || sdkInfos.size === 0) { - return; + const declaration = symbol.getDeclarations()?.[0]; + if (declaration && ts.isImportClause(declaration)) { + const importDecl = declaration.parent; + const importPath = TsUtils.removeOrReplaceQuotes(importDecl.moduleSpecifier.getText(), false); + const import_path = TypeScriptLinter.getLocalApiListItemByKey(SdkNameInfo.ImportPath, apiList); + if (import_path.includes(importPath)) { + return true; + } } + return false; + } - for (const sdkInfo of sdkInfos) { - const propertyName = node.name.getText(); - if (propertyName === sdkInfo.api_name) { - this.incrementCounters(node.name, FaultID.ConstructorTypesDeprecated); - } + private static getLocalApiListItemByKey(key: string, apiList: ApiListItem): string | string[] { + if (!apiList) { + return ''; + } + if (SdkNameInfo.ImportPath === key) { + return apiList.import_path; + } + return ''; + } + + private handleSdkForConstructorFuncs(node: ts.PropertyAccessExpression | ts.QualifiedName): void { + if (!this.options.arkts2) { + return; } + const rightNode = ts.isPropertyAccessExpression(node) ? node.name : node.right; + const leftNode = ts.isPropertyAccessExpression(node) ? node.expression : node.left; + const constructorFuncsInfos = Array.from(TypeScriptLinter.constructorFuncsSet); + constructorFuncsInfos.some((constructorFuncsInfo) => { + const api_name = constructorFuncsInfo.api_info.api_name; + if (api_name !== rightNode.getText()) { + return; + } + const parentSym = this.tsTypeChecker.getSymbolAtLocation(leftNode); + if (TypeScriptLinter.isThirdPartyBySymbol(parentSym, constructorFuncsInfo)) { + this.incrementCounters(rightNode, FaultID.ConstructorTypesDeprecated); + } + }); } private handleArkTSPropertyAccess(node: ts.PropertyAccessExpression): void { diff --git a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets index c50d5885da..d14c65ae1c 100755 --- a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets +++ b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets @@ -13,8 +13,30 @@ * limitations under the License. */ -import {cloudDatabase} from '@hms.core.deviceCloudGateway.cloudDatabase'; +import cloudDatabase from '@hms.core.deviceCloudGateway.cloudDatabase'; class Test extends cloudDatabase.DatabaseObject{ - + query = new cloudDatabase.DatabaseQuery(Test); //Error + equalTo(){ + return this.query.equalTo('test',''); + } } -new cloudDatabase.DatabaseQuery(Test); // NOT OK \ No newline at end of file +const localQuery = new cloudDatabase.DatabaseQuery(Test); //Error +class LocalDatabaseQuery extends cloudDatabase.DatabaseQuery{ //Error + query = new cloudDatabase.DatabaseQuery(Test); //Error + set(query:cloudDatabase.DatabaseQuery){ //Error + query.equalTo('test',''); + } + getTypeQuery(): cloudDatabase.DatabaseQuery { //Error + typeof new cloudDatabase.DatabaseQuery(Test); //Error + return new cloudDatabase.DatabaseQuery(Test); //Error + } + getEqual(){ + this.query = new Test().equalTo(); //Error? + } + +} +function useDatabaseQuery1(query:cloudDatabase.DatabaseQuery){ //Error + console.log(' '+new cloudDatabase.DatabaseQuery(Test)); //Error +} +class DatabaseQuery{} +new DatabaseQuery(); \ No newline at end of file diff --git a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.arkts2.json b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.arkts2.json index 745ab994b2..0356091ac5 100755 --- a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.arkts2.json +++ b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.arkts2.json @@ -15,20 +15,200 @@ ], "result": [ { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 32, + "line": 18, + "column": 3, + "endLine": 18, + "endColumn": 49, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 15, + "endLine": 18, + "endColumn": 42, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 29, + "endLine": 18, + "endColumn": 42, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 3, + "endLine": 19, + "endColumn": 10, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 8, + "endLine": 23, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 25, + "endLine": 23, + "endColumn": 52, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 39, + "endLine": 23, + "endColumn": 52, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 48, + "endLine": 24, + "endColumn": 61, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 3, + "endLine": 25, + "endColumn": 49, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 15, + "endLine": 25, + "endColumn": 42, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 29, + "endLine": 25, + "endColumn": 42, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 27, + "endLine": 26, + "endColumn": 40, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 33, + "endLine": 29, + "endColumn": 46, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 16, + "endLine": 30, + "endColumn": 43, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 30, + "endLine": 30, + "endColumn": 43, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 16, + "endLine": 31, + "endColumn": 43, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 30, + "endLine": 31, + "endColumn": 43, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 48, + "endLine": 38, + "endColumn": 61, + "problem": "ConstructorTypesDeprecated", + "suggest": "", + "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 23, + "endLine": 39, + "endColumn": 50, "problem": "DynamicCtorCall", "suggest": "", "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", "severity": "ERROR" }, { - "line": 20, - "column": 19, - "endLine": 20, - "endColumn": 32, + "line": 39, + "column": 37, + "endLine": 39, + "endColumn": 50, "problem": "ConstructorTypesDeprecated", "suggest": "", "rule": "Constructor types are not supported - use lambda functions instead. (sdk-constructor-funcs)", diff --git a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.json b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.json index 9f305c86d7..7cf57b141b 100755 --- a/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.json +++ b/ets2panda/linter/test/sdkwhite/sdk_constructor_funcs.ets.json @@ -13,5 +13,46 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 18, + "column": 3, + "endLine": 18, + "endColumn": 49, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 3, + "endLine": 19, + "endColumn": 10, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 8, + "endLine": 23, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 3, + "endLine": 25, + "endColumn": 49, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + } + ] } -- Gitee From 9a8e436e7bf6b277431341401c4732838bd23329 Mon Sep 17 00:00:00 2001 From: Sergey Khil Date: Thu, 22 May 2025 18:50:45 +0300 Subject: [PATCH 003/747] add env var to driver Issue:#IC9VYC Signed-off-by: Sergey Khil --- ets2panda/driver/build_system/src/build/compile_worker.ts | 4 ++-- .../driver/build_system/src/init/process_build_config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/compile_worker.ts b/ets2panda/driver/build_system/src/build/compile_worker.ts index 4c69a0c8a4..5d81e0c996 100644 --- a/ets2panda/driver/build_system/src/build/compile_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_worker.ts @@ -45,7 +45,7 @@ process.on('message', (message: { Logger.getInstance(buildConfig); PluginDriver.getInstance().initPlugins(buildConfig); - const koalaWrapperPath = path.resolve(buildConfig.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); + const koalaWrapperPath = process.env.KOALA_WRAPPER_PATH ?? path.resolve(buildConfig.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); let { arkts, arktsGlobal } = require(koalaWrapperPath); for (const fileInfo of taskList) { @@ -103,4 +103,4 @@ process.on('message', (message: { } process.exit(0); -}); \ No newline at end of file +}); diff --git a/ets2panda/driver/build_system/src/init/process_build_config.ts b/ets2panda/driver/build_system/src/init/process_build_config.ts index 596b32486d..96376391d2 100644 --- a/ets2panda/driver/build_system/src/init/process_build_config.ts +++ b/ets2panda/driver/build_system/src/init/process_build_config.ts @@ -135,7 +135,7 @@ export function initBuildEnv(buildConfig: BuildConfig): void { } function initKoalaWrapper(buildConfig: BuildConfig): void { - let koalaWrapperPath: string = path.resolve(buildConfig.buildSdkPath as string, KOALA_WRAPPER_PATH_FROM_SDK); + let koalaWrapperPath: string = process.env.KOALA_WRAPPER_PATH ?? path.resolve(buildConfig.buildSdkPath as string, KOALA_WRAPPER_PATH_FROM_SDK); const { arkts, arktsGlobal } = require(koalaWrapperPath); buildConfig.arkts = arkts; buildConfig.arktsGlobal = arktsGlobal; -- Gitee From e8e9beb27e01cf0165757dae34a74f4d0937039c Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Tue, 27 May 2025 15:16:54 +0800 Subject: [PATCH 004/747] fix issue for arkts-no-classes-as-obj Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAO3W Test scenarios: fix issue arkts-no-classes-as-obj Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 14 +++++-- .../linter/test/main/class_as_object.ets | 11 ++++- .../test/main/class_as_object.ets.arkts2.json | 42 +++---------------- .../linter/test/main/class_as_object.ets.json | 40 ------------------ 4 files changed, 27 insertions(+), 80 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e4e7c7ee91..f1fdb343ff 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -3953,12 +3953,20 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + this.handleIllegalSymbolUsage(tsIdentifier, tsIdentSym) + } + + private handleIllegalSymbolUsage(tsIdentifier: ts.Identifier, tsIdentSym: ts.Symbol): void { if (tsIdentSym.flags & ts.SymbolFlags.ValueModule) { this.incrementCounters(tsIdentifier, FaultID.NamespaceAsObject); } else { - // missing EnumAsObject - const faultId = this.options.arkts2 ? FaultID.ClassAsObjectError : FaultID.ClassAsObject; - this.incrementCounters(tsIdentifier, faultId); + const typeName = tsIdentifier.getText(); + const isWrapperObject = typeName === 'Number' || typeName === 'String' || typeName === 'Boolean'; + + if (!isWrapperObject) { + const faultId = this.options.arkts2 ? FaultID.ClassAsObjectError : FaultID.ClassAsObject; + this.incrementCounters(tsIdentifier, faultId); + } } } diff --git a/ets2panda/linter/test/main/class_as_object.ets b/ets2panda/linter/test/main/class_as_object.ets index fcc5a36250..a2bdc36a95 100644 --- a/ets2panda/linter/test/main/class_as_object.ets +++ b/ets2panda/linter/test/main/class_as_object.ets @@ -203,4 +203,13 @@ function parse(type: "number" | "boolean", value: string): number | boolean { } function format(input: string | number): string[] | number[] { return typeof input === "string" ? input.split("") : input.toString().split("").map(Number); -} \ No newline at end of file +} + +let version: string = "1.2" +let a1 = version.split('.').map(Number); + +let version2: string = "1.2" +let a2 = version2.split('.').map(String); + +let version3: string = "1.2" +let a3 = version3.split('.').map(Boolean); \ No newline at end of file diff --git a/ets2panda/linter/test/main/class_as_object.ets.arkts2.json b/ets2panda/linter/test/main/class_as_object.ets.arkts2.json index 3bf41adaeb..64c0b7ef62 100644 --- a/ets2panda/linter/test/main/class_as_object.ets.arkts2.json +++ b/ets2panda/linter/test/main/class_as_object.ets.arkts2.json @@ -394,36 +394,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "ERROR" }, - { - "line": 129, - "column": 15, - "endLine": 129, - "endColumn": 21, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, - { - "line": 130, - "column": 15, - "endLine": 130, - "endColumn": 22, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, - { - "line": 131, - "column": 15, - "endLine": 131, - "endColumn": 21, - "problem": "ClassAsObjectError", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "ERROR" - }, { "line": 132, "column": 15, @@ -905,13 +875,13 @@ "severity": "ERROR" }, { - "line": 205, - "column": 87, - "endLine": 205, - "endColumn": 93, - "problem": "ClassAsObjectError", + "line": 209, + "column": 5, + "endLine": 209, + "endColumn": 40, + "problem": "NumericSemantics", "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" } ] diff --git a/ets2panda/linter/test/main/class_as_object.ets.json b/ets2panda/linter/test/main/class_as_object.ets.json index cb35d61776..5bfa876a0a 100644 --- a/ets2panda/linter/test/main/class_as_object.ets.json +++ b/ets2panda/linter/test/main/class_as_object.ets.json @@ -212,36 +212,6 @@ "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "WARNING" }, - { - "line": 129, - "column": 15, - "endLine": 129, - "endColumn": 21, - "problem": "ClassAsObject", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "WARNING" - }, - { - "line": 130, - "column": 15, - "endLine": 130, - "endColumn": 22, - "problem": "ClassAsObject", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "WARNING" - }, - { - "line": 131, - "column": 15, - "endLine": 131, - "endColumn": 21, - "problem": "ClassAsObject", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "WARNING" - }, { "line": 132, "column": 15, @@ -661,16 +631,6 @@ "suggest": "", "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", "severity": "WARNING" - }, - { - "line": 205, - "column": 87, - "endLine": 205, - "endColumn": 93, - "problem": "ClassAsObject", - "suggest": "", - "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", - "severity": "WARNING" } ] } \ No newline at end of file -- Gitee From 9d6339a9c858aa35b6a0f9e87ad17dadff2b2814 Mon Sep 17 00:00:00 2001 From: leo9001 Date: Wed, 28 May 2025 15:50:22 +0800 Subject: [PATCH 005/747] support organizeImports new function support organizeImports new function Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB5WC Signed-off-by: leo9001 --- ets2panda/lsp/src/organize_imports.cpp | 15 +++- .../test/unit/lsp/organize_imports_test.cpp | 85 ++++++++++++------- 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/ets2panda/lsp/src/organize_imports.cpp b/ets2panda/lsp/src/organize_imports.cpp index aacf38ab47..c91ebd45bd 100644 --- a/ets2panda/lsp/src/organize_imports.cpp +++ b/ets2panda/lsp/src/organize_imports.cpp @@ -36,6 +36,13 @@ bool IsImportUsed(es2panda_Context *ctx, const ImportSpecifier &spec) } if (spec.type == ImportType::NAMESPACE) { + if (node->IsTSQualifiedName()) { + auto *qname = node->AsTSQualifiedName(); + found = qname->Left()->IsIdentifier() && + (std::string(qname->Left()->AsIdentifier()->Name()) == spec.localName); + return found; + } + if (node->IsMemberExpression()) { auto *member = node->AsMemberExpression(); found = member->Object()->IsIdentifier() && @@ -182,9 +189,9 @@ std::vector GenerateTextChanges(const std::vector &impor if (index + 1 < imp.namedImports.size()) { osst << ", "; } + index++; } - osst << " } from \"" << imp.moduleName << "\";\n"; - index++; + osst << " } from \'" << imp.moduleName << "\';\n"; }; for (const auto &imp : imports) { @@ -197,10 +204,10 @@ std::vector GenerateTextChanges(const std::vector &impor generateImportBlock(imp, oss, "import { "); break; case ImportType::DEFAULT: - oss << "import " << imp.namedImports[0].localName << " from \"" << imp.moduleName << "\";\n"; + oss << "import " << imp.namedImports[0].localName << " from \'" << imp.moduleName << "\';\n"; break; case ImportType::NAMESPACE: - oss << "import * as " << imp.namedImports[0].localName << " from \"" << imp.moduleName << "\";\n"; + oss << "import * as " << imp.namedImports[0].localName << " from \'" << imp.moduleName << "\';\n"; break; case ImportType::TYPE_ONLY: generateImportBlock(imp, oss, "import type { "); diff --git a/ets2panda/test/unit/lsp/organize_imports_test.cpp b/ets2panda/test/unit/lsp/organize_imports_test.cpp index 573c3dc35b..137fea4d9d 100644 --- a/ets2panda/test/unit/lsp/organize_imports_test.cpp +++ b/ets2panda/test/unit/lsp/organize_imports_test.cpp @@ -28,15 +28,15 @@ class OrganizeImportsTest : public LSPAPITests {}; TEST_F(OrganizeImportsTest, NormalImports) { - std::vector files = {"normal-imports-test.ets", "mod1/organize-imports-1.ets", - "mod2/organize-imports-2.ets"}; + std::vector files = {"normal-imports-test.ets", "organize-imports-1.ets", "organize-imports-2.ets"}; std::vector texts = { R"( - import {B, C} from "./mod1/organize-imports-1"; - import { X } from "./mod2/organize-imports-2"; + import {B, C, A} from "./organize-imports-1"; + import { X } from "./organize-imports-2"; const a = B; + const b = C; )", - R"(const A = 1; export default A; export const B = 2; export const C = 3;)", R"(export const X = 1;)"}; + R"(export const A = 1; export const B = 2; export const C = 3;)", R"(export const X = 1;)"}; auto filePaths = CreateTempFile(files, texts); Initializer initializer; @@ -49,20 +49,20 @@ TEST_F(OrganizeImportsTest, NormalImports) std::string result = changes[0].textChanges[0].newText; - EXPECT_TRUE(result.find("import { X } from \"./mod2/organize-imports-2\";") == std::string::npos); - EXPECT_TRUE(result.find("import { B } from \"./mod1/organize-imports-1\";") != std::string::npos); + EXPECT_TRUE(result.find("import { X } from \'./organize-imports-2\';") == std::string::npos); + EXPECT_TRUE(result.find("import { B, C } from \'./organize-imports-1\';") != std::string::npos); initializer.DestroyContext(ctx); } TEST_F(OrganizeImportsTest, TypeOnlyImports) { - std::vector files = {"typeonly-imports-test.ets", "mod1/typeonly-index.ets"}; + std::vector files = {"typeonly-imports-test.ets", "typeonly-index.ets"}; std::vector texts = { R"( - import type { T } from "./mod1/typeonly-index"; - import type {T as T1} from "./mod1/typeonly-index"; - import type {T as T2} from "./mod1/typeonly-index"; + import type { T } from "./typeonly-index"; + import type {T as T1} from "./typeonly-index"; + import type {T as T2} from "./typeonly-index"; let t: T1; function foo(arg: T2) {}; )", @@ -78,20 +78,20 @@ TEST_F(OrganizeImportsTest, TypeOnlyImports) std::string result = changes[0].textChanges[0].newText; - EXPECT_TRUE(result.find("import type { T } from \"./mod1/typeonly-index\";") == std::string::npos); - EXPECT_TRUE(result.find("import type { T as T1 } from \"./mod1/typeonly-index\";") != std::string::npos); - EXPECT_TRUE(result.find("import type { T as T2 } from \"./mod1/typeonly-index\";") != std::string::npos); + EXPECT_TRUE(result.find("import type { T } from \'./typeonly-index\';") == std::string::npos); + EXPECT_TRUE(result.find("import type { T as T1 } from \'./typeonly-index\';") != std::string::npos); + EXPECT_TRUE(result.find("import type { T as T2 } from \'./typeonly-index\';") != std::string::npos); initializer.DestroyContext(ctx); } TEST_F(OrganizeImportsTest, NamespaceImports) { - std::vector files = {"namespace-imports-test.ets", "mod1/namespace-imports-index.ets"}; + std::vector files = {"namespace-imports-test.ets", "namespace-imports-index.ets"}; std::vector texts = { R"( - import * as NS1 from "./mod1/namespace-imports-index"; - import * as NS2 from "./mod1/namespace-imports-index"; + import * as NS1 from "./namespace-imports-index"; + import * as NS2 from "./namespace-imports-index"; const b = NS1.color.red; )", R"(export const A = 1; export const B = 2;export enum color{red, blue, yellow};)"}; @@ -106,19 +106,19 @@ TEST_F(OrganizeImportsTest, NamespaceImports) std::string result = changes[0].textChanges[0].newText; - EXPECT_TRUE(result.find("import * as NS1 from \"./mod1/namespace-imports-index\";") != std::string::npos); - EXPECT_TRUE(result.find("import * as NS2 from \"./mod1/namespace-imports-index\";") == std::string::npos); + EXPECT_TRUE(result.find("import * as NS1 from \'./namespace-imports-index\';") != std::string::npos); + EXPECT_TRUE(result.find("import * as NS2 from \'./namespace-imports-index\';") == std::string::npos); initializer.DestroyContext(ctx); } TEST_F(OrganizeImportsTest, AliasImports) { - std::vector files = {"alias-imports-test.ets", "mod1/alias-imports-index.ets"}; + std::vector files = {"alias-imports-test.ets", "alias-imports-index.ets"}; std::vector texts = { R"( - import {B as B1, C} from "./mod1/alias-imports-index"; - import { B as B2 } from "./mod1/alias-imports-index"; + import {B as B1, C} from "./alias-imports-index"; + import { B as B2 } from "./alias-imports-index"; const b = B1; )", R"(export const B = 2; export const C = 3;)"}; @@ -133,19 +133,19 @@ TEST_F(OrganizeImportsTest, AliasImports) std::string result = changes[0].textChanges[0].newText; - EXPECT_TRUE(result.find("import { B as B1 } from \"./mod1/alias-imports-index\"") != std::string::npos); - EXPECT_TRUE(result.find("import { B as B2 } from \"./mod1/alias-imports-index\"") == std::string::npos); + EXPECT_TRUE(result.find("import { B as B1 } from \'./alias-imports-index\'") != std::string::npos); + EXPECT_TRUE(result.find("import { B as B2 } from \'./alias-imports-index\'") == std::string::npos); initializer.DestroyContext(ctx); } TEST_F(OrganizeImportsTest, DefaultImports) { - std::vector files = {"default-imports-test.ets", "mod1/default-imports-index.ets"}; + std::vector files = {"default-imports-test.ets", "default-imports-index.ets"}; std::vector texts = { R"( - import B from "./mod1/default-imports-index"; - import {C as C1} from "./mod1/default-imports-index"; + import B from "./default-imports-index"; + import {C as C1} from "./default-imports-index"; const b = B; const c = C1; )", @@ -161,8 +161,35 @@ TEST_F(OrganizeImportsTest, DefaultImports) std::string result = changes[0].textChanges[0].newText; - EXPECT_TRUE(result.find("import B from \"./mod1/default-imports-index\"") != std::string::npos); - EXPECT_TRUE(result.find("import { C as C1 } from \"./mod1/default-imports-index\"") != std::string::npos); + EXPECT_TRUE(result.find("import B from \'./default-imports-index\'") != std::string::npos); + EXPECT_TRUE(result.find("import { C as C1 } from \'./default-imports-index\'") != std::string::npos); + + initializer.DestroyContext(ctx); +} + +TEST_F(OrganizeImportsTest, SystemDefaultImports) +{ + std::vector files = {"system-default-imports-test.ets", "system-default-index.ets"}; + std::vector texts = { + R"( + import * as T1 from "./system-default-index"; + import * as T2 from "./system-default-index"; + let t: T2.T = "hello"; + )", + R"(export type T = string;)"}; + + auto filePaths = CreateTempFile(files, texts); + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + + std::vector changes = OrganizeImports::Organize(ctx, filePaths[0]); + + ASSERT_EQ(changes.size(), 1); + + std::string result = changes[0].textChanges[0].newText; + + EXPECT_TRUE(result.find("import * as T1 from \'./system-default-index\';") == std::string::npos); + EXPECT_TRUE(result.find("import * as T2 from \'./system-default-index\';") != std::string::npos); initializer.DestroyContext(ctx); } -- Gitee From 1c7c554c56293168eaba61ef97bd583a81ca49ec Mon Sep 17 00:00:00 2001 From: Denis Slynko Date: Thu, 29 May 2025 11:07:53 +0300 Subject: [PATCH 006/747] [ArkTS] Rework Class.ofCaller Remove implementation of `GlobalClassHandler::FormDependentInitTriggers`. Right now its not used in any scenarios, but could be reused in future for `import "path"` feature (see #26183) Issue: #ICAJX5 Signed-off-by: Denis Slynko --- .../ets/topLevelStmts/globalClassHandler.cpp | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index a914f8ad66..ff2f8abf1b 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -431,26 +431,11 @@ ArenaVector GlobalClassHandler::FormInitMethodStatements(parser return statements; } -void GlobalClassHandler::FormDependentInitTriggers(ArenaVector &statements, - const ModuleDependencies *moduleDependencies) +void GlobalClassHandler::FormDependentInitTriggers([[maybe_unused]] ArenaVector &statements, + [[maybe_unused]] const ModuleDependencies *moduleDependencies) { - auto const sequence = [&statements](ir::Statement *stmt) { statements.push_back(stmt); }; - - auto triggerInitOf = [this, sequence, initialized = false](parser::Program *prog) mutable { - if (!initialized) { - initialized = true; - sequence(parser_->CreateFormattedStatement("const __linker = Class.ofCaller().getLinker();")); - } - auto name = std::string(prog->ModulePrefix()).append(Signatures::ETS_GLOBAL); - sequence(parser_->CreateFormattedStatement("__linker.loadClass(\"" + name + "\", true);")); - }; - - for (auto depProg : *moduleDependencies) { - if (util::Helpers::IsStdLib(depProg)) { - continue; - } - triggerInitOf(depProg); - } + // NOTE(dslynko, #26183): leaving this function for later reuse in `import "path"` feature, + // which would initialize the dependency. } ir::ClassStaticBlock *GlobalClassHandler::CreateStaticBlock(ir::ClassDefinition *classDef) -- Gitee From 7ca1e9034472034a300daf75242b108a608f031f Mon Sep 17 00:00:00 2001 From: Torok Gergo Date: Wed, 28 May 2025 17:09:00 +0200 Subject: [PATCH 007/747] Implementing rest tuple in lambda Reason: Rest tuple in lambda methods are not supported, a basic support is requiered Description: LambdaLowering extension for rest parameters with tuple type Cornercase fix on element type searching on tuple rest parameters Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB9Q6 Signed-off-by: Torok Gergo --- .../checker/types/ets/etsFunctionType.cpp | 4 +- .../compiler/lowering/ets/lambdaLowering.cpp | 52 +++++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index 1df9fd28ea..74c39bb135 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -73,7 +73,9 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, if (signature->RestVar() != nullptr) { auto *functionN = checker->GlobalBuiltinFunctionType(arity, true)->AsETSObjectType(); auto *substitution = checker->NewSubstitution(); - auto *elementType = checker->GetElementTypeOfArray(signature->RestVar()->TsType()); + auto *elementType = !signature->RestVar()->TsType()->IsETSTupleType() + ? checker->GetElementTypeOfArray(signature->RestVar()->TsType()) + : checker->GlobalETSNullishObjectType(); substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), checker->MaybeBoxType(elementType)); return functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); } diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 656abd766b..d05e75313b 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -499,7 +499,8 @@ static void CreateLambdaClassConstructor(public_lib::Context *ctx, ir::ClassDefi static ArenaVector CreateRestArgumentsArrayReallocation( public_lib::Context *ctx, LambdaClassInvokeInfo const *lciInfo) { - if (!lciInfo->lambdaSignature->HasRestParameter()) { + if (!lciInfo->lambdaSignature->HasRestParameter() || + lciInfo->lambdaSignature->RestVar()->TsType()->IsETSTupleType()) { return ArenaVector(ctx->allocator->Adapter()); } @@ -509,13 +510,12 @@ static ArenaVector CreateRestArgumentsArrayReall auto *restParameterType = lciInfo->lambdaSignature->RestVar()->TsType(); auto *restParameterSubstituteType = restParameterType->Substitute(checker->Relation(), lciInfo->substitution); - bool isFixedArray = restParameterSubstituteType->IsETSArrayType(); auto *elementType = checker->GetElementTypeOfArray(restParameterSubstituteType); std::stringstream statements; auto restParameterIndex = GenName(allocator).View(); auto spreadArrIterator = GenName(allocator).View(); ir::Statement *args = nullptr; - if (isFixedArray) { + if (restParameterSubstituteType->IsETSArrayType()) { auto tmpArray = GenName(allocator).View(); statements << "let @@I1: int = 0;"; if (elementType->IsETSReferenceType()) { @@ -539,6 +539,7 @@ static ArenaVector CreateRestArgumentsArrayReall restParameterIndex, spreadArrIterator, checker->MaybeBoxType(elementType), elementType, restParameterIndex, restParameterIndex); } else { + ES2PANDA_ASSERT(restParameterSubstituteType->IsETSResizableArrayType()); auto *typeNode = allocator->New( checker->GetElementTypeOfArray(lciInfo->lambdaSignature->RestVar()->TsType()), allocator); statements << "let @@I1: int = 0;" @@ -571,9 +572,10 @@ static void CreateInvokeMethodRestParameter(public_lib::Context *ctx, LambdaClas auto *restIdent = Gensym(allocator); lciInfo->restParameterIdentifier = restIdent->Name(); - lciInfo->restArgumentIdentifier = GenName(allocator).View(); auto *spread = allocator->New(ir::AstNodeType::REST_ELEMENT, allocator, restIdent); - auto *arr = checker->CreateETSArrayType(anyType); + auto *arr = lciInfo->lambdaSignature->RestVar()->TsType()->IsETSTupleType() + ? lciInfo->lambdaSignature->RestVar()->TsType() + : checker->CreateETSArrayType(anyType); auto *typeAnnotation = allocator->New(arr, allocator); spread->SetTsTypeAnnotation(typeAnnotation); @@ -615,16 +617,20 @@ static ArenaVector CreateCallArgumentsForLambdaClassInvoke(pub callArguments.push_back(arg); } - if (lciInfo->lambdaSignature->HasRestParameter()) { - auto *restIdent = allocator->New(lciInfo->restArgumentIdentifier, allocator); - if (lciInfo->lambdaSignature->RestVar()->TsType()->IsETSArrayType()) { - auto *spread = allocator->New(ir::AstNodeType::SPREAD_ELEMENT, allocator, restIdent); - restIdent->SetParent(spread); - callArguments.push_back(spread); - } else { - restIdent->AddAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST); - callArguments.push_back(restIdent); - } + if (!lciInfo->lambdaSignature->HasRestParameter()) { + return callArguments; + } + auto restType = lciInfo->lambdaSignature->RestVar()->TsType(); + auto *restIdent = allocator->New( + restType->IsETSTupleType() ? lciInfo->restParameterIdentifier : lciInfo->restArgumentIdentifier, allocator); + if (restType->IsETSArrayType() || restType->IsETSTupleType()) { + auto *spread = allocator->New(ir::AstNodeType::SPREAD_ELEMENT, allocator, restIdent); + restIdent->SetParent(spread); + callArguments.push_back(spread); + } else { + ES2PANDA_ASSERT(restType->IsETSResizableArrayType()); + restIdent->AddAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST); + callArguments.push_back(restIdent); } return callArguments; } @@ -712,6 +718,7 @@ static void CreateLambdaClassInvokeMethod(public_lib::Context *ctx, LambdaInfo c if (lciInfo->lambdaSignature->HasRestParameter()) { CreateInvokeMethodRestParameter(ctx, lciInfo, ¶ms); + lciInfo->restArgumentIdentifier = GenName(allocator).View(); } auto *returnType2 = allocator->New( @@ -874,6 +881,13 @@ static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker CreateLambdaClassInvokeMethod(ctx, info, &lciInfo, invokeMethodName, true); // NOTE(vpukhov): for optional methods, the required invokeRk k={min, max-1} is not emitted } + if (signature->HasRestParameter() && signature->RestVar()->TsType()->IsETSTupleType()) { + auto invokeMethodName = + util::UString {checker::FunctionalInterfaceInvokeName(lciInfo.arity + 1, signature->HasRestParameter()), + ctx->allocator} + .View(); + CreateLambdaClassInvokeMethod(ctx, info, &lciInfo, invokeMethodName, true); + } CreateLambdaClassInvokeMethod(ctx, info, &lciInfo, compiler::Signatures::LAMBDA_OBJECT_INVOKE, false); InitScopesPhaseETS::RunExternalNode(classDeclaration, varBinder); @@ -1125,11 +1139,12 @@ static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpressio auto *ifaceType = oldType->IsETSObjectType() ? oldType->AsETSObjectType() : oldType->AsETSFunctionType()->ArrowToFunctionalInterfaceDesiredArity(checker, arity); + bool hasRestParam = + (oldType->IsETSFunctionType() && oldType->AsETSFunctionType()->ArrowSignature()->HasRestParameter()) || + call->Signature()->HasRestParameter(); if (ifaceType->IsETSDynamicType()) { return call; } - bool hasRestParam = - oldType->IsETSFunctionType() && oldType->AsETSFunctionType()->ArrowSignature()->HasRestParameter(); util::StringView invokeMethodName = util::UString {checker::FunctionalInterfaceInvokeName(arity, hasRestParam), allocator}.View(); auto *prop = ifaceType->GetProperty(invokeMethodName, checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | @@ -1152,6 +1167,9 @@ static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpressio In the future, make sure those conversions behave appropriately. */ for (auto *arg : call->Arguments()) { + if (arg->IsSpreadElement()) { + continue; + } auto boxingFlags = arg->GetBoxingUnboxingFlags(); Recheck(ctx->phaseManager, varBinder, checker, arg); arg->SetBoxingUnboxingFlags(boxingFlags); -- Gitee From 99688e1134909fa48071858216deecc3e2b9ef53 Mon Sep 17 00:00:00 2001 From: abdulsamethaymana Date: Tue, 27 May 2025 11:11:01 +0300 Subject: [PATCH 008/747] Fix: #26010 Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAVS2?from=project-issue Signed-off-by: abdulsamethaymana --- ets2panda/checker/ETSchecker.h | 1 + ets2panda/checker/ets/function.cpp | 38 +++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 06de9f47df..b4e1ab83ce 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -455,6 +455,7 @@ public: bool ValidateArgumentAsIdentifier(const ir::Identifier *identifier); bool IsValidRestArgument(ir::Expression *argument, Signature *substitutedSig, TypeRelationFlag flags, std::size_t index); + bool SetPreferredTypeForArrayArgument(ir::ArrayExpression *arrayExpr, Signature *substitutedSig); bool ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector &arguments, TypeRelationFlag flags, bool reportError, bool unique); void ThrowSignatureMismatch(ArenaVector &signatures, const ArenaVector &arguments, diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 41e6c334e1..01db51e7b2 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -493,6 +493,14 @@ bool ETSChecker::IsValidRestArgument(ir::Expression *const argument, Signature * // Object literals should be checked separately afterwards after call resolution return true; } + + // Set preferred type for array expressions before checking, similar to spread elements + if (argument->IsArrayExpression()) { + if (!SetPreferredTypeForArrayArgument(argument->AsArrayExpression(), substitutedSig)) { + return false; + } + } + const auto argumentType = argument->Check(this); auto *restParam = substitutedSig->RestVar()->TsType(); if (restParam->IsETSTupleType()) { @@ -510,7 +518,35 @@ bool ETSChecker::IsValidRestArgument(ir::Expression *const argument, Signature * Relation(), argument, argumentType, targetType, argument->Start(), {{diagnostic::REST_PARAM_INCOMPAT_AT, {argumentType, targetType, index + 1}}}, flags); - return invocationCtx.IsInvocable(); + bool result = invocationCtx.IsInvocable(); + // Clear preferred type if invocation fails, similar to spread elements + if (!result && argument->IsArrayExpression()) { + ModifyPreferredType(argument->AsArrayExpression(), nullptr); + } + + return result; +} + +bool ETSChecker::SetPreferredTypeForArrayArgument(ir::ArrayExpression *arrayExpr, Signature *substitutedSig) +{ + auto *const restVarType = substitutedSig->RestVar()->TsType(); + if (!restVarType->IsETSArrayType() && !restVarType->IsETSResizableArrayType()) { + return true; + } + auto targetType = GetElementTypeOfArray(restVarType); + if (substitutedSig->OwnerVar() == nullptr) { + targetType = MaybeBoxType(targetType); + } + // Validate tuple size before setting preferred type + if (targetType->IsETSTupleType()) { + auto *tupleType = targetType->AsETSTupleType(); + if (tupleType->GetTupleSize() != arrayExpr->Elements().size()) { + // Size mismatch - don't set preferred type, this will cause a type error + return false; + } + } + arrayExpr->SetPreferredType(targetType); + return true; } bool ETSChecker::ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector &arguments, -- Gitee From 2af741ed0cf58423eddd3d14a794da3f027444e3 Mon Sep 17 00:00:00 2001 From: e84401138 Date: Mon, 2 Jun 2025 10:09:06 +0300 Subject: [PATCH 009/747] Assertion Error on default param interface Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB9G1 Description: Assertion error is given when interface method has a default parameter and no body Tests: ninja tests all Signed-off-by: e84401138 --- .../ets/defaultParametersLowering.cpp | 56 +++++++++---- .../interfaceMethodWithDefaultParameter.ets | 80 +++++++++++++++++++ 2 files changed, 122 insertions(+), 14 deletions(-) create mode 100644 ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets diff --git a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp index d87fc777fd..55a77785c4 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp @@ -38,6 +38,36 @@ static ir::Statement *TransformInitializer(ArenaAllocator *allocator, parser::ET param->Ident()->Name(), init, typeAnnotation->Clone(allocator, nullptr)); } +static void TransformDefaultParameters(public_lib::Context *ctx, ir::ScriptFunction *function, + const std::vector ¶ms, + bool isInterfaceFunction) +{ + if (isInterfaceFunction) { + for (const auto param : params) { + TransformInitializer(ctx->allocator, ctx->parser->AsETSParser(), param); + } + return; + } + + if (!function->HasBody()) { // #23134 + ES2PANDA_ASSERT(ctx->diagnosticEngine->IsAnyError()); + return; + } + + auto const body = function->Body()->AsBlockStatement(); + auto const allocator = ctx->allocator; + auto const parser = ctx->parser->AsETSParser(); + + body->Statements().insert(body->Statements().begin(), params.size(), nullptr); + + for (size_t dfltIdx = 0; dfltIdx < params.size(); ++dfltIdx) { + auto const param = params.at(dfltIdx); + auto stmt = TransformInitializer(allocator, parser, param); + body->Statements()[dfltIdx] = stmt; + stmt->SetParent(body); + } +} + static void TransformFunction(public_lib::Context *ctx, ir::ScriptFunction *function) { auto const ¶ms = function->Params(); @@ -61,22 +91,20 @@ static void TransformFunction(public_lib::Context *ctx, ir::ScriptFunction *func if (defaultParams.empty()) { return; } - if (!function->HasBody()) { // #23134 - ES2PANDA_ASSERT(ctx->diagnosticEngine->IsAnyError()); - return; - } - auto const body = function->Body()->AsBlockStatement(); - auto const allocator = ctx->allocator; - auto const parser = ctx->parser->AsETSParser(); - - body->Statements().insert(body->Statements().begin(), defaultParams.size(), nullptr); - for (size_t dfltIdx = 0; dfltIdx < defaultParams.size(); ++dfltIdx) { - auto const param = defaultParams.at(dfltIdx); - auto stmt = TransformInitializer(allocator, parser, param); - body->Statements()[dfltIdx] = stmt; - stmt->SetParent(body); + bool isInterfaceFunction = function->IsTSInterfaceDeclaration(); + if (!isInterfaceFunction) { + ir::AstNode *node = function->Parent(); + while (node != nullptr) { + if (node->IsTSInterfaceDeclaration()) { + isInterfaceFunction = true; + break; + } + node = node->Parent(); + } } + + TransformDefaultParameters(ctx, function, defaultParams, isInterfaceFunction); } bool DefaultParametersLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) diff --git a/ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets b/ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets new file mode 100644 index 0000000000..7efbf745fc --- /dev/null +++ b/ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface Composer { + getCompositions(count: int = 100): string[] + getIdentification(includeAge: boolean = true, prefix: string = "He is "): string + getChildren(count: int, excludeLast: boolean = false): string[] +} + +class JohannSebastianBach implements Composer { + getCompositions(count: int = 8): string[] { + let compositions: string[] = [ + "The Brandenburg Concertos", + "The Goldberg Variations", + "Concerto for Two Violins in D minor", + "Air on the G String", + "The Well-Tempered Clavier", + "St Matthew Passion", + "Toccata and Fugue in D minor", + "Passacaglia and Fugue in C minor" + ] + + let max: int = min(compositions.length, count) as int + return [...compositions.slice(0, max)] + } + + getIdentification(includeAge: boolean = true, prefix: string = "He is"): string { + return `${prefix} Johann Sebastian Bach, the greatest composer that has ever lived${includeAge ? " who died at the age of 65." : "."}`; + } + + getChildren(count: int, excludeLast: boolean = false): string[] { + let children: string[] = [ + "Catharina Dorothea Bach", + "Wilhelm Friedemann Bach", + "Carl Philipp Emanuel Bach", + "Johann Gottfried Bernhard Bach", + "Gottfried Heinrich Bach", + "Johann Christoph Friedrich Bach", + "Johann Christian Bach III" + ] + + let max: int = min(children.length, count) as int + return excludeLast ? [...children.slice(0, max - 1)] : [...children.slice(0, max)] + } + } + +function main() { + let bach: JohannSebastianBach = {} + let compositions_1: string[] = bach.getCompositions() + let compositions_2: string[] = bach.getCompositions(5) + let identification_1: string = bach.getIdentification() + let identification_2: string = bach.getIdentification(false) + let identification_3: string = bach.getIdentification(true, "He is the") + let children_1: string[] = bach.getChildren(3) + let children_2: string[] = bach.getChildren(7, true) + + assertEQ(compositions_1.length, 8) + assertEQ(compositions_2.length, 5) + assertEQ(compositions_1[3], "Air on the G String") + assertEQ(compositions_2[4], "The Well-Tempered Clavier") + assertEQ(identification_1, "He is Johann Sebastian Bach, the greatest composer that has ever lived who died at the age of 65.") + assertEQ(identification_2, "He is Johann Sebastian Bach, the greatest composer that has ever lived.") + assertEQ(identification_3, "He is the Johann Sebastian Bach, the greatest composer that has ever lived who died at the age of 65.") + assertEQ(children_1.length, 3) + assertEQ(children_2.length, 6) + assertEQ(children_1[0], "Catharina Dorothea Bach") + assertEQ(children_2[5], "Johann Christoph Friedrich Bach") +} \ No newline at end of file -- Gitee From b36ba74feab2a4cbc5ef12f55c344bcb5143a48f Mon Sep 17 00:00:00 2001 From: dYildiz Date: Sat, 24 May 2025 12:42:24 +0300 Subject: [PATCH 010/747] [LSPAPI]Refactor Provider Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC6F9S Signed-off-by: doneyildiz --- ets2panda/bindings/native/src/lsp.cpp | 59 +--------- ets2panda/compiler/lowering/util.cpp | 4 + ets2panda/lsp/BUILD.gn | 2 + ets2panda/lsp/CMakeLists.txt | 2 + ets2panda/lsp/include/api.h | 26 +---- ets2panda/lsp/include/applicable_refactors.h | 46 +------- ets2panda/lsp/include/refactor_provider.h | 54 +++++++++ .../lsp/include/refactors/convert_function.h | 9 +- .../lsp/include/refactors/refactor_types.h | 106 ++++++++++++++++++ .../services/text_change/change_tracker.h | 5 - ets2panda/lsp/src/api.cpp | 4 +- ets2panda/lsp/src/applicable_refactors.cpp | 53 +-------- ets2panda/lsp/src/completions.cpp | 3 + ets2panda/lsp/src/refactor_provider.cpp | 63 +++++++++++ .../lsp/src/refactors/convert_function.cpp | 30 ++++- .../lsp/src/refactors/refactor_types.cpp | 58 ++++++++++ ets2panda/test/unit/lsp/CMakeLists.txt | 8 +- .../test/unit/lsp/refactor_provider_test.cpp | 34 ++++++ .../lsp/refactors_convert_function_test.cpp | 87 -------------- 19 files changed, 378 insertions(+), 275 deletions(-) create mode 100644 ets2panda/lsp/include/refactor_provider.h create mode 100644 ets2panda/lsp/include/refactors/refactor_types.h create mode 100644 ets2panda/lsp/src/refactor_provider.cpp create mode 100644 ets2panda/lsp/src/refactors/refactor_types.cpp create mode 100644 ets2panda/test/unit/lsp/refactor_provider_test.cpp delete mode 100644 ets2panda/test/unit/lsp/refactors_convert_function_test.cpp diff --git a/ets2panda/bindings/native/src/lsp.cpp b/ets2panda/bindings/native/src/lsp.cpp index a74ee5ae80..286efef597 100644 --- a/ets2panda/bindings/native/src/lsp.cpp +++ b/ets2panda/bindings/native/src/lsp.cpp @@ -19,7 +19,7 @@ #include "common.h" #include "panda_types.h" #include "public/es2panda_lib.h" - +#include "lsp/include/refactors/refactor_types.h" #include #include #include @@ -318,15 +318,15 @@ KNativePointer impl_getClassConstructorInfo(KNativePointer context, KInt positio properties.emplace_back(GetStringCopy(const_cast(el))); } LSPAPI const *ctx = GetImpl(); - auto *info = new RefactorEditInfo(ctx->getClassConstructorInfo(reinterpret_cast(context), - static_cast(position), properties)); + auto *info = new ark::es2panda::lsp::RefactorEditInfo(ctx->getClassConstructorInfo( + reinterpret_cast(context), static_cast(position), properties)); return info; } TS_INTEROP_3(getClassConstructorInfo, KNativePointer, KNativePointer, KInt, KStringArray) KNativePointer impl_getFileTextChangesFromConstructorInfo(KNativePointer infoPtr) { - auto *info = reinterpret_cast(infoPtr); + auto *info = reinterpret_cast(infoPtr); std::vector ptrs; for (auto &el : info->GetFileTextChanges()) { ptrs.push_back(new FileTextChanges(el)); @@ -367,57 +367,6 @@ KNativePointer impl_getTextSpanFromConstructorInfo(KNativePointer infoPtr) } TS_INTEROP_1(getTextSpanFromConstructorInfo, KNativePointer, KNativePointer) -KNativePointer impl_getRefactorActionName(KNativePointer refactorActionPtr) -{ - auto *refactorAction = reinterpret_cast(refactorActionPtr); - return new std::string(refactorAction->name); -} -TS_INTEROP_1(getRefactorActionName, KNativePointer, KNativePointer) - -KNativePointer impl_getRefactorActionDescription(KNativePointer refactorActionPtr) -{ - auto *refactorAction = reinterpret_cast(refactorActionPtr); - return new std::string(refactorAction->description); -} -TS_INTEROP_1(getRefactorActionDescription, KNativePointer, KNativePointer) - -KNativePointer impl_getRefactorActionKind(KNativePointer refactorActionPtr) -{ - auto *refactorAction = reinterpret_cast(refactorActionPtr); - return new std::string(refactorAction->kind); -} -TS_INTEROP_1(getRefactorActionKind, KNativePointer, KNativePointer) - -KNativePointer impl_getApplicableRefactors(KNativePointer context, KStringPtr &kindPtr, KInt position) -{ - LSPAPI const *ctx = GetImpl(); - auto *applicableRefactorInfo = new ark::es2panda::lsp::ApplicableRefactorInfo(ctx->getApplicableRefactors( - reinterpret_cast(context), GetStringCopy(kindPtr), static_cast(position))); - return applicableRefactorInfo; -} -TS_INTEROP_3(getApplicableRefactors, KNativePointer, KNativePointer, KStringPtr, KInt) - -KNativePointer impl_getApplicableRefactorName(KNativePointer applRefsPtr) -{ - auto *applRefsInfo = reinterpret_cast(applRefsPtr); - return new std::string(applRefsInfo->name); -} -TS_INTEROP_1(getApplicableRefactorName, KNativePointer, KNativePointer) - -KNativePointer impl_getApplicableRefactorDescription(KNativePointer applRefsPtr) -{ - auto *applRefsInfo = reinterpret_cast(applRefsPtr); - return new std::string(applRefsInfo->description); -} -TS_INTEROP_1(getApplicableRefactorDescription, KNativePointer, KNativePointer) - -KNativePointer impl_getRefactorAction(KNativePointer applRefsPtr) -{ - auto *applRefsInfo = reinterpret_cast(applRefsPtr); - return new ark::es2panda::lsp::RefactorAction(applRefsInfo->action); -} -TS_INTEROP_1(getRefactorAction, KNativePointer, KNativePointer) - KNativePointer impl_getCompletionEntryDetailsSymbolDisplayPart(KNativePointer completionEntryDetailsPtr) { auto *completionEntryDetails = reinterpret_cast(completionEntryDetailsPtr); diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index 09fe048e25..ca9aa4ca82 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -262,6 +262,10 @@ void Recheck(PhaseManager *phaseManager, varbinder::ETSBinder *varBinder, checke // NOTE: used to get the declaration from identifier in Plugin API and LSP ir::AstNode *DeclarationFromIdentifier(const ir::Identifier *node) { + if (node == nullptr) { + return nullptr; + } + auto idVar = node->Variable(); if (idVar == nullptr) { return nullptr; diff --git a/ets2panda/lsp/BUILD.gn b/ets2panda/lsp/BUILD.gn index db6d280f27..94fcff39ba 100644 --- a/ets2panda/lsp/BUILD.gn +++ b/ets2panda/lsp/BUILD.gn @@ -71,7 +71,9 @@ ohos_source_set("libes2panda_lsp_static") { "src/navigate_to.cpp", "src/organize_imports.cpp", "src/quick_info.cpp", + "src/refactor_provider.cpp", "src/refactors/convert_function.cpp", + "src/refactors/refactor_types.cpp", "src/references.cpp", "src/register_code_fix/add_missing_declare_property.cpp", "src/register_code_fix/fix_missing_call_parantheses.cpp", diff --git a/ets2panda/lsp/CMakeLists.txt b/ets2panda/lsp/CMakeLists.txt index 601ab7f0c9..41272e7af7 100644 --- a/ets2panda/lsp/CMakeLists.txt +++ b/ets2panda/lsp/CMakeLists.txt @@ -29,7 +29,9 @@ set(ES2PANDA_LSP_SRC ./src/find_rename_locations.cpp ./src/find_safe_delete_location.cpp ./src/find_references.cpp + ./src/refactors/refactor_types.cpp ./src/applicable_refactors.cpp + ./src/refactor_provider.cpp ./src/refactors/convert_function.cpp ./src/formatting/formatting_context.cpp ./src/formatting/formatting_settings.cpp diff --git a/ets2panda/lsp/include/api.h b/ets2panda/lsp/include/api.h index 099982127c..424200a26f 100644 --- a/ets2panda/lsp/include/api.h +++ b/ets2panda/lsp/include/api.h @@ -28,11 +28,13 @@ #include "line_column_offset.h" #include "public/es2panda_lib.h" #include "cancellation_token.h" +#include "user_preferences.h" #include "class_hierarchies.h" #include "find_references.h" #include "find_rename_locations.h" #include "class_hierarchy_info.h" #include "completions.h" +#include "refactors/refactor_types.h" #include "applicable_refactors.h" #include "todo_comments.h" #include "types.h" @@ -259,22 +261,6 @@ public: } }; -struct RefactorEditInfo { -private: - std::vector fileTextChanges_; - -public: - explicit RefactorEditInfo(std::vector fileTextChanges = {}) - : fileTextChanges_(std::move(fileTextChanges)) - { - } - - std::vector &GetFileTextChanges() - { - return fileTextChanges_; - } -}; - struct QuickInfo { private: std::string kind_; @@ -502,8 +488,8 @@ struct CodeFixOptions { typedef struct LSPAPI { DefinitionInfo (*getDefinitionAtPosition)(es2panda_Context *context, size_t position); - ark::es2panda::lsp::ApplicableRefactorInfo (*getApplicableRefactors)(es2panda_Context *context, const char *kind, - size_t position); + std::vector (*getApplicableRefactors)( + const ark::es2panda::lsp::RefactorContext *context); DefinitionInfo (*getImplementationAtPosition)(es2panda_Context *context, size_t position); bool (*isPackageModule)(es2panda_Context *context); ark::es2panda::lsp::CompletionEntryKind (*getAliasScriptElementKind)(es2panda_Context *context, size_t position); @@ -543,8 +529,8 @@ typedef struct LSPAPI { ark::es2panda::lsp::CompletionInfo (*getCompletionsAtPosition)(es2panda_Context *context, size_t position); ark::es2panda::lsp::ClassHierarchy (*getClassHierarchyInfo)(es2panda_Context *context, size_t position); std::vector (*getBraceMatchingAtPosition)(char const *fileName, size_t position); - RefactorEditInfo (*getClassConstructorInfo)(es2panda_Context *context, size_t position, - const std::vector &properties); + ark::es2panda::lsp::RefactorEditInfo (*getClassConstructorInfo)(es2panda_Context *context, size_t position, + const std::vector &properties); std::vector (*getImplementationLocationAtPosition)(es2panda_Context *context, int position); ark::es2panda::lsp::LineAndCharacter (*toLineColumnOffset)(es2panda_Context *context, size_t position); std::vector (*getTodoComments)( diff --git a/ets2panda/lsp/include/applicable_refactors.h b/ets2panda/lsp/include/applicable_refactors.h index 3329f8891f..9d736ddbf8 100644 --- a/ets2panda/lsp/include/applicable_refactors.h +++ b/ets2panda/lsp/include/applicable_refactors.h @@ -17,56 +17,14 @@ #define APPLICABLE_REFACTORS_H #include "public/es2panda_lib.h" +#include "refactors/refactor_types.h" #include #include #include namespace ark::es2panda::lsp { -using RefactorActionView = struct RefactorActionView { - std::string_view name; - std::string_view description; - std::string_view kind; -}; - -using RefactorAction = struct RefactorAction { - std::string name; - std::string description; - std::string kind; -}; - -using ApplicableRefactorInfo = struct ApplicableRefactorInfo { - std::string name; - std::string description; - RefactorAction action; -}; - -namespace refactor_name { -constexpr std::string_view CONVERT_FUNCTION_REFACTOR_NAME = "Convert arrow function or function expression"; -} // namespace refactor_name - -namespace refactor_description { -constexpr std::string_view CONVERT_FUNCTION_REFACTOR_DESC = "Convert arrow function or function expression"; -} // namespace refactor_description - -class Refactor { -private: - std::vector kinds_; - -public: - bool IsKind(const std::string &kind); - void AddKind(const std::string &kind); - virtual ApplicableRefactorInfo GetAvailableActions(es2panda_Context *context, std::string kind, - size_t position) = 0; - virtual ~Refactor() = default; - Refactor() = default; - Refactor &operator=(const Refactor &other); - Refactor &operator=(Refactor &&other); - Refactor(const Refactor &other); - Refactor(Refactor &&other); -}; - -ApplicableRefactorInfo GetApplicableRefactorsImpl(es2panda_Context *context, const char *kind, size_t position); +std::vector GetApplicableRefactorsImpl(const RefactorContext *context); } // namespace ark::es2panda::lsp #endif // APPLICABLE_REFACTORS_H \ No newline at end of file diff --git a/ets2panda/lsp/include/refactor_provider.h b/ets2panda/lsp/include/refactor_provider.h new file mode 100644 index 0000000000..dbd529c2c2 --- /dev/null +++ b/ets2panda/lsp/include/refactor_provider.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_LSP_INCLUDE_REFACTOR_PROVIDER_H +#define ES2PANDA_LSP_INCLUDE_REFACTOR_PROVIDER_H + +#include "refactors/refactor_types.h" +#include +#include +#include + +namespace ark::es2panda::lsp { + +class RefactorProvider { +public: + void RegisterRefactor(const std::string &name, std::unique_ptr refactor); + static RefactorProvider &Instance(); + std::unique_ptr GetEditsForRefactor(const RefactorContext &context, + const std::string &refactorName, + const std::string &actionName) const; + std::vector GetApplicableRefactors(const RefactorContext &context) const; + + const std::unordered_map> &GetRefactors() const; + +private: + std::unordered_map> refactors_; +}; + +template +struct AutoRefactorRegister { + constexpr explicit AutoRefactorRegister(const std::string &name, std::unique_ptr refactor) + { + RefactorProvider::Instance().RegisterRefactor(name, std::move(refactor)); + } + + constexpr explicit AutoRefactorRegister(const std::string &name) : AutoRefactorRegister(name, std::make_unique()) + { + } +}; + +} // namespace ark::es2panda::lsp +#endif // ES2PANDA_LSP_INCLUDE_REFACTOR_PROVIDER_H diff --git a/ets2panda/lsp/include/refactors/convert_function.h b/ets2panda/lsp/include/refactors/convert_function.h index 2b9767164b..5581ab3dd5 100644 --- a/ets2panda/lsp/include/refactors/convert_function.h +++ b/ets2panda/lsp/include/refactors/convert_function.h @@ -16,7 +16,7 @@ #ifndef CONVERT_FUNCTION_H #define CONVERT_FUNCTION_H -#include "lsp/include/applicable_refactors.h" +#include "refactor_types.h" namespace ark::es2panda::lsp { @@ -30,8 +30,11 @@ constexpr RefactorActionView TO_ARROW_FUNCTION_ACTION {"Convert to arrow functio class ConvertFunctionRefactor : public Refactor { public: ConvertFunctionRefactor(); - ApplicableRefactorInfo GetAvailableActions(es2panda_Context *context, std::string kind, size_t position) override; + ApplicableRefactorInfo GetAvailableActions(const RefactorContext &context) const override; + std::unique_ptr GetEditsForAction(const RefactorContext &context, + const std::string &actionName) const override; }; + } // namespace ark::es2panda::lsp -#endif // CONVERT_FUNCTION_H \ No newline at end of file +#endif // CONVERT_FUNCTION_H diff --git a/ets2panda/lsp/include/refactors/refactor_types.h b/ets2panda/lsp/include/refactors/refactor_types.h new file mode 100644 index 0000000000..72e3dd74ea --- /dev/null +++ b/ets2panda/lsp/include/refactors/refactor_types.h @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef REFACTOR_TYPES_H +#define REFACTOR_TYPES_H + +#include "public/es2panda_lib.h" +#include "../cancellation_token.h" +#include "../user_preferences.h" +#include "../types.h" +#include "es2panda.h" +#include +#include +#include + +namespace ark::es2panda::lsp { + +struct RefactorEditInfo { +private: + std::vector fileTextChanges_; + +public: + explicit RefactorEditInfo(std::vector fileTextChanges = {}) + : fileTextChanges_(std::move(fileTextChanges)) + { + } + + std::vector &GetFileTextChanges() + { + return fileTextChanges_; + } +}; + +struct TextRange { + size_t pos; + size_t end; +}; + +struct RefactorContext { + ark::es2panda::lsp::CancellationToken *cancellationToken; + ark::es2panda::lsp::UserPreferences *preferences; + TextRange span; + es2panda_Context *context; + std::string kind; +}; + +using RefactorActionView = struct RefactorActionView { + std::string_view name; + std::string_view description; + std::string_view kind; +}; + +using RefactorAction = struct RefactorAction { + std::string name; + std::string description; + std::string kind; +}; + +using ApplicableRefactorInfo = struct ApplicableRefactorInfo { + std::string name; + std::string description; + RefactorAction action; +}; + +namespace refactor_name { +constexpr std::string_view CONVERT_FUNCTION_REFACTOR_NAME = "Convert arrow function or function expression"; +} // namespace refactor_name + +namespace refactor_description { +constexpr std::string_view CONVERT_FUNCTION_REFACTOR_DESC = "Convert arrow function or function expression"; +} // namespace refactor_description + +class Refactor { +private: + std::vector kinds_; + +public: + bool IsKind(const std::string &kind) const; + void AddKind(const std::string &kind); + virtual ApplicableRefactorInfo GetAvailableActions(const RefactorContext &context) const = 0; + + virtual std::unique_ptr GetEditsForAction(const RefactorContext &context, + const std::string &actionName) const = 0; + virtual ~Refactor() = default; + Refactor() = default; + Refactor &operator=(const Refactor &other); + Refactor &operator=(Refactor &&other); + Refactor(const Refactor &other); + Refactor(Refactor &&other); +}; + +} // namespace ark::es2panda::lsp + +#endif // REFACTOR_TYPES_H \ No newline at end of file diff --git a/ets2panda/lsp/include/services/text_change/change_tracker.h b/ets2panda/lsp/include/services/text_change/change_tracker.h index 168c1f36b3..d7d6d1042b 100644 --- a/ets2panda/lsp/include/services/text_change/change_tracker.h +++ b/ets2panda/lsp/include/services/text_change/change_tracker.h @@ -46,11 +46,6 @@ struct ConfigurableEnd { std::optional trailingTriviaOption; }; -struct TextRange { - size_t pos; - size_t end; -}; - struct ConfigurableStartEnd { std::optional leadingTriviaOption; std::optional trailingTriviaOption; diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index 9c9b217952..38f34cb0d2 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -338,9 +338,9 @@ LineAndCharacter ToLineColumnOffsetWrapper(es2panda_Context *context, size_t pos // Returns type of refactoring and action that can be performed based // on the input kind information and cursor position -ApplicableRefactorInfo GetApplicableRefactors(es2panda_Context *context, const char *kind, size_t position) +std::vector GetApplicableRefactors(const RefactorContext *context) { - auto result = GetApplicableRefactorsImpl(context, kind, position); + auto result = GetApplicableRefactorsImpl(context); return result; } diff --git a/ets2panda/lsp/src/applicable_refactors.cpp b/ets2panda/lsp/src/applicable_refactors.cpp index 20a8994900..602cfeb76c 100644 --- a/ets2panda/lsp/src/applicable_refactors.cpp +++ b/ets2panda/lsp/src/applicable_refactors.cpp @@ -15,60 +15,15 @@ #include #include +#include "refactors/refactor_types.h" #include "applicable_refactors.h" +#include "lsp/include/refactor_provider.h" #include "refactors/convert_function.h" namespace ark::es2panda::lsp { -Refactor::Refactor(const Refactor &other) -{ - kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); -} - -Refactor &Refactor::operator=(const Refactor &other) -{ - kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); - return *this; -} - -Refactor &Refactor::operator=(Refactor &&other) -{ - kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); - return *this; -} - -Refactor::Refactor(Refactor &&other) -{ - kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); -} - -bool Refactor::IsKind(const std::string &kind) -{ - for (const std::string &rKind : kinds_) { - if (rKind.substr(0, kind.length()) == kind) { - return true; - } - } - return false; -} -void Refactor::AddKind(const std::string &kind) +std::vector GetApplicableRefactorsImpl(const RefactorContext *context) { - kinds_.push_back(kind); -} - -ApplicableRefactorInfo GetApplicableRefactorsImpl(es2panda_Context *context, const char *kind, size_t position) -{ - ApplicableRefactorInfo result; - std::unordered_map> refactors; - Refactor *convertFunctionRefactor = new ConvertFunctionRefactor(); - refactors[std::string(refactor_name::CONVERT_FUNCTION_REFACTOR_NAME)] = - std::shared_ptr(convertFunctionRefactor); - for (const auto &[refactorName, refactor] : refactors) { - if (refactor->IsKind(std::string(kind))) { - return refactor->GetAvailableActions(context, std::string(kind), position); - } - } - - return result; + return RefactorProvider::Instance().GetApplicableRefactors(*context); } } // namespace ark::es2panda::lsp \ No newline at end of file diff --git a/ets2panda/lsp/src/completions.cpp b/ets2panda/lsp/src/completions.cpp index fc0e486bf6..cc8bda9324 100644 --- a/ets2panda/lsp/src/completions.cpp +++ b/ets2panda/lsp/src/completions.cpp @@ -462,6 +462,9 @@ std::vector GetCompletionFromTSInterfaceDeclaration(ir::TSInter auto ident = GetIdentifierFromTSInterfaceHeritage(extend); if (ident != nullptr && ident->IsIdentifier()) { auto extendInterf = compiler::DeclarationFromIdentifier(ident->AsIdentifier()); + if (extendInterf == nullptr) { + continue; + } auto extendCom = extendInterf->IsTSInterfaceDeclaration() ? GetCompletionFromTSInterfaceDeclaration(extendInterf->AsTSInterfaceDeclaration(), triggerWord) diff --git a/ets2panda/lsp/src/refactor_provider.cpp b/ets2panda/lsp/src/refactor_provider.cpp new file mode 100644 index 0000000000..f6e8e598ff --- /dev/null +++ b/ets2panda/lsp/src/refactor_provider.cpp @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "refactor_provider.h" +#include "refactors/refactor_types.h" + +namespace ark::es2panda::lsp { + +void RefactorProvider::RegisterRefactor(const std::string &name, std::unique_ptr refactor) +{ + refactors_.emplace(name, std::move(refactor)); +} + +RefactorProvider &RefactorProvider::Instance() +{ + static RefactorProvider instance; + return instance; +} + +std::unique_ptr RefactorProvider::GetEditsForRefactor(const RefactorContext &context, + const std::string &refactorName, + const std::string &actionName) const +{ + auto it = refactors_.find(refactorName); + if (it == refactors_.end()) { + return nullptr; + } + + return it->second->GetEditsForAction(context, actionName); +} + +std::vector RefactorProvider::GetApplicableRefactors(const RefactorContext &context) const +{ + std::vector applicable; + + for (const auto &[name, refactor] : refactors_) { + auto result = refactor->GetAvailableActions(context); + if (!result.name.empty()) { + applicable.push_back(result); + } + } + + return applicable; +} + +const std::unordered_map> &RefactorProvider::GetRefactors() const +{ + return refactors_; +} + +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/refactors/convert_function.cpp b/ets2panda/lsp/src/refactors/convert_function.cpp index d5996360f3..e594fa230a 100644 --- a/ets2panda/lsp/src/refactors/convert_function.cpp +++ b/ets2panda/lsp/src/refactors/convert_function.cpp @@ -15,10 +15,12 @@ #include #include "refactors/convert_function.h" +#include "refactor_provider.h" #include "compiler/lowering/util.h" #include "internal_api.h" namespace ark::es2panda::lsp { + ConvertFunctionRefactor::ConvertFunctionRefactor() { AddKind(std::string(TO_ANONYMOUS_FUNCTION_ACTION.kind)); @@ -26,27 +28,43 @@ ConvertFunctionRefactor::ConvertFunctionRefactor() AddKind(std::string(TO_ARROW_FUNCTION_ACTION.kind)); } -ApplicableRefactorInfo ConvertFunctionRefactor::GetAvailableActions(es2panda_Context *context, std::string kind, - size_t position) +ApplicableRefactorInfo ConvertFunctionRefactor::GetAvailableActions(const RefactorContext &refContext) const { + es2panda_Context *context = refContext.context; + size_t position = refContext.span.pos; + ApplicableRefactorInfo res; - if (TO_NAMED_FUNCTION_ACTION.kind.substr(0, kind.length()) != kind) { + + if (!IsKind(refContext.kind)) { return res; } + auto node = GetTouchingToken(context, position, false); if (node == nullptr || !node->IsIdentifier()) { return res; } + auto nodeDecl = compiler::DeclarationFromIdentifier(node->AsIdentifier()); - if (nodeDecl->IsClassProperty() && nodeDecl->AsClassProperty()->Value()->IsArrowFunctionExpression()) { + if (nodeDecl != nullptr && nodeDecl->IsClassProperty() && nodeDecl->AsClassProperty()->Value() != nullptr && + nodeDecl->AsClassProperty()->Value()->IsArrowFunctionExpression()) { res.name = refactor_name::CONVERT_FUNCTION_REFACTOR_NAME; res.description = refactor_description::CONVERT_FUNCTION_REFACTOR_DESC; res.action.kind = std::string(TO_NAMED_FUNCTION_ACTION.kind); res.action.name = std::string(TO_NAMED_FUNCTION_ACTION.name); res.action.description = std::string(TO_NAMED_FUNCTION_ACTION.description); - return res; } return res; } -} // namespace ark::es2panda::lsp \ No newline at end of file + +std::unique_ptr ConvertFunctionRefactor::GetEditsForAction(const RefactorContext &context, + const std::string &actionName) const +{ + (void)context; + (void)actionName; + return std::make_unique(); +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoRefactorRegister g_convertFunctionRefactorRegister("ConvertFunctionRefactor"); + +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/refactors/refactor_types.cpp b/ets2panda/lsp/src/refactors/refactor_types.cpp new file mode 100644 index 0000000000..4a9c1a1980 --- /dev/null +++ b/ets2panda/lsp/src/refactors/refactor_types.cpp @@ -0,0 +1,58 @@ + +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "refactors/refactor_types.h" + +namespace ark::es2panda::lsp { + +Refactor::Refactor(const Refactor &other) +{ + kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); +} + +Refactor &Refactor::operator=(const Refactor &other) +{ + kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); + return *this; +} + +Refactor &Refactor::operator=(Refactor &&other) +{ + kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); + return *this; +} + +Refactor::Refactor(Refactor &&other) +{ + kinds_.insert(kinds_.end(), other.kinds_.begin(), other.kinds_.end()); +} + +bool Refactor::IsKind(const std::string &kind) const +{ + for (const std::string &rKind : kinds_) { + if (rKind.substr(0, kind.length()) == kind) { + return true; + } + } + return false; +} + +void Refactor::AddKind(const std::string &kind) +{ + kinds_.push_back(kind); +} + +} // namespace ark::es2panda::lsp \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index 6f10ba2d98..82d3f06764 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -15,10 +15,6 @@ ets2panda_add_gtest(lsp_get_definition_at_position_test CPP_SOURCES get_definition_at_position_test.cpp ) -ets2panda_add_gtest(lsp_api_test_get_applicable_refactors CPP_SOURCES - refactors_convert_function_test.cpp -) - ets2panda_add_gtest(lsp_get_file_references_test CPP_SOURCES get_file_references_test.cpp ) @@ -168,6 +164,10 @@ ets2panda_add_gtest(lsp_api_test_inlay_hints CPP_SOURCES inlay_hints_test.cpp ) +ets2panda_add_gtest(lsp_api_test_refactor_provider_test CPP_SOURCES + refactor_provider_test.cpp +) + ets2panda_add_gtest(lsp_api_test_find_rename_locations CPP_SOURCES find_rename_locations_test.cpp ) diff --git a/ets2panda/test/unit/lsp/refactor_provider_test.cpp b/ets2panda/test/unit/lsp/refactor_provider_test.cpp new file mode 100644 index 0000000000..b033fa469d --- /dev/null +++ b/ets2panda/test/unit/lsp/refactor_provider_test.cpp @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "lsp/include/refactor_provider.h" +#include "lsp/include/refactors/convert_function.h" +#include "lsp/include/types.h" +#include "lsp_api_test.h" // LSPAPITests header file + +namespace { +class RefactorProviderRegistrationTest : public LSPAPITests {}; + +TEST(RefactorProviderRegistrationTest, RegistersConvertFunctionRefactor) +{ + const auto &provider = ark::es2panda::lsp::RefactorProvider::Instance(); + const auto &refactors = provider.GetRefactors(); + + auto it = refactors.find("ConvertFunctionRefactor"); + + ASSERT_NE(it, refactors.end()) << "ConvertFunctionRefactor was not registered in RefactorProvider."; +} +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/refactors_convert_function_test.cpp b/ets2panda/test/unit/lsp/refactors_convert_function_test.cpp deleted file mode 100644 index 2688b3b2c5..0000000000 --- a/ets2panda/test/unit/lsp/refactors_convert_function_test.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "lsp_api_test.h" - -namespace { -using ark::es2panda::lsp::Initializer; - -class LspGetRefTests : public LSPAPITests { -public: - static constexpr std::string_view TO_NAMED_FUNCTION_KIND = "refactor.rewrite.function.named"; - static constexpr std::string_view INVALID_KIND = "aaabbbccc"; - static constexpr std::string_view TO_NAMED_FUNCTION_NAME = "Convert to named function"; -}; - -TEST_F(LspGetRefTests, ConvertFunctionRefactor1) -{ - std::vector files = {"convertFunctionRefactor1.ets"}; - std::vector texts = {R"(const add = (x: number, y: number): number => { - return x + y; - };)"}; - auto filePaths = CreateTempFile(files, texts); - size_t const expectedFileCount = 1; - ASSERT_EQ(filePaths.size(), expectedFileCount); - - LSPAPI const *lspApi = GetImpl(); - size_t const position = 8; - Initializer initializer = Initializer(); - auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); - auto result = lspApi->getApplicableRefactors(ctx, std::string(TO_NAMED_FUNCTION_KIND).c_str(), position); - initializer.DestroyContext(ctx); - ASSERT_EQ(std::string(TO_NAMED_FUNCTION_NAME), result.action.name); -} - -TEST_F(LspGetRefTests, ConvertFunctionRefactor2) -{ - std::vector files = {"convertFunctionRefactor2.ets"}; - std::vector texts = {R"(function sub(a: number, b: number): number{ - return a - b; - };)"}; - auto filePaths = CreateTempFile(files, texts); - size_t const expectedFileCount = 1; - ASSERT_EQ(filePaths.size(), expectedFileCount); - - LSPAPI const *lspApi = GetImpl(); - size_t const position = 11; - Initializer initializer = Initializer(); - auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); - auto result = lspApi->getApplicableRefactors(ctx, std::string(TO_NAMED_FUNCTION_KIND).c_str(), position); - initializer.DestroyContext(ctx); - ASSERT_EQ(std::string(""), result.name); -} - -TEST_F(LspGetRefTests, ConvertFunctionRefactor3) -{ - std::vector files = {"convertFunctionRefactor3.ets"}; - std::vector texts = {R"(const add = (x: number, y: number): number => { - return x + y; - };)"}; - auto filePaths = CreateTempFile(files, texts); - size_t const expectedFileCount = 1; - ASSERT_EQ(filePaths.size(), expectedFileCount); - - LSPAPI const *lspApi = GetImpl(); - size_t const position = 8; - Initializer initializer = Initializer(); - auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); - auto result = lspApi->getApplicableRefactors(ctx, std::string(INVALID_KIND).c_str(), position); - initializer.DestroyContext(ctx); - ASSERT_EQ(std::string(""), result.name); -} -} // namespace \ No newline at end of file -- Gitee From 2c9506b90380f0861f2a310998a201cc9f2b3650 Mon Sep 17 00:00:00 2001 From: Musa Nazif Boya Date: Thu, 22 May 2025 01:10:57 +0300 Subject: [PATCH 011/747] fix: Optional variable is depricated Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IBZVO9 Reason: Optional type is not supported due to spec 2025.03.11. Description: Optional varibale types should CTE. Tests: No new tests, old tests updated. Signed-off-by: Musa Nazif Boya --- ets2panda/parser/ETSparser.cpp | 3 +++ .../test/{runtime => ast/parser}/ets/optional_field.ets | 3 +++ .../test/{ => ast}/parser/ets/optional_field_variable.ets | 3 +++ .../test/{runtime => ast/parser}/ets/optional_primitive.ets | 4 +++- ets2panda/test/ast/parser/ets/unexpected_token_56.ets | 1 + ets2panda/util/diagnostic/syntax.yaml | 6 +++++- 6 files changed, 18 insertions(+), 2 deletions(-) rename ets2panda/test/{runtime => ast/parser}/ets/optional_field.ets (86%) rename ets2panda/test/{ => ast}/parser/ets/optional_field_variable.ets (81%) rename ets2panda/test/{runtime => ast/parser}/ets/optional_primitive.ets (87%) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 6a1ca88c8b..e5fdd5ac3e 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -1634,6 +1634,9 @@ ir::AnnotatedExpression *ETSParser::ParseVariableDeclaratorKey([[maybe_unused]] } Lexer()->NextToken(); // eat '?' init->AddModifier(ir::ModifierFlags::OPTIONAL); + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COLON) { + LogError(diagnostic::OPTIONAL_VARIABLE); + } } if (auto const tokenType = Lexer()->GetToken().Type(); tokenType == lexer::TokenType::PUNCTUATOR_COLON) { diff --git a/ets2panda/test/runtime/ets/optional_field.ets b/ets2panda/test/ast/parser/ets/optional_field.ets similarity index 86% rename from ets2panda/test/runtime/ets/optional_field.ets rename to ets2panda/test/ast/parser/ets/optional_field.ets index 3190aa7e6e..7ab9960947 100644 --- a/ets2panda/test/runtime/ets/optional_field.ets +++ b/ets2panda/test/ast/parser/ets/optional_field.ets @@ -53,3 +53,6 @@ function main() : int return 0; } + +/* @@? 27:4 Error TypeError: Function method with this assembly signature already declared. */ +/* @@? 41:14 Error SyntaxError: Optional variable is deprecated and no longer supported. */ \ No newline at end of file diff --git a/ets2panda/test/parser/ets/optional_field_variable.ets b/ets2panda/test/ast/parser/ets/optional_field_variable.ets similarity index 81% rename from ets2panda/test/parser/ets/optional_field_variable.ets rename to ets2panda/test/ast/parser/ets/optional_field_variable.ets index 47da757660..36a1540c41 100644 --- a/ets2panda/test/parser/ets/optional_field_variable.ets +++ b/ets2panda/test/ast/parser/ets/optional_field_variable.ets @@ -25,3 +25,6 @@ function foo(param? : Object) let var3? = goo(); for (let i? : Number = 1;;) { break; } } + +/* @@? 23:14 Error SyntaxError: Optional variable is deprecated and no longer supported. */ +/* @@? 26:16 Error SyntaxError: Optional variable is deprecated and no longer supported. */ \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/optional_primitive.ets b/ets2panda/test/ast/parser/ets/optional_primitive.ets similarity index 87% rename from ets2panda/test/runtime/ets/optional_primitive.ets rename to ets2panda/test/ast/parser/ets/optional_primitive.ets index 3ef1125541..8d51ff1d62 100644 --- a/ets2panda/test/runtime/ets/optional_primitive.ets +++ b/ets2panda/test/ast/parser/ets/optional_primitive.ets @@ -16,4 +16,6 @@ function main() { let a ?: number = 1 assertEQ(a, 1) -} \ No newline at end of file +} + +/* @@? 17:12 Error SyntaxError: Optional variable is deprecated and no longer supported. */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_56.ets b/ets2panda/test/ast/parser/ets/unexpected_token_56.ets index a5017ce1b8..556f4484e1 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_56.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_56.ets @@ -31,3 +31,4 @@ for (let i? : Number = 1;;) { break; } /* @@? 17:23 Error TypeError: Indexed access is not supported for such expression type. */ /* @@? 17:49 Error TypeError: Unresolved reference a */ /* @@? 17:49 Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 19:13 Error SyntaxError: Optional variable is deprecated and no longer supported. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index a412c35ab5..d18a5f9766 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1230,4 +1230,8 @@ syntax: - name: DEEP_NESTING id: 305 - message: "Maximum allowed nesting level exceeded." \ No newline at end of file + message: "Maximum allowed nesting level exceeded." + +- name: OPTIONAL_VARIABLE + id: 306 + message: "Optional variable is deprecated and no longer supported." \ No newline at end of file -- Gitee From cef734963a3bdc75ff6088c2e3ed4349a051e1cc Mon Sep 17 00:00:00 2001 From: fanglou Date: Wed, 28 May 2025 19:14:31 +0800 Subject: [PATCH 012/747] modify use static spec Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB2II Signed-off-by: fanglou Change-Id: Icba1b881159e4177e2164f15e45b679d2da830a3 --- ets2panda/linter/src/lib/CookBookMsg.ts | 3 +- ets2panda/linter/src/lib/FaultAttrs.ts | 1 - ets2panda/linter/src/lib/FaultDesc.ts | 1 - ets2panda/linter/src/lib/HomeCheck.ts | 11 +- ets2panda/linter/src/lib/LinterOptions.ts | 1 + ets2panda/linter/src/lib/LinterRunner.ts | 37 +- ets2panda/linter/src/lib/Problems.ts | 1 - ets2panda/linter/src/lib/TypeScriptLinter.ts | 233 +- .../linter/src/lib/autofixes/Autofixer.ts | 292 ++- .../linter/src/lib/autofixes/QuasiEditor.ts | 29 +- ets2panda/linter/src/lib/utils/TsUtils.ts | 23 +- .../src/lib/utils/consts/ArkTS2Rules.ts | 6 +- .../linter/src/lib/utils/consts/InteropAPI.ts | 10 +- .../concurrent_sharedarraybuffer_arkts2.ets | 8 +- ...t_sharedarraybuffer_arkts2.ets.arkts2.json | 22 +- ..._sharedarraybuffer_arkts2.ets.autofix.json | 54 +- ...t_sharedarraybuffer_arkts2.ets.migrate.ets | 8 +- .../no_support_isconcurrent.ets.arkts2.json | 12 +- .../test/interop/binary_operation_js_obj.ets | 1 - .../binary_operation_js_obj.ets.args.json | 42 +- .../binary_operation_js_obj.ets.arkts2.json | 64 +- .../binary_operation_js_obj.ets.autofix.json | 124 +- .../interop/binary_operation_js_obj.ets.json | 13 +- .../binary_operation_js_obj.ets.migrate.ets | 1 - .../binary_operation_js_obj.ets.migrate.json | 22 +- .../linter/test/interop/call_function.ets | 35 +- .../interop/call_function.ets.arkts2.json | 26 +- .../test/interop/call_function.ets.json | 13 +- .../test/interop/call_object_methods.ets | 1 - .../call_object_methods.ets.arkts2.json | 22 +- .../call_object_methods.ets.autofix.json | 62 +- .../test/interop/call_object_methods.ets.json | 13 +- .../call_object_methods.ets.migrate.ets | 1 - .../call_object_methods.ets.migrate.json | 10 +- .../interop/increases_decreases_js_obj.ets | 1 - ...increases_decreases_js_obj.ets.arkts2.json | 104 +- ...ncreases_decreases_js_obj.ets.autofix.json | 216 +- .../increases_decreases_js_obj.ets.json | 13 +- ...increases_decreases_js_obj.ets.migrate.ets | 9 +- ...ncreases_decreases_js_obj.ets.migrate.json | 10 +- .../test/interop/instantiated_js_obj.ets | 1 - .../instantiated_js_obj.ets.arkts2.json | 58 +- .../instantiated_js_obj.ets.autofix.json | 164 +- .../test/interop/instantiated_js_obj.ets.json | 13 +- .../instantiated_js_obj.ets.migrate.ets | 1 - .../instantiated_js_obj.ets.migrate.json | 14 +- .../test/interop/interop_convert_import.ets | 26 +- .../interop_convert_import.ets.arkts2.json | 454 ++-- .../interop_convert_import.ets.autofix.json | 336 +-- .../interop/interop_convert_import.ets.json | 54 +- .../interop_convert_import.ets.migrate.ets | 90 +- .../interop_convert_import.ets.migrate.json | 38 +- .../interop/interop_equality_judgment.ets | 1 - .../interop_equality_judgment.ets.arkts2.json | 26 +- ...interop_equality_judgment.ets.autofix.json | 90 +- .../interop_equality_judgment.ets.json | 13 +- .../interop_equality_judgment.ets.migrate.ets | 1 - ...interop_equality_judgment.ets.migrate.json | 14 +- .../test/interop/interop_export_js_rules.ets | 1 - .../interop_export_js_rules.ets.arkts2.json | 174 +- .../interop/interop_export_js_rules.ets.json | 43 +- .../linter/test/interop/interop_import_js.ets | 1 - .../interop/interop_import_js.ets.arkts2.json | 86 +- .../interop_import_js.ets.autofix.json | 238 +- .../test/interop/interop_import_js.ets.json | 73 +- .../interop/interop_import_js.ets.migrate.ets | 1 - .../interop_import_js.ets.migrate.json | 50 +- .../interop/interop_import_js_compare.ets | 1 - .../interop_import_js_compare.ets.arkts2.json | 162 +- .../interop_import_js_compare.ets.json | 14 +- .../test/interop/interop_import_js_index.ets | 1 - .../interop_import_js_index.ets.arkts2.json | 68 +- .../interop_import_js_index.ets.autofix.json | 135 +- .../interop/interop_import_js_index.ets.json | 13 +- .../interop_import_js_index.ets.migrate.ets | 1 - .../interop_import_js_index.ets.migrate.json | 14 +- .../test/interop/interop_import_js_rules.ets | 11 + .../interop_import_js_rules.ets.arkts2.json | 220 +- .../interop_import_js_rules.ets.autofix.json | 2083 ++++++++--------- .../interop/interop_import_js_rules.ets.json | 28 +- .../test/interop/interop_import_typeof_js.ets | 3 +- .../interop_import_typeof_js.ets.arkts2.json | 884 ++++--- .../interop_import_typeof_js.ets.autofix.json | 1708 ++++++-------- .../interop/interop_import_typeof_js.ets.json | 33 +- .../interop_import_typeof_js.ets.migrate.ets | 7 +- .../interop_import_typeof_js.ets.migrate.json | 334 +-- .../interop_not_have_property_arkts2.ets | 1 - ...p_not_have_property_arkts2.ets.arkts2.json | 92 +- ..._not_have_property_arkts2.ets.autofix.json | 235 +- .../interop_not_have_property_arkts2.ets.json | 13 +- ...p_not_have_property_arkts2.ets.migrate.ets | 1 - ..._not_have_property_arkts2.ets.migrate.json | 14 +- .../interop_not_have_property_num_arkts2.ets | 1 - ...t_have_property_num_arkts2.ets.arkts2.json | 186 +- ..._have_property_num_arkts2.ets.autofix.json | 424 +--- ...erop_not_have_property_num_arkts2.ets.json | 13 +- ...t_have_property_num_arkts2.ets.migrate.ets | 1 - ..._have_property_num_arkts2.ets.migrate.json | 34 +- .../test/interop/no_await_js_promise.ets | 127 +- .../no_await_js_promise.ets.arkts2.json | 122 +- .../test/interop/no_await_js_promise.ets.json | 18 +- .../linter/test/interop/no_js_instanceof.ets | 1 - .../interop/no_js_instanceof.ets.arkts2.json | 104 +- .../test/interop/no_js_instanceof.ets.json | 38 +- .../linter/test/interop/object_built_in.ets | 2 +- .../interop/object_built_in.ets.arkts2.json | 12 +- .../test/interop/object_built_in.ets.json | 12 +- .../interop/object_literal_constructor.ets | 1 - ...object_literal_constructor.ets.arkts2.json | 82 +- .../object_literal_constructor.ets.json | 18 +- .../interop/object_literal_union_type.ets | 1 - .../object_literal_union_type.ets.arkts2.json | 38 +- .../object_literal_union_type.ets.json | 23 +- .../object_literal_union_type_arkts2.ets | 1 - .../interop/oh_modules/reflect_export.ets | 1 - .../static_object_literals_export.ets | 1 - .../linter/test/interop/reflect_built_in.ets | 2 +- .../interop/reflect_built_in.ets.arkts2.json | 12 +- .../test/interop/reflect_built_in.ets.json | 15 +- .../test/interop/static_dynamic_import.ets | 24 + .../static_dynamic_import.ets.arkts2.json | 98 + .../interop/static_dynamic_import.ets.json | 58 + .../interop/static_object_literals.ets.json | 63 +- .../linter/test/interop/unique_types.ets | 1 - .../test/interop/unique_types.ets.arkts2.json | 40 +- .../interop/unique_types.ets.autofix.json | 56 +- .../linter/test/interop/unique_types.ets.json | 27 +- .../test/interop/unique_types.ets.migrate.ets | 1 - .../interop/unique_types.ets.migrate.json | 32 +- .../array_index_expr_type.ets.arkts2.json | 208 +- .../array_index_expr_type.ets.autofix.json | 208 +- .../array_index_expr_type.ets.migrate.json | 90 + .../main/dynamic_ctor_call.ets.arkts2.json | 10 + .../explicit_function_type.ets.arkts2.json | 10 + .../explicit_function_type.ets.autofix.json | 10 + .../explicit_function_type.ets.migrate.json | 10 + .../func_inferred_type_args_2.ets.arkts2.json | 104 +- ...func_inferred_type_args_2.ets.autofix.json | 194 +- ...func_inferred_type_args_2.ets.migrate.json | 80 + .../test/main/index_negative.ets.arkts2.json | 150 ++ .../main/invalid_identifier.ets.arkts2.json | 10 + .../test/main/limit_void_type.ets.arkts2.json | 20 + .../literals_as_prop_names.ets.arkts2.json | 10 + .../literals_as_prop_names.ets.autofix.json | 10 + .../literals_as_prop_names.ets.migrate.json | 10 + .../main/no_tuples_arrays.ets.arkts2.json | 10 + .../main/numeric_semantics.ets.arkts2.json | 20 + .../main/numeric_semantics.ets.autofix.json | 20 + .../main/numeric_semantics.ets.migrate.json | 20 + .../main/numeric_semantics2.ets.arkts2.json | 10 + .../main/numeric_semantics2.ets.autofix.json | 10 + .../main/numeric_semantics2.ets.migrate.json | 10 + ...object_literals_properties.ets.arkts2.json | 10 + ...bject_literals_properties.ets.autofix.json | 10 + ...bject_literals_properties.ets.migrate.json | 10 + .../main/prop_name_from_value.ets.arkts2.json | 10 + .../property_access_by_index.ets.arkts2.json | 200 ++ .../test/main/stdlib_array.ets.arkts2.json | 20 + .../main/structural_identity.ets.arkts2.json | 30 + .../test/main/ts_overload.ets.arkts2.json | 22 +- .../linter/test/rules/rule37.ets.migrate.json | 13 +- ...phen_props_deprecated_sdk2.ets.arkts2.json | 20 + 162 files changed, 6304 insertions(+), 6657 deletions(-) mode change 100755 => 100644 ets2panda/linter/test/interop/binary_operation_js_obj.ets mode change 100755 => 100644 ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json mode change 100755 => 100644 ets2panda/linter/test/interop/increases_decreases_js_obj.ets mode change 100755 => 100644 ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_convert_import.ets mode change 100755 => 100644 ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_import_js.ets mode change 100755 => 100644 ets2panda/linter/test/interop/interop_import_typeof_js.ets mode change 100755 => 100644 ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.autofix.json mode change 100755 => 100644 ets2panda/linter/test/interop/no_await_js_promise.ets mode change 100755 => 100644 ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json mode change 100755 => 100644 ets2panda/linter/test/interop/no_js_instanceof.ets mode change 100755 => 100644 ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json create mode 100644 ets2panda/linter/test/interop/static_dynamic_import.ets create mode 100644 ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json create mode 100644 ets2panda/linter/test/interop/static_dynamic_import.ets.json diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 4fe5be4659..62c12d1403 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -270,14 +270,13 @@ cookBookTag[260] = 'The "@Entry" annotation does not support dynamic parameters cookBookTag[262] = 'The makeObserved function is not supported (arkui-no-makeobserved-function)'; cookBookTag[263] = 'The "@Provide" annotation does not support dynamic parameters (arkui-provide-annotation-parameters)'; -cookBookTag[264] = 'Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)'; cookBookTag[265] = 'Direct inheritance of interop JS classes is not supported (arkts-interop-js2s-inherit-js-class)'; cookBookTag[266] = 'Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)'; cookBookTag[267] = 'Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)'; cookBookTag[268] = 'Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)'; cookBookTag[269] = 'Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)'; -cookBookTag[270] = 'Trying to catch JS errors is not permitted (arkts-interop-js2s-js-exception)'; +cookBookTag[270] = 'ArkTS1.2 cannot catch a non Error instance thrown from JS code (arkts-interop-js2s-js-exception)'; cookBookTag[274] = 'The subclass constructor must call the parent class\'s parametered constructor (arkts-subclass-must-call-super-constructor-with-args)'; cookBookTag[275] = diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index e198eb4e83..2d555b1a2a 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -186,7 +186,6 @@ faultsAttrs[FaultID.UIInterfaceImport] = new FaultAttributes(259); faultsAttrs[FaultID.EntryAnnotation] = new FaultAttributes(260); faultsAttrs[FaultID.MakeObservedIsNotSupported] = new FaultAttributes(262); faultsAttrs[FaultID.ProvideAnnotation] = new FaultAttributes(263); -faultsAttrs[FaultID.InteropJsObjectUsage] = new FaultAttributes(264); faultsAttrs[FaultID.InteropJsObjectInheritance] = new FaultAttributes(265); faultsAttrs[FaultID.InteropJsObjectTraverseJsInstance] = new FaultAttributes(266); faultsAttrs[FaultID.InteropJsObjectCallStaticFunc] = new FaultAttributes(267); diff --git a/ets2panda/linter/src/lib/FaultDesc.ts b/ets2panda/linter/src/lib/FaultDesc.ts index 1dd89ea968..d33c364676 100644 --- a/ets2panda/linter/src/lib/FaultDesc.ts +++ b/ets2panda/linter/src/lib/FaultDesc.ts @@ -190,7 +190,6 @@ faultDesc[FaultID.UseConcurrentDeprecated] = '"use concurrent" is not supported' faultDesc[FaultID.MethodInheritRule] = 'Method parameters/returns violate inheritance principles'; faultDesc[FaultID.EntryAnnotation] = '"@Entry" decorator parameter'; faultDesc[FaultID.ProvideAnnotation] = '"@Provide" decorator parameter'; -faultDesc[FaultID.InteropJsObjectUsage] = 'Interop JS object usage'; faultDesc[FaultID.InteropJsObjectInheritance] = 'Interop JS class inheritance'; faultDesc[FaultID.InteropJsObjectTraverseJsInstance] = 'Interop JS object traverse usage'; faultDesc[FaultID.InteropJsObjectCallStaticFunc] = 'Interop JS function usage'; diff --git a/ets2panda/linter/src/lib/HomeCheck.ts b/ets2panda/linter/src/lib/HomeCheck.ts index abf128b57f..a8845c1999 100644 --- a/ets2panda/linter/src/lib/HomeCheck.ts +++ b/ets2panda/linter/src/lib/HomeCheck.ts @@ -18,6 +18,7 @@ import type { FileIssues, RuleFix } from 'homecheck'; import type { CommandLineOptions } from './CommandLineOptions'; import type { ProblemInfo } from './ProblemInfo'; import { FaultID } from './Problems'; +import { shouldProcessFile } from './LinterRunner'; interface RuleConfigInfo { ruleSet: string[]; @@ -39,8 +40,14 @@ export function getHomeCheckConfigInfo(cmdOptions: CommandLineOptions): { ruleConfigInfo: RuleConfigInfo; projectConfigInfo: ProjectConfigInfo; } { + let inputFiles = cmdOptions.inputFiles; + inputFiles = inputFiles.filter((input) => { + return shouldProcessFile(cmdOptions, input); + }); const languageTags = new Map(); - const inputFiles = cmdOptions.inputFiles; + inputFiles.forEach((file) => { + languageTags.set(file, 2); + }); const ruleConfigInfo = { ruleSet: ['plugin:@migration/all'], files: ['**/*.ets', '**/*.ts', '**/*.js'] @@ -54,7 +61,7 @@ export function getHomeCheckConfigInfo(cmdOptions: CommandLineOptions): { hmsSdkPath: cmdOptions.sdkExternalApiPath ? cmdOptions.sdkExternalApiPath[0] : '', reportDir: './', languageTags: languageTags, - fileOrFolderToCheck: inputFiles, + fileOrFolderToCheck: [], logLevel: cmdOptions.verbose ? 'DEBUG' : 'INFO', arkAnalyzerLogLevel: cmdOptions.verbose ? 'DEBUG' : 'ERROR' }; diff --git a/ets2panda/linter/src/lib/LinterOptions.ts b/ets2panda/linter/src/lib/LinterOptions.ts index f6124ac4ab..72613a4cd1 100644 --- a/ets2panda/linter/src/lib/LinterOptions.ts +++ b/ets2panda/linter/src/lib/LinterOptions.ts @@ -45,4 +45,5 @@ export interface LinterOptions { migrationReport?: boolean; wholeProjectPath?: string; checkTsAndJs?: boolean; + inputFiles?: string[]; } diff --git a/ets2panda/linter/src/lib/LinterRunner.ts b/ets2panda/linter/src/lib/LinterRunner.ts index 04fc4174f4..83d5c4ba59 100644 --- a/ets2panda/linter/src/lib/LinterRunner.ts +++ b/ets2panda/linter/src/lib/LinterRunner.ts @@ -31,6 +31,7 @@ import { ARKTS_IGNORE_DIRS_OH_MODULES, ARKTS_IGNORE_FILES } from './utils/consts/ArktsIgnorePaths'; +import { USE_STATIC } from './utils/consts/InteropAPI'; import { EXTNAME_TS, EXTNAME_JS } from './utils/consts/ExtensionName'; import { mergeArrayMaps } from './utils/functions/MergeArrayMaps'; import { clearPathHelperCache, pathContainsDirectory } from './utils/functions/PathHelper'; @@ -93,6 +94,7 @@ function lintImpl(config: LinterConfig): LintRunResult { inputFiles = inputFiles.filter((input) => { return shouldProcessFile(options, input); }); + options.inputFiles = inputFiles; const srcFiles: ts.SourceFile[] = []; for (const inputFile of inputFiles) { const srcFile = tsProgram.getSourceFile(inputFile); @@ -185,6 +187,18 @@ function migrate( return lintResult; } +function hasUseStaticDirective(srcFile: ts.SourceFile): boolean { + if (!srcFile?.statements.length) { + return false; + } + const statements = srcFile.statements; + return ( + ts.isExpressionStatement(statements[0]) && + ts.isStringLiteral(statements[0].expression) && + statements[0].expression.getText() === USE_STATIC + ); +} + function fix( linterConfig: LinterConfig, lintResult: LintRunResult, @@ -204,17 +218,22 @@ function fix( } } mergedProblems.forEach((problemInfos, fileName) => { - // If nothing to fix, skip file - if (!qEd.QuasiEditor.hasAnyAutofixes(problemInfos)) { - return; - } - const srcFile = program.getSourceFile(fileName); if (!srcFile) { - Logger.error(`Failed to retrieve source file: ${fileName}`); + if (!linterConfig.cmdOptions.homecheck) { + Logger.error(`Failed to retrieve source file: ${fileName}`); + } + return; + } + const needToAddUseStatic = + linterConfig.cmdOptions.linterOptions.arkts2 && + linterConfig.cmdOptions.inputFiles.includes(fileName) && + !hasUseStaticDirective(srcFile) && + linterConfig.cmdOptions.linterOptions.ideInteractive; + // If nothing to fix or don't need to add 'use static', then skip file + if (!qEd.QuasiEditor.hasAnyAutofixes(problemInfos) && !needToAddUseStatic) { return; } - const qe: qEd.QuasiEditor = new qEd.QuasiEditor( fileName, srcFile.text, @@ -222,7 +241,7 @@ function fix( undefined, linterConfig.cmdOptions.outputFilePath ); - updatedSourceTexts.set(fileName, qe.fix(problemInfos)); + updatedSourceTexts.set(fileName, qe.fix(problemInfos, needToAddUseStatic)); appliedFix = true; }); @@ -242,7 +261,7 @@ function getMigrationCreateProgramCallback(updatedSourceTexts: Map { + this.handleSharedArrayBuffer(type); const expr = type.expression; if (ts.isIdentifier(expr)) { this.processApiNodeSdkDuplicateDeclName(expr.text, expr); @@ -7890,7 +7896,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private fixJsImportCallExpression(callExpr: ts.CallExpression): void { - if (!this.options.arkts2 || !this.useStatic) { + if ( + !this.options.arkts2 || + !this.useStatic || + ts.isAwaitExpression(callExpr.parent) || + ts.isTypeOfExpression(callExpr.parent) + ) { return; } @@ -7956,27 +7967,16 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } // Try direct check first - if (this.tsUtils.isImportedFromJS(identifier)) { - const autofix = this.autofixer?.createReplacementForJsImportPropertyAccessExpression( - node as ts.PropertyAccessExpression - ); - - this.incrementCounters( - node, - TsUtils.isInsideIfCondition(node) ? FaultID.InteropJsObjectConditionJudgment : FaultID.InteropJsObjectUsage, - autofix - ); + if (!this.tsUtils.isImportedFromJS(identifier)) { return; } - - // Try indirect reference (e.g., const foo = importedObj;) - const originalIdentifier = this.tsUtils.findOriginalIdentifier(identifier); - if (originalIdentifier && this.tsUtils.isImportedFromJS(originalIdentifier)) { - const autofix = this.autofixer?.createReplacementForJsIndirectImportPropertyAccessExpression( - node as ts.PropertyAccessExpression - ); - this.incrementCounters(node, FaultID.InteropJsObjectUsage, autofix); + const autofix = this.autofixer?.createReplacementForJsImportPropertyAccessExpression( + node as ts.PropertyAccessExpression + ); + if (!TsUtils.isInsideIfCondition(node)) { + return; } + this.incrementCounters(node, FaultID.InteropJsObjectConditionJudgment, autofix); } private fixJsImportElementAccessExpression(elementAccessExpr: ts.ElementAccessExpression): void { @@ -8002,10 +8002,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - const autofix = this.autofixer?.createReplacementJsImportElementAccessExpression( - elementAccessExpr, - elementAccessExpr.expression as ts.Identifier - ); + const autofix = this.autofixer?.fixJsImportElementAccessExpression(elementAccessExpr); this.incrementCounters(elementAccessExpr, FaultID.InteropJsObjectTraverseJsInstance, autofix); } @@ -8070,6 +8067,25 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { ); } + private handleForOfJsArray(node: ts.ForOfStatement): void { + if (!this.options.arkts2 || !this.useStatic) { + return; + } + + const expr = node.expression; + if (!ts.isIdentifier(expr) || !this.tsUtils.isPossiblyImportedFromJS(expr)) { + return; + } + + const exprType = this.tsTypeChecker.getTypeAtLocation(expr); + + if (!this.tsUtils.isArray(exprType)) { + return; + } + + this.incrementCounters(node, FaultID.InteropJsObjectTraverseJsInstance); + } + private checkStdLibConcurrencyImport(importDeclaration: ts.ImportDeclaration): void { if (!this.options.arkts2) { return; @@ -8242,7 +8258,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { defaultSymbol = this.tsUtils.trueSymbolAtLocation(importClause.name); } if (namedBindings) { - if (ts.isNamedImports(namedBindings)) { + if (ts.isNamedImports(namedBindings) && namedBindings.elements?.length > 0 && namedBindings.elements[0]?.name) { symbol = this.tsUtils.trueSymbolAtLocation(namedBindings.elements[0].name); } else if (ts.isNamespaceImport(namedBindings)) { symbol = this.tsUtils.trueSymbolAtLocation(namedBindings.name); @@ -8349,7 +8365,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } for (const declaration of symbol.declarations ?? []) { - if (!TsUtils.isArkts12File(declaration.getSourceFile())) { + if (!this.tsUtils.isArkts12File(declaration.getSourceFile())) { return true; } } @@ -8414,7 +8430,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const isFromArkTs2 = declarations.some((decl) => { - return TsUtils.isArkts12File(decl.getSourceFile()); + return this.tsUtils.isArkts12File(decl.getSourceFile()); }); if (isFromArkTs2) { @@ -8551,17 +8567,17 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } - return TypeScriptLinter.isTypeFromArkts12(type); + return this.isTypeFromArkts12(type); } - private static isTypeFromArkts12(type: ts.Type): boolean { + private isTypeFromArkts12(type: ts.Type): boolean { const symbol = type?.getSymbol(); if (!symbol) { return false; } const isFromArkts12 = (symbol.declarations ?? []).some((decl) => { - return TsUtils.isArkts12File(decl.getSourceFile()); + return this.tsUtils.isArkts12File(decl.getSourceFile()); }); if (isFromArkts12) { @@ -8607,13 +8623,13 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const propType = this.tsTypeChecker.getTypeOfSymbolAtLocation(property, property.valueDeclaration); - if (TypeScriptLinter.isTypeFromArkts12(propType)) { + if (this.isTypeFromArkts12(propType)) { this.incrementCounters(prop.initializer, FaultID.InteropStaticObjectLiterals); } } private handleObjectLiteralAssignment(node: ts.VariableDeclaration): void { - if (TsUtils.isArkts12File(node.getSourceFile())) { + if (this.tsUtils.isArkts12File(node.getSourceFile())) { return; } @@ -8637,7 +8653,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private handleObjectLiteralInFunctionArgs(node: ts.CallExpression): void { - if (TsUtils.isArkts12File(node.getSourceFile())) { + if (this.tsUtils.isArkts12File(node.getSourceFile())) { return; } const signature = this.tsTypeChecker.getResolvedSignature(node); @@ -8660,7 +8676,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const paramType = this.tsTypeChecker.getTypeOfSymbolAtLocation(param, param.valueDeclaration); - if (TypeScriptLinter.isTypeFromArkts12(paramType)) { + if (this.isTypeFromArkts12(paramType)) { this.incrementCounters(arg, FaultID.InteropStaticObjectLiterals); } } else if (this.isObjectLiteralAssignedToArkts12Type(arg)) { @@ -8670,7 +8686,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private handleObjectLiteralInReturn(node: ts.ReturnStatement): void { - if (TsUtils.isArkts12File(node.getSourceFile())) { + if (this.tsUtils.isArkts12File(node.getSourceFile())) { return; } @@ -8696,7 +8712,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (functionNode?.type) { const returnType = this.tsTypeChecker.getTypeAtLocation(functionNode.type); - if (TypeScriptLinter.isTypeFromArkts12(returnType)) { + if (this.isTypeFromArkts12(returnType)) { this.incrementCounters(node.expression, FaultID.InteropStaticObjectLiterals); } } else if (this.isObjectLiteralAssignedToArkts12Type(node.expression)) { @@ -8872,23 +8888,77 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return targetTypes.includes(storageType.getText()); } - private handleAwaitExpression(node: ts.Node): void { + private getIdentifierForAwaitExpr(awaitExpr: ts.AwaitExpression): IdentifierAndArguments { + void this; + + let ident: undefined | ts.Identifier; + let args: ts.NodeArray | undefined; + + const expr = awaitExpr.expression; + if (ts.isCallExpression(expr)) { + if (ts.isIdentifier(expr.expression)) { + ident = expr.expression; + } + + if (ts.isPropertyAccessExpression(expr.expression)) { + if (ts.isIdentifier(expr.expression.name)) { + ident = expr.expression.name; + } + } + args = expr.arguments; + } else if (ts.isIdentifier(expr)) { + ident = expr; + } + + return { ident, args }; + } + + private handleAwaitExpression(awaitExpr: ts.AwaitExpression): void { if (!this.options.arkts2 || !this.useStatic) { return; } - const awaitExpr = node as ts.AwaitExpression; - const checkAndReportJsImportAwait = (targetNode: ts.Node): boolean => { - if (ts.isIdentifier(targetNode) && this.tsUtils.isJsImport(targetNode)) { - this.incrementCounters(node, FaultID.NoAwaitJsPromise); - return true; - } - return false; - }; - const expr = awaitExpr.expression; - checkAndReportJsImportAwait(expr); - if (ts.isCallExpression(expr)) { - checkAndReportJsImportAwait(expr.expression); + const { ident, args } = this.getIdentifierForAwaitExpr(awaitExpr); + if (!ident) { + return; + } + + if (!this.tsUtils.isJsImport(ident)) { + return; + } + + const declaration = this.tsUtils.getDeclarationNode(ident); + if (!declaration) { + return; + } + + if ( + ts.isFunctionDeclaration(declaration) && + TsUtils.hasModifier(declaration.modifiers, ts.SyntaxKind.AsyncKeyword) + ) { + const autofix = this.autofixer?.fixAwaitJsCallExpression(ident, args); + this.incrementCounters(awaitExpr, FaultID.NoAwaitJsPromise, autofix); + return; + } + + if (ts.isMethodDeclaration(declaration) && TsUtils.hasModifier(declaration.modifiers, ts.SyntaxKind.AsyncKeyword)) { + const autofix = this.autofixer?.fixAwaitJsMethodCallExpression(ident, args); + this.incrementCounters(awaitExpr, FaultID.NoAwaitJsPromise, autofix); + return; + } + + if (!ts.isVariableDeclaration(declaration)) { + return; } + + const type = this.tsTypeChecker.getTypeAtLocation(declaration); + const typeString = this.tsTypeChecker.typeToString(type); + + if (typeString.split('<')[0] !== 'Promise') { + return; + } + + const autofix = this.autofixer?.fixAwaitJsPromise(ident); + this.incrementCounters(awaitExpr, FaultID.NoAwaitJsPromise, autofix); } private handleNotsLikeSmartType(classDecl: ts.ClassDeclaration): void { @@ -8983,7 +9053,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return (type.flags & ts.TypeFlags.Number) !== 0 || (type.flags & ts.TypeFlags.NumberLiteral) !== 0; }; - const isBigIntAndNumberOperand = isNumber(leftType) && isBigInt(rightType) || isBigInt(leftType) && isNumber(rightType); + const isBigIntAndNumberOperand = + isNumber(leftType) && isBigInt(rightType) || isBigInt(leftType) && isNumber(rightType); if (isBigIntAndNumberOperand) { this.incrementCounters(node, FaultID.NumericBigintCompare); } diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 564ebc117d..dd1918fbf2 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -53,8 +53,10 @@ import { WRAP, INSTANTIATE, TO_NUMBER, + TO_PROMISE, INVOKE, - INVOKE_METHOD + INVOKE_METHOD, + LENGTH } from '../utils/consts/InteropAPI'; import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; @@ -3603,7 +3605,7 @@ export class Autofixer { let start = node.getStart(); let end = node.getEnd(); - let replacementText = `${objName}.getPropertyByName('${propName}')`; + let replacementText = `${objName}.${GET_PROPERTY_BY_NAME}('${propName}')`; // Check if there is an "as number" type assertion in the statement if (ts.isAsExpression(node.parent) && node.parent.type.kind === ts.SyntaxKind.NumberKeyword) { @@ -3622,29 +3624,93 @@ export class Autofixer { const start = node.getStart(); const end = node.getEnd(); - const replacement = `${objName}.getPropertyByName('${propName}')${this.utils.findTypeOfNodeForConversion(node)}`; + const typeTag = this.utils.findTypeOfNodeForConversion(node); + const replacement = `${objName}.${GET_PROPERTY_BY_NAME}('${propName}')${typeTag}`; return [{ replacementText: replacement, start, end }]; } - createReplacementJsImportElementAccessExpression( - elementAccessExpr: ts.ElementAccessExpression, - identifier: ts.Identifier - ): Autofix[] { - const isParentBinaryExp = ts.isBinaryExpression(elementAccessExpr.parent); - const exprText = elementAccessExpr.argumentExpression.getText(); - const start = isParentBinaryExp ? elementAccessExpr.parent.getStart() : elementAccessExpr.getStart(); - const end = isParentBinaryExp ? elementAccessExpr.parent.getEnd() : elementAccessExpr.getEnd(); - - const replacementText = - isParentBinaryExp && elementAccessExpr.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken ? - `${identifier.text}.setPropertyByIndex(${exprText},` + - ` ESValue.wrap(${elementAccessExpr.parent.right.getText()}))` : - `${identifier.text}.getPropertyByIndex(${exprText})` + - this.utils.findTypeOfNodeForConversion(elementAccessExpr); + /** + * Converts a JS element access (e.g. `arr[index]`) into the corresponding + * interop call: + * - On assignment (`arr[index] = value`), emits `arr.setPropertyByIndex(index, ESValue.wrap(value))` + * - On read, emits `arr.getPropertyByIndex(index)` plus any type conversion suffix + * + * @param elementAccessExpr The original `ElementAccessExpression` node. + * @returns An array with a single `Autofix` describing the replacement range and text. + */ + fixJsImportElementAccessExpression(elementAccessExpr: ts.ElementAccessExpression): Autofix[] { + const parent = elementAccessExpr.parent; + + const isAssignment = + parent !== undefined && ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken; + + // array identifier (e.g. "arr") + const identifierNode = elementAccessExpr.expression as ts.Identifier; + + let replacementText: string; + if (isAssignment) { + // arr.setPropertyByIndex(index, ESValue.wrap(value)) + const wrapped = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(ES_VALUE), + ts.factory.createIdentifier(WRAP) + ), + undefined, + [parent.right] + ); + + const callExpr = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(identifierNode, ts.factory.createIdentifier(SET_PROPERTY_BY_INDEX)), + undefined, + [elementAccessExpr.argumentExpression, wrapped] + ); + + replacementText = this.printer.printNode(ts.EmitHint.Unspecified, callExpr, elementAccessExpr.getSourceFile()); + } else { + // arr.getPropertyByIndex(index) plus conversion + const callExpr = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(identifierNode, ts.factory.createIdentifier(GET_PROPERTY_BY_INDEX)), + undefined, + [elementAccessExpr.argumentExpression] + ); + + replacementText = + this.printer.printNode(ts.EmitHint.Unspecified, callExpr, elementAccessExpr.getSourceFile()) + + this.utils.findTypeOfNodeForConversion(elementAccessExpr); + } + + const start = isAssignment ? (parent as ts.Node).getStart() : elementAccessExpr.getStart(); + const end = isAssignment ? (parent as ts.Node).getEnd() : elementAccessExpr.getEnd(); + return [{ replacementText, start, end }]; } + /** + * Replace each loop‐variable reference (e.g. `element`) with + * `array.getPropertyByIndex(i)` plus appropriate conversion. + * + * @param identifier The Identifier node of the loop variable usage. + * @param arrayName The name of the array being iterated. + */ + fixInteropArrayElementUsage(identifier: ts.Identifier, arrayName: string): Autofix { + // arr.getPropertyByIndex(i) + const callExpr = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(arrayName), + ts.factory.createIdentifier(GET_PROPERTY_BY_INDEX) + ), + undefined, + [ts.factory.createIdentifier('i')] + ); + + // Print and append proper conversion suffix + const printed = this.printer.printNode(ts.EmitHint.Unspecified, callExpr, identifier.getSourceFile()); + const replacementText = printed + this.utils.findTypeOfNodeForConversion(identifier); + + return { replacementText, start: identifier.getStart(), end: identifier.getEnd() }; + } + fixSharedArrayBufferConstructor(node: ts.NewExpression): Autofix[] | undefined { void this; @@ -3671,6 +3737,63 @@ export class Autofixer { return [{ replacementText, start: node.getStart(), end: node.getEnd() }]; } + /** + * Converts a `for...of` over an interop array into + * an index-based `for` loop using `getPropertyByName("length")`. + * + * @param node The `ForOfStatement` node to fix. + * @returns A single Autofix for the loop header replacement. + */ + fixInteropArrayForOf(node: ts.ForOfStatement): Autofix { + const iterableName = node.expression.getText(); + + const initializer = ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier('i'), + undefined, + undefined, + ts.factory.createNumericLiteral('0') + ) + ], + ts.NodeFlags.Let + ); + + const lengthAccess = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(iterableName), + ts.factory.createIdentifier(GET_PROPERTY_BY_NAME) + ), + undefined, + [ts.factory.createStringLiteral(LENGTH)] + ); + const condition = ts.factory.createBinaryExpression( + ts.factory.createIdentifier('i'), + ts.SyntaxKind.LessThanToken, + lengthAccess + ); + + const incrementor = ts.factory.createPrefixUnaryExpression( + ts.SyntaxKind.PlusPlusToken, + ts.factory.createIdentifier('i') + ); + + // Render just the "(initializer; condition; incrementor)" text: + const headerText = [ + this.printer.printNode(ts.EmitHint.Unspecified, initializer, node.getSourceFile()), + '; ', + this.printer.printNode(ts.EmitHint.Unspecified, condition, node.getSourceFile()), + '; ', + this.printer.printNode(ts.EmitHint.Unspecified, incrementor, node.getSourceFile()) + ].join(''); + + // Only replace from the start of the initializer to the end of the 'of' expression + const start = node.initializer.getStart(); + const end = node.expression.getEnd(); + + return { start, end, replacementText: headerText }; + } + fixAppStorageCallExpression(callExpr: ts.CallExpression): Autofix[] | undefined { const varDecl = Autofixer.findParentVariableDeclaration(callExpr); if (!varDecl || varDecl.type) { @@ -3757,30 +3880,52 @@ export class Autofixer { return ''; } - private static fixInterOpImportJsWrapArgs(args: ts.NodeArray): string { - return args. - map((arg) => { - return `ESValue.wrap(${arg.getText()})`; - }). - join(', '); - } - - private fixInterOpImportJsProcessNode(node: ts.Node): string { + private fixInterOpImportJsProcessNode(node: ts.Node): string | undefined { if (ts.isIdentifier(node)) { return node.text; } else if (ts.isCallExpression(node)) { - const callee = this.fixInterOpImportJsProcessNode(node.expression); - const args = Autofixer.fixInterOpImportJsWrapArgs(node.arguments); - return `${callee}.invoke(${args})`; + const newArgs = this.createArgs(node.arguments); + const callee = node.expression; + switch (callee.kind) { + case ts.SyntaxKind.PropertyAccessExpression: { + const propertyAccessExpr = node.expression as ts.PropertyAccessExpression; + const newCallExpr = this.createJSInvokeCallExpression(propertyAccessExpr.expression, INVOKE_METHOD, [ + ts.factory.createStringLiteral(propertyAccessExpr.name.text), + ...newArgs || [] + ]); + + if (!newCallExpr) { + return undefined; + } + return this.printer.printNode(ts.EmitHint.Unspecified, newCallExpr, node.getSourceFile()); + } + default: { + const callExpr = this.createJSInvokeCallExpression(node.expression, INVOKE, [...newArgs || []]); + + if (!callExpr) { + return undefined; + } + + return this.printer.printNode(ts.EmitHint.Unspecified, callExpr, node.getSourceFile()); + } + } } else if (ts.isPropertyAccessExpression(node)) { const base = this.fixInterOpImportJsProcessNode(node.expression); + if (!base) { + return undefined; + } const propName = node.name.text; - return `${base}.getPropertyByName('${propName}')`; + return `${base}.${GET_PROPERTY_BY_NAME}('${propName}')`; } else if (ts.isNewExpression(node)) { - const constructor = this.fixInterOpImportJsProcessNode(node.expression); - return `${constructor}.instantiate()`; + const newArgs = this.createArgs(node.arguments); + const newCallExpr = this.createJSInvokeCallExpression(node.expression, INSTANTIATE, [...newArgs || []]); + + if (!newCallExpr) { + return undefined; + } + return this.printer.printNode(ts.EmitHint.Unspecified, newCallExpr, node.getSourceFile()); } - return ''; + return undefined; } fixInterOpImportJs( @@ -3986,8 +4131,11 @@ export class Autofixer { const start = typeofExpress.getStart(); const end = typeofExpress.getEnd(); const processed = this.fixInterOpImportJsProcessNode(node); + if (!processed) { + return undefined; + } const replacementText = `${processed}.typeOf()`; - return replacementText ? [{ start, end, replacementText }] : undefined; + return [{ start, end, replacementText }]; } fixInteropInterfaceConvertNum(express: ts.PrefixUnaryExpression): Autofix[] | undefined { @@ -4250,6 +4398,80 @@ export class Autofixer { return undefined; } + private createJSInvokeCallExpression( + ident: ts.Expression, + method: string, + args: ts.Expression[] | undefined + ): ts.CallExpression | undefined { + if (ts.isNewExpression(ident)) { + const instantiatedClass = this.createJSInvokeCallExpression( + ident.expression, + INSTANTIATE, + this.createArgs(ident.arguments) + ); + if (!instantiatedClass) { + return undefined; + } + return this.createJSInvokeCallExpression(instantiatedClass, method, args); + } + return ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(ident, ts.factory.createIdentifier(method)), + undefined, + args + ); + } + + fixAwaitJsCallExpression(ident: ts.Identifier, args: ts.NodeArray | undefined): Autofix[] | undefined { + const newArgs = this.createArgs(args); + + const newCallExpr = this.createJSInvokeCallExpression(ident, INVOKE, newArgs); + if (!newCallExpr) { + return undefined; + } + + const replacedNode = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(newCallExpr, ts.factory.createIdentifier(TO_PROMISE)), + undefined, + undefined + ); + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, replacedNode, ident.getSourceFile()); + return [{ start: ident.parent.getStart(), end: ident.parent.getEnd(), replacementText }]; + } + + fixAwaitJsMethodCallExpression( + ident: ts.Identifier, + args: ts.NodeArray | undefined + ): Autofix[] | undefined { + const propertyAccessExpr = ident.parent as ts.PropertyAccessExpression; + const accessedProperty = propertyAccessExpr.expression; + const newArgs = this.createArgs(args); + + const newCallExpr = this.createJSInvokeCallExpression(accessedProperty, INVOKE_METHOD, [ + ts.factory.createStringLiteral(ident.text), + ...newArgs || [] + ]); + + if (!newCallExpr) { + return undefined; + } + + const replacedNode = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(newCallExpr, ts.factory.createIdentifier(TO_PROMISE)), + undefined, + undefined + ); + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, replacedNode, ident.getSourceFile()); + return [{ start: propertyAccessExpr.parent.getStart(), end: propertyAccessExpr.parent.getEnd(), replacementText }]; + } + + fixAwaitJsPromise(ident: ts.Identifier): Autofix[] { + void this; + const replacementText = `${ident.text}.toPromise()`; + return [{ start: ident.getStart(), end: ident.getEnd(), replacementText }]; + } + fixMissingAttribute(node: ts.PropertyAccessExpression): Autofix[] { const exprName = node.expression.getText(); const propertyAccessExpr = ts.factory.createPropertyAccessExpression( diff --git a/ets2panda/linter/src/lib/autofixes/QuasiEditor.ts b/ets2panda/linter/src/lib/autofixes/QuasiEditor.ts index 462d6d8b13..7d8aad8513 100644 --- a/ets2panda/linter/src/lib/autofixes/QuasiEditor.ts +++ b/ets2panda/linter/src/lib/autofixes/QuasiEditor.ts @@ -20,6 +20,7 @@ import { Logger } from '../Logger'; import type { ProblemInfo } from '../ProblemInfo'; import type { Autofix } from './Autofixer'; import type { LinterOptions } from '../LinterOptions'; +import { USE_STATIC } from '../utils/consts/InteropAPI'; import { AUTOFIX_HTML_TEMPLATE_TEXT, AutofixHtmlTemplate } from './AutofixReportHtmlHelper'; const BACKUP_AFFIX = '~'; @@ -42,12 +43,6 @@ export class QuasiEditor { fs.copyFileSync(filePath, QuasiEditor.getBackupFileName(filePath)); } - static hasAnyAutofixes(problemInfos: ProblemInfo[]): boolean { - return problemInfos.some((problemInfo) => { - return problemInfo.autofix !== undefined; - }); - } - private generateReport(acceptedPatches: Autofix[]): void { const report = { filePath: this.srcFileName, @@ -95,14 +90,16 @@ export class QuasiEditor { } } - fix(problemInfos: ProblemInfo[]): string { + fix(problemInfos: ProblemInfo[], needAddUseStatic: boolean | undefined): string { const acceptedPatches = QuasiEditor.sortAndRemoveIntersections(problemInfos); - const result = this.applyFixes(acceptedPatches); + let result = this.applyFixes(acceptedPatches); if (this.linterOpts.migrationReport) { this.generateReport(acceptedPatches); } - + if (needAddUseStatic) { + result = QuasiEditor.addUseStaticDirective(result); + } return result; } @@ -196,4 +193,18 @@ export class QuasiEditor { */ return !(lhs.end < rhs.start || rhs.end < lhs.start); } + + private static addUseStaticDirective(content: string): string { + const lines = content.split('\n'); + if (lines.length > 0 && lines[0].trim() === USE_STATIC) { + return content; + } + return USE_STATIC + '\n' + content; + } + + static hasAnyAutofixes(problemInfos: ProblemInfo[]): boolean { + return problemInfos.some((problemInfo) => { + return problemInfo.autofix !== undefined; + }); + } } diff --git a/ets2panda/linter/src/lib/utils/TsUtils.ts b/ets2panda/linter/src/lib/utils/TsUtils.ts index 2327bf026c..5ed15ab452 100644 --- a/ets2panda/linter/src/lib/utils/TsUtils.ts +++ b/ets2panda/linter/src/lib/utils/TsUtils.ts @@ -44,9 +44,8 @@ import { isIntrinsicObjectType } from './functions/isIntrinsicObjectType'; import type { LinterOptions } from '../LinterOptions'; import { ETS } from './consts/TsSuffix'; import { STRINGLITERAL_NUMBER, STRINGLITERAL_NUMBER_ARRAY } from './consts/StringLiteral'; -import { USE_STATIC } from './consts/InteropAPI'; import { ETS_MODULE, PATH_SEPARATOR, VALID_OHM_COMPONENTS_MODULE_PATH } from './consts/OhmUrl'; -import { EXTNAME_ETS, EXTNAME_JS } from './consts/ExtensionName'; +import { EXTNAME_ETS, EXTNAME_JS, EXTNAME_D_ETS } from './consts/ExtensionName'; import { STRING_ERROR_LITERAL } from './consts/Literals'; export const SYMBOL = 'Symbol'; @@ -3654,7 +3653,7 @@ export class TsUtils { ) { return false; } - + return true; } current = current.parent; @@ -3722,21 +3721,19 @@ export class TsUtils { return ( importSourceFile.fileName.endsWith(EXTNAME_ETS) && currentSourceFile.fileName.endsWith(EXTNAME_ETS) && - !TsUtils.isArkts12File(importSourceFile) && - TsUtils.isArkts12File(currentSourceFile) + !this.isArkts12File(importSourceFile) && + this.isArkts12File(currentSourceFile) ); } - static isArkts12File(sourceFile: ts.SourceFile): boolean { - if (!sourceFile?.statements.length) { + isArkts12File(sourceFile: ts.SourceFile): boolean { + if (!sourceFile?.fileName) { return false; } - const statements = sourceFile.statements; - return ( - ts.isExpressionStatement(statements[0]) && - ts.isStringLiteral(statements[0].expression) && - statements[0].expression.getText() === USE_STATIC - ); + if (sourceFile.fileName.endsWith(EXTNAME_D_ETS)) { + return true; + } + return !!this.options.inputFiles?.includes(sourceFile.fileName); } static removeOrReplaceQuotes(str: string, isReplace: boolean): string { diff --git a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts index 74a8769931..725c29fdce 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts @@ -69,7 +69,6 @@ export const arkts2Rules: number[] = [ 261, 262, 263, - 264, 265, 266, 267, @@ -78,6 +77,11 @@ export const arkts2Rules: number[] = [ 270, 274, 275, + 281, + 282, + 283, + 284, + 285, 300, 301, 302, diff --git a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts index c3566b66db..1a2255324b 100644 --- a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts +++ b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts @@ -12,14 +12,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import type * as ts from 'typescript'; -export const USE_STATIC = '\'use static\''; export const ARE_EQUAL = 'areEqual'; export const ARE_STRICTLY_EQUAL = 'areStrictlyEqual'; export const WRAP = 'wrap'; export const INSTANTIATE = 'instantiate'; +export const LENGTH = 'length'; export const INVOKE = 'invoke'; export const INVOKE_METHOD = 'invokeMethod'; +export const TO_PROMISE = 'toPromise'; export const REFLECT_PROPERTIES = [ 'get', @@ -56,6 +58,7 @@ export const OBJECT_PROPERTIES = [ 'isFrozen', 'isSealed' ]; +export const USE_STATIC = '\'use static\''; export const OBJECT_LITERAL = 'Object'; export const REFLECT_LITERAL = 'Reflect'; export const NONE = 'none'; @@ -73,3 +76,8 @@ export enum InteropType { LEGACY = '1.0', NONE = 'none' } + +export type IdentifierAndArguments = { + ident: undefined | ts.Identifier; + args: ts.NodeArray | undefined; +}; diff --git a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets index d3e0b2ca58..b6c511a7ad 100644 --- a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets +++ b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets @@ -21,4 +21,10 @@ let newTypeName: NewTypeName // disable use new NewTypeName() let ntn: NewTypeName = new SharedArrayBuffer(0) // ERROR -function foo(atmo: Atomics) {} // NOT ERROR \ No newline at end of file +function foo(atmo: Atomics) {} // NOT ERROR + +class A extends SharedArrayBuffer { + constructor() { + supper(1) + } +} diff --git a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.arkts2.json b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.arkts2.json index fa8024c8d3..c390c26562 100644 --- a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.arkts2.json +++ b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.arkts2.json @@ -83,6 +83,26 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 26, + "column": 17, + "endLine": 26, + "endColumn": 34, + "problem": "SharedArrayBufferDeprecated", + "suggest": "", + "rule": "SharedArrayBuffer is not supported (arkts-no-need-stdlib-sharedArrayBuffer)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 16, + "endLine": 28, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.autofix.json b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.autofix.json index 01e6621c9d..4eea7766a3 100644 --- a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.autofix.json +++ b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.autofix.json @@ -22,9 +22,9 @@ "problem": "SharedArrayBufferDeprecated", "autofix": [ { - "replacementText": "ArrayBuffer", "start": 624, "end": 641, + "replacementText": "ArrayBuffer", "line": 16, "column": 15, "endLine": 16, @@ -43,9 +43,9 @@ "problem": "SharedArrayBufferDeprecated", "autofix": [ { - "replacementText": "ArrayBuffer", "start": 661, "end": 678, + "replacementText": "ArrayBuffer", "line": 17, "column": 10, "endLine": 17, @@ -64,9 +64,9 @@ "problem": "SharedArrayBufferDeprecated", "autofix": [ { - "replacementText": "ArrayBuffer", "start": 685, "end": 702, + "replacementText": "ArrayBuffer", "line": 17, "column": 34, "endLine": 17, @@ -106,9 +106,9 @@ "problem": "SharedArrayBufferDeprecated", "autofix": [ { - "replacementText": "ArrayBuffer", "start": 737, "end": 754, + "replacementText": "ArrayBuffer", "line": 19, "column": 20, "endLine": 19, @@ -127,9 +127,9 @@ "problem": "SharedArrayBufferDeprecated", "autofix": [ { - "replacementText": "ArrayBuffer", "start": 853, "end": 870, + "replacementText": "ArrayBuffer", "line": 22, "column": 28, "endLine": 22, @@ -160,6 +160,48 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 26, + "column": 17, + "endLine": 26, + "endColumn": 34, + "problem": "SharedArrayBufferDeprecated", + "autofix": [ + { + "start": 945, + "end": 962, + "replacementText": "ArrayBuffer", + "line": 26, + "column": 17, + "endLine": 26, + "endColumn": 34 + } + ], + "suggest": "", + "rule": "SharedArrayBuffer is not supported (arkts-no-need-stdlib-sharedArrayBuffer)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 16, + "endLine": 28, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1000, + "end": 1001, + "replacementText": "1.0", + "line": 28, + "column": 16, + "endLine": 28, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.migrate.ets b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.migrate.ets index 7a393ab10f..b7e398fb0a 100644 --- a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.migrate.ets +++ b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets.migrate.ets @@ -21,4 +21,10 @@ let newTypeName: NewTypeName // disable use new NewTypeName() let ntn: NewTypeName = new ArrayBuffer(0.0) // ERROR -function foo(atmo: Atomics) {} // NOT ERROR \ No newline at end of file +function foo(atmo: Atomics) {} // NOT ERROR + +class A extends ArrayBuffer { + constructor() { + supper(1.0) + } +} diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json b/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json index ca28292f8e..9b627b9d72 100644 --- a/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 12, + "problem": "LimitedStdLibNoDoncurrentDecorator", + "suggest": "", + "rule": "Usage of standard library is restricted(arkts-limited-stdlib-no-concurrent-decorator)", + "severity": "ERROR" + }, { "line": 23, "column": 32, @@ -35,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets b/ets2panda/linter/test/interop/binary_operation_js_obj.ets old mode 100755 new mode 100644 index 29bfa417e5..44c53b8012 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import {foo} from "./binary_operation_js_obj_js" let a = foo.a let b = foo.b diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.args.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.args.json index 3318ebbbcf..b13bb90d5b 100755 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.args.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.args.json @@ -1,21 +1,21 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "mode": { - "arkts2": "", - "autofix": "--arkts-2", - "migrate": "--arkts-2" - } -} +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json old mode 100755 new mode 100644 index f069ac9eeb..e7eb94f512 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, - "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 49, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 9, - "endLine": 17, + "endLine": 16, "endColumn": 14, "problem": "InteropObjectProperty", "suggest": "", @@ -49,29 +39,29 @@ "column": 9, "endLine": 17, "endColumn": 14, - "problem": "InteropJsObjectUsage", + "problem": "InteropObjectProperty", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", "severity": "ERROR" }, { "line": 18, - "column": 9, + "column": 1, "endLine": 18, - "endColumn": 14, - "problem": "InteropObjectProperty", + "endColumn": 2, + "problem": "BinaryOperations", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" }, { "line": 18, - "column": 9, + "column": 5, "endLine": 18, - "endColumn": 14, - "problem": "InteropJsObjectUsage", + "endColumn": 6, + "problem": "BinaryOperations", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" }, { @@ -166,28 +156,8 @@ }, { "line": 23, - "column": 5, - "endLine": 23, - "endColumn": 6, - "problem": "BinaryOperations", - "suggest": "", - "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 2, - "problem": "BinaryOperations", - "suggest": "", - "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", - "severity": "ERROR" - }, - { - "line": 24, "column": 6, - "endLine": 24, + "endLine": 23, "endColumn": 7, "problem": "BinaryOperations", "suggest": "", @@ -195,9 +165,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 3, - "endLine": 24, + "endLine": 23, "endColumn": 5, "problem": "ExponentOp", "suggest": "", diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json old mode 100755 new mode 100644 index 18043cd8a0..b67555d475 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json @@ -15,38 +15,28 @@ ], "result": [ { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 49, "problem": "InterOpImportJs", "autofix": [ { - "start": 617, - "end": 665, + "start": 604, + "end": 652, "replacementText": "", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 49 }, { - "start": 665, - "end": 665, + "start": 652, + "end": 652, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 49 } ], @@ -55,19 +45,19 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 9, - "endLine": 17, + "endLine": 16, "endColumn": 14, "problem": "InteropObjectProperty", "autofix": [ { - "start": 674, - "end": 679, + "start": 661, + "end": 666, "replacementText": "foo.getPropertyByName(\"a\")", - "line": 17, + "line": 16, "column": 9, - "endLine": 17, + "endLine": 16, "endColumn": 14 } ], @@ -80,12 +70,12 @@ "column": 9, "endLine": 17, "endColumn": 14, - "problem": "InteropJsObjectUsage", + "problem": "InteropObjectProperty", "autofix": [ { - "replacementText": "foo.getPropertyByName('a').toNumber()", - "start": 674, - "end": 679, + "start": 675, + "end": 680, + "replacementText": "foo.getPropertyByName(\"b\")", "line": 17, "column": 9, "endLine": 17, @@ -93,49 +83,27 @@ } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", "severity": "ERROR" }, { "line": 18, - "column": 9, + "column": 1, "endLine": 18, - "endColumn": 14, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 688, - "end": 693, - "replacementText": "foo.getPropertyByName(\"b\")", - "line": 18, - "column": 9, - "endLine": 18, - "endColumn": 14 - } - ], + "endColumn": 2, + "problem": "BinaryOperations", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" }, { "line": 18, - "column": 9, + "column": 5, "endLine": 18, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('b').toNumber()", - "start": 688, - "end": 693, - "line": 18, - "column": 9, - "endLine": 18, - "endColumn": 14 - } - ], + "endColumn": 6, + "problem": "BinaryOperations", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" }, { @@ -230,28 +198,8 @@ }, { "line": 23, - "column": 5, - "endLine": 23, - "endColumn": 6, - "problem": "BinaryOperations", - "suggest": "", - "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 2, - "problem": "BinaryOperations", - "suggest": "", - "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", - "severity": "ERROR" - }, - { - "line": 24, "column": 6, - "endLine": 24, + "endLine": 23, "endColumn": 7, "problem": "BinaryOperations", "suggest": "", @@ -259,19 +207,19 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 3, - "endLine": 24, + "endLine": 23, "endColumn": 5, "problem": "ExponentOp", "autofix": [ { "replacementText": "Math.pow(a, b)", - "start": 724, - "end": 730, - "line": 24, + "start": 711, + "end": 717, + "line": 23, "column": 3, - "endLine": 24, + "endLine": 23, "endColumn": 5 } ], diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json index 24e48e6dcb..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets index 72c3c6c688..83e761ce7f 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json index 2caa23e507..bf73aefbeb 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 5, - "endLine": 16, + "endLine": 15, "endColumn": 72, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, + "endLine": 18, "endColumn": 35, "problem": "AnyType", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 5, - "endLine": 20, + "endLine": 19, "endColumn": 35, "problem": "AnyType", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 26, + "line": 25, "column": 1, - "endLine": 26, + "endLine": 25, "endColumn": 15, "problem": "MathPow", "suggest": "", @@ -65,4 +65,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/call_function.ets b/ets2panda/linter/test/interop/call_function.ets index b76d862f4a..74665b905c 100644 --- a/ets2panda/linter/test/interop/call_function.ets +++ b/ets2panda/linter/test/interop/call_function.ets @@ -1,19 +1,18 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -'use static' -import {foo,bar} from "./call_function_js" - -foo() +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {foo,bar} from "./call_function_js" + +foo() bar(123) \ No newline at end of file diff --git a/ets2panda/linter/test/interop/call_function.ets.arkts2.json b/ets2panda/linter/test/interop/call_function.ets.arkts2.json index ed94001123..66335fa504 100644 --- a/ets2panda/linter/test/interop/call_function.ets.arkts2.json +++ b/ets2panda/linter/test/interop/call_function.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, - "endColumn": 43, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, - "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 43, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 6, "problem": "CallJSFunction", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "CallJSFunction", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, + "endLine": 18, "endColumn": 8, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/call_function.ets.json b/ets2panda/linter/test/interop/call_function.ets.json index 08b4bd7b56..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/call_function.ets.json +++ b/ets2panda/linter/test/interop/call_function.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 43, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/call_object_methods.ets b/ets2panda/linter/test/interop/call_object_methods.ets index ee45f2bcf3..891ae57a57 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets +++ b/ets2panda/linter/test/interop/call_object_methods.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import { foo } from "./call_object_methods_js" foo.bar(123) diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.arkts2.json b/ets2panda/linter/test/interop/call_object_methods.ets.arkts2.json index d088101b49..92c91ccd5b 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.arkts2.json +++ b/ets2panda/linter/test/interop/call_object_methods.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, - "endColumn": 47, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, - "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 47, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 13, "problem": "InteropCallObjectMethods", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 9, - "endLine": 18, + "endLine": 17, "endColumn": 12, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.autofix.json b/ets2panda/linter/test/interop/call_object_methods.ets.autofix.json index 85d3430d17..5776d747e9 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.autofix.json +++ b/ets2panda/linter/test/interop/call_object_methods.ets.autofix.json @@ -15,38 +15,28 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, - "endColumn": 47, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, - "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 47, "problem": "InterOpImportJs", "autofix": [ { - "start": 617, - "end": 663, + "start": 604, + "end": 650, "replacementText": "", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 47 }, { - "start": 663, - "end": 663, + "start": 650, + "end": 650, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./call_object_methods_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 47 } ], @@ -55,36 +45,40 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 13, "problem": "InteropCallObjectMethods", "autofix": [ - { - "start": 665, - "end": 677, - "replacementText": "foo.invokeMethod(\"bar\", ESValue.wrap(123))" - } + { + "start": 652, + "end": 664, + "replacementText": "foo.invokeMethod(\"bar\", ESValue.wrap(123))", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 13 + } ], "suggest": "", "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 9, - "endLine": 18, + "endLine": 17, "endColumn": 12, "problem": "NumericSemantics", "autofix": [ { - "start": 673, - "end": 676, + "start": 660, + "end": 663, "replacementText": "123.0", - "line": 18, + "line": 17, "column": 9, - "endLine": 18, + "endLine": 17, "endColumn": 12 } ], @@ -93,4 +87,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.json b/ets2panda/linter/test/interop/call_object_methods.ets.json index 8866623ce5..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.json +++ b/ets2panda/linter/test/interop/call_object_methods.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 47, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets b/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets index aeed85e300..2d455bda8e 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets +++ b/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./call_object_methods_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.migrate.json b/ets2panda/linter/test/interop/call_object_methods.ets.migrate.json index 5399cc769e..4f96146af1 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.migrate.json +++ b/ets2panda/linter/test/interop/call_object_methods.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 5, - "endLine": 16, + "endLine": 15, "endColumn": 68, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,4 +35,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets old mode 100755 new mode 100644 index e1d4d726e4..826f43035f --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import {foo} from "./increases_decreases_js_obj_js" let a: number =0 a = foo.num++ diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json old mode 100755 new mode 100644 index 5e29c71a76..7be0663596 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 52, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 16, - "endLine": 17, + "endLine": 16, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -58,26 +48,6 @@ "line": 18, "column": 5, "endLine": 18, - "endColumn": 12, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 5, - "endLine": 18, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 5, - "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -86,28 +56,8 @@ }, { "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, "column": 5, - "endLine": 20, + "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -118,51 +68,11 @@ "line": 20, "column": 5, "endLine": 20, - "endColumn": 12, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 5, - "endLine": 21, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" - }, - { - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json old mode 100755 new mode 100644 index 0654070343..4131e60caa --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json @@ -15,38 +15,28 @@ ], "result": [ { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 52, "problem": "InterOpImportJs", "autofix": [ { - "start": 617, - "end": 668, + "start": 604, + "end": 655, "replacementText": "", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 52 }, { - "start": 668, - "end": 668, + "start": 655, + "end": 655, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./increases_decreases_js_obj_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, + "endLine": 15, "endColumn": 52 } ], @@ -55,19 +45,19 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 16, - "endLine": 17, + "endLine": 16, "endColumn": 17, "problem": "NumericSemantics", "autofix": [ { - "start": 684, - "end": 685, + "start": 671, + "end": 672, "replacementText": "0.0", - "line": 17, + "line": 16, "column": 16, - "endLine": 17, + "endLine": 16, "endColumn": 17 } ], @@ -76,9 +66,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -89,48 +79,6 @@ "line": 18, "column": 5, "endLine": 18, - "endColumn": 12, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 690, - "end": 697, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 18, - "column": 5, - "endLine": 18, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 5, - "endLine": 18, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 690, - "end": 697, - "line": 18, - "column": 5, - "endLine": 18, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 5, - "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -139,50 +87,8 @@ }, { "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 706, - "end": 713, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 706, - "end": 713, - "line": 19, - "column": 7, - "endLine": 19, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, "column": 5, - "endLine": 20, + "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", @@ -193,95 +99,11 @@ "line": 20, "column": 5, "endLine": 20, - "endColumn": 12, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 718, - "end": 725, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 718, - "end": 725, - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 5, - "endLine": 21, "endColumn": 14, "problem": "InteropIncrementDecrement", "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" - }, - { - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 734, - "end": 741, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 734, - "end": 741, - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.json index cf493da1d6..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 52, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets index 3be959d07a..58c43c2c1d 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets @@ -12,12 +12,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./increases_decreases_js_obj_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); let a: number =0.0 -a = foo.getPropertyByName("num")++ -a = ++foo.getPropertyByName("num") -a = foo.getPropertyByName("num")-- -a = --foo.getPropertyByName("num") +a = foo.num++ +a = ++foo.num +a = foo.num-- +a = --foo.num diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json index f6439adcf2..f2f6070e65 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 16, + "line": 15, "column": 5, - "endLine": 16, + "endLine": 15, "endColumn": 75, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,4 +35,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets b/ets2panda/linter/test/interop/instantiated_js_obj.ets index f24de83f1a..e4208df9fe 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' import {Foo, Foo1} from "./instantiated_js_obj_js" class A { num: number = 1; diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/instantiated_js_obj.ets.arkts2.json index d5efb9f32d..f116dfb988 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets.arkts2.json +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 51, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 19, - "endLine": 19, + "endLine": 18, "endColumn": 20, "problem": "NumericSemantics", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 9, - "endLine": 23, + "endLine": 22, "endColumn": 12, "problem": "NumericSemantics", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 17, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -75,9 +65,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 17, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -85,9 +75,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 15, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -95,9 +85,9 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 11, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -105,9 +95,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 10, - "endLine": 30, + "endLine": 29, "endColumn": 11, "problem": "NumericSemantics", "suggest": "", @@ -115,9 +105,9 @@ "severity": "ERROR" }, { - "line": 32, + "line": 31, "column": 1, - "endLine": 32, + "endLine": 31, "endColumn": 16, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -125,9 +115,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 1, - "endLine": 33, + "endLine": 32, "endColumn": 23, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -135,9 +125,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 10, - "endLine": 33, + "endLine": 32, "endColumn": 13, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/instantiated_js_obj.ets.autofix.json index 7a22b7b9aa..f9ae170771 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets.autofix.json +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets.autofix.json @@ -15,38 +15,28 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 51, "problem": "InterOpImportJs", "autofix": [ { - "start": 618, - "end": 668, + "start": 605, + "end": 655, "replacementText": "", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 51 }, { - "start": 668, - "end": 668, + "start": 655, + "end": 655, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./instantiated_js_obj_js');\nlet Foo = GeneratedImportVar_1.getPropertyByName('Foo');\nlet Foo1 = GeneratedImportVar_1.getPropertyByName('Foo1');\n", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 51 } ], @@ -55,19 +45,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 19, - "endLine": 19, + "endLine": 18, "endColumn": 20, "problem": "NumericSemantics", "autofix": [ { - "start": 697, - "end": 698, + "start": 684, + "end": 685, "replacementText": "1.0", - "line": 19, + "line": 18, "column": 19, - "endLine": 19, + "endLine": 18, "endColumn": 20 } ], @@ -76,19 +66,19 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 728, - "end": 740, + "start": 715, + "end": 727, "replacementText": "Foo.instantiate(ESValue.wrap(123))", - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13 } ], @@ -97,19 +87,19 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 9, - "endLine": 23, + "endLine": 22, "endColumn": 12, "problem": "NumericSemantics", "autofix": [ { - "start": 736, - "end": 739, + "start": 723, + "end": 726, "replacementText": "123.0", - "line": 23, + "line": 22, "column": 9, - "endLine": 23, + "endLine": 22, "endColumn": 12 } ], @@ -118,19 +108,19 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 17, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 741, - "end": 757, + "start": 728, + "end": 744, "replacementText": "Foo.instantiate(ESValue.wrap('hello'))", - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 17 } ], @@ -139,19 +129,19 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 17, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 758, - "end": 774, + "start": 745, + "end": 761, "replacementText": "Foo.instantiate(ESValue.wrap(new A()))", - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 17 } ], @@ -160,19 +150,19 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 15, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 795, - "end": 809, + "start": 782, + "end": 796, "replacementText": "Foo.instantiate(ESValue.wrap(a.num))", - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 15 } ], @@ -181,19 +171,19 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 11, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 810, - "end": 820, + "start": 797, + "end": 807, "replacementText": "Foo.instantiate(ESValue.wrap(a))", - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 11 } ], @@ -202,19 +192,19 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 10, - "endLine": 30, + "endLine": 29, "endColumn": 11, "problem": "NumericSemantics", "autofix": [ { - "start": 856, - "end": 857, + "start": 843, + "end": 844, "replacementText": "1.0", - "line": 30, + "line": 29, "column": 10, - "endLine": 30, + "endLine": 29, "endColumn": 11 } ], @@ -223,19 +213,19 @@ "severity": "ERROR" }, { - "line": 32, + "line": 31, "column": 1, - "endLine": 32, + "endLine": 31, "endColumn": 16, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 861, - "end": 876, + "start": 848, + "end": 863, "replacementText": "Foo.instantiate(ESValue.wrap(test()))", - "line": 32, + "line": 31, "column": 1, - "endLine": 32, + "endLine": 31, "endColumn": 16 } ], @@ -244,16 +234,20 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 1, - "endLine": 33, + "endLine": 32, "endColumn": 23, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 877, - "end": 899, - "replacementText": "Foo1.instantiate(ESValue.wrap(123), ESValue.wrap('hello'))" + "start": 864, + "end": 886, + "replacementText": "Foo1.instantiate(ESValue.wrap(123), ESValue.wrap('hello'))", + "line": 32, + "column": 1, + "endLine": 32, + "endColumn": 23 } ], "suggest": "", @@ -261,19 +255,19 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 10, - "endLine": 33, + "endLine": 32, "endColumn": 13, "problem": "NumericSemantics", "autofix": [ { - "start": 886, - "end": 889, + "start": 873, + "end": 876, "replacementText": "123.0", - "line": 33, + "line": 32, "column": 10, - "endLine": 33, + "endLine": 32, "endColumn": 13 } ], diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets.json b/ets2panda/linter/test/interop/instantiated_js_obj.ets.json index ad8f5eb1ae..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets.json +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.ets index 06c8b9ee78..b033816ddb 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.ets +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./instantiated_js_obj_js'); let Foo = GeneratedImportVar_1.getPropertyByName('Foo'); let Foo1 = GeneratedImportVar_1.getPropertyByName('Foo1'); diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.json index 915dad64c5..2084de8763 100644 --- a/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.json +++ b/ets2panda/linter/test/interop/instantiated_js_obj.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 68, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, + "endLine": 18, "endColumn": 58, "problem": "AnyType", "suggest": "", @@ -45,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets b/ets2panda/linter/test/interop/interop_convert_import.ets old mode 100755 new mode 100644 index e5fa5c03c7..02426a4318 --- a/ets2panda/linter/test/interop/interop_convert_import.ets +++ b/ets2panda/linter/test/interop/interop_convert_import.ets @@ -1,3 +1,4 @@ +<<<<<<< HEAD /* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,4 +39,27 @@ return null_val as null === null;// 扫描出 arkts-interop-js2s-convert-js-type // convert type - undefined test_helper.test(() => { return undefined_val as undefined === undefined; // 扫描出 arkts-interop-js2s-convert-js-type - no pass -}, "undefined_val as undefined === undefined"); \ No newline at end of file +}, "undefined_val as undefined === undefined"); +======= +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + import {foo, foo2, foo3, foo4} from "./interop_convert_import_js.js" + + let a: number = foo.num as number + let a: boolean = foo2.bool as boolean + let a: string = foo3.str as string + let a: bigint = foo4.big as bigint" +>>>>>>> efeb0a81e (modify use static spec) diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json b/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json old mode 100755 new mode 100644 index b6255d07e7..f4460de05a --- a/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json @@ -1,268 +1,188 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], -"result": [ - { - "line": 17, - "column": 2, - "endLine": 17, - "endColumn": 106, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 2, - "endLine": 17, - "endColumn": 106, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 35, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 41, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 38, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 38, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 9, - "endLine": 25, - "endColumn": 27, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 44, - "endLine": 25, - "endColumn": 62, - "problem": "GenericCallNoTypeArgs", - "suggest": "", - "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 54, - "endLine": 25, - "endColumn": 55, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 57, - "endLine": 25, - "endColumn": 58, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 60, - "endLine": 25, - "endColumn": 61, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 9, - "endLine": 30, - "endColumn": 30, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 48, - "endLine": 30, - "endColumn": 49, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 50, - "endLine": 30, - "endColumn": 51, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 52, - "endLine": 30, - "endColumn": 53, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 35, - "column": 8, - "endLine": 35, - "endColumn": 24, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - }, - { - "line": 40, - "column": 8, - "endLine": 40, - "endColumn": 34, - "problem": "InterOpConvertImport", - "suggest": "", - "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", - "severity": "ERROR" - } - ] +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 2, + "endLine": 18, + "endColumn": 106, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 2, + "endLine": 18, + "endColumn": 106, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 18, + "endLine": 20, + "endColumn": 35, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 20, + "endLine": 21, + "endColumn": 41, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 19, + "endLine": 22, + "endColumn": 38, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 19, + "endLine": 23, + "endColumn": 38, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 9, + "endLine": 26, + "endColumn": 27, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 44, + "endLine": 26, + "endColumn": 62, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 54, + "endLine": 26, + "endColumn": 55, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 57, + "endLine": 26, + "endColumn": 58, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 60, + "endLine": 26, + "endColumn": 61, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 9, + "endLine": 31, + "endColumn": 30, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 48, + "endLine": 31, + "endColumn": 49, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 50, + "endLine": 31, + "endColumn": 51, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 52, + "endLine": 31, + "endColumn": 53, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 8, + "endLine": 36, + "endColumn": 24, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 8, + "endLine": 41, + "endColumn": 34, + "problem": "InterOpConvertImport", + "suggest": "", + "rule": "Casting interop JS objects to primitive types is not allowed (arkts-interop-js2s-convert-js-type)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets.autofix.json b/ets2panda/linter/test/interop/interop_convert_import.ets.autofix.json index 5aca1b631b..cfa646085a 100644 --- a/ets2panda/linter/test/interop/interop_convert_import.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.autofix.json @@ -13,11 +13,11 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], -"result": [ + "result": [ { - "line": 17, + "line": 18, "column": 2, - "endLine": 17, + "endLine": 18, "endColumn": 106, "problem": "ImportAfterStatement", "suggest": "", @@ -25,28 +25,28 @@ "severity": "ERROR" }, { - "line": 17, + "line": 18, "column": 2, - "endLine": 17, + "endLine": 18, "endColumn": 106, "problem": "InterOpImportJs", "autofix": [ { - "start": 636, - "end": 740, + "start": 649, + "end": 753, "replacementText": "", - "line": 17, + "line": 18, "column": 2, - "endLine": 17, + "endLine": 18, "endColumn": 106 }, { - "start": 740, - "end": 740, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_convert_import_js.js');\r\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\r\nlet foo2 = GeneratedImportVar_1.getPropertyByName('foo2');\r\nlet foo3 = GeneratedImportVar_1.getPropertyByName('foo3');\r\nlet foo4 = GeneratedImportVar_1.getPropertyByName('foo4');\r\nlet array_val = GeneratedImportVar_1.getPropertyByName('array_val');\r\nlet null_val = GeneratedImportVar_1.getPropertyByName('null_val');\r\nlet undefined_val = GeneratedImportVar_1.getPropertyByName('undefined_val');\r\n", - "line": 17, + "start": 753, + "end": 753, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_convert_import_js.js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet foo2 = GeneratedImportVar_1.getPropertyByName('foo2');\nlet foo3 = GeneratedImportVar_1.getPropertyByName('foo3');\nlet foo4 = GeneratedImportVar_1.getPropertyByName('foo4');\nlet array_val = GeneratedImportVar_1.getPropertyByName('array_val');\nlet null_val = GeneratedImportVar_1.getPropertyByName('null_val');\nlet undefined_val = GeneratedImportVar_1.getPropertyByName('undefined_val');\n", + "line": 18, "column": 2, - "endLine": 17, + "endLine": 18, "endColumn": 106 } ], @@ -55,19 +55,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 20, "column": 18, - "endLine": 19, + "endLine": 20, "endColumn": 35, "problem": "InterOpConvertImport", "autofix": [ { - "start": 761, - "end": 778, + "start": 774, + "end": 791, "replacementText": "foo.getPropertyByName(\"num\").toNumber()", - "line": 19, + "line": 20, "column": 18, - "endLine": 19, + "endLine": 20, "endColumn": 35 } ], @@ -76,61 +76,19 @@ "severity": "ERROR" }, { - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 761, - "end": 768, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num')", - "start": 761, - "end": 768, - "line": 19, - "column": 18, - "endLine": 19, - "endColumn": 25 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, + "line": 21, "column": 20, - "endLine": 20, + "endLine": 21, "endColumn": 41, "problem": "InterOpConvertImport", "autofix": [ { - "start": 799, - "end": 820, + "start": 812, + "end": 833, "replacementText": "foo2.getPropertyByName(\"bool\").toBoolean()", - "line": 20, + "line": 21, "column": 20, - "endLine": 20, + "endLine": 21, "endColumn": 41 } ], @@ -139,61 +97,19 @@ "severity": "ERROR" }, { - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 799, - "end": 808, - "replacementText": "foo2.getPropertyByName(\"bool\")", - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo2.getPropertyByName('bool').toBoolean()", - "start": 799, - "end": 808, - "line": 20, - "column": 20, - "endLine": 20, - "endColumn": 29 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, + "line": 22, "column": 19, - "endLine": 21, + "endLine": 22, "endColumn": 38, "problem": "InterOpConvertImport", "autofix": [ { - "start": 840, - "end": 859, + "start": 853, + "end": 872, "replacementText": "foo3.getPropertyByName(\"str\").toString()", - "line": 21, + "line": 22, "column": 19, - "endLine": 21, + "endLine": 22, "endColumn": 38 } ], @@ -202,61 +118,19 @@ "severity": "ERROR" }, { - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 840, - "end": 848, - "replacementText": "foo3.getPropertyByName(\"str\")", - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo3.getPropertyByName('str').toString()", - "start": 840, - "end": 848, - "line": 21, - "column": 19, - "endLine": 21, - "endColumn": 27 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 22, + "line": 23, "column": 19, - "endLine": 22, + "endLine": 23, "endColumn": 38, "problem": "InterOpConvertImport", "autofix": [ { - "start": 879, - "end": 898, + "start": 892, + "end": 911, "replacementText": "foo4.getPropertyByName(\"big\").toBigInt()", - "line": 22, + "line": 23, "column": 19, - "endLine": 22, + "endLine": 23, "endColumn": 38 } ], @@ -265,51 +139,9 @@ "severity": "ERROR" }, { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 879, - "end": 887, - "replacementText": "foo4.getPropertyByName(\"big\")", - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo4.getPropertyByName('big')", - "start": 879, - "end": 887, - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 27 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 25, + "line": 26, "column": 9, - "endLine": 25, + "endLine": 26, "endColumn": 27, "problem": "InterOpConvertImport", "suggest": "", @@ -317,9 +149,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 26, "column": 44, - "endLine": 25, + "endLine": 26, "endColumn": 62, "problem": "GenericCallNoTypeArgs", "suggest": "", @@ -327,19 +159,19 @@ "severity": "ERROR" }, { - "line": 25, + "line": 26, "column": 54, - "endLine": 25, + "endLine": 26, "endColumn": 55, "problem": "NumericSemantics", "autofix": [ { - "start": 981, - "end": 982, + "start": 994, + "end": 995, "replacementText": "1.0", - "line": 25, + "line": 26, "column": 54, - "endLine": 25, + "endLine": 26, "endColumn": 55 } ], @@ -348,19 +180,19 @@ "severity": "ERROR" }, { - "line": 25, + "line": 26, "column": 57, - "endLine": 25, + "endLine": 26, "endColumn": 58, "problem": "NumericSemantics", "autofix": [ { - "start": 984, - "end": 985, + "start": 997, + "end": 998, "replacementText": "2.0", - "line": 25, + "line": 26, "column": 57, - "endLine": 25, + "endLine": 26, "endColumn": 58 } ], @@ -369,19 +201,19 @@ "severity": "ERROR" }, { - "line": 25, + "line": 26, "column": 60, - "endLine": 25, + "endLine": 26, "endColumn": 61, "problem": "NumericSemantics", "autofix": [ { - "start": 987, - "end": 988, + "start": 1000, + "end": 1001, "replacementText": "3.0", - "line": 25, + "line": 26, "column": 60, - "endLine": 25, + "endLine": 26, "endColumn": 61 } ], @@ -390,9 +222,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 31, "column": 9, - "endLine": 30, + "endLine": 31, "endColumn": 30, "problem": "InterOpConvertImport", "suggest": "", @@ -400,19 +232,19 @@ "severity": "ERROR" }, { - "line": 30, + "line": 31, "column": 48, - "endLine": 30, + "endLine": 31, "endColumn": 49, "problem": "NumericSemantics", "autofix": [ { - "start": 1195, - "end": 1196, + "start": 1208, + "end": 1209, "replacementText": "1.0", - "line": 30, + "line": 31, "column": 48, - "endLine": 30, + "endLine": 31, "endColumn": 49 } ], @@ -421,19 +253,19 @@ "severity": "ERROR" }, { - "line": 30, + "line": 31, "column": 50, - "endLine": 30, + "endLine": 31, "endColumn": 51, "problem": "NumericSemantics", "autofix": [ { - "start": 1197, - "end": 1198, + "start": 1210, + "end": 1211, "replacementText": "2.0", - "line": 30, + "line": 31, "column": 50, - "endLine": 30, + "endLine": 31, "endColumn": 51 } ], @@ -442,19 +274,19 @@ "severity": "ERROR" }, { - "line": 30, + "line": 31, "column": 52, - "endLine": 30, + "endLine": 31, "endColumn": 53, "problem": "NumericSemantics", "autofix": [ { - "start": 1199, - "end": 1200, + "start": 1212, + "end": 1213, "replacementText": "3.0", - "line": 30, + "line": 31, "column": 52, - "endLine": 30, + "endLine": 31, "endColumn": 53 } ], @@ -463,9 +295,9 @@ "severity": "ERROR" }, { - "line": 35, + "line": 36, "column": 8, - "endLine": 35, + "endLine": 36, "endColumn": 24, "problem": "InterOpConvertImport", "suggest": "", @@ -473,9 +305,9 @@ "severity": "ERROR" }, { - "line": 40, + "line": 41, "column": 8, - "endLine": 40, + "endLine": 41, "endColumn": 34, "problem": "InterOpConvertImport", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets.json b/ets2panda/linter/test/interop/interop_convert_import.ets.json index ac2dfbe6f8..5a3f5938e4 100755 --- a/ets2panda/linter/test/interop/interop_convert_import.ets.json +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.json @@ -1,28 +1,28 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 2, - "endLine": 17, - "endColumn": 106, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 2, + "endLine": 18, + "endColumn": 106, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.ets b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.ets index a1c78f19fe..1e107cf338 100644 --- a/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.ets @@ -1,3 +1,54 @@ +<<<<<<< HEAD +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 'use static' + + let GeneratedImportVar_1 = ESValue.load('./interop_convert_import_js.js'); +let foo = GeneratedImportVar_1.getPropertyByName('foo'); +let foo2 = GeneratedImportVar_1.getPropertyByName('foo2'); +let foo3 = GeneratedImportVar_1.getPropertyByName('foo3'); +let foo4 = GeneratedImportVar_1.getPropertyByName('foo4'); +let array_val = GeneratedImportVar_1.getPropertyByName('array_val'); +let null_val = GeneratedImportVar_1.getPropertyByName('null_val'); +let undefined_val = GeneratedImportVar_1.getPropertyByName('undefined_val'); + + + let a: number = foo.getPropertyByName("num").toNumber() + let a1: boolean = foo2.getPropertyByName("bool").toBoolean() + let a2: string = foo3.getPropertyByName("str").toString() + let a3: bigint = foo4.getPropertyByName("big").toBigInt() + +test_helper.test(() => { +return (array_val as Array).toString() === new Array(1.0, 2.0, 3.0).toString();// 扫描出 arkts-interop-js2s-convert-js-type - no pass +}, "array_val as Array === [1, 2, 3]"); + +// convert type - Array +test_helper.test(() => { +return (array_val as number[]).toString() === [1.0,2.0,3.0].toString();// 扫描出 arkts-interop-js2s-convert-js-type - no pass +}, "array_val as Array === [1, 2, 3]"); + +// convert type - null +test_helper.test(() => { +return null_val as null === null;// 扫描出 arkts-interop-js2s-convert-js-type - no pass +}, "null_val as null === null"); + +// convert type - undefined +test_helper.test(() => { +return undefined_val as undefined === undefined; // 扫描出 arkts-interop-js2s-convert-js-type - no pass +}, "undefined_val as undefined === undefined"); +======= /* * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,38 +63,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - 'use static' - - let GeneratedImportVar_1 = ESValue.load('./interop_convert_import_js.js'); -let foo = GeneratedImportVar_1.getPropertyByName('foo'); -let foo2 = GeneratedImportVar_1.getPropertyByName('foo2'); -let foo3 = GeneratedImportVar_1.getPropertyByName('foo3'); -let foo4 = GeneratedImportVar_1.getPropertyByName('foo4'); -let array_val = GeneratedImportVar_1.getPropertyByName('array_val'); -let null_val = GeneratedImportVar_1.getPropertyByName('null_val'); -let undefined_val = GeneratedImportVar_1.getPropertyByName('undefined_val'); - - - let a: number = foo.getPropertyByName("num").toNumber() - let a1: boolean = foo2.getPropertyByName("bool").toBoolean() - let a2: string = foo3.getPropertyByName("str").toString() - let a3: bigint = foo4.getPropertyByName("big").toBigInt() - -test_helper.test(() => { -return (array_val as Array).toString() === new Array(1.0, 2.0, 3.0).toString();// 扫描出 arkts-interop-js2s-convert-js-type - no pass -}, "array_val as Array === [1, 2, 3]"); - -// convert type - Array -test_helper.test(() => { -return (array_val as number[]).toString() === [1.0,2.0,3.0].toString();// 扫描出 arkts-interop-js2s-convert-js-type - no pass -}, "array_val as Array === [1, 2, 3]"); -// convert type - null -test_helper.test(() => { -return null_val as null === null;// 扫描出 arkts-interop-js2s-convert-js-type - no pass -}, "null_val as null === null"); + import {foo, foo2, foo3, foo4} from "./interop_convert_import_js.js" -// convert type - undefined -test_helper.test(() => { -return undefined_val as undefined === undefined; // 扫描出 arkts-interop-js2s-convert-js-type - no pass -}, "undefined_val as undefined === undefined"); \ No newline at end of file + let a: number = foo.num as number + let a: boolean = foo2.bool as boolean + let a: string = foo3.str as string + let a: bigint = foo4.big as bigint" +>>>>>>> efeb0a81e (modify use static spec) diff --git a/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.json b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.json index 85e135ecca..a49b70a952 100644 --- a/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.json @@ -14,21 +14,11 @@ "limitations under the License." ], "result": [ - { - "line": 17, - "column": 6, - "endLine": 17, - "endColumn": 75, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, { "line": 18, - "column": 5, + "column": 6, "endLine": 18, - "endColumn": 56, + "endColumn": 75, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -38,7 +28,7 @@ "line": 19, "column": 5, "endLine": 19, - "endColumn": 58, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -68,7 +58,7 @@ "line": 22, "column": 5, "endLine": 22, - "endColumn": 68, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -78,7 +68,7 @@ "line": 23, "column": 5, "endLine": 23, - "endColumn": 66, + "endColumn": 68, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -88,6 +78,16 @@ "line": 24, "column": 5, "endLine": 24, + "endColumn": 66, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, "endColumn": 76, "problem": "AnyType", "suggest": "", @@ -95,9 +95,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 44, - "endLine": 33, + "endLine": 34, "endColumn": 68, "problem": "GenericCallNoTypeArgs", "suggest": "", @@ -105,9 +105,9 @@ "severity": "ERROR" }, { - "line": 43, + "line": 44, "column": 8, - "endLine": 43, + "endLine": 44, "endColumn": 24, "problem": "InterOpConvertImport", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets b/ets2panda/linter/test/interop/interop_equality_judgment.ets index 7fe09978d3..65ce20fddc 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' import {a, b} from "./interop_equality_judgment_js" a == b a != b diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json index 916e1b51ca..920de865a7 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.arkts2.json @@ -15,23 +15,23 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 52, - "problem": "ImportAfterStatement", + "problem": "InterOpImportJs", "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", "severity": "ERROR" }, { "line": 17, "column": 1, "endLine": 17, - "endColumn": 52, - "problem": "InterOpImportJs", + "endColumn": 7, + "problem": "InteropEqualityJudgment", "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", "severity": "ERROR" }, { @@ -48,7 +48,7 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 7, + "endColumn": 8, "problem": "InteropEqualityJudgment", "suggest": "", "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", @@ -63,16 +63,6 @@ "suggest": "", "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 8, - "problem": "InteropEqualityJudgment", - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json index c198972221..7145a50507 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.autofix.json @@ -15,31 +15,29 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 52, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 52, "problem": "InterOpImportJs", "autofix": [ { - "start": 618, - "end": 669, - "replacementText": "" + "start": 605, + "end": 656, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 52 }, { - "start": 669, - "end": 669, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_equality_judgment_js');\nlet a = GeneratedImportVar_1.getPropertyByName('a');\nlet b = GeneratedImportVar_1.getPropertyByName('b');\n" + "start": 656, + "end": 656, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_equality_judgment_js');\nlet a = GeneratedImportVar_1.getPropertyByName('a');\nlet b = GeneratedImportVar_1.getPropertyByName('b');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 52 } ], "suggest": "", @@ -47,16 +45,20 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 7, "problem": "InteropEqualityJudgment", "autofix": [ { - "start": 670, - "end": 676, - "replacementText": "a.areEqual(b)" + "start": 657, + "end": 663, + "replacementText": "a.areEqual(b)", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 7 } ], "suggest": "", @@ -64,16 +66,20 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "InteropEqualityJudgment", "autofix": [ { - "start": 677, - "end": 683, - "replacementText": "!a.areEqual(b)" + "start": 664, + "end": 670, + "replacementText": "!a.areEqual(b)", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 7 } ], "suggest": "", @@ -81,16 +87,20 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 8, "problem": "InteropEqualityJudgment", "autofix": [ { - "start": 684, - "end": 691, - "replacementText": "a.areStrictlyEqual(b)" + "start": 671, + "end": 678, + "replacementText": "a.areStrictlyEqual(b)", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 8 } ], "suggest": "", @@ -98,16 +108,20 @@ "severity": "ERROR" }, { - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 8, "problem": "InteropEqualityJudgment", "autofix": [ { - "start": 692, - "end": 699, - "replacementText": "!a.areStrictlyEqual(b)" + "start": 679, + "end": 686, + "replacementText": "!a.areStrictlyEqual(b)", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 8 } ], "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.json index e48cf9a99b..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 52, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets index 8bbbd750c9..796cf7f898 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./interop_equality_judgment_js'); let a = GeneratedImportVar_1.getPropertyByName('a'); let b = GeneratedImportVar_1.getPropertyByName('b'); diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json index a3c218b7b2..c3d33e531c 100644 --- a/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_equality_judgment.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 74, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 52, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, + "endLine": 18, "endColumn": 52, "problem": "AnyType", "suggest": "", @@ -45,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_export_js_rules.ets b/ets2panda/linter/test/interop/interop_export_js_rules.ets index 4e6b76262c..e729a7c2c3 100644 --- a/ets2panda/linter/test/interop/interop_export_js_rules.ets +++ b/ets2panda/linter/test/interop/interop_export_js_rules.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import { ff1 } from "./interop_import_js_rules_js" diff --git a/ets2panda/linter/test/interop/interop_export_js_rules.ets.arkts2.json b/ets2panda/linter/test/interop/interop_export_js_rules.ets.arkts2.json index 4fc44d8a3c..1f92c538cd 100644 --- a/ets2panda/linter/test/interop/interop_export_js_rules.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_export_js_rules.ets.arkts2.json @@ -1,88 +1,88 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 13, - "problem": "InteropJsObjectExport", - "suggest": "", - "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 51, - "problem": "InteropJsObjectExport", - "suggest": "", - "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 57, - "problem": "InteropArkTs1ObjectExport", - "suggest": "", - "rule": "Direct export of interop ArkTS1.0 objects is not supported (arkts-interop-d2s-export-entity)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 57, - "problem": "InteropArkTs1ObjectExport", - "suggest": "", - "rule": "Direct export of interop ArkTS1.0 objects is not supported (arkts-interop-d2s-export-entity)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 59, - "problem": "InteropJsObjectExport", - "suggest": "", - "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", - "severity": "ERROR" - } - ] -} + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 51, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 13, + "problem": "InteropJsObjectExport", + "suggest": "", + "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 51, + "problem": "InteropJsObjectExport", + "suggest": "", + "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 57, + "problem": "InteropArkTs1ObjectExport", + "suggest": "", + "rule": "Direct export of interop ArkTS1.0 objects is not supported (arkts-interop-d2s-export-entity)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 57, + "problem": "InteropArkTs1ObjectExport", + "suggest": "", + "rule": "Direct export of interop ArkTS1.0 objects is not supported (arkts-interop-d2s-export-entity)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 57, + "problem": "InteropArkTs1ObjectExport", + "suggest": "", + "rule": "Direct export of interop ArkTS1.0 objects is not supported (arkts-interop-d2s-export-entity)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 1, + "endLine": 28, + "endColumn": 59, + "problem": "InteropJsObjectExport", + "suggest": "", + "rule": "Direct export of interop JS objects is not supported (arkts-interop-js2s-export-js)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_export_js_rules.ets.json b/ets2panda/linter/test/interop/interop_export_js_rules.ets.json index 91f5b61ed1..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/interop_export_js_rules.ets.json +++ b/ets2panda/linter/test/interop/interop_export_js_rules.ets.json @@ -1,28 +1,17 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] -} + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js.ets b/ets2panda/linter/test/interop/interop_import_js.ets old mode 100755 new mode 100644 index 3325f1bdd9..337d1600c6 --- a/ets2panda/linter/test/interop/interop_import_js.ets +++ b/ets2panda/linter/test/interop/interop_import_js.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' import { Cjs } from '../main/js_lib'; import { fjs } from '../main/js_lib'; import { CPreview,bar,foo } from "./jsfiles/preview_import_js"; diff --git a/ets2panda/linter/test/interop/interop_import_js.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js.ets.arkts2.json index 17f26fd8dc..7d56ee5afd 100755 --- a/ets2panda/linter/test/interop/interop_import_js.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js.ets.arkts2.json @@ -15,13 +15,13 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 38, - "problem": "ImportAfterStatement", + "problem": "InterOpImportJs", "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", "severity": "ERROR" }, { @@ -38,17 +38,7 @@ "line": 18, "column": 1, "endLine": 18, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 38, + "endColumn": 64, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -58,17 +48,7 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 64, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 64, + "endColumn": 44, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -78,17 +58,7 @@ "line": 20, "column": 1, "endLine": 20, - "endColumn": 44, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 44, + "endColumn": 57, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -98,17 +68,7 @@ "line": 21, "column": 1, "endLine": 21, - "endColumn": 57, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 57, + "endColumn": 53, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -118,36 +78,6 @@ "line": 22, "column": 1, "endLine": 22, - "endColumn": 53, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 53, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, "endColumn": 59, "problem": "InterOpImportJs", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_import_js.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js.ets.autofix.json index 295af0943a..bda0908dba 100755 --- a/ets2panda/linter/test/interop/interop_import_js.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js.ets.autofix.json @@ -15,31 +15,29 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 38, "problem": "InterOpImportJs", "autofix": [ { - "start": 619, - "end": 656, - "replacementText": "" + "start": 606, + "end": 643, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 38 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('../main/js_lib');\nlet Cjs = GeneratedImportVar_1.getPropertyByName('Cjs');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('../main/js_lib');\nlet Cjs = GeneratedImportVar_1.getPropertyByName('Cjs');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 38 } ], "suggest": "", @@ -47,31 +45,29 @@ "severity": "ERROR" }, { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 38, "problem": "InterOpImportJs", "autofix": [ { - "start": 657, - "end": 694, - "replacementText": "" + "start": 644, + "end": 681, + "replacementText": "", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 38 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_2 = ESValue.load('../main/js_lib');\nlet fjs = GeneratedImportVar_2.getPropertyByName('fjs');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_2 = ESValue.load('../main/js_lib');\nlet fjs = GeneratedImportVar_2.getPropertyByName('fjs');\n", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 38 } ], "suggest": "", @@ -79,31 +75,29 @@ "severity": "ERROR" }, { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 64, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 64, "problem": "InterOpImportJs", "autofix": [ { - "start": 695, - "end": 758, - "replacementText": "" + "start": 682, + "end": 745, + "replacementText": "", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 64 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_3 = ESValue.load('./jsfiles/preview_import_js');\nlet CPreview = GeneratedImportVar_3.getPropertyByName('CPreview');\nlet bar = GeneratedImportVar_3.getPropertyByName('bar');\nlet foo = GeneratedImportVar_3.getPropertyByName('foo');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_3 = ESValue.load('./jsfiles/preview_import_js');\nlet CPreview = GeneratedImportVar_3.getPropertyByName('CPreview');\nlet bar = GeneratedImportVar_3.getPropertyByName('bar');\nlet foo = GeneratedImportVar_3.getPropertyByName('foo');\n", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 64 } ], "suggest": "", @@ -111,31 +105,29 @@ "severity": "ERROR" }, { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 44, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 44, "problem": "InterOpImportJs", "autofix": [ { - "start": 759, - "end": 802, - "replacementText": "" + "start": 746, + "end": 789, + "replacementText": "", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 44 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_4 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_4.getPropertyByName('aaa');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_4 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_4.getPropertyByName('aaa');\n", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 44 } ], "suggest": "", @@ -143,31 +135,29 @@ "severity": "ERROR" }, { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 57, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 57, "problem": "InterOpImportJs", "autofix": [ { - "start": 803, - "end": 859, - "replacementText": "" + "start": 790, + "end": 846, + "replacementText": "", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 57 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_5 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_5.getPropertyByName('aaa');\nlet ClassA = GeneratedImportVar_5.getPropertyByName('ClassA');\nlet Dog = GeneratedImportVar_5.getPropertyByName('Dog');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_5 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_5.getPropertyByName('aaa');\nlet ClassA = GeneratedImportVar_5.getPropertyByName('ClassA');\nlet Dog = GeneratedImportVar_5.getPropertyByName('Dog');\n", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 57 } ], "suggest": "", @@ -175,31 +165,29 @@ "severity": "ERROR" }, { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 53, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 22, + "line": 21, "column": 1, - "endLine": 22, + "endLine": 21, "endColumn": 53, "problem": "InterOpImportJs", "autofix": [ { - "start": 860, - "end": 912, - "replacementText": "" + "start": 847, + "end": 899, + "replacementText": "", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 53 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_6 = ESValue.load('./interop_import_js_js');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_6 = ESValue.load('./interop_import_js_js');\n", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 53 } ], "suggest": "", @@ -207,31 +195,29 @@ "severity": "ERROR" }, { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 59, "problem": "InterOpImportJs", "autofix": [ { - "start": 913, - "end": 971, - "replacementText": "" + "start": 900, + "end": 958, + "replacementText": "", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 59 }, { - "start": 971, - "end": 971, - "replacementText": "let GeneratedImportVar_7 = ESValue.load('./interop_import_js_js');\nlet Wiki = GeneratedImportVar_7.getPropertyByName('Wiki');\nlet Doge = GeneratedImportVar_7.getPropertyByName('Dog');\n" + "start": 958, + "end": 958, + "replacementText": "let GeneratedImportVar_7 = ESValue.load('./interop_import_js_js');\nlet Wiki = GeneratedImportVar_7.getPropertyByName('Wiki');\nlet Doge = GeneratedImportVar_7.getPropertyByName('Dog');\n", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 59 } ], "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_import_js.ets.json b/ets2panda/linter/test/interop/interop_import_js.ets.json index c75509e775..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/interop_import_js.ets.json +++ b/ets2panda/linter/test/interop/interop_import_js.ets.json @@ -13,76 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 64, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 44, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 57, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 53, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js.ets.migrate.ets index 4aa7a4bbf1..80f88726e3 100644 --- a/ets2panda/linter/test/interop/interop_import_js.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_js.ets.migrate.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' diff --git a/ets2panda/linter/test/interop/interop_import_js.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_js.ets.migrate.json index 625afb93e1..c422eb1668 100644 --- a/ets2panda/linter/test/interop/interop_import_js.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_js.ets.migrate.json @@ -14,11 +14,21 @@ "limitations under the License." ], "result": [ + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 66, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, { "line": 23, "column": 5, "endLine": 23, - "endColumn": 66, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -28,7 +38,7 @@ "line": 24, "column": 5, "endLine": 24, - "endColumn": 58, + "endColumn": 57, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -38,7 +48,7 @@ "line": 25, "column": 5, "endLine": 25, - "endColumn": 57, + "endColumn": 66, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -58,7 +68,7 @@ "line": 27, "column": 5, "endLine": 27, - "endColumn": 66, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -68,7 +78,7 @@ "line": 28, "column": 5, "endLine": 28, - "endColumn": 58, + "endColumn": 62, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -78,7 +88,7 @@ "line": 29, "column": 5, "endLine": 29, - "endColumn": 62, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -88,7 +98,7 @@ "line": 30, "column": 5, "endLine": 30, - "endColumn": 56, + "endColumn": 66, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -98,7 +108,7 @@ "line": 31, "column": 5, "endLine": 31, - "endColumn": 66, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -108,7 +118,7 @@ "line": 32, "column": 5, "endLine": 32, - "endColumn": 58, + "endColumn": 71, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -118,7 +128,7 @@ "line": 33, "column": 5, "endLine": 33, - "endColumn": 71, + "endColumn": 66, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -128,7 +138,7 @@ "line": 34, "column": 5, "endLine": 34, - "endColumn": 66, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -148,7 +158,7 @@ "line": 36, "column": 5, "endLine": 36, - "endColumn": 56, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -158,7 +168,7 @@ "line": 37, "column": 5, "endLine": 37, - "endColumn": 58, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -168,7 +178,7 @@ "line": 38, "column": 5, "endLine": 38, - "endColumn": 56, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -178,16 +188,6 @@ "line": 39, "column": 5, "endLine": 39, - "endColumn": 58, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 40, - "column": 5, - "endLine": 40, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -195,4 +195,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets b/ets2panda/linter/test/interop/interop_import_js_compare.ets index 496fe91c55..bc81463101 100644 --- a/ets2panda/linter/test/interop/interop_import_js_compare.ets +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' import {foo, m, n} from "./interop_import_js_compare_js" let a = foo.a diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.arkts2.json index 4ce217d61e..0d056023ed 100644 --- a/ets2panda/linter/test/interop/interop_import_js_compare.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, - "endColumn": 57, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 57, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 9, - "endLine": 19, + "endLine": 18, "endColumn": 14, "problem": "InteropObjectProperty", "suggest": "", @@ -49,29 +39,29 @@ "column": 9, "endLine": 19, "endColumn": 14, - "problem": "InteropJsObjectUsage", + "problem": "InteropObjectProperty", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", "severity": "ERROR" }, { "line": 20, - "column": 9, + "column": 1, "endLine": 20, - "endColumn": 14, - "problem": "InteropObjectProperty", + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", "severity": "ERROR" }, { "line": 20, - "column": 9, + "column": 5, "endLine": 20, - "endColumn": 14, - "problem": "InteropJsObjectUsage", + "endColumn": 6, + "problem": "InterOpImportJsDataCompare", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", "severity": "ERROR" }, { @@ -106,9 +96,9 @@ }, { "line": 22, - "column": 5, + "column": 6, "endLine": 22, - "endColumn": 6, + "endColumn": 7, "problem": "InterOpImportJsDataCompare", "suggest": "", "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", @@ -136,28 +126,8 @@ }, { "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 2, - "problem": "InterOpImportJsDataCompare", - "suggest": "", - "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 6, - "endLine": 24, - "endColumn": 7, - "problem": "InterOpImportJsDataCompare", - "suggest": "", - "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", - "severity": "ERROR" - }, - { - "line": 25, "column": 5, - "endLine": 25, + "endLine": 24, "endColumn": 6, "problem": "NumericSemantics", "suggest": "", @@ -165,9 +135,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 2, "problem": "InterOpImportJsDataCompare", "suggest": "", @@ -175,9 +145,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 5, - "endLine": 27, + "endLine": 26, "endColumn": 6, "problem": "InterOpImportJsDataCompare", "suggest": "", @@ -185,9 +155,9 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 5, - "endLine": 28, + "endLine": 27, "endColumn": 6, "problem": "NumericSemantics", "suggest": "", @@ -195,9 +165,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 5, - "endLine": 30, + "endLine": 29, "endColumn": 10, "problem": "NumericSemantics", "suggest": "", @@ -205,9 +175,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 9, - "endLine": 30, + "endLine": 29, "endColumn": 10, "problem": "NumericSemantics", "suggest": "", @@ -215,9 +185,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 12, - "endLine": 30, + "endLine": 29, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -225,9 +195,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 16, - "endLine": 30, + "endLine": 29, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -235,9 +205,9 @@ "severity": "ERROR" }, { - "line": 36, + "line": 35, "column": 11, - "endLine": 36, + "endLine": 35, "endColumn": 12, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -245,9 +215,9 @@ "severity": "ERROR" }, { - "line": 36, + "line": 35, "column": 16, - "endLine": 36, + "endLine": 35, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -255,9 +225,9 @@ "severity": "ERROR" }, { - "line": 36, + "line": 35, "column": 22, - "endLine": 36, + "endLine": 35, "endColumn": 23, "problem": "NumericSemantics", "suggest": "", @@ -265,9 +235,9 @@ "severity": "ERROR" }, { - "line": 38, + "line": 37, "column": 5, - "endLine": 38, + "endLine": 37, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -275,9 +245,9 @@ "severity": "ERROR" }, { - "line": 38, + "line": 37, "column": 17, - "endLine": 38, + "endLine": 37, "endColumn": 27, "problem": "NumericSemantics", "suggest": "", @@ -285,9 +255,9 @@ "severity": "ERROR" }, { - "line": 44, + "line": 43, "column": 1, - "endLine": 44, + "endLine": 43, "endColumn": 6, "problem": "InterOpImportJsDataCompare", "suggest": "", @@ -295,54 +265,14 @@ "severity": "ERROR" }, { - "line": 44, + "line": 43, "column": 9, - "endLine": 44, + "endLine": 43, "endColumn": 14, "problem": "InterOpImportJsDataCompare", "suggest": "", "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", "severity": "ERROR" - }, - { - "line": 44, - "column": 1, - "endLine": 44, - "endColumn": 6, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 1, - "endLine": 44, - "endColumn": 6, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 9, - "endLine": 44, - "endColumn": 14, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 9, - "endLine": 44, - "endColumn": 14, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.json index 25d2c46ecd..e28baca176 100644 --- a/ets2panda/linter/test/interop/interop_import_js_compare.ets.json +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 57, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 36, + "line": 35, "column": 11, - "endLine": 36, + "endLine": 35, "endColumn": 12, "problem": "ObjectLiteralNoContextType", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets index daf1403ab2..ba165c68fd 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' import {foo} from "./interop_import_js_index_js" let arr = foo.arr arr[1] diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json index 01e50a4c69..3fc1baeadf 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json @@ -1,19 +1,23 @@ { + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 49, "problem": "InterOpImportJs", "suggest": "", @@ -21,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 11, - "endLine": 18, + "endLine": 17, "endColumn": 18, "problem": "InteropObjectProperty", "suggest": "", @@ -32,18 +36,8 @@ }, { "line": 18, - "column": 11, - "endLine": 18, - "endColumn": 18, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 19, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "RuntimeArrayCheck", "suggest": "", @@ -51,9 +45,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -61,9 +55,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "InterOpImportJsIndex", "suggest": "", @@ -71,9 +65,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 7, "problem": "RuntimeArrayCheck", "suggest": "", @@ -81,9 +75,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 7, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -91,9 +85,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 11, "problem": "InterOpImportJsIndex", "suggest": "", @@ -101,9 +95,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 10, - "endLine": 20, + "endLine": 19, "endColumn": 11, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json index f5e605ca86..157682563b 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json @@ -15,35 +15,29 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 49, "problem": "InterOpImportJs", "autofix": [ { - "start": 619, - "end": 667, + "start": 606, + "end": 654, "replacementText": "", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 49 }, { - "start": 667, - "end": 667, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_index_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n" + "start": 654, + "end": 654, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_index_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 49 } ], "suggest": "", @@ -51,19 +45,19 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 11, - "endLine": 18, + "endLine": 17, "endColumn": 18, "problem": "InteropObjectProperty", "autofix": [ { - "start": 678, - "end": 685, + "start": 665, + "end": 672, "replacementText": "foo.getPropertyByName(\"arr\")", - "line": 18, + "line": 17, "column": 11, - "endLine": 18, + "endLine": 17, "endColumn": 18 } ], @@ -73,29 +67,8 @@ }, { "line": 18, - "column": 11, - "endLine": 18, - "endColumn": 18, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('arr')", - "start": 678, - "end": 685, - "line": 18, - "column": 11, - "endLine": 18, - "endColumn": 18 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 19, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "RuntimeArrayCheck", "suggest": "", @@ -103,19 +76,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "InteropJsObjectTraverseJsInstance", "autofix": [ { "replacementText": "arr.getPropertyByIndex(1).toNumber()", - "start": 686, - "end": 692, - "line": 19, + "start": 673, + "end": 679, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7 } ], @@ -124,19 +97,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7, "problem": "InterOpImportJsIndex", "autofix": [ { - "start": 686, - "end": 692, + "start": 673, + "end": 679, "replacementText": "arr.getPropertyByIndex(1)", - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 7 } ], @@ -145,9 +118,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 7, "problem": "RuntimeArrayCheck", "suggest": "", @@ -155,19 +128,19 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 7, "problem": "InteropJsObjectTraverseJsInstance", "autofix": [ { "replacementText": "arr.setPropertyByIndex(3, ESValue.wrap(4))", - "start": 693, - "end": 703, - "line": 20, + "start": 680, + "end": 690, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 7 } ], @@ -176,16 +149,20 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 11, "problem": "InterOpImportJsIndex", "autofix": [ { - "start": 693, - "end": 703, - "replacementText": "arr.setPropertyByIndex(3, ESValue.wrap(4))" + "start": 680, + "end": 690, + "replacementText": "arr.setPropertyByIndex(3, ESValue.wrap(4))", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 11 } ], "suggest": "", @@ -193,19 +170,19 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 10, - "endLine": 20, + "endLine": 19, "endColumn": 11, "problem": "NumericSemantics", "autofix": [ { - "start": 702, - "end": 703, + "start": 689, + "end": 690, "replacementText": "4.0", - "line": 20, + "line": 19, "column": 10, - "endLine": 20, + "endLine": 19, "endColumn": 11 } ], @@ -214,4 +191,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.json index 5619e69d78..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets index 65d9325e8b..d521cdc8aa 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./interop_import_js_index_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json index 957ef0239d..d12c3ee91b 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 72, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 5, - "endLine": 20, + "endLine": 19, "endColumn": 39, "problem": "AnyType", "suggest": "", @@ -45,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets b/ets2panda/linter/test/interop/interop_import_js_rules.ets index d7e3b52fca..d4c110abcf 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets @@ -28,6 +28,7 @@ import { handle } from "./interop_import_js_rules_js" import { expand } from "./interop_import_js_rules_js" import { orange } from "./interop_import_js_rules_js" + if (foo.isGood) {} if (ff1.f1 > 18) { @@ -65,17 +66,27 @@ handle(lambda) class X{a = 1; b= 2; c= 3} expand(new X()) // ERROR expand-static + class Y { str: string = 'str'; bool: boolean = false; } + let testY: Y = { str: "hello", bool: false, } + expand(testY); expand({x: '1', y: "hello", z: false}); + let flag = false; if (orange.isVegetable1 === 123) { flag = true } + +for (let element of arr) { + if (element == 8) { + console.log("hi"); + } +} diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json index 299b2732c8..dec39fff4b 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json @@ -195,19 +195,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 32, "column": 5, - "endLine": 31, - "endColumn": 15, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 31, - "column": 5, - "endLine": 31, + "endLine": 32, "endColumn": 15, "problem": "InteropJsObjectConditionJudgment", "suggest": "", @@ -215,9 +205,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11, "problem": "InterOpImportJsDataCompare", "suggest": "", @@ -225,19 +215,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 5, - "endLine": 33, - "endColumn": 11, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11, "problem": "InteropJsObjectConditionJudgment", "suggest": "", @@ -245,9 +225,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 14, - "endLine": 33, + "endLine": 34, "endColumn": 16, "problem": "NumericSemantics", "suggest": "", @@ -255,9 +235,9 @@ "severity": "ERROR" }, { - "line": 37, + "line": 38, "column": 1, - "endLine": 37, + "endLine": 38, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -265,9 +245,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 42, "column": 1, - "endLine": 41, + "endLine": 42, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -275,19 +255,19 @@ "severity": "ERROR" }, { - "line": 44, + "line": 45, "column": 3, - "endLine": 44, + "endLine": 45, "endColumn": 8, "problem": "InteropJSFunctionInvoke", "suggest": "", - "rule": "Trying to catch JS errors is not permitted (arkts-interop-js2s-js-exception)", + "rule": "ArkTS1.2 cannot catch a non Error instance thrown from JS code (arkts-interop-js2s-js-exception)", "severity": "ERROR" }, { - "line": 44, + "line": 45, "column": 3, - "endLine": 44, + "endLine": 45, "endColumn": 8, "problem": "CallJSFunction", "suggest": "", @@ -295,9 +275,9 @@ "severity": "ERROR" }, { - "line": 45, + "line": 46, "column": 3, - "endLine": 47, + "endLine": 48, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -305,9 +285,9 @@ "severity": "ERROR" }, { - "line": 49, + "line": 50, "column": 11, - "endLine": 49, + "endLine": 50, "endColumn": 18, "problem": "InteropObjectProperty", "suggest": "", @@ -315,29 +295,9 @@ "severity": "ERROR" }, { - "line": 49, - "column": 11, - "endLine": 49, - "endColumn": 18, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 50, - "column": 11, - "endLine": 50, - "endColumn": 21, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9, "problem": "RuntimeArrayCheck", "suggest": "", @@ -345,9 +305,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 10, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -355,9 +315,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 14, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -365,9 +325,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "RuntimeArrayCheck", "suggest": "", @@ -375,9 +335,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -385,9 +345,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InterOpImportJsIndex", "suggest": "", @@ -395,9 +355,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -405,9 +365,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "InterOpImportJsIndex", "suggest": "", @@ -415,9 +375,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 12, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "NumericSemantics", "suggest": "", @@ -425,9 +385,9 @@ "severity": "ERROR" }, { - "line": 63, + "line": 64, "column": 8, - "endLine": 63, + "endLine": 64, "endColumn": 12, "problem": "InteropJsObjectCallStaticFunc", "suggest": "", @@ -435,9 +395,9 @@ "severity": "ERROR" }, { - "line": 63, + "line": 64, "column": 1, - "endLine": 63, + "endLine": 64, "endColumn": 13, "problem": "CallJSFunction", "suggest": "", @@ -445,9 +405,9 @@ "severity": "ERROR" }, { - "line": 64, + "line": 65, "column": 8, - "endLine": 64, + "endLine": 65, "endColumn": 14, "problem": "InteropJsObjectCallStaticFunc", "suggest": "", @@ -455,9 +415,9 @@ "severity": "ERROR" }, { - "line": 64, + "line": 65, "column": 1, - "endLine": 64, + "endLine": 65, "endColumn": 15, "problem": "CallJSFunction", "suggest": "", @@ -465,9 +425,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 9, - "endLine": 66, + "endLine": 67, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -475,9 +435,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 13, - "endLine": 66, + "endLine": 67, "endColumn": 14, "problem": "NumericSemantics", "suggest": "", @@ -485,9 +445,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 16, - "endLine": 66, + "endLine": 67, "endColumn": 21, "problem": "NumericSemantics", "suggest": "", @@ -495,9 +455,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 19, - "endLine": 66, + "endLine": 67, "endColumn": 20, "problem": "NumericSemantics", "suggest": "", @@ -505,9 +465,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 22, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "suggest": "", @@ -515,9 +475,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 25, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "suggest": "", @@ -525,9 +485,9 @@ "severity": "ERROR" }, { - "line": 67, + "line": 68, "column": 8, - "endLine": 67, + "endLine": 68, "endColumn": 15, "problem": "InteropJsObjectExpandStaticInstance", "suggest": "", @@ -535,9 +495,9 @@ "severity": "ERROR" }, { - "line": 67, + "line": 68, "column": 1, - "endLine": 67, + "endLine": 68, "endColumn": 16, "problem": "CallJSFunction", "suggest": "", @@ -545,9 +505,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 80, "column": 8, - "endLine": 76, + "endLine": 80, "endColumn": 13, "problem": "InteropJsObjectExpandStaticInstance", "suggest": "", @@ -555,9 +515,9 @@ "severity": "ERROR" }, { - "line": 76, + "line": 80, "column": 1, - "endLine": 76, + "endLine": 80, "endColumn": 14, "problem": "CallJSFunction", "suggest": "", @@ -565,9 +525,9 @@ "severity": "ERROR" }, { - "line": 77, + "line": 81, "column": 8, - "endLine": 77, + "endLine": 81, "endColumn": 38, "problem": "InteropJsObjectExpandStaticInstance", "suggest": "", @@ -575,9 +535,9 @@ "severity": "ERROR" }, { - "line": 77, + "line": 81, "column": 1, - "endLine": 77, + "endLine": 81, "endColumn": 39, "problem": "CallJSFunction", "suggest": "", @@ -585,9 +545,9 @@ "severity": "ERROR" }, { - "line": 79, + "line": 84, "column": 5, - "endLine": 79, + "endLine": 84, "endColumn": 32, "problem": "InteropEqualityJudgment", "suggest": "", @@ -595,34 +555,34 @@ "severity": "ERROR" }, { - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24, - "problem": "InteropObjectProperty", + "line": 84, + "column": 29, + "endLine": 84, + "endColumn": 32, + "problem": "NumericSemantics", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24, - "problem": "InteropJsObjectUsage", + "line": 88, + "column": 1, + "endLine": 92, + "endColumn": 2, + "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", "severity": "ERROR" }, { - "line": 79, - "column": 29, - "endLine": 79, - "endColumn": 32, + "line": 89, + "column": 18, + "endLine": 89, + "endColumn": 19, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json index 4e7f1b6c7a..c7bff146b9 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json @@ -1,1149 +1,1054 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51, - "problem": "InterOpImportJs", - "autofix": [ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ { - "start": 619, - "end": 669, - "replacementText": "", - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51 + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 51, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_rules_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 51 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 56, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 56, - "problem": "InterOpImportJs", - "autofix": [ + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 51, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 619, + "end": 669, + "replacementText": "", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 51 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_rules_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 670, - "end": 725, - "replacementText": "", - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 56 + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 56, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_rules_js');\nlet ff1 = GeneratedImportVar_2.getPropertyByName('ff1');\nlet ff2 = GeneratedImportVar_2.getPropertyByName('ff2');\n", - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 56 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 49, - "problem": "InterOpImportJs", - "autofix": [ + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 56, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 670, + "end": 725, + "replacementText": "", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 56 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_rules_js');\nlet ff1 = GeneratedImportVar_2.getPropertyByName('ff1');\nlet ff2 = GeneratedImportVar_2.getPropertyByName('ff2');\n", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 56 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 727, - "end": 775, - "replacementText": "", - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 49 + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 49, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_3 = ESValue.load('./interop_import_js_rules_js');\nlet A = GeneratedImportVar_3.getPropertyByName('A');\n", - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 49 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 49, - "problem": "InterOpImportJs", - "autofix": [ + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 49, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 727, + "end": 775, + "replacementText": "", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 49 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_3 = ESValue.load('./interop_import_js_rules_js');\nlet A = GeneratedImportVar_3.getPropertyByName('A');\n", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 49 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 776, - "end": 824, - "replacementText": "", - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 49 + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 49, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_4 = ESValue.load('./interop_import_js_rules_js');\nlet C = GeneratedImportVar_4.getPropertyByName('C');\n", - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 49 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 51, - "problem": "InterOpImportJs", - "autofix": [ + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 49, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 776, + "end": 824, + "replacementText": "", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 49 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_4 = ESValue.load('./interop_import_js_rules_js');\nlet C = GeneratedImportVar_4.getPropertyByName('C');\n", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 49 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 826, - "end": 876, - "replacementText": "", - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 51 + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 51, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_5 = ESValue.load('./interop_import_js_rules_js');\nlet ff3 = GeneratedImportVar_5.getPropertyByName('ff3');\n", - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 51 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 51, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 51, - "problem": "InterOpImportJs", - "autofix": [ + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 51, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 826, + "end": 876, + "replacementText": "", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 51 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_5 = ESValue.load('./interop_import_js_rules_js');\nlet ff3 = GeneratedImportVar_5.getPropertyByName('ff3');\n", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 878, - "end": 928, - "replacementText": "", - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 51 + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 51, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_6 = ESValue.load('./interop_import_js_rules_js');\nlet ff4 = GeneratedImportVar_6.getPropertyByName('ff4');\n", - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 51 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 54, - "problem": "InterOpImportJs", - "autofix": [ + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 51, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 878, + "end": 928, + "replacementText": "", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 51 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_6 = ESValue.load('./interop_import_js_rules_js');\nlet ff4 = GeneratedImportVar_6.getPropertyByName('ff4');\n", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 930, - "end": 983, - "replacementText": "", - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 54 + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 54, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_7 = ESValue.load('./interop_import_js_rules_js');\nlet handle = GeneratedImportVar_7.getPropertyByName('handle');\n", - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 54 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 54, - "problem": "InterOpImportJs", - "autofix": [ + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 54, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 930, + "end": 983, + "replacementText": "", + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 54 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_7 = ESValue.load('./interop_import_js_rules_js');\nlet handle = GeneratedImportVar_7.getPropertyByName('handle');\n", + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 54 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 985, - "end": 1038, - "replacementText": "", - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 54 + "line": 29, + "column": 1, + "endLine": 29, + "endColumn": 54, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_8 = ESValue.load('./interop_import_js_rules_js');\nlet expand = GeneratedImportVar_8.getPropertyByName('expand');\n", - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 54 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 1, - "endLine": 30, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 1, - "endLine": 30, - "endColumn": 54, - "problem": "InterOpImportJs", - "autofix": [ + "line": 29, + "column": 1, + "endLine": 29, + "endColumn": 54, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 985, + "end": 1038, + "replacementText": "", + "line": 29, + "column": 1, + "endLine": 29, + "endColumn": 54 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_8 = ESValue.load('./interop_import_js_rules_js');\nlet expand = GeneratedImportVar_8.getPropertyByName('expand');\n", + "line": 29, + "column": 1, + "endLine": 29, + "endColumn": 54 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 1039, - "end": 1092, - "replacementText": "", - "line": 30, - "column": 1, - "endLine": 30, - "endColumn": 54 + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 54, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" }, { - "start": 1092, - "end": 1092, - "replacementText": "let GeneratedImportVar_9 = ESValue.load('./interop_import_js_rules_js');\nlet orange = GeneratedImportVar_9.getPropertyByName('orange');\n", - "line": 30, - "column": 1, - "endLine": 30, - "endColumn": 54 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15, - "problem": "InteropObjectProperty", - "autofix": [ + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 54, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 1039, + "end": 1092, + "replacementText": "", + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 54 + }, + { + "start": 1092, + "end": 1092, + "replacementText": "let GeneratedImportVar_9 = ESValue.load('./interop_import_js_rules_js');\nlet orange = GeneratedImportVar_9.getPropertyByName('orange');\n", + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 54 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { - "start": 1097, - "end": 1107, - "replacementText": "foo.getPropertyByName(\"isGood\")", - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15, - "problem": "InteropJsObjectConditionJudgment", - "autofix": [ + "line": 32, + "column": 5, + "endLine": 32, + "endColumn": 15, + "problem": "InteropJsObjectConditionJudgment", + "autofix": [ + { + "replacementText": "foo.getPropertyByName('isGood').toBoolean()", + "start": 1098, + "end": 1108, + "line": 32, + "column": 5, + "endLine": 32, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)", + "severity": "ERROR" + }, { - "replacementText": "foo.getPropertyByName('isGood').toBoolean()", - "start": 1097, - "end": 1107, - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11, - "problem": "InterOpImportJsDataCompare", - "suggest": "", - "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11, - "problem": "InteropObjectProperty", - "autofix": [ + "line": 34, + "column": 5, + "endLine": 34, + "endColumn": 11, + "problem": "InterOpImportJsDataCompare", + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, { - "start": 1117, - "end": 1123, - "replacementText": "ff1.getPropertyByName(\"f1\")", - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11, - "problem": "InteropJsObjectConditionJudgment", - "autofix": [ + "line": 34, + "column": 5, + "endLine": 34, + "endColumn": 11, + "problem": "InteropJsObjectConditionJudgment", + "autofix": [ + { + "replacementText": "ff1.getPropertyByName('f1').toNumber()", + "start": 1118, + "end": 1124, + "line": 34, + "column": 5, + "endLine": 34, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)", + "severity": "ERROR" + }, { - "replacementText": "ff1.getPropertyByName('f1').toNumber()", - "start": 1117, - "end": 1123, - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 14, - "endLine": 33, - "endColumn": 16, - "problem": "NumericSemantics", - "autofix": [ + "line": 34, + "column": 14, + "endLine": 34, + "endColumn": 16, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1127, + "end": 1129, + "replacementText": "18.0", + "line": 34, + "column": 14, + "endLine": 34, + "endColumn": 16 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1126, - "end": 1128, - "replacementText": "18.0", - "line": 33, - "column": 14, - "endLine": 33, - "endColumn": 16 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 37, - "column": 1, - "endLine": 37, - "endColumn": 21, - "problem": "InteropJsObjectInheritance", - "suggest": "", - "rule": "Direct inheritance of interop JS classes is not supported (arkts-interop-js2s-inherit-js-class)", - "severity": "ERROR" - }, - { - "line": 41, - "column": 1, - "endLine": 41, - "endColumn": 21, - "problem": "InteropJsObjectInheritance", - "suggest": "", - "rule": "Direct inheritance of interop JS classes is not supported (arkts-interop-js2s-inherit-js-class)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 3, - "endLine": 44, - "endColumn": 8, - "problem": "InteropJSFunctionInvoke", - "suggest": "", - "rule": "Trying to catch JS errors is not permitted (arkts-interop-js2s-js-exception)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 3, - "endLine": 44, - "endColumn": 8, - "problem": "CallJSFunction", - "autofix": [ + "line": 38, + "column": 1, + "endLine": 38, + "endColumn": 21, + "problem": "InteropJsObjectInheritance", + "suggest": "", + "rule": "Direct inheritance of interop JS classes is not supported (arkts-interop-js2s-inherit-js-class)", + "severity": "ERROR" + }, { - "start": 1288, - "end": 1293, - "replacementText": "ff4.invoke()", - "line": 44, - "column": 3, - "endLine": 44, - "endColumn": 8 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 45, - "column": 3, - "endLine": 47, - "endColumn": 2, - "problem": "TsLikeCatchType", - "suggest": "", - "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", - "severity": "ERROR" - }, - { - "line": 49, - "column": 11, - "endLine": 49, - "endColumn": 18, - "problem": "InteropObjectProperty", - "autofix": [ + "line": 42, + "column": 1, + "endLine": 42, + "endColumn": 21, + "problem": "InteropJsObjectInheritance", + "suggest": "", + "rule": "Direct inheritance of interop JS classes is not supported (arkts-interop-js2s-inherit-js-class)", + "severity": "ERROR" + }, { - "start": 1343, - "end": 1350, - "replacementText": "ff3.getPropertyByName(\"arr\")", - "line": 49, - "column": 11, - "endLine": 49, - "endColumn": 18 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 49, - "column": 11, - "endLine": 49, - "endColumn": 18, - "problem": "InteropJsObjectUsage", - "autofix": [ + "line": 45, + "column": 3, + "endLine": 45, + "endColumn": 8, + "problem": "InteropJSFunctionInvoke", + "suggest": "", + "rule": "ArkTS1.2 cannot catch a non Error instance thrown from JS code (arkts-interop-js2s-js-exception)", + "severity": "ERROR" + }, { - "replacementText": "ff3.getPropertyByName('arr')", - "start": 1343, - "end": 1350, - "line": 49, - "column": 11, - "endLine": 49, - "endColumn": 18 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 50, - "column": 11, - "endLine": 50, - "endColumn": 21, - "problem": "InteropJsObjectUsage", - "autofix": [ + "line": 45, + "column": 3, + "endLine": 45, + "endColumn": 8, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1289, + "end": 1294, + "replacementText": "ff4.invoke()", + "line": 45, + "column": 3, + "endLine": 45, + "endColumn": 8 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, { - "replacementText": "arr.getPropertyByName('length').toNumber()", - "start": 1361, - "end": 1381, - "line": 50, - "column": 11, - "endLine": 50, - "endColumn": 21 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 53, - "column": 3, - "endLine": 53, - "endColumn": 9, - "problem": "RuntimeArrayCheck", - "suggest": "", - "rule": "Array bound not checked. (arkts-runtime-array-check)", - "severity": "ERROR" - }, - { - "line": 51, - "column": 10, - "endLine": 51, - "endColumn": 15, - "problem": "NumericSemantics", - "autofix": [ + "line": 46, + "column": 3, + "endLine": 48, + "endColumn": 2, + "problem": "TsLikeCatchType", + "suggest": "", + "rule": "TS catch type are not supported (arkts-no-ts-like-catch-type)", + "severity": "ERROR" + }, { - "start": 1391, - "end": 1396, - "replacementText": "i: number = 0", - "line": 51, - "column": 10, - "endLine": 51, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 51, - "column": 14, - "endLine": 51, - "endColumn": 15, - "problem": "NumericSemantics", - "autofix": [ + "line": 50, + "column": 11, + "endLine": 50, + "endColumn": 18, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 1344, + "end": 1351, + "replacementText": "ff3.getPropertyByName(\"arr\")", + "line": 50, + "column": 11, + "endLine": 50, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, { - "start": 1395, - "end": 1396, - "replacementText": "0.0", - "line": 51, - "column": 14, - "endLine": 51, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 52, - "column": 11, - "endLine": 52, - "endColumn": 17, - "problem": "RuntimeArrayCheck", - "suggest": "", - "rule": "Array bound not checked. (arkts-runtime-array-check)", - "severity": "ERROR" - }, - { - "line": 52, - "column": 11, - "endLine": 52, - "endColumn": 17, - "problem": "InteropJsObjectTraverseJsInstance", - "autofix": [ + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 9, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { - "replacementText": "arr.getPropertyByIndex(i).toNumber()", - "start": 1424, - "end": 1430, - "line": 52, - "column": 11, - "endLine": 52, - "endColumn": 17 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", - "severity": "ERROR" - }, - { - "line": 52, - "column": 11, - "endLine": 52, - "endColumn": 17, - "problem": "InterOpImportJsIndex", - "autofix": [ + "line": 52, + "column": 10, + "endLine": 52, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1392, + "end": 1397, + "replacementText": "i: number = 0", + "line": 52, + "column": 10, + "endLine": 52, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1424, - "end": 1430, - "replacementText": "arr.getPropertyByIndex(i)", - "line": 52, - "column": 11, - "endLine": 52, - "endColumn": 17 - } - ], - "suggest": "", - "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", - "severity": "ERROR" - }, - { - "line": 53, - "column": 3, - "endLine": 53, - "endColumn": 9, - "problem": "InteropJsObjectTraverseJsInstance", - "autofix": [ + "line": 52, + "column": 14, + "endLine": 52, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1396, + "end": 1397, + "replacementText": "0.0", + "line": 52, + "column": 14, + "endLine": 52, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", - "start": 1433, - "end": 1443, - "line": 53, - "column": 3, - "endLine": 53, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", - "severity": "ERROR" - }, - { - "line": 53, - "column": 3, - "endLine": 53, - "endColumn": 13, - "problem": "InterOpImportJsIndex", - "autofix": [ + "line": 53, + "column": 11, + "endLine": 53, + "endColumn": 17, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { - "start": 1433, - "end": 1443, - "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", - "line": 53, - "column": 3, - "endLine": 53, - "endColumn": 13 - } - ], - "suggest": "", - "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", - "severity": "ERROR" - }, - { - "line": 53, - "column": 12, - "endLine": 53, - "endColumn": 13, - "problem": "NumericSemantics", - "autofix": [ + "line": 53, + "column": 11, + "endLine": 53, + "endColumn": 17, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr.getPropertyByIndex(i).toNumber()", + "start": 1425, + "end": 1431, + "line": 53, + "column": 11, + "endLine": 53, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, { - "start": 1442, - "end": 1443, - "replacementText": "0.0", - "line": 53, - "column": 12, - "endLine": 53, - "endColumn": 13 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 63, - "column": 8, - "endLine": 63, - "endColumn": 12, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 63, - "column": 1, - "endLine": 63, - "endColumn": 13, - "problem": "CallJSFunction", - "autofix": [ + "line": 53, + "column": 11, + "endLine": 53, + "endColumn": 17, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 1425, + "end": 1431, + "replacementText": "arr.getPropertyByIndex(i)", + "line": 53, + "column": 11, + "endLine": 53, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, { - "start": 1544, - "end": 1556, - "replacementText": "handle.invoke(ESValue.wrap(foo2))", - "line": 63, - "column": 1, - "endLine": 63, - "endColumn": 13 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 64, - "column": 8, - "endLine": 64, - "endColumn": 14, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 64, - "column": 1, - "endLine": 64, - "endColumn": 15, - "problem": "CallJSFunction", - "autofix": [ + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 9, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", + "start": 1434, + "end": 1444, + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 9 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, { - "start": 1557, - "end": 1571, - "replacementText": "handle.invoke(ESValue.wrap(lambda))", - "line": 64, - "column": 1, - "endLine": 64, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 9, - "endLine": 66, - "endColumn": 15, - "problem": "NumericSemantics", - "autofix": [ + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 13, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 1434, + "end": 1444, + "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, { - "start": 1581, - "end": 1587, - "replacementText": "a: number = 1;", - "line": 66, - "column": 9, - "endLine": 66, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 13, - "endLine": 66, - "endColumn": 14, - "problem": "NumericSemantics", - "autofix": [ + "line": 54, + "column": 12, + "endLine": 54, + "endColumn": 13, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1443, + "end": 1444, + "replacementText": "0.0", + "line": 54, + "column": 12, + "endLine": 54, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1585, - "end": 1586, - "replacementText": "1.0", - "line": 66, - "column": 13, - "endLine": 66, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 16, - "endLine": 66, - "endColumn": 21, - "problem": "NumericSemantics", - "autofix": [ + "line": 64, + "column": 8, + "endLine": 64, + "endColumn": 12, + "problem": "InteropJsObjectCallStaticFunc", + "suggest": "", + "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", + "severity": "ERROR" + }, { - "start": 1588, - "end": 1593, - "replacementText": "b: number = 2;", - "line": 66, - "column": 16, - "endLine": 66, - "endColumn": 21 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 19, - "endLine": 66, - "endColumn": 20, - "problem": "NumericSemantics", - "autofix": [ + "line": 64, + "column": 1, + "endLine": 64, + "endColumn": 13, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1545, + "end": 1557, + "replacementText": "handle.invoke(ESValue.wrap(foo2))", + "line": 64, + "column": 1, + "endLine": 64, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, { - "start": 1591, - "end": 1592, - "replacementText": "2.0", - "line": 66, - "column": 19, - "endLine": 66, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 22, - "endLine": 66, - "endColumn": 26, - "problem": "NumericSemantics", - "autofix": [ + "line": 65, + "column": 8, + "endLine": 65, + "endColumn": 14, + "problem": "InteropJsObjectCallStaticFunc", + "suggest": "", + "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", + "severity": "ERROR" + }, { - "start": 1594, - "end": 1598, - "replacementText": "c: number = 3;", - "line": 66, - "column": 22, - "endLine": 66, - "endColumn": 26 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 25, - "endLine": 66, - "endColumn": 26, - "problem": "NumericSemantics", - "autofix": [ + "line": 65, + "column": 1, + "endLine": 65, + "endColumn": 15, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1558, + "end": 1572, + "replacementText": "handle.invoke(ESValue.wrap(lambda))", + "line": 65, + "column": 1, + "endLine": 65, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, { - "start": 1597, - "end": 1598, - "replacementText": "3.0", - "line": 66, - "column": 25, - "endLine": 66, - "endColumn": 26 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 67, - "column": 8, - "endLine": 67, - "endColumn": 15, - "problem": "InteropJsObjectExpandStaticInstance", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", - "severity": "ERROR" - }, - { - "line": 67, - "column": 1, - "endLine": 67, - "endColumn": 16, - "problem": "CallJSFunction", - "autofix": [ + "line": 67, + "column": 9, + "endLine": 67, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1582, + "end": 1588, + "replacementText": "a: number = 1;", + "line": 67, + "column": 9, + "endLine": 67, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1600, - "end": 1615, - "replacementText": "expand.invoke(ESValue.wrap(new X()))", - "line": 67, - "column": 1, - "endLine": 67, - "endColumn": 16 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 76, - "column": 8, - "endLine": 76, - "endColumn": 13, - "problem": "InteropJsObjectExpandStaticInstance", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", - "severity": "ERROR" - }, - { - "line": 76, - "column": 1, - "endLine": 76, - "endColumn": 14, - "problem": "CallJSFunction", - "autofix": [ + "line": 67, + "column": 13, + "endLine": 67, + "endColumn": 14, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1586, + "end": 1587, + "replacementText": "1.0", + "line": 67, + "column": 13, + "endLine": 67, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1749, - "end": 1762, - "replacementText": "expand.invoke(ESValue.wrap(testY))", - "line": 76, - "column": 1, - "endLine": 76, - "endColumn": 14 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 77, - "column": 8, - "endLine": 77, - "endColumn": 38, - "problem": "InteropJsObjectExpandStaticInstance", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", - "severity": "ERROR" - }, - { - "line": 77, - "column": 1, - "endLine": 77, - "endColumn": 39, - "problem": "CallJSFunction", - "autofix": [ + "line": 67, + "column": 16, + "endLine": 67, + "endColumn": 21, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1589, + "end": 1594, + "replacementText": "b: number = 2;", + "line": 67, + "column": 16, + "endLine": 67, + "endColumn": 21 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1764, - "end": 1802, - "replacementText": "expand.invoke(ESValue.wrap({x: '1', y: \"hello\", z: false}))", - "line": 77, - "column": 1, - "endLine": 77, - "endColumn": 39 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 32, - "problem": "InteropEqualityJudgment", - "autofix": [ + "line": 67, + "column": 19, + "endLine": 67, + "endColumn": 20, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1592, + "end": 1593, + "replacementText": "2.0", + "line": 67, + "column": 19, + "endLine": 67, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1826, - "end": 1853, - "replacementText": "orange.isVegetable1.areStrictlyEqual(123)", - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 32 - } - ], - "suggest": "", - "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", - "severity": "ERROR" - }, - { - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24, - "problem": "InteropObjectProperty", - "autofix": [ + "line": 67, + "column": 22, + "endLine": 67, + "endColumn": 26, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1595, + "end": 1599, + "replacementText": "c: number = 3;", + "line": 67, + "column": 22, + "endLine": 67, + "endColumn": 26 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "start": 1826, - "end": 1845, - "replacementText": "orange.getPropertyByName(\"isVegetable1\")", - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24, - "problem": "InteropJsObjectUsage", - "autofix": [ + "line": 67, + "column": 25, + "endLine": 67, + "endColumn": 26, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1598, + "end": 1599, + "replacementText": "3.0", + "line": 67, + "column": 25, + "endLine": 67, + "endColumn": 26 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, { - "replacementText": "orange.getPropertyByName('isVegetable1').toNumber()", - "start": 1826, - "end": 1845, - "line": 79, - "column": 5, - "endLine": 79, - "endColumn": 24 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 79, - "column": 29, - "endLine": 79, - "endColumn": 32, - "problem": "NumericSemantics", - "autofix": [ + "line": 68, + "column": 8, + "endLine": 68, + "endColumn": 15, + "problem": "InteropJsObjectExpandStaticInstance", + "suggest": "", + "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 1, + "endLine": 68, + "endColumn": 16, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1601, + "end": 1616, + "replacementText": "expand.invoke(ESValue.wrap(new X()))", + "line": 68, + "column": 1, + "endLine": 68, + "endColumn": 16 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 8, + "endLine": 80, + "endColumn": 13, + "problem": "InteropJsObjectExpandStaticInstance", + "suggest": "", + "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 1, + "endLine": 80, + "endColumn": 14, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1753, + "end": 1766, + "replacementText": "expand.invoke(ESValue.wrap(testY))", + "line": 80, + "column": 1, + "endLine": 80, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 81, + "column": 8, + "endLine": 81, + "endColumn": 38, + "problem": "InteropJsObjectExpandStaticInstance", + "suggest": "", + "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-expand-static-instance)", + "severity": "ERROR" + }, + { + "line": 81, + "column": 1, + "endLine": 81, + "endColumn": 39, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1768, + "end": 1806, + "replacementText": "expand.invoke(ESValue.wrap({x: '1', y: \"hello\", z: false}))", + "line": 81, + "column": 1, + "endLine": 81, + "endColumn": 39 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 84, + "column": 5, + "endLine": 84, + "endColumn": 32, + "problem": "InteropEqualityJudgment", + "autofix": [ + { + "start": 1831, + "end": 1858, + "replacementText": "orange.isVegetable1.areStrictlyEqual(123)", + "line": 84, + "column": 5, + "endLine": 84, + "endColumn": 32 + } + ], + "suggest": "", + "rule": "\"JS\" objects can't be used directly as operands of the equality operators (arkts-interop-js2s-equality-judgment)", + "severity": "ERROR" + }, + { + "line": 84, + "column": 29, + "endLine": 84, + "endColumn": 32, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1855, + "end": 1858, + "replacementText": "123.0", + "line": 84, + "column": 29, + "endLine": 84, + "endColumn": 32 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 1, + "endLine": 92, + "endColumn": 2, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, { - "start": 1850, - "end": 1853, - "replacementText": "123.0", - "line": 79, - "column": 29, - "endLine": 79, - "endColumn": 32 + "line": 89, + "column": 18, + "endLine": 89, + "endColumn": 19, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1921, + "end": 1922, + "replacementText": "8.0", + "line": 89, + "column": 18, + "endLine": 89, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - } - ] -} + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.json index 097539546e..ab212bc3f3 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.json @@ -1,18 +1,18 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], "result": [ { "line": 17, diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets b/ets2panda/linter/test/interop/interop_import_typeof_js.ets old mode 100755 new mode 100644 index 3c4c0728f9..b8941c7ac5 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets @@ -12,8 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -'use static' + import myAaa,{ClassA,Dog,Person,Wiki} from "./interop_import_js_js"; import { Dog as Doge } from './interop_import_js_js'; import { Wiki as wiki } from './interop_import_js_js'; diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json old mode 100755 new mode 100644 index 07bd210812..0d41c5dd84 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json @@ -1,488 +1,398 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55, - "problem": "InterOpImportJs", - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 15, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 11, - "endLine": 22, - "endColumn": 18, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 11, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 19, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 20, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 12, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 1, - "endLine": 28, - "endColumn": 17, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 12, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 32, - "column": 23, - "endLine": 32, - "endColumn": 35, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 1, - "endLine": 33, - "endColumn": 20, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 8, - "endLine": 33, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 35, - "column": 21, - "endLine": 35, - "endColumn": 33, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 37, - "column": 12, - "endLine": 37, - "endColumn": 28, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 43, - "column": 10, - "endLine": 43, - "endColumn": 28, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 43, - "column": 24, - "endLine": 43, - "endColumn": 27, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 45, - "column": 3, - "endLine": 45, - "endColumn": 22, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 45, - "column": 10, - "endLine": 45, - "endColumn": 22, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 48, - "column": 21, - "endLine": 48, - "endColumn": 39, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 48, - "column": 35, - "endLine": 48, - "endColumn": 38, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 50, - "column": 7, - "endLine": 50, - "endColumn": 13, - "problem": "InvalidIdentifier", - "suggest": "", - "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 5, - "endLine": 62, - "endColumn": 21, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 28, - "endLine": 66, - "endColumn": 47, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 35, - "endLine": 66, - "endColumn": 47, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 70, - "column": 1, - "endLine": 70, - "endColumn": 13, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 1, - "endLine": 71, - "endColumn": 25, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 25, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 1, - "endLine": 72, - "endColumn": 30, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 1, - "endLine": 73, - "endColumn": 31, - "problem": "InterOpImportJsForTypeOf", - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 31, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 28, - "endLine": 73, - "endColumn": 30, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - } - ] -} + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 69, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 54, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 55, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 15, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 18, + "problem": "CallJSFunction", + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 11, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 19, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 8, + "endLine": 24, + "endColumn": 19, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 20, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 8, + "endLine": 25, + "endColumn": 20, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 12, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 17, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 1, + "endLine": 28, + "endColumn": 12, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 11, + "endLine": 29, + "endColumn": 20, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 23, + "endLine": 31, + "endColumn": 35, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 1, + "endLine": 32, + "endColumn": 20, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 8, + "endLine": 32, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 21, + "endLine": 34, + "endColumn": 33, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 12, + "endLine": 36, + "endColumn": 28, + "problem": "InteropCallObjectMethods", + "suggest": "", + "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 10, + "endLine": 42, + "endColumn": 28, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 24, + "endLine": 42, + "endColumn": 27, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 22, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 22, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 21, + "endLine": 47, + "endColumn": 39, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 35, + "endLine": 47, + "endColumn": 38, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 7, + "endLine": 49, + "endColumn": 13, + "problem": "InvalidIdentifier", + "suggest": "", + "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 5, + "endLine": 61, + "endColumn": 21, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 28, + "endLine": 65, + "endColumn": 47, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 35, + "endLine": 65, + "endColumn": 47, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 1, + "endLine": 69, + "endColumn": 13, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 1, + "endLine": 70, + "endColumn": 25, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 8, + "endLine": 70, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 1, + "endLine": 71, + "endColumn": 30, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 8, + "endLine": 71, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 1, + "endLine": 72, + "endColumn": 31, + "problem": "InterOpImportJsForTypeOf", + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 8, + "endLine": 72, + "endColumn": 31, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 8, + "endLine": 72, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 28, + "endLine": 72, + "endColumn": 30, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json old mode 100755 new mode 100644 index e913452998..f9f9b5c814 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json @@ -1,933 +1,777 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69, - "problem": "InterOpImportJs", - "autofix": [ - { - "start": 618, - "end": 686, - "replacementText": "", - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69 - }, - { - "start": 795, - "end": 795, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_1.getPropertyByName('aaa');\nlet ClassA = GeneratedImportVar_1.getPropertyByName('ClassA');\nlet Dog = GeneratedImportVar_1.getPropertyByName('Dog');\nlet Person = GeneratedImportVar_1.getPropertyByName('Person');\nlet Wiki = GeneratedImportVar_1.getPropertyByName('Wiki');\n", - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54, - "problem": "InterOpImportJs", - "autofix": [ - { - "start": 687, - "end": 740, - "replacementText": "", - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54 - }, - { - "start": 795, - "end": 795, - "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_js');\nlet Doge = GeneratedImportVar_2.getPropertyByName('Dog');\n", - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55, - "problem": "InterOpImportJs", - "autofix": [ - { - "start": 741, - "end": 795, - "replacementText": "", - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55 - }, - { - "start": 795, - "end": 795, - "replacementText": "let GeneratedImportVar_3 = ESValue.load('./interop_import_js_js');\nlet wiki = GeneratedImportVar_3.getPropertyByName('Wiki');\n", - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55 - } - ], - "suggest": "", - "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 15, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 797, - "end": 811, - "replacementText": "myAaa.invoke().typeOf()", - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 15 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 11, - "endLine": 22, - "endColumn": 18, - "problem": "CallJSFunction", - "autofix": [ - { - "start": 831, - "end": 838, - "replacementText": "myAaa.invoke()", - "line": 22, - "column": 11, - "endLine": 22, - "endColumn": 18 - } - ], - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 11, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 852, - "end": 862, - "replacementText": "Dog.typeOf()", - "line": 24, - "column": 1, - "endLine": 24, - "endColumn": 11 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 19, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 872, - "end": 890, - "replacementText": "Dog.invoke(ESValue.wrap('doge')).typeOf()", - "line": 25, - "column": 1, - "endLine": 25, - "endColumn": 19 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 20, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 900, - "end": 919, - "replacementText": "Doge.invoke(ESValue.wrap('doge')).typeOf()", - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 12, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 929, - "end": 940, - "replacementText": "Wiki.typeOf()", - "line": 27, - "column": 1, - "endLine": 27, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 1, - "endLine": 28, - "endColumn": 17, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 949, - "end": 965, - "replacementText": "Wiki.getPropertyByName('name').typeOf()", - "line": 28, - "column": 1, - "endLine": 28, - "endColumn": 17 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 956, - "end": 965, - "replacementText": "Wiki.getPropertyByName(\"name\")", - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "Wiki.getPropertyByName('name').toString()", - "start": 956, - "end": 965, - "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 12, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 974, - "end": 985, - "replacementText": "wiki.typeOf()", - "line": 29, - "column": 1, - "endLine": 29, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 1004, - "end": 1013, - "replacementText": "wiki.getPropertyByName(\"name\")", - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "wiki.getPropertyByName('name').toString()", - "start": 1004, - "end": 1013, - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 32, - "column": 23, - "endLine": 32, - "endColumn": 35, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1048, - "end": 1060, - "replacementText": "ClassA.instantiate()", - "line": 32, - "column": 23, - "endLine": 32, - "endColumn": 35 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 1, - "endLine": 33, - "endColumn": 20, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1061, - "end": 1080, - "replacementText": "ClassA.instantiate().typeOf()", - "line": 33, - "column": 1, - "endLine": 33, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 33, - "column": 8, - "endLine": 33, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1068, - "end": 1080, - "replacementText": "ClassA.instantiate()", - "line": 33, - "column": 8, - "endLine": 33, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 35, - "column": 21, - "endLine": 35, - "endColumn": 33, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1124, - "end": 1136, - "replacementText": "Person.instantiate()", - "line": 35, - "column": 21, - "endLine": 35, - "endColumn": 33 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 37, - "column": 12, - "endLine": 37, - "endColumn": 28, - "problem": "InteropCallObjectMethods", - "autofix": [ - { - "start": 1171, - "end": 1187, - "replacementText": "person.invokeMethod(\"getName\")", - "line": 37, - "column": 12, - "endLine": 37, - "endColumn": 28 - } - ], - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 43, - "column": 10, - "endLine": 43, - "endColumn": 28, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 43, - "column": 24, - "endLine": 43, - "endColumn": 27, - "problem": "NumericSemantics", - "autofix": [ - { - "start": 1312, - "end": 1315, - "replacementText": "111.0", - "line": 43, - "column": 24, - "endLine": 43, - "endColumn": 27 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 45, - "column": 3, - "endLine": 45, - "endColumn": 22, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1337, - "end": 1356, - "replacementText": "Person.instantiate().typeOf()", - "line": 45, - "column": 3, - "endLine": 45, - "endColumn": 22 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 45, - "column": 10, - "endLine": 45, - "endColumn": 22, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1344, - "end": 1356, - "replacementText": "Person.instantiate()", - "line": 45, - "column": 10, - "endLine": 45, - "endColumn": 22 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 48, - "column": 21, - "endLine": 48, - "endColumn": 39, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 48, - "column": 35, - "endLine": 48, - "endColumn": 38, - "problem": "NumericSemantics", - "autofix": [ - { - "start": 1403, - "end": 1406, - "replacementText": "111.0", - "line": 48, - "column": 35, - "endLine": 48, - "endColumn": 38 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 50, - "column": 7, - "endLine": 50, - "endColumn": 13, - "problem": "InvalidIdentifier", - "suggest": "", - "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 5, - "endLine": 62, - "endColumn": 21, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1713, - "end": 1729, - "replacementText": "wiki.getPropertyByName('name').typeOf()", - "line": 62, - "column": 5, - "endLine": 62, - "endColumn": 21 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 1720, - "end": 1729, - "replacementText": "wiki.getPropertyByName(\"name\")", - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "wiki.getPropertyByName('name').toString()", - "start": 1720, - "end": 1729, - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 28, - "endLine": 66, - "endColumn": 47, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1818, - "end": 1837, - "replacementText": "ClassA.instantiate().typeOf()", - "line": 66, - "column": 28, - "endLine": 66, - "endColumn": 47 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 66, - "column": 35, - "endLine": 66, - "endColumn": 47, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1825, - "end": 1837, - "replacementText": "ClassA.instantiate()", - "line": 66, - "column": 35, - "endLine": 66, - "endColumn": 47 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 70, - "column": 1, - "endLine": 70, - "endColumn": 13, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1858, - "end": 1870, - "replacementText": "myAaa.typeOf()", - "line": 70, - "column": 1, - "endLine": 70, - "endColumn": 13 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 1, - "endLine": 71, - "endColumn": 25, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1880, - "end": 1904, - "replacementText": "Person.instantiate().getPropertyByName('name').typeOf()", - "line": 71, - "column": 1, - "endLine": 71, - "endColumn": 25 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 25, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "new Person().getPropertyByName('name').toString()", - "start": 1887, - "end": 1904, - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 25 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1887, - "end": 1899, - "replacementText": "Person.instantiate()", - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 1, - "endLine": 72, - "endColumn": 30, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1914, - "end": 1943, - "replacementText": "Person.instantiate().getPropertyByName('getName').invoke().typeOf()", - "line": 72, - "column": 1, - "endLine": 72, - "endColumn": 30 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1921, - "end": 1933, - "replacementText": "Person.instantiate()", - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 1, - "endLine": 73, - "endColumn": 31, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1952, - "end": 1982, - "replacementText": "Person.instantiate().getPropertyByName('setAge').invoke(ESValue.wrap(22)).typeOf()", - "line": 73, - "column": 1, - "endLine": 73, - "endColumn": 31 - } - ], - "suggest": "", - "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 31, - "problem": "LimitedVoidType", - "suggest": "", - "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1959, - "end": 1971, - "replacementText": "Person.instantiate()", - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 20 - } - ], - "suggest": "", - "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 28, - "endLine": 73, - "endColumn": 30, - "problem": "NumericSemantics", - "autofix": [ - { - "start": 1979, - "end": 1981, - "replacementText": "22.0", - "line": 73, - "column": 28, - "endLine": 73, - "endColumn": 30 - } - ], - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - } - ] -} + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 69, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 606, + "end": 674, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 69 + }, + { + "start": 783, + "end": 783, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_js');\nlet myAaa = GeneratedImportVar_1.getPropertyByName('aaa');\nlet ClassA = GeneratedImportVar_1.getPropertyByName('ClassA');\nlet Dog = GeneratedImportVar_1.getPropertyByName('Dog');\nlet Person = GeneratedImportVar_1.getPropertyByName('Person');\nlet Wiki = GeneratedImportVar_1.getPropertyByName('Wiki');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 69 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 54, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 675, + "end": 728, + "replacementText": "", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 54 + }, + { + "start": 783, + "end": 783, + "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_js');\nlet Doge = GeneratedImportVar_2.getPropertyByName('Dog');\n", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 54 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 55, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 729, + "end": 783, + "replacementText": "", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 55 + }, + { + "start": 783, + "end": 783, + "replacementText": "let GeneratedImportVar_3 = ESValue.load('./interop_import_js_js');\nlet wiki = GeneratedImportVar_3.getPropertyByName('Wiki');\n", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 55 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 15, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 785, + "end": 799, + "replacementText": "myAaa.invoke().typeOf()", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 18, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 819, + "end": 826, + "replacementText": "myAaa.invoke()", + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 11, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 840, + "end": 850, + "replacementText": "Dog.typeOf()", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 19, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 860, + "end": 878, + "replacementText": "Dog.invoke(ESValue.wrap('doge')).typeOf()", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 8, + "endLine": 24, + "endColumn": 19, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 20, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 888, + "end": 907, + "replacementText": "Doge.invoke(ESValue.wrap('doge')).typeOf()", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 8, + "endLine": 25, + "endColumn": 20, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 12, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 917, + "end": 928, + "replacementText": "Wiki.typeOf()", + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 17, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 937, + "end": 953, + "replacementText": "Wiki.getPropertyByName('name').typeOf()", + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 1, + "endLine": 28, + "endColumn": 12, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 962, + "end": 973, + "replacementText": "wiki.typeOf()", + "line": 28, + "column": 1, + "endLine": 28, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 11, + "endLine": 29, + "endColumn": 20, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 992, + "end": 1001, + "replacementText": "wiki.getPropertyByName(\"name\")", + "line": 29, + "column": 11, + "endLine": 29, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 23, + "endLine": 31, + "endColumn": 35, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1036, + "end": 1048, + "replacementText": "ClassA.instantiate()", + "line": 31, + "column": 23, + "endLine": 31, + "endColumn": 35 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 1, + "endLine": 32, + "endColumn": 20, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1049, + "end": 1068, + "replacementText": "ClassA.instantiate().typeOf()", + "line": 32, + "column": 1, + "endLine": 32, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 8, + "endLine": 32, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1056, + "end": 1068, + "replacementText": "ClassA.instantiate()", + "line": 32, + "column": 8, + "endLine": 32, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 21, + "endLine": 34, + "endColumn": 33, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1112, + "end": 1124, + "replacementText": "Person.instantiate()", + "line": 34, + "column": 21, + "endLine": 34, + "endColumn": 33 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 12, + "endLine": 36, + "endColumn": 28, + "problem": "InteropCallObjectMethods", + "autofix": [ + { + "start": 1159, + "end": 1175, + "replacementText": "person.invokeMethod(\"getName\")", + "line": 36, + "column": 12, + "endLine": 36, + "endColumn": 28 + } + ], + "suggest": "", + "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 10, + "endLine": 42, + "endColumn": 28, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 42, + "column": 24, + "endLine": 42, + "endColumn": 27, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1300, + "end": 1303, + "replacementText": "111.0", + "line": 42, + "column": 24, + "endLine": 42, + "endColumn": 27 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 22, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1325, + "end": 1344, + "replacementText": "Person.instantiate().typeOf()", + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 22 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 22, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1332, + "end": 1344, + "replacementText": "Person.instantiate()", + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 22 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 21, + "endLine": 47, + "endColumn": 39, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 35, + "endLine": 47, + "endColumn": 38, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1391, + "end": 1394, + "replacementText": "111.0", + "line": 47, + "column": 35, + "endLine": 47, + "endColumn": 38 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 7, + "endLine": 49, + "endColumn": 13, + "problem": "InvalidIdentifier", + "suggest": "", + "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 5, + "endLine": 61, + "endColumn": 21, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1701, + "end": 1717, + "replacementText": "wiki.getPropertyByName('name').typeOf()", + "line": 61, + "column": 5, + "endLine": 61, + "endColumn": 21 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 28, + "endLine": 65, + "endColumn": 47, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1806, + "end": 1825, + "replacementText": "ClassA.instantiate().typeOf()", + "line": 65, + "column": 28, + "endLine": 65, + "endColumn": 47 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 35, + "endLine": 65, + "endColumn": 47, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1813, + "end": 1825, + "replacementText": "ClassA.instantiate()", + "line": 65, + "column": 35, + "endLine": 65, + "endColumn": 47 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 69, + "column": 1, + "endLine": 69, + "endColumn": 13, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1846, + "end": 1858, + "replacementText": "myAaa.typeOf()", + "line": 69, + "column": 1, + "endLine": 69, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 1, + "endLine": 70, + "endColumn": 25, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1868, + "end": 1892, + "replacementText": "Person.instantiate().getPropertyByName('name').typeOf()", + "line": 70, + "column": 1, + "endLine": 70, + "endColumn": 25 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 8, + "endLine": 70, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1875, + "end": 1887, + "replacementText": "Person.instantiate()", + "line": 70, + "column": 8, + "endLine": 70, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 1, + "endLine": 71, + "endColumn": 30, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1902, + "end": 1931, + "replacementText": "Person.instantiate().invokeMethod(\"getName\").typeOf()", + "line": 71, + "column": 1, + "endLine": 71, + "endColumn": 30 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 8, + "endLine": 71, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1909, + "end": 1921, + "replacementText": "Person.instantiate()", + "line": 71, + "column": 8, + "endLine": 71, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 1, + "endLine": 72, + "endColumn": 31, + "problem": "InterOpImportJsForTypeOf", + "autofix": [ + { + "start": 1940, + "end": 1970, + "replacementText": "Person.instantiate().invokeMethod(\"setAge\", ESValue.wrap(22)).typeOf()", + "line": 72, + "column": 1, + "endLine": 72, + "endColumn": 31 + } + ], + "suggest": "", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 8, + "endLine": 72, + "endColumn": 31, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 8, + "endLine": 72, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 1947, + "end": 1959, + "replacementText": "Person.instantiate()", + "line": 72, + "column": 8, + "endLine": 72, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 28, + "endLine": 72, + "endColumn": 30, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1967, + "end": 1969, + "replacementText": "22.0", + "line": 72, + "column": 28, + "endLine": 72, + "endColumn": 30 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.json index b61974a218..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.json @@ -13,36 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 69, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 54, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 55, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets index c5dde90dd5..71c8bd3946 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets @@ -12,8 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -'use static' + let GeneratedImportVar_3 = ESValue.load('./interop_import_js_js'); @@ -79,5 +78,5 @@ class Object { myAaa.typeOf(); //error Person.instantiate().getPropertyByName('name').typeOf() //error -Person.instantiate().getPropertyByName('getName').invoke().typeOf() //error -Person.instantiate().getPropertyByName('setAge').invoke(ESValue.wrap(22.0)).typeOf() //error +Person.instantiate().invokeMethod("getName").typeOf() //error +Person.instantiate().invokeMethod("setAge", ESValue.wrap(22.0)).typeOf() //error diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json index 983fb8071b..221ab45494 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json @@ -1,168 +1,168 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 19, - "column": 5, - "endLine": 19, - "endColumn": 66, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 58, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 5, - "endLine": 21, - "endColumn": 66, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 5, - "endLine": 22, - "endColumn": 57, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 5, - "endLine": 23, - "endColumn": 66, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 5, - "endLine": 24, - "endColumn": 58, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 5, - "endLine": 25, - "endColumn": 62, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 5, - "endLine": 26, - "endColumn": 56, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 27, - "column": 5, - "endLine": 27, - "endColumn": 62, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 28, - "column": 5, - "endLine": 28, - "endColumn": 58, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 32, - "column": 5, - "endLine": 32, - "endColumn": 25, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 40, - "column": 5, - "endLine": 40, - "endColumn": 41, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 46, - "column": 5, - "endLine": 46, - "endColumn": 22, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 47, - "column": 5, - "endLine": 47, - "endColumn": 42, - "problem": "AnyType", - "suggest": "", - "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", - "severity": "ERROR" - }, - { - "line": 60, - "column": 7, - "endLine": 60, - "endColumn": 13, - "problem": "InvalidIdentifier", - "suggest": "", - "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", - "severity": "ERROR" - } - ] -} + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 66, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 66, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 57, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 66, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 5, + "endLine": 23, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 5, + "endLine": 24, + "endColumn": 62, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 62, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 5, + "endLine": 27, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 5, + "endLine": 31, + "endColumn": 25, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 5, + "endLine": 39, + "endColumn": 41, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 5, + "endLine": 45, + "endColumn": 22, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 5, + "endLine": 46, + "endColumn": 42, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 7, + "endLine": 59, + "endColumn": 13, + "problem": "InvalidIdentifier", + "suggest": "", + "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets old mode 100755 new mode 100644 index 3f72e3cf20..ad6fbcab7d --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import {foo, person} from "./interop_not_have_property_js" diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json old mode 100755 new mode 100644 index ce2c2d2d38..cb366b21c4 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 59, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "InteropObjectProperty", "suggest": "", @@ -48,16 +38,6 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, "endColumn": 17, "problem": "InteropObjectProperty", "suggest": "", @@ -68,16 +48,6 @@ "line": 20, "column": 1, "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, "endColumn": 16, "problem": "InteropObjectProperty", "suggest": "", @@ -85,19 +55,9 @@ "severity": "ERROR" }, { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 11, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, + "line": 20, "column": 14, - "endLine": 21, + "endLine": 20, "endColumn": 16, "problem": "NumericSemantics", "suggest": "", @@ -105,9 +65,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 1, - "endLine": 22, + "endLine": 21, "endColumn": 21, "problem": "InteropObjectProperty", "suggest": "", @@ -115,19 +75,9 @@ "severity": "ERROR" }, { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 22, + "line": 21, "column": 16, - "endLine": 22, + "endLine": 21, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -135,9 +85,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 19, - "endLine": 22, + "endLine": 21, "endColumn": 20, "problem": "NumericSemantics", "suggest": "", @@ -145,9 +95,9 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "InteropObjectProperty", "suggest": "", @@ -155,19 +105,9 @@ "severity": "ERROR" }, { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 8, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 23, + "line": 22, "column": 11, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json old mode 100755 new mode 100644 index 0c4beba4af..bc3b0d40f5 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json @@ -15,38 +15,28 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 59, "problem": "InterOpImportJs", "autofix": [ { - "start": 618, - "end": 676, + "start": 605, + "end": 663, "replacementText": "", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 59 }, { - "start": 676, - "end": 676, + "start": 663, + "end": 663, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_not_have_property_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet person = GeneratedImportVar_1.getPropertyByName('person');\n", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 59 } ], @@ -55,19 +45,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "InteropObjectProperty", "autofix": [ { - "start": 678, - "end": 686, + "start": 665, + "end": 673, "replacementText": "foo.getPropertyByName(\"name\")", - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9 } ], @@ -79,37 +69,16 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('name').toString()", - "start": 678, - "end": 686, - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 1, - "endLine": 20, "endColumn": 17, "problem": "InteropObjectProperty", "autofix": [ { - "start": 687, - "end": 703, + "start": 674, + "end": 690, "replacementText": "foo.setPropertyByName(\"name\", ESValue.wrap(\"456\"))", - "line": 20, + "line": 19, "column": 1, - "endLine": 20, + "endLine": 19, "endColumn": 17 } ], @@ -121,37 +90,16 @@ "line": 20, "column": 1, "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('name').toString()", - "start": 687, - "end": 695, - "line": 20, - "column": 1, - "endLine": 20, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 1, - "endLine": 21, "endColumn": 16, "problem": "InteropObjectProperty", "autofix": [ { - "start": 704, - "end": 719, + "start": 691, + "end": 706, "replacementText": "person.setPropertyByName(\"age\", ESValue.wrap(23))", - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 16 } ], @@ -160,40 +108,19 @@ "severity": "ERROR" }, { - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 11, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "person.getPropertyByName('age').toNumber()", - "start": 704, - "end": 714, - "line": 21, - "column": 1, - "endLine": 21, - "endColumn": 11 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, + "line": 20, "column": 14, - "endLine": 21, + "endLine": 20, "endColumn": 16, "problem": "NumericSemantics", "autofix": [ { - "start": 717, - "end": 719, + "start": 704, + "end": 706, "replacementText": "23.0", - "line": 21, + "line": 20, "column": 14, - "endLine": 21, + "endLine": 20, "endColumn": 16 } ], @@ -202,19 +129,19 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 1, - "endLine": 22, + "endLine": 21, "endColumn": 21, "problem": "InteropObjectProperty", "autofix": [ { - "start": 720, - "end": 740, + "start": 707, + "end": 727, "replacementText": "person.setPropertyByName(\"male\", ESValue.wrap([2, 3]))", - "line": 22, + "line": 21, "column": 1, - "endLine": 22, + "endLine": 21, "endColumn": 21 } ], @@ -223,40 +150,19 @@ "severity": "ERROR" }, { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "person.getPropertyByName('male')", - "start": 720, - "end": 731, - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 12 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 22, + "line": 21, "column": 16, - "endLine": 22, + "endLine": 21, "endColumn": 17, "problem": "NumericSemantics", "autofix": [ { - "start": 735, - "end": 736, + "start": 722, + "end": 723, "replacementText": "2.0", - "line": 22, + "line": 21, "column": 16, - "endLine": 22, + "endLine": 21, "endColumn": 17 } ], @@ -265,19 +171,19 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 19, - "endLine": 22, + "endLine": 21, "endColumn": 20, "problem": "NumericSemantics", "autofix": [ { - "start": 738, - "end": 739, + "start": 725, + "end": 726, "replacementText": "3.0", - "line": 22, + "line": 21, "column": 19, - "endLine": 22, + "endLine": 21, "endColumn": 20 } ], @@ -286,19 +192,19 @@ "severity": "ERROR" }, { - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "InteropObjectProperty", "autofix": [ { - "start": 741, - "end": 753, + "start": 728, + "end": 740, "replacementText": "foo.setPropertyByName(\"age\", ESValue.wrap(12))", - "line": 23, + "line": 22, "column": 1, - "endLine": 23, + "endLine": 22, "endColumn": 13 } ], @@ -307,40 +213,19 @@ "severity": "ERROR" }, { - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 8, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('age')", - "start": 741, - "end": 748, - "line": 23, - "column": 1, - "endLine": 23, - "endColumn": 8 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 23, + "line": 22, "column": 11, - "endLine": 23, + "endLine": 22, "endColumn": 13, "problem": "NumericSemantics", "autofix": [ { - "start": 751, - "end": 753, + "start": 738, + "end": 740, "replacementText": "12.0", - "line": 23, + "line": 22, "column": 11, - "endLine": 23, + "endLine": 22, "endColumn": 13 } ], diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json index 838a0500a5..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 59, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets index 586868511b..cfddb44b00 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./interop_not_have_property_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json index 17bc19346a..ae940558e7 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 74, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, + "endLine": 18, "endColumn": 62, "problem": "AnyType", "suggest": "", @@ -45,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets old mode 100755 new mode 100644 index 1049aac0f0..8c41ae4182 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import {foo} from "./interop_property_num_js" diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.arkts2.json b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.arkts2.json old mode 100755 new mode 100644 index 414d9f7721..622761b380 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 46, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 46, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "InteropNoHaveNum", "suggest": "", @@ -46,22 +36,12 @@ }, { "line": 19, - "column": 2, - "endLine": 19, - "endColumn": 9, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 2, + "column": 1, "endLine": 19, "endColumn": 9, - "problem": "InteropJsObjectUsage", + "problem": "InteropNoHaveNum", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, { @@ -74,26 +54,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 21, "column": 1, @@ -104,56 +64,16 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 22, "column": 1, "endLine": 22, - "endColumn": 9, + "endColumn": 11, "problem": "InteropNoHaveNum", "suggest": "", "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 23, "column": 1, @@ -164,26 +84,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 24, "column": 1, @@ -194,26 +94,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 25, "column": 1, @@ -223,56 +103,6 @@ "suggest": "", "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" - }, - { - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 11, - "problem": "InteropNoHaveNum", - "suggest": "", - "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.autofix.json b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.autofix.json old mode 100755 new mode 100644 index 4452cefcfd..fc4732acc4 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.autofix.json @@ -15,35 +15,29 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 46, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 46, "problem": "InterOpImportJs", "autofix": [ { - "start": 618, - "end": 663, + "start": 605, + "end": 650, "replacementText": "", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 46 }, { - "start": 663, - "end": 663, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_property_num_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n" + "start": 650, + "end": 650, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_property_num_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 46 } ], "suggest": "", @@ -51,19 +45,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "InteropNoHaveNum", "autofix": [ { - "start": 666, - "end": 673, + "start": 653, + "end": 660, "replacementText": "foo.getPropertyByName(\"num\").toNumber()", - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9 } ], @@ -73,44 +67,23 @@ }, { "line": 19, - "column": 2, - "endLine": 19, - "endColumn": 9, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 666, - "end": 673, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 19, - "column": 2, - "endLine": 19, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 2, + "column": 1, "endLine": 19, "endColumn": 9, - "problem": "InteropJsObjectUsage", + "problem": "InteropNoHaveNum", "autofix": [ { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 666, - "end": 673, + "start": 663, + "end": 670, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", "line": 19, - "column": 2, + "column": 1, "endLine": 19, "endColumn": 9 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, { @@ -121,8 +94,8 @@ "problem": "InteropNoHaveNum", "autofix": [ { - "start": 676, - "end": 683, + "start": 673, + "end": 680, "replacementText": "foo.getPropertyByName(\"num\").toNumber()", "line": 20, "column": 1, @@ -134,48 +107,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 676, - "end": 683, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 676, - "end": 683, - "line": 20, - "column": 2, - "endLine": 20, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 21, "column": 1, @@ -184,8 +115,8 @@ "problem": "InteropNoHaveNum", "autofix": [ { - "start": 686, - "end": 693, + "start": 683, + "end": 690, "replacementText": "foo.getPropertyByName(\"num\").toNumber()", "line": 21, "column": 1, @@ -197,111 +128,27 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 686, - "end": 693, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 686, - "end": 693, - "line": 21, - "column": 2, - "endLine": 21, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 22, "column": 1, "endLine": 22, - "endColumn": 9, + "endColumn": 11, "problem": "InteropNoHaveNum", "autofix": [ { - "start": 696, - "end": 703, - "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "start": 693, + "end": 702, + "replacementText": "(foo.getPropertyByName(\"num\").toNumber())", "line": 22, "column": 1, "endLine": 22, - "endColumn": 9 + "endColumn": 11 } ], "suggest": "", "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 696, - "end": 703, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 696, - "end": 703, - "line": 22, - "column": 2, - "endLine": 22, - "endColumn": 9 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 23, "column": 1, @@ -310,8 +157,8 @@ "problem": "InteropNoHaveNum", "autofix": [ { - "start": 706, - "end": 715, + "start": 705, + "end": 714, "replacementText": "(foo.getPropertyByName(\"num\").toNumber())", "line": 23, "column": 1, @@ -323,48 +170,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 707, - "end": 714, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 707, - "end": 714, - "line": 23, - "column": 3, - "endLine": 23, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 24, "column": 1, @@ -373,8 +178,8 @@ "problem": "InteropNoHaveNum", "autofix": [ { - "start": 718, - "end": 727, + "start": 717, + "end": 726, "replacementText": "(foo.getPropertyByName(\"num\").toNumber())", "line": 24, "column": 1, @@ -386,48 +191,6 @@ "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" }, - { - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 719, - "end": 726, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 719, - "end": 726, - "line": 24, - "column": 3, - "endLine": 24, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, { "line": 25, "column": 1, @@ -436,8 +199,8 @@ "problem": "InteropNoHaveNum", "autofix": [ { - "start": 730, - "end": 739, + "start": 729, + "end": 738, "replacementText": "(foo.getPropertyByName(\"num\").toNumber())", "line": 25, "column": 1, @@ -448,111 +211,6 @@ "suggest": "", "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", "severity": "ERROR" - }, - { - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 731, - "end": 738, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 731, - "end": 738, - "line": 25, - "column": 3, - "endLine": 25, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 11, - "problem": "InteropNoHaveNum", - "autofix": [ - { - "start": 742, - "end": 751, - "replacementText": "(foo.getPropertyByName(\"num\").toNumber())", - "line": 26, - "column": 1, - "endLine": 26, - "endColumn": 11 - } - ], - "suggest": "", - "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 743, - "end": 750, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 743, - "end": 750, - "line": 26, - "column": 3, - "endLine": 26, - "endColumn": 10 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.json b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.json index 456612d680..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 46, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.ets b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.ets index 1a22e1418c..09086d9892 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let GeneratedImportVar_1 = ESValue.load('./interop_property_num_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); diff --git a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.json b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.json index 01cf629ed9..ef4a1a04e1 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_num_arkts2.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 69, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 41, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 1, - "endLine": 22, + "endLine": 21, "endColumn": 41, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 41, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -65,9 +65,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 43, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -75,9 +75,9 @@ "severity": "ERROR" }, { - "line": 26, + "line": 25, "column": 1, - "endLine": 26, + "endLine": 25, "endColumn": 43, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -85,9 +85,9 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 43, "problem": "UnaryArithmNotNumber", "suggest": "", @@ -95,4 +95,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets b/ets2panda/linter/test/interop/no_await_js_promise.ets old mode 100755 new mode 100644 index 9247c363b4..124f7b4dab --- a/ets2panda/linter/test/interop/no_await_js_promise.ets +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets @@ -1,65 +1,64 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -'use static' - -import { p, foo, pFuncCall, arrowFunc, pArrowCall } from "./no_await_js_promise_export"; - -async function awaitPromise() { - return await p; -} - -async function awaitFunctionCall() { - return await foo(); -} - -async function awaitFuncResult() { - return await pFuncCall; -} - -async function awaitArrowCall() { - return await arrowFunc(); -} - -async function awaitArrowResult() { - return await pArrowCall; -} - -class ExampleClass { - async classMethod() { - return await p; - } - - handler = async () => { - return await pFuncCall; - }; -} - -const exampleObj = { - async objMethod() { - return await pArrowCall; - }, - - arrowHandler: async () => { - return await foo(); - } -}; - -(async function() { - console.log("IIFE result:", await p); -})(); - -(async () => { - console.log("IIFE Arrow result:", await arrowFunc()); +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { p, foo, pFuncCall, arrowFunc, pArrowCall } from "./no_await_js_promise_export"; + +async function awaitPromise() { + return await p; +} + +async function awaitFunctionCall() { + return await foo(); +} + +async function awaitFuncResult() { + return await pFuncCall; +} + +async function awaitArrowCall() { + return await arrowFunc(); +} + +async function awaitArrowResult() { + return await pArrowCall; +} + +class ExampleClass { + async classMethod() { + return await p; + } + + handler = async () => { + return await pFuncCall; + }; +} + +const exampleObj = { + async objMethod() { + return await pArrowCall; + }, + + arrowHandler: async () => { + return await foo(); + } +}; + +(async function() { + console.log("IIFE result:", await p); +})(); + +(async () => { + console.log("IIFE Arrow result:", await arrowFunc()); })(); \ No newline at end of file diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json old mode 100755 new mode 100644 index 5021d02c43..7201a52ae1 --- a/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 89, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 89, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 10, - "endLine": 20, + "endLine": 19, "endColumn": 17, "problem": "NoAwaitJsPromise", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 10, - "endLine": 24, + "endLine": 23, "endColumn": 21, "problem": "NoAwaitJsPromise", "suggest": "", @@ -55,19 +45,9 @@ "severity": "ERROR" }, { - "line": 24, - "column": 16, - "endLine": 24, - "endColumn": 21, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 28, + "line": 27, "column": 10, - "endLine": 28, + "endLine": 27, "endColumn": 25, "problem": "NoAwaitJsPromise", "suggest": "", @@ -75,29 +55,9 @@ "severity": "ERROR" }, { - "line": 32, + "line": 35, "column": 10, - "endLine": 32, - "endColumn": 27, - "problem": "NoAwaitJsPromise", - "suggest": "", - "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", - "severity": "ERROR" - }, - { - "line": 32, - "column": 16, - "endLine": 32, - "endColumn": 27, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 36, - "column": 10, - "endLine": 36, + "endLine": 35, "endColumn": 26, "problem": "NoAwaitJsPromise", "suggest": "", @@ -105,9 +65,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 40, "column": 12, - "endLine": 41, + "endLine": 40, "endColumn": 19, "problem": "NoAwaitJsPromise", "suggest": "", @@ -115,9 +75,9 @@ "severity": "ERROR" }, { - "line": 45, + "line": 44, "column": 12, - "endLine": 45, + "endLine": 44, "endColumn": 27, "problem": "NoAwaitJsPromise", "suggest": "", @@ -125,9 +85,9 @@ "severity": "ERROR" }, { - "line": 49, + "line": 48, "column": 20, - "endLine": 49, + "endLine": 48, "endColumn": 21, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -135,9 +95,9 @@ "severity": "ERROR" }, { - "line": 50, + "line": 49, "column": 3, - "endLine": 52, + "endLine": 51, "endColumn": 4, "problem": "ObjectLiteralProperty", "suggest": "", @@ -145,9 +105,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 50, "column": 12, - "endLine": 51, + "endLine": 50, "endColumn": 28, "problem": "NoAwaitJsPromise", "suggest": "", @@ -155,9 +115,9 @@ "severity": "ERROR" }, { - "line": 55, + "line": 54, "column": 12, - "endLine": 55, + "endLine": 54, "endColumn": 23, "problem": "NoAwaitJsPromise", "suggest": "", @@ -165,19 +125,9 @@ "severity": "ERROR" }, { - "line": 55, - "column": 18, - "endLine": 55, - "endColumn": 23, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 59, + "line": 58, "column": 2, - "endLine": 61, + "endLine": 60, "endColumn": 2, "problem": "FunctionExpression", "suggest": "", @@ -185,34 +135,14 @@ "severity": "ERROR" }, { - "line": 60, + "line": 59, "column": 31, - "endLine": 60, + "endLine": 59, "endColumn": 38, "problem": "NoAwaitJsPromise", "suggest": "", "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", "severity": "ERROR" - }, - { - "line": 64, - "column": 37, - "endLine": 64, - "endColumn": 54, - "problem": "NoAwaitJsPromise", - "suggest": "", - "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", - "severity": "ERROR" - }, - { - "line": 64, - "column": 43, - "endLine": 64, - "endColumn": 54, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.json index 5285bc41f6..02889dfd82 100755 --- a/ets2panda/linter/test/interop/no_await_js_promise.ets.json +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 89, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 49, + "line": 48, "column": 20, - "endLine": 49, + "endLine": 48, "endColumn": 21, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 59, + "line": 58, "column": 2, - "endLine": 61, + "endLine": 60, "endColumn": 2, "problem": "FunctionExpression", "suggest": "", diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets b/ets2panda/linter/test/interop/no_js_instanceof.ets old mode 100755 new mode 100644 index f3e57eeee8..9c7c1b6453 --- a/ets2panda/linter/test/interop/no_js_instanceof.ets +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import { Foo, foo, CreatePerson, a , b, MyNamespace } from "./no_js_instanceof_file.js" diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json old mode 100755 new mode 100644 index 31d9a91eef..616006bedf --- a/ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, - "endColumn": 88, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 17, - "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 88, "problem": "InterOpImportJs", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 4, - "endLine": 27, + "endLine": 26, "endColumn": 22, "problem": "InteropJsInstanceof", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 30, "column": 4, - "endLine": 31, + "endLine": 30, "endColumn": 23, "problem": "InteropJsInstanceof", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 35, + "line": 34, "column": 4, - "endLine": 35, + "endLine": 34, "endColumn": 23, "problem": "InteropJsInstanceof", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 39, + "line": 38, "column": 28, - "endLine": 39, + "endLine": 38, "endColumn": 50, "problem": "CallJSFunction", "suggest": "", @@ -75,9 +65,9 @@ "severity": "ERROR" }, { - "line": 39, + "line": 38, "column": 47, - "endLine": 39, + "endLine": 38, "endColumn": 49, "problem": "NumericSemantics", "suggest": "", @@ -85,9 +75,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 40, "column": 4, - "endLine": 41, + "endLine": 40, "endColumn": 34, "problem": "InteropJsInstanceof", "suggest": "", @@ -95,9 +85,9 @@ "severity": "ERROR" }, { - "line": 46, + "line": 45, "column": 8, - "endLine": 46, + "endLine": 45, "endColumn": 38, "problem": "InteropJsInstanceof", "suggest": "", @@ -105,9 +95,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 51, "column": 8, - "endLine": 52, + "endLine": 51, "endColumn": 38, "problem": "InteropJsInstanceof", "suggest": "", @@ -115,9 +105,9 @@ "severity": "ERROR" }, { - "line": 59, + "line": 58, "column": 12, - "endLine": 59, + "endLine": 58, "endColumn": 42, "problem": "InteropJsInstanceof", "suggest": "", @@ -125,9 +115,9 @@ "severity": "ERROR" }, { - "line": 65, + "line": 64, "column": 4, - "endLine": 65, + "endLine": 64, "endColumn": 22, "problem": "InteropJsInstanceof", "suggest": "", @@ -135,9 +125,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 68, "column": 4, - "endLine": 69, + "endLine": 68, "endColumn": 24, "problem": "InteropJsInstanceof", "suggest": "", @@ -145,9 +135,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 68, "column": 4, - "endLine": 69, + "endLine": 68, "endColumn": 7, "problem": "CallJSFunction", "suggest": "", @@ -155,9 +145,9 @@ "severity": "ERROR" }, { - "line": 73, + "line": 72, "column": 36, - "endLine": 73, + "endLine": 72, "endColumn": 51, "problem": "DynamicCtorCall", "suggest": "", @@ -165,29 +155,9 @@ "severity": "ERROR" }, { - "line": 73, - "column": 36, - "endLine": 73, - "endColumn": 51, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 36, - "endLine": 73, - "endColumn": 51, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 75, + "line": 74, "column": 5, - "endLine": 75, + "endLine": 74, "endColumn": 37, "problem": "InteropJsInstanceof", "suggest": "", @@ -195,19 +165,9 @@ "severity": "ERROR" }, { - "line": 75, - "column": 22, - "endLine": 75, - "endColumn": 37, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 75, + "line": 74, "column": 22, - "endLine": 75, + "endLine": 74, "endColumn": 37, "problem": "InteropJsObjectConditionJudgment", "suggest": "", diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.json index e6955adae6..ca88f857e9 100755 --- a/ets2panda/linter/test/interop/no_js_instanceof.ets.json +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.json @@ -1,29 +1,17 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 88, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/object_built_in.ets b/ets2panda/linter/test/interop/object_built_in.ets index 7797930ffd..3170f3f087 100644 --- a/ets2panda/linter/test/interop/object_built_in.ets +++ b/ets2panda/linter/test/interop/object_built_in.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' + import { X } from "./oh_modules/object_built_in" diff --git a/ets2panda/linter/test/interop/object_built_in.ets.arkts2.json b/ets2panda/linter/test/interop/object_built_in.ets.arkts2.json index 07296c65fc..aea5d55ddb 100644 --- a/ets2panda/linter/test/interop/object_built_in.ets.arkts2.json +++ b/ets2panda/linter/test/interop/object_built_in.ets.arkts2.json @@ -14,16 +14,6 @@ "limitations under the License." ], "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, { "line": 20, "column": 12, @@ -65,4 +55,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/object_built_in.ets.json b/ets2panda/linter/test/interop/object_built_in.ets.json index 582a700d94..d756197f15 100644 --- a/ets2panda/linter/test/interop/object_built_in.ets.json +++ b/ets2panda/linter/test/interop/object_built_in.ets.json @@ -14,16 +14,6 @@ "limitations under the License." ], "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 49, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, { "line": 20, "column": 5, @@ -55,4 +45,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/object_literal_constructor.ets b/ets2panda/linter/test/interop/object_literal_constructor.ets index 7c15e1bf64..c66bdfabca 100644 --- a/ets2panda/linter/test/interop/object_literal_constructor.ets +++ b/ets2panda/linter/test/interop/object_literal_constructor.ets @@ -1,4 +1,3 @@ -'use static' /* * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/ets2panda/linter/test/interop/object_literal_constructor.ets.arkts2.json b/ets2panda/linter/test/interop/object_literal_constructor.ets.arkts2.json index 6a51dd80b2..7fe4087dbb 100644 --- a/ets2panda/linter/test/interop/object_literal_constructor.ets.arkts2.json +++ b/ets2panda/linter/test/interop/object_literal_constructor.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 101, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 20, + "line": 19, "column": 18, - "endLine": 20, + "endLine": 19, "endColumn": 27, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 24, - "endLine": 20, + "endLine": 19, "endColumn": 25, "problem": "NumericSemantics", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 22, - "endLine": 24, + "endLine": 23, "endColumn": 51, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 26, + "line": 25, "column": 14, - "endLine": 26, + "endLine": 25, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 14, - "endLine": 27, + "endLine": 26, "endColumn": 25, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -75,9 +65,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 16, - "endLine": 27, + "endLine": 26, "endColumn": 23, "problem": "ObjectLiteralProperty", "suggest": "", @@ -85,9 +75,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 16, - "endLine": 27, + "endLine": 26, "endColumn": 23, "problem": "SpreadOperator", "suggest": "", @@ -95,9 +85,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 5, - "endLine": 30, + "endLine": 29, "endColumn": 18, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -105,9 +95,9 @@ "severity": "ERROR" }, { - "line": 36, + "line": 35, "column": 12, - "endLine": 36, + "endLine": 35, "endColumn": 29, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -115,9 +105,9 @@ "severity": "ERROR" }, { - "line": 49, + "line": 48, "column": 15, - "endLine": 49, + "endLine": 48, "endColumn": 35, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -125,9 +115,9 @@ "severity": "ERROR" }, { - "line": 57, + "line": 56, "column": 11, - "endLine": 57, + "endLine": 56, "endColumn": 29, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -135,9 +125,9 @@ "severity": "ERROR" }, { - "line": 63, + "line": 62, "column": 30, - "endLine": 63, + "endLine": 62, "endColumn": 48, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -145,9 +135,9 @@ "severity": "ERROR" }, { - "line": 70, + "line": 69, "column": 5, - "endLine": 73, + "endLine": 72, "endColumn": 2, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -155,9 +145,9 @@ "severity": "ERROR" }, { - "line": 72, + "line": 71, "column": 6, - "endLine": 72, + "endLine": 71, "endColumn": 8, "problem": "NumericSemantics", "suggest": "", @@ -165,9 +155,9 @@ "severity": "ERROR" }, { - "line": 79, + "line": 78, "column": 5, - "endLine": 79, + "endLine": 78, "endColumn": 24, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -175,9 +165,9 @@ "severity": "ERROR" }, { - "line": 80, + "line": 79, "column": 5, - "endLine": 80, + "endLine": 79, "endColumn": 23, "problem": "InteropObjectLiteralClass", "suggest": "", @@ -185,9 +175,9 @@ "severity": "ERROR" }, { - "line": 79, + "line": 78, "column": 21, - "endLine": 79, + "endLine": 78, "endColumn": 22, "problem": "NumericSemantics", "suggest": "", @@ -195,9 +185,9 @@ "severity": "ERROR" }, { - "line": 80, + "line": 79, "column": 20, - "endLine": 80, + "endLine": 79, "endColumn": 21, "problem": "NumericSemantics", "suggest": "", diff --git a/ets2panda/linter/test/interop/object_literal_constructor.ets.json b/ets2panda/linter/test/interop/object_literal_constructor.ets.json index bafc2e9e54..b242a6c5b9 100644 --- a/ets2panda/linter/test/interop/object_literal_constructor.ets.json +++ b/ets2panda/linter/test/interop/object_literal_constructor.ets.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 101, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 26, + "line": 25, "column": 14, - "endLine": 26, + "endLine": 25, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 16, - "endLine": 27, + "endLine": 26, "endColumn": 23, "problem": "SpreadOperator", "suggest": "", diff --git a/ets2panda/linter/test/interop/object_literal_union_type.ets b/ets2panda/linter/test/interop/object_literal_union_type.ets index f57fd51379..2e730940c3 100644 --- a/ets2panda/linter/test/interop/object_literal_union_type.ets +++ b/ets2panda/linter/test/interop/object_literal_union_type.ets @@ -1,4 +1,3 @@ -'use static' /* * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/ets2panda/linter/test/interop/object_literal_union_type.ets.arkts2.json b/ets2panda/linter/test/interop/object_literal_union_type.ets.arkts2.json index 5c02f0cb4d..4b9be812e4 100644 --- a/ets2panda/linter/test/interop/object_literal_union_type.ets.arkts2.json +++ b/ets2panda/linter/test/interop/object_literal_union_type.ets.arkts2.json @@ -15,29 +15,19 @@ ], "result": [ { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 63, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 67, - "problem": "ImportAfterStatement", + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 31, + "problem": "InteropObjectLiteralAmbiguity", "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "rule": "Object literal not compatible with target union type. (arkts-interop-d2s-object-literal-no-ambiguity)", "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 5, - "endLine": 21, + "endLine": 22, "endColumn": 31, "problem": "InteropObjectLiteralAmbiguity", "suggest": "", @@ -45,20 +35,20 @@ "severity": "ERROR" }, { - "line": 23, + "line": 24, "column": 5, - "endLine": 23, - "endColumn": 31, + "endLine": 24, + "endColumn": 37, "problem": "InteropObjectLiteralAmbiguity", "suggest": "", "rule": "Object literal not compatible with target union type. (arkts-interop-d2s-object-literal-no-ambiguity)", "severity": "ERROR" }, { - "line": 25, + "line": 26, "column": 5, - "endLine": 25, - "endColumn": 37, + "endLine": 26, + "endColumn": 34, "problem": "InteropObjectLiteralAmbiguity", "suggest": "", "rule": "Object literal not compatible with target union type. (arkts-interop-d2s-object-literal-no-ambiguity)", diff --git a/ets2panda/linter/test/interop/object_literal_union_type.ets.json b/ets2panda/linter/test/interop/object_literal_union_type.ets.json index 25154ac0c6..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/object_literal_union_type.ets.json +++ b/ets2panda/linter/test/interop/object_literal_union_type.ets.json @@ -13,26 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 63, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 67, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/oh_modules/object_literal_union_type_arkts2.ets b/ets2panda/linter/test/interop/oh_modules/object_literal_union_type_arkts2.ets index dad32c88ba..81c8a334d4 100644 --- a/ets2panda/linter/test/interop/oh_modules/object_literal_union_type_arkts2.ets +++ b/ets2panda/linter/test/interop/oh_modules/object_literal_union_type_arkts2.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' export class A { name: string = '' } export interface B { name: string, age?: number } diff --git a/ets2panda/linter/test/interop/oh_modules/reflect_export.ets b/ets2panda/linter/test/interop/oh_modules/reflect_export.ets index 4fd2894dd8..418b723cf9 100644 --- a/ets2panda/linter/test/interop/oh_modules/reflect_export.ets +++ b/ets2panda/linter/test/interop/oh_modules/reflect_export.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' export function foo(prx: Object) { Reflect.get(prx, 'a') // 'hello' diff --git a/ets2panda/linter/test/interop/oh_modules/static_object_literals_export.ets b/ets2panda/linter/test/interop/oh_modules/static_object_literals_export.ets index 2191e01971..540539ec6b 100644 --- a/ets2panda/linter/test/interop/oh_modules/static_object_literals_export.ets +++ b/ets2panda/linter/test/interop/oh_modules/static_object_literals_export.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' export class X { name: string = '' } diff --git a/ets2panda/linter/test/interop/reflect_built_in.ets b/ets2panda/linter/test/interop/reflect_built_in.ets index 96b0800185..63eb6869e2 100644 --- a/ets2panda/linter/test/interop/reflect_built_in.ets +++ b/ets2panda/linter/test/interop/reflect_built_in.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' + import { X } from "./oh_modules/reflect_export" diff --git a/ets2panda/linter/test/interop/reflect_built_in.ets.arkts2.json b/ets2panda/linter/test/interop/reflect_built_in.ets.arkts2.json index f16e3c2498..e874522c34 100644 --- a/ets2panda/linter/test/interop/reflect_built_in.ets.arkts2.json +++ b/ets2panda/linter/test/interop/reflect_built_in.ets.arkts2.json @@ -14,16 +14,6 @@ "limitations under the License." ], "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 48, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, { "line": 29, "column": 1, @@ -45,4 +35,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/reflect_built_in.ets.json b/ets2panda/linter/test/interop/reflect_built_in.ets.json index 0ee87e87fb..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/reflect_built_in.ets.json +++ b/ets2panda/linter/test/interop/reflect_built_in.ets.json @@ -13,16 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 17, - "column": 1, - "endLine": 17, - "endColumn": 48, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] -} + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/static_dynamic_import.ets b/ets2panda/linter/test/interop/static_dynamic_import.ets new file mode 100644 index 0000000000..7eec28c419 --- /dev/null +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let arkTsMod = await import('./test_files/dummy_arkts1_file'); +let tsModule = await import('./test_files/dummy_ts_file'); +let jsModule = await import('./test_files/dummy_js_file'); + +function main(): void { + import('./test_files/dummy_ts_file').then((m) => { + console.log(m.Data.name) + }) +} diff --git a/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json b/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json new file mode 100644 index 0000000000..dc7f9e0521 --- /dev/null +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json @@ -0,0 +1,98 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 16, + "endLine": 16, + "endColumn": 62, + "problem": "InteropDynamicImport", + "suggest": "", + "rule": "No support for static dynamic import (arkts-interop-d2s-dynamic-import)", + "severity": "ERROR" + }, + { + "line": 16, + "column": 22, + "endLine": 16, + "endColumn": 62, + "problem": "DynamicImport", + "suggest": "", + "rule": "Dynamic import is not supported(arkts-no-dynamic-import)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 17, + "endLine": 17, + "endColumn": 59, + "problem": "InteropDynamicImportTs", + "suggest": "", + "rule": "No support for static dynamic import (arkts-interop-ts2s-dynamic-import-ts)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 23, + "endLine": 17, + "endColumn": 59, + "problem": "DynamicImport", + "suggest": "", + "rule": "Dynamic import is not supported(arkts-no-dynamic-import)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 16, + "endLine": 18, + "endColumn": 58, + "problem": "InteropDynamicImportJs", + "suggest": "", + "rule": "No support for static dynamic import (arkts-interop-js2s-dynamic-import-js)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 22, + "endLine": 18, + "endColumn": 58, + "problem": "DynamicImport", + "suggest": "", + "rule": "Dynamic import is not supported(arkts-no-dynamic-import)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 3, + "endLine": 21, + "endColumn": 44, + "problem": "InteropDynamicImportTs", + "suggest": "", + "rule": "No support for static dynamic import (arkts-interop-ts2s-dynamic-import-ts)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 3, + "endLine": 21, + "endColumn": 39, + "problem": "DynamicImport", + "suggest": "", + "rule": "Dynamic import is not supported(arkts-no-dynamic-import)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/static_dynamic_import.ets.json b/ets2panda/linter/test/interop/static_dynamic_import.ets.json new file mode 100644 index 0000000000..999000f1d0 --- /dev/null +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets.json @@ -0,0 +1,58 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 5, + "endLine": 16, + "endColumn": 62, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 59, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 46, + "endLine": 21, + "endColumn": 47, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/static_object_literals.ets.json b/ets2panda/linter/test/interop/static_object_literals.ets.json index 12d46c0860..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/static_object_literals.ets.json +++ b/ets2panda/linter/test/interop/static_object_literals.ets.json @@ -13,66 +13,5 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ - { - "line": 18, - "column": 12, - "endLine": 18, - "endColumn": 29, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 12, - "endLine": 22, - "endColumn": 25, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 5, - "endLine": 26, - "endColumn": 22, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 5, - "endLine": 30, - "endColumn": 18, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - }, - { - "line": 35, - "column": 12, - "endLine": 35, - "endColumn": 29, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - }, - { - "line": 40, - "column": 17, - "endLine": 40, - "endColumn": 34, - "problem": "InteropStaticObjectLiterals", - "suggest": "", - "rule": "It is not allowed to create object literal in interop calls (arkts-interop-s2d-object-literal)", - "severity": "ERROR" - } - ] + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unique_types.ets b/ets2panda/linter/test/interop/unique_types.ets index 35f8bae391..da2c034f53 100644 --- a/ets2panda/linter/test/interop/unique_types.ets +++ b/ets2panda/linter/test/interop/unique_types.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import { objectLiteralType, diff --git a/ets2panda/linter/test/interop/unique_types.ets.arkts2.json b/ets2panda/linter/test/interop/unique_types.ets.arkts2.json index 3c2bcf66a7..46c7e59925 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.arkts2.json +++ b/ets2panda/linter/test/interop/unique_types.ets.arkts2.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 24, "column": 1, - "endLine": 23, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 23, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 22, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 13, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 30, "column": 3, - "endLine": 32, + "endLine": 31, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -75,9 +65,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 20, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -85,9 +75,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -95,4 +85,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unique_types.ets.autofix.json b/ets2panda/linter/test/interop/unique_types.ets.autofix.json index 5f1b6e40b9..bf760d1cf6 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.autofix.json +++ b/ets2panda/linter/test/interop/unique_types.ets.autofix.json @@ -15,29 +15,19 @@ ], "result": [ { - "line": 17, + "line": 24, "column": 1, - "endLine": 23, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 23, "problem": "InteropDirectAccessToTSTypes", "autofix": [ { - "start": 744, - "end": 775, + "start": 731, + "end": 762, "replacementText": "objectLiteralType.setPropertyByName('name',ESValue.wrap(\"test\"))", - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 23 } ], @@ -46,19 +36,19 @@ "severity": "ERROR" }, { - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 22, "problem": "InteropDirectAccessToTSTypes", "autofix": [ { - "start": 777, - "end": 807, + "start": 764, + "end": 794, "replacementText": "intersectionType.setPropertyByName('name',ESValue.wrap(\"test\"))", - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 22 } ], @@ -67,9 +57,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 13, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -77,9 +67,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -87,9 +77,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 30, "column": 3, - "endLine": 32, + "endLine": 31, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -97,9 +87,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 20, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -107,9 +97,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -117,4 +107,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unique_types.ets.json b/ets2panda/linter/test/interop/unique_types.ets.json index 3e8e488310..ca88f857e9 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.json +++ b/ets2panda/linter/test/interop/unique_types.ets.json @@ -1,14 +1,17 @@ { - "result": [ - { - "line": 17, - "column": 1, - "endLine": 23, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - } - ] + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unique_types.ets.migrate.ets b/ets2panda/linter/test/interop/unique_types.ets.migrate.ets index 86dd5f4ed0..884003da24 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.migrate.ets +++ b/ets2panda/linter/test/interop/unique_types.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' import { objectLiteralType, diff --git a/ets2panda/linter/test/interop/unique_types.ets.migrate.json b/ets2panda/linter/test/interop/unique_types.ets.migrate.json index 4eb8c2c72d..47c591c577 100644 --- a/ets2panda/linter/test/interop/unique_types.ets.migrate.json +++ b/ets2panda/linter/test/interop/unique_types.ets.migrate.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 17, + "line": 29, "column": 1, - "endLine": 23, - "endColumn": 38, - "problem": "ImportAfterStatement", - "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", - "severity": "ERROR" - }, - { - "line": 30, - "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 13, "problem": "InteropTSFunctionInvoke", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 1, - "endLine": 30, + "endLine": 29, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 31, + "line": 30, "column": 3, - "endLine": 32, + "endLine": 31, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 20, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 1, - "endLine": 34, + "endLine": 33, "endColumn": 11, "problem": "InteropDirectAccessToTSTypes", "suggest": "", @@ -75,4 +65,4 @@ "severity": "ERROR" } ] -} +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/array_index_expr_type.ets.arkts2.json b/ets2panda/linter/test/main/array_index_expr_type.ets.arkts2.json index 40493eb175..3643204633 100644 --- a/ets2panda/linter/test/main/array_index_expr_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/array_index_expr_type.ets.arkts2.json @@ -1,18 +1,18 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], "result": [ { "line": 17, @@ -64,6 +64,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 18, + "column": 11, + "endLine": 18, + "endColumn": 26, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 18, "column": 20, @@ -124,6 +134,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 25, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 21, "column": 20, @@ -184,6 +204,16 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 24, + "column": 11, + "endLine": 24, + "endColumn": 30, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 24, "column": 20, @@ -224,6 +254,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 26, + "column": 11, + "endLine": 26, + "endColumn": 21, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 26, "column": 20, @@ -244,6 +284,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 27, "column": 20, @@ -264,6 +314,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 28, + "column": 11, + "endLine": 28, + "endColumn": 25, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 28, "column": 20, @@ -284,6 +344,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 29, + "column": 11, + "endLine": 29, + "endColumn": 22, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 30, "column": 7, @@ -394,6 +464,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 39, + "column": 1, + "endLine": 39, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 39, "column": 7, @@ -404,6 +484,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 40, + "column": 1, + "endLine": 40, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 40, "column": 7, @@ -414,6 +504,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 41, + "column": 1, + "endLine": 41, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 41, "column": 7, @@ -434,6 +534,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 1, + "endLine": 45, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 45, "column": 7, @@ -554,6 +674,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 55, + "column": 15, + "endLine": 55, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 55, "column": 22, @@ -574,6 +704,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 59, + "column": 15, + "endLine": 59, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 62, "column": 22, @@ -724,6 +864,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 82, + "column": 1, + "endLine": 82, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 82, "column": 10, @@ -734,6 +884,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 83, + "column": 1, + "endLine": 83, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 83, "column": 10, @@ -744,6 +904,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 84, + "column": 1, + "endLine": 84, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 84, "column": 10, @@ -754,6 +924,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 85, + "column": 1, + "endLine": 85, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 85, "column": 10, diff --git a/ets2panda/linter/test/main/array_index_expr_type.ets.autofix.json b/ets2panda/linter/test/main/array_index_expr_type.ets.autofix.json index ec4168139c..f3c4133394 100644 --- a/ets2panda/linter/test/main/array_index_expr_type.ets.autofix.json +++ b/ets2panda/linter/test/main/array_index_expr_type.ets.autofix.json @@ -1,18 +1,18 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], "result": [ { "line": 17, @@ -119,6 +119,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 18, + "column": 11, + "endLine": 18, + "endColumn": 26, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 18, "column": 20, @@ -245,6 +255,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 21, + "column": 11, + "endLine": 21, + "endColumn": 25, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 21, "column": 20, @@ -316,6 +336,16 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 24, + "column": 11, + "endLine": 24, + "endColumn": 30, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 24, "column": 20, @@ -367,6 +397,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 26, + "column": 11, + "endLine": 26, + "endColumn": 21, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 26, "column": 20, @@ -398,6 +438,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 27, + "column": 11, + "endLine": 27, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 27, "column": 20, @@ -440,6 +490,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 28, + "column": 11, + "endLine": 28, + "endColumn": 25, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 28, "column": 20, @@ -482,6 +542,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 29, + "column": 11, + "endLine": 29, + "endColumn": 22, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 30, "column": 7, @@ -713,6 +783,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 39, + "column": 1, + "endLine": 39, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 39, "column": 7, @@ -734,6 +814,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 40, + "column": 1, + "endLine": 40, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 40, "column": 7, @@ -755,6 +845,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 41, + "column": 1, + "endLine": 41, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 41, "column": 7, @@ -797,6 +897,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 1, + "endLine": 45, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 45, "column": 7, @@ -1049,6 +1169,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 55, + "column": 15, + "endLine": 55, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 55, "column": 22, @@ -1091,6 +1221,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 59, + "column": 15, + "endLine": 59, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 62, "column": 22, @@ -1373,6 +1513,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 82, + "column": 1, + "endLine": 82, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 82, "column": 10, @@ -1394,6 +1544,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 83, + "column": 1, + "endLine": 83, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 83, "column": 10, @@ -1415,6 +1575,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 84, + "column": 1, + "endLine": 84, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 84, "column": 10, @@ -1436,6 +1606,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 85, + "column": 1, + "endLine": 85, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 85, "column": 10, diff --git a/ets2panda/linter/test/main/array_index_expr_type.ets.migrate.json b/ets2panda/linter/test/main/array_index_expr_type.ets.migrate.json index 8407a76e0f..12700705c3 100644 --- a/ets2panda/linter/test/main/array_index_expr_type.ets.migrate.json +++ b/ets2panda/linter/test/main/array_index_expr_type.ets.migrate.json @@ -64,6 +64,16 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 24, + "column": 11, + "endLine": 24, + "endColumn": 30, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 24, "column": 20, @@ -94,6 +104,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 26, + "column": 19, + "endLine": 26, + "endColumn": 29, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 26, "column": 28, @@ -104,6 +124,36 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 29, + "column": 19, + "endLine": 29, + "endColumn": 30, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 15, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 15, + "endLine": 59, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 64, "column": 3, @@ -133,6 +183,46 @@ "suggest": "", "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" + }, + { + "line": 82, + "column": 1, + "endLine": 82, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 83, + "column": 1, + "endLine": 83, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 84, + "column": 1, + "endLine": 84, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 85, + "column": 1, + "endLine": 85, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/dynamic_ctor_call.ets.arkts2.json b/ets2panda/linter/test/main/dynamic_ctor_call.ets.arkts2.json index 0ef26c352d..b4ee74500e 100644 --- a/ets2panda/linter/test/main/dynamic_ctor_call.ets.arkts2.json +++ b/ets2panda/linter/test/main/dynamic_ctor_call.ets.arkts2.json @@ -124,6 +124,16 @@ "rule": "Construct signatures are not supported in interfaces (arkts-no-ctor-signatures-iface)", "severity": "ERROR" }, + { + "line": 39, + "column": 14, + "endLine": 39, + "endColumn": 18, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 39, "column": 14, diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json index 6c7ca94b92..d79abde569 100755 --- a/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.arkts2.json @@ -323,6 +323,16 @@ "suggest": "", "rule": "The function type should be explicit (arkts-no-ts-like-function-call)", "severity": "ERROR" + }, + { + "line": 175, + "column": 1, + "endLine": 175, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json b/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json index 6f0f0a0481..d3870c4c8f 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.autofix.json @@ -521,6 +521,16 @@ "suggest": "", "rule": "The function type should be explicit (arkts-no-ts-like-function-call)", "severity": "ERROR" + }, + { + "line": 175, + "column": 1, + "endLine": 175, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json index ca5758bca2..b4e8db486e 100644 --- a/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json +++ b/ets2panda/linter/test/main/explicit_function_type.ets.migrate.json @@ -143,6 +143,16 @@ "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" + }, + { + "line": 175, + "column": 1, + "endLine": 175, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json index 8332379fa7..10523de7b5 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.arkts2.json @@ -1,17 +1,17 @@ { "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." ], "result": [ { @@ -254,6 +254,16 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 43, + "column": 14, + "endLine": 43, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 43, "column": 10, @@ -264,6 +274,16 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 47, + "column": 14, + "endLine": 47, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 47, "column": 10, @@ -284,6 +304,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 51, + "column": 14, + "endLine": 51, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 51, "column": 10, @@ -304,6 +334,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 55, + "column": 14, + "endLine": 55, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 55, "column": 10, @@ -314,6 +354,16 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 60, + "column": 16, + "endLine": 60, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 60, "column": 12, @@ -324,6 +374,16 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 64, + "column": 16, + "endLine": 64, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 64, "column": 12, @@ -344,6 +404,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 68, + "column": 16, + "endLine": 68, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 68, "column": 12, @@ -364,6 +434,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 72, + "column": 16, + "endLine": 72, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 72, "column": 12, diff --git a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json index 773fea5ff8..08fe89b9bc 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.autofix.json @@ -1,17 +1,17 @@ { "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." ], "result": [ { @@ -44,7 +44,11 @@ { "start": 676, "end": 687, - "replacementText": "new Array()" + "replacementText": "new Array()", + "line": 17, + "column": 36, + "endLine": 17, + "endColumn": 47 } ], "suggest": "", @@ -61,7 +65,11 @@ { "start": 705, "end": 716, - "replacementText": "new Array()" + "replacementText": "new Array()", + "line": 18, + "column": 17, + "endLine": 18, + "endColumn": 28 } ], "suggest": "", @@ -108,7 +116,11 @@ { "start": 796, "end": 805, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 21, + "column": 44, + "endLine": 21, + "endColumn": 53 } ], "suggest": "", @@ -125,7 +137,11 @@ { "start": 823, "end": 832, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 22, + "column": 17, + "endLine": 22, + "endColumn": 26 } ], "suggest": "", @@ -192,7 +208,11 @@ { "start": 994, "end": 1003, - "replacementText": "new Map string[]>()" + "replacementText": "new Map string[]>()", + "line": 27, + "column": 55, + "endLine": 27, + "endColumn": 64 } ], "suggest": "", @@ -209,7 +229,11 @@ { "start": 1065, "end": 1074, - "replacementText": "new Map string[]>()" + "replacementText": "new Map string[]>()", + "line": 28, + "column": 61, + "endLine": 28, + "endColumn": 70 } ], "suggest": "", @@ -246,7 +270,11 @@ { "start": 1215, "end": 1228, - "replacementText": "new MyClass()" + "replacementText": "new MyClass()", + "line": 34, + "column": 38, + "endLine": 34, + "endColumn": 51 } ], "suggest": "", @@ -273,7 +301,11 @@ { "start": 1298, "end": 1307, - "replacementText": "new Set()" + "replacementText": "new Set()", + "line": 36, + "column": 29, + "endLine": 36, + "endColumn": 38 } ], "suggest": "", @@ -290,7 +322,11 @@ { "start": 1337, "end": 1346, - "replacementText": "new Map string[]>()" + "replacementText": "new Map string[]>()", + "line": 37, + "column": 29, + "endLine": 37, + "endColumn": 38 } ], "suggest": "", @@ -307,7 +343,11 @@ { "start": 1378, "end": 1387, - "replacementText": "new Map string[]>()" + "replacementText": "new Map string[]>()", + "line": 38, + "column": 31, + "endLine": 38, + "endColumn": 40 } ], "suggest": "", @@ -324,13 +364,27 @@ { "start": 1423, "end": 1452, - "replacementText": "new Promise(() => { return ''; })" + "replacementText": "new Promise(() => { return ''; })", + "line": 40, + "column": 34, + "endLine": 40, + "endColumn": 63 } ], "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 43, + "column": 14, + "endLine": 43, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 43, "column": 10, @@ -341,13 +395,27 @@ { "start": 1504, "end": 1513, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 43, + "column": 10, + "endLine": 43, + "endColumn": 19 } ], "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 47, + "column": 14, + "endLine": 47, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 47, "column": 10, @@ -358,7 +426,11 @@ { "start": 1582, "end": 1591, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 47, + "column": 10, + "endLine": 47, + "endColumn": 19 } ], "suggest": "", @@ -375,6 +447,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 51, + "column": 14, + "endLine": 51, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 51, "column": 10, @@ -395,6 +477,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 55, + "column": 14, + "endLine": 55, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 55, "column": 10, @@ -405,6 +497,16 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 60, + "column": 16, + "endLine": 60, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 60, "column": 12, @@ -415,13 +517,27 @@ { "start": 1798, "end": 1807, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 60, + "column": 12, + "endLine": 60, + "endColumn": 21 } ], "suggest": "", "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 64, + "column": 16, + "endLine": 64, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 64, "column": 12, @@ -432,7 +548,11 @@ { "start": 1873, "end": 1882, - "replacementText": "new Map()" + "replacementText": "new Map()", + "line": 64, + "column": 12, + "endLine": 64, + "endColumn": 21 } ], "suggest": "", @@ -449,6 +569,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 68, + "column": 16, + "endLine": 68, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 68, "column": 12, @@ -469,6 +599,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 72, + "column": 16, + "endLine": 72, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 72, "column": 12, diff --git a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.json b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.json index a3d92d0d96..27185a830c 100644 --- a/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.json +++ b/ets2panda/linter/test/main/func_inferred_type_args_2.ets.migrate.json @@ -144,6 +144,26 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 43, + "column": 14, + "endLine": 43, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 14, + "endLine": 47, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 51, "column": 10, @@ -154,6 +174,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 51, + "column": 14, + "endLine": 51, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 51, "column": 10, @@ -174,6 +204,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 55, + "column": 14, + "endLine": 55, + "endColumn": 17, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 55, "column": 10, @@ -184,6 +224,26 @@ "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", "severity": "ERROR" }, + { + "line": 60, + "column": 16, + "endLine": 60, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 16, + "endLine": 64, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 68, "column": 12, @@ -194,6 +254,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 68, + "column": 16, + "endLine": 68, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 68, "column": 12, @@ -214,6 +284,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 72, + "column": 16, + "endLine": 72, + "endColumn": 19, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 72, "column": 12, diff --git a/ets2panda/linter/test/main/index_negative.ets.arkts2.json b/ets2panda/linter/test/main/index_negative.ets.arkts2.json index d1daebd5f8..d8c630fa30 100755 --- a/ets2panda/linter/test/main/index_negative.ets.arkts2.json +++ b/ets2panda/linter/test/main/index_negative.ets.arkts2.json @@ -64,6 +64,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 17, + "column": 15, + "endLine": 17, + "endColumn": 26, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 18, "column": 5, @@ -154,6 +164,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 21, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 32, "column": 1, @@ -234,6 +254,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 42, + "column": 1, + "endLine": 42, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 42, "column": 5, @@ -324,6 +354,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 53, + "column": 1, + "endLine": 53, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 53, "column": 5, @@ -384,6 +424,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 58, + "column": 1, + "endLine": 58, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 58, "column": 5, @@ -524,6 +574,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 69, + "column": 1, + "endLine": 69, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 69, "column": 5, @@ -574,6 +634,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 73, + "column": 1, + "endLine": 73, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 73, "column": 5, @@ -724,6 +794,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 80, + "column": 1, + "endLine": 80, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 80, "column": 5, @@ -734,6 +814,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 81, + "column": 1, + "endLine": 81, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 81, "column": 5, @@ -754,6 +844,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 82, + "column": 1, + "endLine": 82, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 82, "column": 5, @@ -774,6 +874,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 83, + "column": 1, + "endLine": 83, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 83, "column": 5, @@ -784,6 +894,16 @@ "rule": "The index expression must be of a numeric type (arkts-array-index-expr-type)", "severity": "ERROR" }, + { + "line": 84, + "column": 1, + "endLine": 84, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 84, "column": 5, @@ -804,6 +924,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 85, + "column": 1, + "endLine": 85, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 85, "column": 5, @@ -844,6 +974,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 87, + "column": 1, + "endLine": 87, + "endColumn": 8, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 87, "column": 5, @@ -924,6 +1064,16 @@ "rule": "The index expression must be zero or positive value.(arkts-array-index-negative)", "severity": "ERROR" }, + { + "line": 91, + "column": 1, + "endLine": 91, + "endColumn": 9, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 91, "column": 5, diff --git a/ets2panda/linter/test/main/invalid_identifier.ets.arkts2.json b/ets2panda/linter/test/main/invalid_identifier.ets.arkts2.json index 2999205f95..df7367f9de 100644 --- a/ets2panda/linter/test/main/invalid_identifier.ets.arkts2.json +++ b/ets2panda/linter/test/main/invalid_identifier.ets.arkts2.json @@ -24,6 +24,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 56, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { "line": 18, "column": 8, diff --git a/ets2panda/linter/test/main/limit_void_type.ets.arkts2.json b/ets2panda/linter/test/main/limit_void_type.ets.arkts2.json index 39d24845a6..5a91df9df0 100644 --- a/ets2panda/linter/test/main/limit_void_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/limit_void_type.ets.arkts2.json @@ -204,6 +204,16 @@ "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, + { + "line": 45, + "column": 15, + "endLine": 45, + "endColumn": 25, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 47, "column": 13, @@ -884,6 +894,16 @@ "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, + { + "line": 144, + "column": 1, + "endLine": 144, + "endColumn": 6, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 144, "column": 9, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json index 286fd756ff..0293db338b 100755 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json @@ -274,6 +274,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 84, + "column": 12, + "endLine": 84, + "endColumn": 31, + "problem": "InteropDirectAccessToTSTypes", + "suggest": "", + "rule": "Cannot access typescript types directly (arkts-interop-ts2s-static-access-ts-type)", + "severity": "ERROR" + }, { "line": 84, "column": 36, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json index 282458e4e5..4c937491cd 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json @@ -656,6 +656,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 84, + "column": 12, + "endLine": 84, + "endColumn": 31, + "problem": "InteropDirectAccessToTSTypes", + "suggest": "", + "rule": "Cannot access typescript types directly (arkts-interop-ts2s-static-access-ts-type)", + "severity": "ERROR" + }, { "line": 84, "column": 36, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json index 7756bd5397..112cbe6bb0 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json @@ -74,6 +74,16 @@ "rule": "This keyword cannot be used as identifiers (arkts-invalid-identifier)", "severity": "ERROR" }, + { + "line": 90, + "column": 12, + "endLine": 90, + "endColumn": 31, + "problem": "InteropDirectAccessToTSTypes", + "suggest": "", + "rule": "Cannot access typescript types directly (arkts-interop-ts2s-static-access-ts-type)", + "severity": "ERROR" + }, { "line": 90, "column": 36, diff --git a/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json b/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json index f4753e594f..a3ca4dc49b 100644 --- a/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json @@ -94,6 +94,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 30, + "column": 16, + "endLine": 30, + "endColumn": 21, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 33, "column": 23, diff --git a/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json b/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json index d8d76c5ce8..d7c46831b1 100755 --- a/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json +++ b/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json @@ -474,6 +474,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 107, + "column": 9, + "endLine": 107, + "endColumn": 19, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 107, "column": 18, @@ -964,6 +974,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 183, + "column": 6, + "endLine": 183, + "endColumn": 13, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 185, "column": 5, diff --git a/ets2panda/linter/test/main/numeric_semantics.ets.autofix.json b/ets2panda/linter/test/main/numeric_semantics.ets.autofix.json index 148d39bc82..5045e3f3cb 100644 --- a/ets2panda/linter/test/main/numeric_semantics.ets.autofix.json +++ b/ets2panda/linter/test/main/numeric_semantics.ets.autofix.json @@ -1011,6 +1011,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 107, + "column": 9, + "endLine": 107, + "endColumn": 19, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 107, "column": 18, @@ -1963,6 +1973,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 183, + "column": 6, + "endLine": 183, + "endColumn": 13, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 185, "column": 5, diff --git a/ets2panda/linter/test/main/numeric_semantics.ets.migrate.json b/ets2panda/linter/test/main/numeric_semantics.ets.migrate.json index c86c2373e1..e61c55a40d 100644 --- a/ets2panda/linter/test/main/numeric_semantics.ets.migrate.json +++ b/ets2panda/linter/test/main/numeric_semantics.ets.migrate.json @@ -24,6 +24,16 @@ "rule": "Definite assignment assertions are not supported (arkts-no-definite-assignment)", "severity": "ERROR" }, + { + "line": 110, + "column": 17, + "endLine": 110, + "endColumn": 27, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 110, "column": 26, @@ -74,6 +84,16 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 189, + "column": 6, + "endLine": 189, + "endColumn": 13, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 203, "column": 1, diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json b/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json index 0b572f009a..f7e900af40 100755 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json @@ -204,6 +204,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 45, + "column": 17, + "endLine": 45, + "endColumn": 23, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 68, "column": 28, diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json b/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json index e649323550..2a6aa3c531 100644 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json @@ -419,6 +419,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 45, + "column": 17, + "endLine": 45, + "endColumn": 23, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 68, "column": 28, diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json b/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json index 2b4699fa61..6d6b2576f7 100644 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json @@ -74,6 +74,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 47, + "column": 17, + "endLine": 47, + "endColumn": 23, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 74, "column": 5, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json index cc12e25c14..ac48689e30 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json @@ -1024,6 +1024,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 226, + "column": 16, + "endLine": 226, + "endColumn": 29, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 229, "column": 20, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json index 8e5ca87403..706c09bb34 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json @@ -1776,6 +1776,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 226, + "column": 16, + "endLine": 226, + "endColumn": 29, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 229, "column": 20, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json index 9143d0676d..972e1c73e2 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json @@ -294,6 +294,16 @@ "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, + { + "line": 281, + "column": 16, + "endLine": 281, + "endColumn": 29, + "problem": "MissingSuperCall", + "suggest": "", + "rule": "The subclass constructor must call the parent class's parametered constructor (arkts-subclass-must-call-super-constructor-with-args)", + "severity": "ERROR" + }, { "line": 284, "column": 20, diff --git a/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json b/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json index 4218268d31..62d4d681bf 100644 --- a/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json +++ b/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json @@ -23,6 +23,16 @@ "suggest": "", "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", "severity": "ERROR" + }, + { + "line": 25, + "column": 16, + "endLine": 25, + "endColumn": 22, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json b/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json index 8bdc1c6d5d..eaf2af73c9 100644 --- a/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json +++ b/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json @@ -124,6 +124,36 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 37, + "column": 1, + "endLine": 37, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 1, + "endLine": 38, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 1, + "endLine": 39, + "endColumn": 7, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 41, "column": 7, @@ -494,6 +524,166 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 70, + "column": 1, + "endLine": 70, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 1, + "endLine": 71, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 1, + "endLine": 72, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 73, + "column": 1, + "endLine": 73, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 1, + "endLine": 74, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 75, + "column": 1, + "endLine": 75, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 1, + "endLine": 76, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 1, + "endLine": 77, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 78, + "column": 1, + "endLine": 78, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 1, + "endLine": 79, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 1, + "endLine": 80, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 81, + "column": 1, + "endLine": 81, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 1, + "endLine": 82, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 83, + "column": 1, + "endLine": 83, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 84, + "column": 1, + "endLine": 84, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 85, + "column": 1, + "endLine": 85, + "endColumn": 11, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 105, "column": 31, @@ -674,6 +864,16 @@ "rule": "Indexed access is not supported for fields (arkts-no-props-by-index)", "severity": "ERROR" }, + { + "line": 176, + "column": 1, + "endLine": 176, + "endColumn": 10, + "problem": "LimitedStdLibNoSendableDecorator", + "suggest": "", + "rule": "Usage of standard library is restricted(arkts-limited-stdlib-no-sendable-decorator)", + "severity": "ERROR" + }, { "line": 177, "column": 23, diff --git a/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json b/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json index 071dffbe54..f7b6b0c4e8 100644 --- a/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json +++ b/ets2panda/linter/test/main/stdlib_array.ets.arkts2.json @@ -224,6 +224,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 49, + "column": 12, + "endLine": 49, + "endColumn": 16, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 19, + "endLine": 49, + "endColumn": 23, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 53, "column": 10, diff --git a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json index 1a9ca3c7cf..d621318a9c 100644 --- a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json +++ b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json @@ -64,6 +64,16 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 54, + "column": 3, + "endLine": 54, + "endColumn": 10, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 57, "column": 13, @@ -984,6 +994,26 @@ "rule": "Structural typing is not supported (arkts-no-structural-typing)", "severity": "ERROR" }, + { + "line": 480, + "column": 1, + "endLine": 480, + "endColumn": 10, + "problem": "LimitedStdLibNoSendableDecorator", + "suggest": "", + "rule": "Usage of standard library is restricted(arkts-limited-stdlib-no-sendable-decorator)", + "severity": "ERROR" + }, + { + "line": 485, + "column": 1, + "endLine": 485, + "endColumn": 10, + "problem": "LimitedStdLibNoSendableDecorator", + "suggest": "", + "rule": "Usage of standard library is restricted(arkts-limited-stdlib-no-sendable-decorator)", + "severity": "ERROR" + }, { "line": 502, "column": 7, diff --git a/ets2panda/linter/test/main/ts_overload.ets.arkts2.json b/ets2panda/linter/test/main/ts_overload.ets.arkts2.json index 013ef916fe..3f46c402c2 100644 --- a/ets2panda/linter/test/main/ts_overload.ets.arkts2.json +++ b/ets2panda/linter/test/main/ts_overload.ets.arkts2.json @@ -13,7 +13,7 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ + "result": [ { "line": 16, "column": 1, @@ -44,6 +44,26 @@ "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", "severity": "ERROR" }, + { + "line": 20, + "column": 16, + "endLine": 20, + "endColumn": 20, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 16, + "endLine": 22, + "endColumn": 20, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + }, { "line": 25, "column": 21, diff --git a/ets2panda/linter/test/rules/rule37.ets.migrate.json b/ets2panda/linter/test/rules/rule37.ets.migrate.json index ca88f857e9..0a1c7ec097 100644 --- a/ets2panda/linter/test/rules/rule37.ets.migrate.json +++ b/ets2panda/linter/test/rules/rule37.ets.migrate.json @@ -13,5 +13,16 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 59, + "column": 21, + "endLine": 59, + "endColumn": 27, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/sdkwhite/quoted_hyphen_props_deprecated_sdk2.ets.arkts2.json b/ets2panda/linter/test/sdkwhite/quoted_hyphen_props_deprecated_sdk2.ets.arkts2.json index f2d125c578..84106d351a 100755 --- a/ets2panda/linter/test/sdkwhite/quoted_hyphen_props_deprecated_sdk2.ets.arkts2.json +++ b/ets2panda/linter/test/sdkwhite/quoted_hyphen_props_deprecated_sdk2.ets.arkts2.json @@ -14,6 +14,26 @@ "limitations under the License." ], "result": [ + { + "line": 42, + "column": 10, + "endLine": 42, + "endColumn": 20, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 20, + "endLine": 48, + "endColumn": 30, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, { "line": 65, "column": 5, -- Gitee From 98d2909aff1926ddd91a1a2da27ad1bba8044a90 Mon Sep 17 00:00:00 2001 From: leo9001 Date: Thu, 29 May 2025 10:33:52 +0800 Subject: [PATCH 013/747] Add more tests and Fix bug Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC8GDW Signed-off-by: leo9001 --- ets2panda/lsp/src/completions_details.cpp | 3 + ets2panda/lsp/src/quick_info.cpp | 29 +- .../lsp/get_completions_entry_details.cpp | 299 ++++++++++++++++++ 3 files changed, 328 insertions(+), 3 deletions(-) diff --git a/ets2panda/lsp/src/completions_details.cpp b/ets2panda/lsp/src/completions_details.cpp index 54b46cc224..f82c5f40a4 100644 --- a/ets2panda/lsp/src/completions_details.cpp +++ b/ets2panda/lsp/src/completions_details.cpp @@ -109,6 +109,9 @@ CompletionEntryDetails GetCompletionEntryDetailsImpl(es2panda_Context *context, auto ast = ctx->parserProgram->Ast(); auto leIdentifier = ast->FindChild([entryName](ir::AstNode *node) { return HasPropertyAccessExpressionWithName(node, entryName); }); + if (leIdentifier == nullptr || !leIdentifier->IsIdentifier()) { + return CompletionEntryDetails(); + } auto targetNode = compiler::DeclarationFromIdentifier(leIdentifier->AsIdentifier()); if (targetNode == nullptr) { return CompletionEntryDetails(); diff --git a/ets2panda/lsp/src/quick_info.cpp b/ets2panda/lsp/src/quick_info.cpp index 4ddcbee32d..5caeada8ba 100644 --- a/ets2panda/lsp/src/quick_info.cpp +++ b/ets2panda/lsp/src/quick_info.cpp @@ -681,6 +681,10 @@ std::vector CreateDisplayOfReturnType(ark::es2panda::ir::Type std::vector displayParts; displayParts.emplace_back(CreatePunctuation(":")); displayParts.emplace_back(CreateSpace()); + if (returnType == nullptr) { + displayParts.emplace_back(CreateReturnType("void")); + return displayParts; + } if (returnType->Type() == ir::AstNodeType::ETS_TYPE_REFERENCE) { auto part = returnType->AsETSTypeReference()->Part()->AsETSTypeReferencePart(); auto typeName = part->Name()->AsIdentifier()->Name(); @@ -947,9 +951,17 @@ std::vector CreateDisplayForMethodDefinition(ir::AstNode *nod if (node->Parent() != nullptr && node->Parent()->Type() == ir::AstNodeType::TS_INTERFACE_BODY) { return CreateDisplayForMethodDefinitionOfInterfaceBody(node); } + if (node->Parent() != nullptr && node->Parent()->IsClassDefinition()) { + auto className = node->Parent()->AsClassDefinition()->Ident()->Name(); + if (className != "ETSGLOBAL") { + displayParts.emplace_back(CreateClassName(std::string(className))); + displayParts.emplace_back(CreatePunctuation(".")); + } else { + displayParts.emplace_back(CreateKeyword("function")); + displayParts.emplace_back(CreateSpace()); + } + } - displayParts.emplace_back(CreateKeyword("function")); - displayParts.emplace_back(CreateSpace()); auto functionName = node->AsMethodDefinition()->Key()->AsIdentifier()->Name(); displayParts.emplace_back(CreateFunctionName(std::string(functionName))); @@ -979,6 +991,12 @@ std::vector CreateDisplayForMethodDefinition(ir::AstNode *nod return displayParts; } +bool IsKindModifierInSet(const std::string &target) +{ + static std::set kindModifierSet = {"const", "static public declare const"}; + return kindModifierSet.find(target) != kindModifierSet.end(); +} + std::vector CreateDisplayForClassProperty(ir::AstNode *node, const std::string &kindModifier) { std::vector displayParts; @@ -991,7 +1009,7 @@ std::vector CreateDisplayForClassProperty(ir::AstNode *node, if (className != "ETSGLOBAL") { displayParts.emplace_back(CreateClassName(std::string(className))); displayParts.emplace_back(CreatePunctuation(".")); - } else if (kindModifier == "const") { + } else if (IsKindModifierInSet(kindModifier)) { displayParts.emplace_back(CreateKeyword("const")); displayParts.emplace_back(CreateSpace()); } else { @@ -1006,6 +1024,11 @@ std::vector CreateDisplayForClassProperty(ir::AstNode *node, auto typeAnnotation = node->AsClassProperty()->TypeAnnotation(); std::string type; if (typeAnnotation == nullptr) { + if (node->AsClassProperty()->Value() == nullptr || + !node->AsClassProperty()->Value()->IsETSNewClassInstanceExpression()) { + displayParts.emplace_back(CreateTypeName("undefined")); + return displayParts; + } auto newClassExpr = node->AsClassProperty()->Value()->AsETSNewClassInstanceExpression(); if (newClassExpr != nullptr) { type = std::string(newClassExpr->GetTypeRef()->AsETSTypeReference()->Part()->GetIdent()->Name()); diff --git a/ets2panda/test/unit/lsp/get_completions_entry_details.cpp b/ets2panda/test/unit/lsp/get_completions_entry_details.cpp index d55b0df0f4..1bb64d6bba 100644 --- a/ets2panda/test/unit/lsp/get_completions_entry_details.cpp +++ b/ets2panda/test/unit/lsp/get_completions_entry_details.cpp @@ -18,6 +18,9 @@ #include "lsp/include/internal_api.h" #include "lsp/include/api.h" #include "lsp/include/completions_details.h" +#include "lsp/include/quick_info.h" +#include "lsp/include/suggestion_diagnostics.h" +#include "compiler/lowering/util.h" namespace { @@ -119,4 +122,300 @@ TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails2) initializer.DestroyContext(ctx); } +TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails3) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext("completion_entry_details9.ets", ES2PANDA_STATE_CHECKED, + R"(function name (params: string) { + new CC().getName() +} + +class CC { + getName() { + } +})"); + size_t const offset = 79; + LSPAPI const *lspApi = GetImpl(); + const char *entryName = "getName"; + auto completionEntryDetails = + lspApi->getCompletionEntryDetails(entryName, "completion_entry_details9.ets", ctx, offset); + ASSERT_NE(completionEntryDetails, CompletionEntryDetails()); + std::vector source {}; + std::vector sourceDisplay {}; + std::vector document {}; + const std::string kind = "function"; + const std::string kindModifiers = "public"; + const std::string expectedFileName = "completion_entry_details9.ets"; + + std::vector expected; + expected.emplace_back("CC", "className"); + expected.emplace_back(".", "punctuation"); + expected.emplace_back("getName", "functionName"); + expected.emplace_back("(", "punctuation"); + expected.emplace_back(")", "punctuation"); + expected.emplace_back(":", "punctuation"); + expected.emplace_back(" ", "space"); + expected.emplace_back("void", "returnType"); + + auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document, + source, sourceDisplay, expectedFileName); + initializer.DestroyContext(ctx); + ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails); +} + +TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails4) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext("completion_entry_details10.ets", ES2PANDA_STATE_CHECKED, + R"(interface DuttonInterface { + ff(): number; +} + +declare const Dutton: DuttonInterface;)"); + size_t const offset = 66; + LSPAPI const *lspApi = GetImpl(); + const char *entryName = "Dutton"; + auto completionEntryDetails = + lspApi->getCompletionEntryDetails(entryName, "completion_entry_details10.ets", ctx, offset); + ASSERT_NE(completionEntryDetails, CompletionEntryDetails()); + std::vector source {}; + std::vector sourceDisplay {}; + std::vector document {}; + const std::string kind = "property"; + const std::string kindModifiers = "static public declare const"; + const std::string expectedFileName = "completion_entry_details10.ets"; + + std::vector expected; + expected.emplace_back("const", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("Dutton", "property"); + expected.emplace_back(":", "punctuation"); + expected.emplace_back(" ", "space"); + expected.emplace_back("DuttonInterface", "typeName"); + + auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document, + source, sourceDisplay, expectedFileName); + initializer.DestroyContext(ctx); + ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails); +} + +TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails5) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext("completion_entry_details11.ets", ES2PANDA_STATE_CHECKED, + R"(class DuttonInterface { + ff : number; + constructor(ff:number) { + this.ff = ff; + } + static buttonRun(value: string | number | boolean):number{ + return 1; + } +} + + function aa() { + let Dutton: DuttonInterface = new DuttonInterface(1); + let a = DuttonInterface.buttonRun(1) +})"); + size_t const offset = 280; + LSPAPI const *lspApi = GetImpl(); + const char *entryName = "buttonRun"; + auto completionEntryDetails = + lspApi->getCompletionEntryDetails(entryName, "completion_entry_details11.ets", ctx, offset); + ASSERT_NE(completionEntryDetails, CompletionEntryDetails()); + std::vector source {}; + std::vector sourceDisplay {}; + std::vector document {}; + const std::string kind = "function"; + const std::string kindModifiers = "static public"; + const std::string expectedFileName = "completion_entry_details11.ets"; + + std::vector expected; + expected.emplace_back("DuttonInterface", "className"); + expected.emplace_back(".", "punctuation"); + expected.emplace_back("buttonRun", "functionName"); + expected.emplace_back("(", "punctuation"); + expected.emplace_back("value", "functionParameter"); + expected.emplace_back(":", "punctuation"); + expected.emplace_back(" ", "space"); + expected.emplace_back("string|number|boolean", "typeParameter"); + expected.emplace_back(")", "punctuation"); + expected.emplace_back(":", "punctuation"); + expected.emplace_back(" ", "space"); + expected.emplace_back("number", "returnType"); + + auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document, + source, sourceDisplay, expectedFileName); + initializer.DestroyContext(ctx); + ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForClass) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("completion_entry_details3.ets", ES2PANDA_STATE_CHECKED, + "class Test {\n private _a: number = 1;\n public get a(): number {\n " + "return this._a;\n }\n public static ccc:number = 1\n\n constructor(a : " + "number) {\n }\n}\n\nlet a = 1\nlet test: Test = new Test(a)\nlet t_a = test.a"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "Test"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForClass(targetNode); + std::vector expected; + auto keyword1 = SymbolDisplayPart("class", "keyword"); + auto keyword2 = SymbolDisplayPart(" ", "space"); + auto keyword3 = SymbolDisplayPart("Test", "className"); + expected.push_back(keyword1); + expected.push_back(keyword2); + expected.push_back(keyword3); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForClassDeclarationTypeParameter) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext("completion_entry_details4.ets", ES2PANDA_STATE_CHECKED, + "class Queue { private items: T[] = []; }"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "T"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForTypeParameter(targetNode); + std::vector expected; + expected.emplace_back("T", "typeParameter"); + expected.emplace_back(" ", "space"); + expected.emplace_back("in", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("Queue", "className"); + expected.emplace_back("<", "punctuation"); + expected.emplace_back("T", "typeParameter"); + expected.emplace_back(">", "punctuation"); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForUnionTypeAlias) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext("completion_entry_details5.ets", ES2PANDA_STATE_CHECKED, + "type TestUnion = string | number;"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "TestUnion"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForTypeAlias(targetNode); + std::vector expected; + expected.emplace_back("type", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("TestUnion", "className"); + expected.emplace_back(" ", "space"); + expected.emplace_back("=", "operator"); + expected.emplace_back(" ", "space"); + expected.emplace_back("string|number", "typeName"); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForTypeAlias) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("completion_entry_details6.ets", ES2PANDA_STATE_CHECKED, "type TestType = string;"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "TestType"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForTypeAlias(targetNode); + std::vector expected; + expected.emplace_back("type", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("TestType", "className"); + expected.emplace_back(" ", "space"); + expected.emplace_back("=", "operator"); + expected.emplace_back(" ", "space"); + expected.emplace_back("string", "typeName"); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForInterface) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = initializer.CreateContext( + "completion_entry_details7.ets", ES2PANDA_STATE_CHECKED, + "interface Inner { key : string; }\ninterface Outer { inner : Inner; keyValue : number; }"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "Inner"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForInterface(targetNode); + std::vector expected; + auto keyword1 = SymbolDisplayPart("interface", "keyword"); + auto keyword2 = SymbolDisplayPart(" ", "space"); + auto keyword3 = SymbolDisplayPart("Inner", "className"); + expected.push_back(keyword1); + expected.push_back(keyword2); + expected.push_back(keyword3); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForTypeAliasTypeParameter) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("completion_entry_details8.ets", ES2PANDA_STATE_CHECKED, "type list = T[]"); + ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + const char *entryName = "T"; + auto context = reinterpret_cast(ctx); + auto ast = reinterpret_cast(context->parserProgram->Ast()); + auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) { + return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName); + }; + auto found = ast->FindChild(checkFunc); + auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier()); + std::vector display = ark::es2panda::lsp::CreateDisplayForTypeParameter(targetNode); + std::vector expected; + expected.emplace_back("T", "typeParameter"); + expected.emplace_back(" ", "space"); + expected.emplace_back("in", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("type", "keyword"); + expected.emplace_back(" ", "space"); + expected.emplace_back("list", "typeName"); + expected.emplace_back("<", "punctuation"); + expected.emplace_back("T", "typeParameter"); + expected.emplace_back(">", "punctuation"); + ASSERT_EQ(expected, display); + initializer.DestroyContext(ctx); +} + } // namespace \ No newline at end of file -- Gitee From 742fb6bc0857ef61e075e40a93fce36fcaebbe54 Mon Sep 17 00:00:00 2001 From: ekkoruse Date: Wed, 7 May 2025 21:40:45 +0800 Subject: [PATCH 014/747] ast-cache Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC6FKB?from=project-issue Change-Id: Ib2c4c9a9f9a061f42a01d5ffad1b5fe1ed5b73c5 Signed-off-by: ekkoruse --- ets2panda/BUILD.gn | 1 + ets2panda/CMakeLists.txt | 1 + ets2panda/checker/ASchecker.cpp | 4 +- ets2panda/checker/ASchecker.h | 5 +- ets2panda/checker/ETSAnalyzer.cpp | 10 +- ets2panda/checker/ETSAnalyzerHelpers.cpp | 4 +- ets2panda/checker/ETSchecker.cpp | 108 ++-- ets2panda/checker/ETSchecker.h | 50 +- ets2panda/checker/JSchecker.cpp | 1 - ets2panda/checker/JSchecker.h | 6 +- ets2panda/checker/TSchecker.cpp | 1 - ets2panda/checker/TSchecker.h | 5 +- ets2panda/checker/checker.cpp | 11 +- ets2panda/checker/checker.h | 28 +- ets2panda/checker/ets/dynamic.cpp | 6 +- ets2panda/checker/ets/function.cpp | 42 +- ets2panda/checker/ets/helpers.cpp | 8 +- ets2panda/checker/ets/object.cpp | 30 +- ets2panda/checker/ets/typeCreation.cpp | 11 +- ets2panda/checker/ets/typeRelationContext.cpp | 2 +- ets2panda/checker/ets/utilityTypeHandlers.cpp | 21 +- .../types/ets/etsAsyncFuncReturnType.h | 2 +- ets2panda/checker/types/ets/etsBigIntType.h | 4 +- ets2panda/checker/types/ets/etsDynamicType.h | 3 +- ets2panda/checker/types/ets/etsEnumType.h | 8 +- .../checker/types/ets/etsFunctionType.cpp | 24 +- ets2panda/checker/types/ets/etsFunctionType.h | 2 - ets2panda/checker/types/ets/etsObjectType.cpp | 185 +++++- ets2panda/checker/types/ets/etsObjectType.h | 42 +- .../checker/types/ets/etsResizableArrayType.h | 6 +- ets2panda/checker/types/ets/etsStringType.h | 6 +- ets2panda/checker/types/type.cpp | 2 + ets2panda/checker/types/type.h | 3 + ets2panda/checker/types/typeRelation.h | 14 +- ets2panda/compiler/core/ETSGen.cpp | 2 +- ets2panda/compiler/core/ETSemitter.cpp | 18 +- ets2panda/compiler/core/compilerImpl.cpp | 37 +- ets2panda/compiler/core/pandagen.cpp | 2 +- ets2panda/compiler/lowering/checkerPhase.cpp | 25 +- ets2panda/compiler/lowering/checkerPhase.h | 5 +- .../compiler/lowering/ets/ambientLowering.cpp | 17 +- .../lowering/ets/arrayLiteralLowering.cpp | 2 +- .../lowering/ets/asyncMethodLowering.cpp | 6 +- .../compiler/lowering/ets/bigintLowering.cpp | 6 +- .../lowering/ets/boxedTypeLowering.cpp | 16 +- .../compiler/lowering/ets/boxedTypeLowering.h | 7 +- .../compiler/lowering/ets/boxingForLocals.cpp | 14 +- .../compiler/lowering/ets/cfgBuilderPhase.cpp | 4 +- .../ets/convertPrimitiveCastMethodCall.cpp | 2 +- .../lowering/ets/declareOverloadLowering.cpp | 8 +- ...defaultParametersInConstructorLowering.cpp | 12 +- .../ets/defaultParametersLowering.cpp | 5 +- .../lowering/ets/dynamicImportLowering.cpp | 2 +- .../compiler/lowering/ets/enumLowering.cpp | 18 +- .../lowering/ets/enumPostCheckLowering.cpp | 4 +- .../compiler/lowering/ets/expandBrackets.cpp | 6 +- .../lowering/ets/exportAnonymousConst.cpp | 28 +- .../lowering/ets/exportAnonymousConst.h | 4 +- .../ets/extensionAccessorLowering.cpp | 2 +- .../lowering/ets/genericBridgesLowering.cpp | 10 +- .../insertOptionalParametersAnnotation.cpp | 2 +- .../ets/interfaceObjectLiteralLowering.cpp | 18 +- .../compiler/lowering/ets/lambdaLowering.cpp | 84 +-- .../lowering/ets/lateInitialization.cpp | 6 +- .../lowering/ets/localClassLowering.cpp | 12 +- .../lowering/ets/objectIndexAccess.cpp | 2 +- .../compiler/lowering/ets/objectIterator.cpp | 6 +- .../lowering/ets/objectLiteralLowering.cpp | 6 +- .../compiler/lowering/ets/opAssignment.cpp | 8 +- .../ets/optionalArgumentsLowering.cpp | 3 +- .../lowering/ets/packageImplicitImport.cpp | 2 +- .../lowering/ets/partialExportClassGen.cpp | 16 +- .../lowering/ets/partialExportClassGen.h | 4 +- .../compiler/lowering/ets/recordLowering.cpp | 12 +- .../lowering/ets/resizableArrayLowering.cpp | 2 +- .../lowering/ets/restArgsLowering.cpp | 13 +- .../lowering/ets/restTupleLowering.cpp | 2 +- .../compiler/lowering/ets/setJumpTarget.cpp | 12 +- .../compiler/lowering/ets/setJumpTarget.h | 5 +- .../compiler/lowering/ets/spreadLowering.cpp | 9 +- .../lowering/ets/stringComparison.cpp | 6 +- .../lowering/ets/stringConstantsLowering.cpp | 14 +- .../lowering/ets/stringConstantsLowering.h | 7 +- .../ets/stringConstructorLowering.cpp | 2 +- .../ets/topLevelStmts/globalClassHandler.cpp | 38 +- .../ets/topLevelStmts/globalClassHandler.h | 4 +- .../topLevelStmts/globalDeclTransformer.cpp | 2 +- .../ets/topLevelStmts/importExportDecls.cpp | 8 +- .../ets/topLevelStmts/topLevelStmts.cpp | 6 +- .../lowering/ets/typeFromLowering.cpp | 2 +- .../compiler/lowering/ets/unionLowering.cpp | 20 +- ets2panda/compiler/lowering/phase.cpp | 282 +++++----- ets2panda/compiler/lowering/phase.h | 90 ++- ets2panda/compiler/lowering/phase_id.h | 56 ++ ets2panda/compiler/lowering/plugin_phase.cpp | 4 +- .../compiler/lowering/resolveIdentifiers.cpp | 37 +- .../compiler/lowering/resolveIdentifiers.h | 6 +- .../lowering/scopesInit/savedBindingsCtx.cpp | 4 +- .../lowering/scopesInit/scopesInitPhase.cpp | 9 +- ets2panda/compiler/lowering/util.cpp | 59 +- ets2panda/declgen_ets2ts/main.cpp | 2 +- .../build_system/src/build/base_mode.ts | 525 +++++++++++++++++- .../build_system/src/build/build_mode.ts | 2 +- .../src/build/compile_thread_worker.ts | 170 ++++++ ets2panda/driver/build_system/src/entry.ts | 3 +- .../build_system/src/plugins/FileManager.ts | 11 +- .../src/plugins/plugins_driver.ts | 25 +- ets2panda/driver/build_system/src/types.ts | 19 +- .../build_system/test/demo_hap/entry/a.ets | 15 + .../build_system/test/demo_hap/entry/c.ets | 4 +- .../build_system/test/demo_hap/entry/d.ets | 7 +- .../dependency_analyzer/dep_analyzer.cpp | 10 +- ets2panda/es2panda.cpp | 8 +- ets2panda/es2panda.h | 2 +- .../debugInfoDeserialization/classBuilder.cpp | 2 +- ets2panda/evaluate/scopedDebugInfoPlugin.cpp | 4 +- ets2panda/ir/annotationAllowed.h | 73 ++- ets2panda/ir/as/namedType.cpp | 7 +- ets2panda/ir/astNode.cpp | 138 ++++- ets2panda/ir/astNode.h | 180 +++--- ets2panda/ir/astNodeFlags.h | 2 + ets2panda/ir/astNodeHistory.cpp | 21 +- ets2panda/ir/astNodeHistory.h | 24 +- ets2panda/ir/base/classDefinition.cpp | 290 +++++++--- ets2panda/ir/base/classDefinition.h | 231 ++++---- ets2panda/ir/base/classElement.cpp | 57 +- ets2panda/ir/base/classElement.h | 58 +- ets2panda/ir/base/classProperty.cpp | 104 ++-- ets2panda/ir/base/classProperty.h | 14 +- ets2panda/ir/base/classStaticBlock.cpp | 16 +- ets2panda/ir/base/classStaticBlock.h | 13 +- ets2panda/ir/base/methodDefinition.cpp | 159 ++++-- ets2panda/ir/base/methodDefinition.h | 103 ++-- ets2panda/ir/base/scriptFunction.cpp | 176 ++++-- ets2panda/ir/base/scriptFunction.h | 151 +++-- ets2panda/ir/base/scriptFunctionSignature.h | 2 + ets2panda/ir/base/spreadElement.cpp | 2 +- ets2panda/ir/base/spreadElement.h | 5 - ets2panda/ir/ets/etsFunctionType.cpp | 49 +- ets2panda/ir/ets/etsFunctionType.h | 40 +- ets2panda/ir/ets/etsImportDeclaration.h | 47 +- ets2panda/ir/ets/etsModule.cpp | 3 +- ets2panda/ir/ets/etsModule.h | 70 ++- ets2panda/ir/ets/etsNeverType.cpp | 7 +- ets2panda/ir/ets/etsNullishTypes.cpp | 14 +- ets2panda/ir/ets/etsParameterExpression.cpp | 149 +++-- ets2panda/ir/ets/etsParameterExpression.h | 43 +- ets2panda/ir/ets/etsPrimitiveType.cpp | 11 +- ets2panda/ir/ets/etsPrimitiveType.h | 19 +- ets2panda/ir/ets/etsReExportDeclaration.cpp | 28 +- ets2panda/ir/ets/etsReExportDeclaration.h | 11 +- ets2panda/ir/ets/etsStringLiteralType.cpp | 7 +- ets2panda/ir/ets/etsStructDeclaration.h | 21 + ets2panda/ir/ets/etsTuple.cpp | 7 +- ets2panda/ir/ets/etsTypeReference.cpp | 38 +- ets2panda/ir/ets/etsTypeReference.h | 17 +- ets2panda/ir/ets/etsTypeReferencePart.cpp | 128 +++-- ets2panda/ir/ets/etsTypeReferencePart.h | 43 +- ets2panda/ir/ets/etsUnionType.cpp | 33 +- ets2panda/ir/ets/etsUnionType.h | 24 +- ets2panda/ir/ets/etsWildcardType.cpp | 8 +- ets2panda/ir/expression.h | 24 +- ets2panda/ir/expressions/arrayExpression.h | 5 - .../expressions/arrowFunctionExpression.cpp | 7 +- ets2panda/ir/expressions/callExpression.h | 18 + ets2panda/ir/expressions/identifier.cpp | 32 +- ets2panda/ir/expressions/identifier.h | 90 ++- ets2panda/ir/expressions/objectExpression.h | 5 - ets2panda/ir/module/importDeclaration.cpp | 69 ++- ets2panda/ir/module/importDeclaration.h | 35 +- ets2panda/ir/opaqueTypeNode.cpp | 7 +- .../ir/statements/annotationDeclaration.cpp | 97 +++- .../ir/statements/annotationDeclaration.h | 56 +- ets2panda/ir/statements/blockStatement.cpp | 32 +- ets2panda/ir/statements/blockStatement.h | 76 ++- ets2panda/ir/statements/classDeclaration.cpp | 65 ++- ets2panda/ir/statements/classDeclaration.h | 34 +- .../ir/statements/functionDeclaration.cpp | 77 ++- ets2panda/ir/statements/functionDeclaration.h | 44 +- .../ir/statements/variableDeclaration.cpp | 142 ++++- ets2panda/ir/statements/variableDeclaration.h | 49 +- ets2panda/ir/ts/tsAnyKeyword.cpp | 7 +- ets2panda/ir/ts/tsArrayType.cpp | 8 +- ets2panda/ir/ts/tsBigintKeyword.cpp | 7 +- ets2panda/ir/ts/tsBooleanKeyword.cpp | 7 +- ets2panda/ir/ts/tsConditionalType.cpp | 8 +- ets2panda/ir/ts/tsConstructorType.cpp | 7 +- ets2panda/ir/ts/tsEnumDeclaration.cpp | 117 +++- ets2panda/ir/ts/tsEnumDeclaration.h | 74 ++- ets2panda/ir/ts/tsFunctionType.cpp | 7 +- ets2panda/ir/ts/tsImportType.cpp | 8 +- ets2panda/ir/ts/tsIndexedAccessType.cpp | 8 +- ets2panda/ir/ts/tsInferType.cpp | 8 +- ets2panda/ir/ts/tsInterfaceDeclaration.cpp | 182 ++++-- ets2panda/ir/ts/tsInterfaceDeclaration.h | 97 ++-- ets2panda/ir/ts/tsIntersectionType.cpp | 8 +- ets2panda/ir/ts/tsLiteralType.cpp | 8 +- ets2panda/ir/ts/tsMappedType.cpp | 8 +- ets2panda/ir/ts/tsNamedTupleMember.cpp | 8 +- ets2panda/ir/ts/tsNeverKeyword.cpp | 7 +- ets2panda/ir/ts/tsNullKeyword.cpp | 7 +- ets2panda/ir/ts/tsNumberKeyword.cpp | 7 +- ets2panda/ir/ts/tsObjectKeyword.cpp | 7 +- ets2panda/ir/ts/tsParenthesizedType.cpp | 8 +- ets2panda/ir/ts/tsStringKeyword.cpp | 7 +- ets2panda/ir/ts/tsThisType.cpp | 7 +- ets2panda/ir/ts/tsTupleType.cpp | 8 +- ets2panda/ir/ts/tsTypeAliasDeclaration.cpp | 148 ++++- ets2panda/ir/ts/tsTypeAliasDeclaration.h | 59 +- ets2panda/ir/ts/tsTypeLiteral.cpp | 8 +- ets2panda/ir/ts/tsTypeOperator.cpp | 8 +- ets2panda/ir/ts/tsTypeParameter.cpp | 80 ++- ets2panda/ir/ts/tsTypeParameter.h | 54 +- .../ir/ts/tsTypeParameterDeclaration.cpp | 28 +- ets2panda/ir/ts/tsTypeParameterDeclaration.h | 45 +- ets2panda/ir/ts/tsTypePredicate.cpp | 8 +- ets2panda/ir/ts/tsTypeQuery.cpp | 8 +- ets2panda/ir/ts/tsTypeReference.cpp | 8 +- ets2panda/ir/ts/tsUndefinedKeyword.cpp | 7 +- ets2panda/ir/ts/tsUnionType.cpp | 8 +- ets2panda/ir/ts/tsUnknownKeyword.cpp | 7 +- ets2panda/ir/ts/tsVoidKeyword.cpp | 7 +- ets2panda/ir/typed.h | 10 +- ets2panda/lexer/token/sourceLocation.h | 10 + ets2panda/lsp/src/rename.cpp | 2 +- ets2panda/parser/ETSFormattedParser.cpp | 4 +- ets2panda/parser/ETSparser.cpp | 44 +- ets2panda/parser/ETSparser.h | 4 +- ets2panda/parser/ETSparserClasses.cpp | 1 - ets2panda/parser/ETSparserNamespaces.cpp | 2 +- ets2panda/parser/ETSparserTypes.cpp | 2 +- ets2panda/parser/parserImpl.h | 15 + ets2panda/parser/program/program.cpp | 81 ++- ets2panda/parser/program/program.h | 59 +- ets2panda/public/cppToCTypes.yaml | 4 +- ets2panda/public/es2panda_lib.cpp | 292 ++++++++-- ets2panda/public/es2panda_lib.h | 13 + ets2panda/public/public.cpp | 31 ++ ets2panda/public/public.h | 60 +- .../annotation_for_array_type01.ets | 4 +- .../ast/parser/ets/re_export/re_export_4.ets | 4 +- .../parser/ets/getterOverride-expected.txt | 6 +- .../ets/re_export/import_10-expected.txt | 2 +- .../ets/re_export/re_export_4-expected.txt | 2 +- .../ets/class_implements_interface_export.ets | 25 + .../ets/class_implements_interface_import.ets | 16 + .../astchecker/astchecker-ets-ignored.txt | 4 + .../srcdumper/srcdumper-ets-ignored.txt | 2 + .../test/unit/lowerings/node_history.cpp | 117 ++-- .../unit/lowerings/scopes_initialization.cpp | 7 +- .../get_type_of_symbol_at_location_test.cpp | 4 +- .../test/unit/lsp/isolated_declaration.cpp | 10 +- ets2panda/test/unit/lsp/lsp_rename_test.cpp | 2 +- .../unit/plugin/plugin_proceed_to_state.cpp | 2 + .../plugin_proceed_to_state_create_import.cpp | 2 +- ...oceed_to_state_find_import_declaration.cpp | 2 +- .../plugin_conversion_rule_part_i.cpp | 2 +- .../plugin_conversion_rule_part_ii.cpp | 2 +- .../plugin_conversion_rule_part_iv.cpp | 7 +- .../ast_verifier_check_abstract_call_test.cpp | 2 +- ...t_verifier_check_const_properties_test.cpp | 2 +- ...verifier_check_struct_declaration_test.cpp | 2 +- .../ast_verifier_getter_setter_neg_test.cpp | 16 +- .../ast_verifier_getter_setter_test.cpp | 6 +- .../unit/public/ast_verifier_short_test.cpp | 12 +- ets2panda/test/unit/sizeof_node_test.cpp | 4 +- .../test/unit/union_normalisation_test.h | 23 +- ets2panda/test/utils/ast_verifier_test.cpp | 8 +- ets2panda/test/utils/ast_verifier_test.h | 8 +- ets2panda/test/utils/checker_test.h | 22 +- ets2panda/test/utils/scope_init_test.h | 15 +- ets2panda/util/diagnosticEngine.cpp | 8 +- ets2panda/util/diagnosticEngine.h | 10 +- ets2panda/util/enumbitops.h | 18 +- ets2panda/util/es2pandaMacros.h | 1 + ets2panda/util/importPathManager.h | 8 +- ets2panda/varbinder/ETSBinder.cpp | 47 +- ets2panda/varbinder/ETSBinder.h | 32 +- ets2panda/varbinder/recordTable.h | 33 +- ets2panda/varbinder/varbinder.cpp | 13 + ets2panda/varbinder/varbinder.h | 9 + ets2panda/varbinder/variable.h | 2 +- 282 files changed, 5994 insertions(+), 2495 deletions(-) create mode 100644 ets2panda/compiler/lowering/phase_id.h create mode 100644 ets2panda/driver/build_system/src/build/compile_thread_worker.ts create mode 100644 ets2panda/public/public.cpp create mode 100644 ets2panda/test/runtime/ets/class_implements_interface_export.ets create mode 100644 ets2panda/test/runtime/ets/class_implements_interface_import.ets diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index dec0dc9a48..2ef3ae274a 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -478,6 +478,7 @@ libes2panda_sources = [ "parser/program/program.cpp", "parser/statementParser.cpp", "parser/statementTSParser.cpp", + "public/public.cpp", "util/arktsconfig.cpp", "util/bitset.cpp", "util/diagnostic.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 10cf792e94..0857184f54 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -526,6 +526,7 @@ set(ES2PANDA_LIB_SRC parser/program/program.cpp parser/statementParser.cpp parser/statementTSParser.cpp + public/public.cpp checker/checker.cpp checker/checkerContext.cpp checker/ETSAnalyzer.cpp diff --git a/ets2panda/checker/ASchecker.cpp b/ets2panda/checker/ASchecker.cpp index 3a3cb8e691..ee3cd234f8 100644 --- a/ets2panda/checker/ASchecker.cpp +++ b/ets2panda/checker/ASchecker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,8 +21,6 @@ namespace ark::es2panda::checker { bool ASChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const util::Options &options) { - Initialize(varbinder); - if (options.IsDumpAst()) { std::cout << Program()->Dump() << std::endl; } diff --git a/ets2panda/checker/ASchecker.h b/ets2panda/checker/ASchecker.h index 69a80488ab..84ba809e5b 100644 --- a/ets2panda/checker/ASchecker.h +++ b/ets2panda/checker/ASchecker.h @@ -23,8 +23,9 @@ namespace ark::es2panda::checker { class ASChecker : public Checker { public: // NOLINTNEXTLINE(readability-redundant-member-init) - explicit ASChecker(util::DiagnosticEngine &diagnosticEngine, [[maybe_unused]] ArenaAllocator *allocator) - : Checker(diagnosticEngine) + explicit ASChecker([[maybe_unused]] ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + [[maybe_unused]] ArenaAllocator *programAllocator) + : Checker(allocator, diagnosticEngine) { } diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 0f45d11123..cc87b76f34 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1692,7 +1692,7 @@ checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const } std::pair SearchReExportsType(ETSObjectType *baseType, ir::MemberExpression *expr, - util::StringView &aliasName, ETSChecker *checker) + util::StringView const &aliasName, ETSChecker *checker) { std::pair ret {}; @@ -2753,10 +2753,9 @@ checker::Type *ETSAnalyzer::Check(ir::BlockStatement *st) const stmt->Check(checker); // NOTE! Processing of trailing blocks was moved here so that smart casts could be applied correctly - if (auto const tb = st->trailingBlocks_.find(stmt); tb != st->trailingBlocks_.end()) { - auto *const trailingBlock = tb->second; + if (auto *const trailingBlock = st->SearchStatementInTrailingBlock(stmt); trailingBlock != nullptr) { trailingBlock->Check(checker); - st->Statements().emplace(std::next(st->Statements().begin() + idx), trailingBlock); + st->AddStatement(idx, trailingBlock); ++idx; } } @@ -3092,7 +3091,8 @@ static bool CheckIsValidReturnTypeAnnotation(ir::ReturnStatement *st, ir::Script ir::TypeNode *returnTypeAnnotation, ETSChecker *checker) { // check valid `this` type as return type - if (containingFunc->GetPreferredReturnType() != nullptr || !returnTypeAnnotation->IsTSThisType()) { + if (containingFunc->GetPreferredReturnType() != nullptr || + (returnTypeAnnotation != nullptr && !returnTypeAnnotation->IsTSThisType())) { return true; } diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index f652f68e78..ff4be3487e 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -420,7 +420,7 @@ checker::Signature *GetMostSpecificSigFromExtensionFuncAndClassMethod(checker::E methodCallSig->GetSignatureInfo()->minArgCount++; auto ¶msVar = methodCallSig->Params(); paramsVar.insert(paramsVar.begin(), dummyReceiverVar); - auto ¶ms = methodCallSig->Function()->Params(); + auto ¶ms = methodCallSig->Function()->ParamsForUpdate(); params.insert(params.begin(), dummyReceiver); if (typeParamsNeeded) { auto &typeParams = methodCallSig->TypeParams(); @@ -436,7 +436,7 @@ checker::Signature *GetMostSpecificSigFromExtensionFuncAndClassMethod(checker::E methodCallSig->GetSignatureInfo()->minArgCount--; auto ¶msVar = methodCallSig->Params(); paramsVar.erase(paramsVar.begin()); - auto ¶ms = methodCallSig->Function()->Params(); + auto ¶ms = methodCallSig->Function()->ParamsForUpdate(); params.erase(params.begin()); if (typeParamsNeeded) { auto &typeParams = methodCallSig->TypeParams(); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 452cf67b95..01e68b8bac 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -13,6 +13,10 @@ * limitations under the License. */ +#include +#include +#include + #include "ETSchecker.h" #include "es2panda.h" @@ -33,40 +37,57 @@ namespace ark::es2panda::checker { -ETSChecker::ETSChecker(util::DiagnosticEngine &diagnosticEngine) - // NOLINTNEXTLINE(readability-redundant-member-init) - : Checker(diagnosticEngine), - arrayTypes_(Allocator()->Adapter()), - pendingConstraintCheckRecords_(Allocator()->Adapter()), - globalArraySignatures_(Allocator()->Adapter()), - dynamicIntrinsics_ {DynamicCallIntrinsicsMap {Allocator()->Adapter()}, - DynamicCallIntrinsicsMap {Allocator()->Adapter()}}, - dynamicClasses_ {DynamicClassIntrinsicsMap(Allocator()->Adapter()), - DynamicClassIntrinsicsMap(Allocator()->Adapter())}, - dynamicLambdaSignatureCache_(Allocator()->Adapter()), - functionalInterfaceCache_(Allocator()->Adapter()), - apparentTypes_(Allocator()->Adapter()), - dynamicCallNames_ {{DynamicCallNamesMap(Allocator()->Adapter()), DynamicCallNamesMap(Allocator()->Adapter())}}, - overloadSigContainer_(Allocator()->Adapter()) -{ -} - -ETSChecker::ETSChecker(util::DiagnosticEngine &diagnosticEngine, ArenaAllocator *programAllocator) - // NOLINTNEXTLINE(readability-redundant-member-init) - : Checker(diagnosticEngine, programAllocator), - arrayTypes_(Allocator()->Adapter()), - pendingConstraintCheckRecords_(Allocator()->Adapter()), - globalArraySignatures_(Allocator()->Adapter()), - dynamicIntrinsics_ {DynamicCallIntrinsicsMap {Allocator()->Adapter()}, - DynamicCallIntrinsicsMap {Allocator()->Adapter()}}, - dynamicClasses_ {DynamicClassIntrinsicsMap(Allocator()->Adapter()), - DynamicClassIntrinsicsMap(Allocator()->Adapter())}, - dynamicLambdaSignatureCache_(Allocator()->Adapter()), - functionalInterfaceCache_(Allocator()->Adapter()), - apparentTypes_(Allocator()->Adapter()), - dynamicCallNames_ {{DynamicCallNamesMap(Allocator()->Adapter()), DynamicCallNamesMap(Allocator()->Adapter())}}, - overloadSigContainer_(Allocator()->Adapter()) +void ETSChecker::ReputCheckerData() { + readdedChecker_.insert(this); + for (auto &[_, extPrograms] : Program()->ExternalSources()) { + (void)_; + auto *extProg = extPrograms.front(); + if (!extProg->IsASTLowered()) { + continue; + } + auto eChecker = extProg->Checker()->AsETSChecker(); + + if (!HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) { + SetGlobalTypesHolder(eChecker->GetGlobalTypesHolder()); + AddStatus(CheckerStatus::BUILTINS_INITIALIZED); + } + + if (auto it = readdedChecker_.find(eChecker); it != readdedChecker_.end()) { + continue; + } + readdedChecker_.insert(eChecker->readdedChecker_.begin(), eChecker->readdedChecker_.end()); + auto computedAbstractMapToCopy = eChecker->GetCachedComputedAbstracts(); + for (auto &[key, value] : *computedAbstractMapToCopy) { + if (GetCachedComputedAbstracts()->find(key) != GetCachedComputedAbstracts()->end()) { + continue; + } + auto &[v1, v2] = value; + ArenaVector newV1(Allocator()->Adapter()); + ArenaUnorderedSet newV2(Allocator()->Adapter()); + newV1.assign(v1.cbegin(), v1.cend()); + newV2.insert(v2.cbegin(), v2.cend()); + GetCachedComputedAbstracts()->try_emplace(key, newV1, newV2); + } + + auto &globalArraySigs = eChecker->globalArraySignatures_; + globalArraySignatures_.insert(globalArraySigs.cbegin(), globalArraySigs.cend()); + + auto &apparentTypes = eChecker->apparentTypes_; + apparentTypes_.insert(apparentTypes.cbegin(), apparentTypes.cend()); + + auto &objectInstantiationMap = eChecker->objectInstantiationMap_; + for (auto &[key, value] : objectInstantiationMap) { + if (objectInstantiationMap_.find(key) == objectInstantiationMap_.end()) { + objectInstantiationMap_.insert(objectInstantiationMap.cbegin(), objectInstantiationMap.cend()); + } + } + + auto &invokeToArrowSignatures = eChecker->invokeToArrowSignatures_; + invokeToArrowSignatures_.insert(invokeToArrowSignatures.cbegin(), invokeToArrowSignatures.cend()); + auto &arrowToFuncInterfaces = eChecker->arrowToFuncInterfaces_; + arrowToFuncInterfaces_.insert(arrowToFuncInterfaces.cbegin(), arrowToFuncInterfaces.cend()); + } } static util::StringView InitBuiltin(ETSChecker *checker, std::string_view signature) @@ -88,8 +109,7 @@ static util::StringView InitBuiltin(ETSChecker *checker, std::string_view signat void ETSChecker::CheckObjectLiteralKeys(const ArenaVector &properties) { - static std::set names; - names.clear(); + std::set names; for (auto property : properties) { if (!property->IsProperty()) { @@ -291,8 +311,6 @@ void ETSChecker::InitializeBuiltin(varbinder::Variable *var, const util::StringV bool ETSChecker::StartChecker(varbinder::VarBinder *varbinder, const util::Options &options) { - Initialize(varbinder); - if (options.IsParseOnly()) { return false; } @@ -352,23 +370,19 @@ void ETSChecker::SetDebugInfoPlugin(evaluate::ScopedDebugInfoPlugin *debugInfo) void ETSChecker::CheckProgram(parser::Program *program, bool runAnalysis) { - if (program->IsASTChecked()) { - return; - } - auto *savedProgram = Program(); SetProgram(program); for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { - if (extProg->IsASTChecked()) { - continue; + if (!extProg->IsASTLowered()) { + extProg->PushChecker(this); + varbinder::RecordTableContext recordTableCtx(VarBinder()->AsETSBinder(), extProg); + checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); + AddStatus(checker::CheckerStatus::IN_EXTERNAL); + CheckProgram(extProg, VarBinder()->IsGenStdLib()); } - checker::SavedCheckerContext savedContext(this, Context().Status(), Context().ContainingClass()); - AddStatus(checker::CheckerStatus::IN_EXTERNAL); - CheckProgram(extProg, VarBinder()->IsGenStdLib()); - extProg->SetFlag(parser::ProgramFlags::AST_CHECK_PROCESSED); } } diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 06de9f47df..c57c46c019 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -25,7 +25,6 @@ #include "checker/types/ets/etsResizableArrayType.h" #include "checker/types/ets/types.h" #include "checker/resolveResult.h" -#include "ir/ts/tsInterfaceDeclaration.h" #include "ir/visitor/AstVisitor.h" #include "util/helpers.h" @@ -65,8 +64,11 @@ struct PairHash { using ComputedAbstracts = ArenaUnorderedMap, ArenaUnorderedSet>>; using ArrayMap = ArenaUnorderedMap, ETSArrayType *, PairHash>; +using ObjectInstantiationMap = ArenaUnorderedMap>; using GlobalArraySignatureMap = ArenaUnorderedMap; using DynamicCallIntrinsicsMap = ArenaUnorderedMap>; +using FunctionSignatureMap = ArenaUnorderedMap; +using FunctionInterfaceMap = ArenaUnorderedMap; using DynamicClassIntrinsicsMap = ArenaUnorderedMap; using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap; using FunctionalInterfaceMap = ArenaUnorderedMap; @@ -80,8 +82,29 @@ using AstNodePtr = ir::AstNode *; class ETSChecker final : public Checker { public: - explicit ETSChecker(util::DiagnosticEngine &diagnosticEngine); - explicit ETSChecker(util::DiagnosticEngine &diagnosticEngine, ArenaAllocator *programAllocator); + explicit ETSChecker(ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + ThreadSafeArenaAllocator *programAllocator = nullptr) + // NOLINTNEXTLINE(readability-redundant-member-init) + : Checker(allocator, diagnosticEngine, programAllocator), + arrayTypes_(Allocator()->Adapter()), + pendingConstraintCheckRecords_(Allocator()->Adapter()), + objectInstantiationMap_(Allocator()->Adapter()), + invokeToArrowSignatures_(Allocator()->Adapter()), + arrowToFuncInterfaces_(Allocator()->Adapter()), + globalArraySignatures_(Allocator()->Adapter()), + dynamicIntrinsics_ {DynamicCallIntrinsicsMap {Allocator()->Adapter()}, + DynamicCallIntrinsicsMap {Allocator()->Adapter()}}, + dynamicClasses_ {DynamicClassIntrinsicsMap(Allocator()->Adapter()), + DynamicClassIntrinsicsMap(Allocator()->Adapter())}, + dynamicLambdaSignatureCache_(Allocator()->Adapter()), + functionalInterfaceCache_(Allocator()->Adapter()), + apparentTypes_(Allocator()->Adapter()), + dynamicCallNames_ { + {DynamicCallNamesMap(Allocator()->Adapter()), DynamicCallNamesMap(Allocator()->Adapter())}}, + overloadSigContainer_(Allocator()->Adapter()), + readdedChecker_(Allocator()->Adapter()) + { + } ~ETSChecker() override = default; @@ -172,6 +195,7 @@ public: Type *GuaranteedTypeForUncheckedCallReturn(Signature *sig); Type *GuaranteedTypeForUncheckedPropertyAccess(varbinder::Variable *prop); Type *GuaranteedTypeForUnionFieldAccess(ir::MemberExpression *memberExpression, ETSUnionType *etsUnionType); + void ReputCheckerData(); [[nodiscard]] bool IsETSChecker() const noexcept override { @@ -884,6 +908,21 @@ public: return overloadSigContainer_; } + ObjectInstantiationMap &GetObjectInstantiationMap() + { + return objectInstantiationMap_; + } + + FunctionSignatureMap &GetInvokeToArrowSignatures() + { + return invokeToArrowSignatures_; + } + + FunctionInterfaceMap &GetArrowToFuncInterfaces() + { + return arrowToFuncInterfaces_; + } + void CleanUp() override { Checker::CleanUp(); @@ -1028,6 +1067,7 @@ private: const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags); // Trailing lambda void MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression *callExpr); + ir::ScriptFunction *CreateLambdaFunction(ir::BlockStatement *trailingBlock, Signature *sig); void TransformTraillingLambda(ir::CallExpression *callExpr, Signature *sig); ArenaVector ExtendArgumentsWithFakeLamda(ir::CallExpression *callExpr); @@ -1053,6 +1093,9 @@ private: ArrayMap arrayTypes_; ArenaVector pendingConstraintCheckRecords_; + ObjectInstantiationMap objectInstantiationMap_; + FunctionSignatureMap invokeToArrowSignatures_; + FunctionInterfaceMap arrowToFuncInterfaces_; size_t constraintCheckScopesCount_ {0}; GlobalArraySignatureMap globalArraySignatures_; ComputedAbstracts *cachedComputedAbstracts_ {nullptr}; @@ -1067,6 +1110,7 @@ private: evaluate::ScopedDebugInfoPlugin *debugInfoPlugin_ {nullptr}; std::unordered_set elementStack_; ArenaVector overloadSigContainer_; + ArenaSet readdedChecker_; }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/JSchecker.cpp b/ets2panda/checker/JSchecker.cpp index 3efe6f5b8d..62c02cc206 100644 --- a/ets2panda/checker/JSchecker.cpp +++ b/ets2panda/checker/JSchecker.cpp @@ -23,7 +23,6 @@ namespace ark::es2panda::checker { bool JSChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const util::Options &options) { - Initialize(varbinder); varbinder->IdentifierAnalysis(); if (options.IsDumpAst()) { diff --git a/ets2panda/checker/JSchecker.h b/ets2panda/checker/JSchecker.h index 0d0a605208..3e261069aa 100644 --- a/ets2panda/checker/JSchecker.h +++ b/ets2panda/checker/JSchecker.h @@ -23,9 +23,9 @@ namespace ark::es2panda::checker { class JSChecker : public Checker { public: // NOLINTNEXTLINE(readability-redundant-member-init) - explicit JSChecker(util::DiagnosticEngine &diagnosticEngine, - [[maybe_unused]] ArenaAllocator *programAllocator = nullptr) - : Checker(diagnosticEngine) + explicit JSChecker([[maybe_unused]] ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + [[maybe_unused]] ThreadSafeArenaAllocator *programAllocator = nullptr) + : Checker(allocator, diagnosticEngine, programAllocator) { } diff --git a/ets2panda/checker/TSchecker.cpp b/ets2panda/checker/TSchecker.cpp index 9e820dfc4d..4fe4acde54 100644 --- a/ets2panda/checker/TSchecker.cpp +++ b/ets2panda/checker/TSchecker.cpp @@ -23,7 +23,6 @@ namespace ark::es2panda::checker { bool TSChecker::StartChecker([[maybe_unused]] varbinder::VarBinder *varbinder, const util::Options &options) { - Initialize(varbinder); varbinder->IdentifierAnalysis(); if (options.IsDumpAst()) { diff --git a/ets2panda/checker/TSchecker.h b/ets2panda/checker/TSchecker.h index 83ecaa50ca..4d360a1f4f 100644 --- a/ets2panda/checker/TSchecker.h +++ b/ets2panda/checker/TSchecker.h @@ -121,8 +121,9 @@ struct TupleTypeInfo { class TSChecker : public Checker { public: // NOLINTNEXTLINE(readability-redundant-member-init) - explicit TSChecker(util::DiagnosticEngine &diagnosticEngine, [[maybe_unused]] ArenaAllocator *programAllocator) - : Checker(diagnosticEngine) + explicit TSChecker([[maybe_unused]] ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + [[maybe_unused]] ThreadSafeArenaAllocator *programAllocator) + : Checker(allocator, diagnosticEngine, programAllocator) { } diff --git a/ets2panda/checker/checker.cpp b/ets2panda/checker/checker.cpp index d4adeb07cc..39c4be1b59 100644 --- a/ets2panda/checker/checker.cpp +++ b/ets2panda/checker/checker.cpp @@ -20,8 +20,9 @@ #include "checker/types/ts/unionType.h" namespace ark::es2panda::checker { -Checker::Checker(util::DiagnosticEngine &diagnosticEngine, ArenaAllocator *programAllocator) - : allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true), +Checker::Checker(ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + ThreadSafeArenaAllocator *programAllocator) + : allocator_(allocator), programAllocator_(programAllocator), context_(this, CheckerStatus::NO_OPTS), diagnosticEngine_(diagnosticEngine) @@ -177,9 +178,11 @@ ScopeContext::ScopeContext(Checker *checker, varbinder::Scope *newScope) void Checker::CleanUp() { + if (!program_->IsASTLowered()) { + globalTypes_ = allocator_->New(allocator_); + } context_ = CheckerContext(this, CheckerStatus::NO_OPTS); - globalTypes_ = allocator_.New(&allocator_); - relation_ = allocator_.New(this); + relation_ = allocator_->New(this); identicalResults_.cached.clear(); assignableResults_.cached.clear(); comparableResults_.cached.clear(); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index 8c0e0dc583..c41af2dbd8 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -50,6 +50,7 @@ namespace ark::es2panda::checker { class ETSChecker; class InterfaceType; class GlobalTypesHolder; +class SemanticAnalyzer; using StringLiteralPool = std::unordered_map; using NumberLiteralPool = std::unordered_map; @@ -63,15 +64,16 @@ using ArgRange = std::pair; class Checker { public: - explicit Checker(util::DiagnosticEngine &diagnosticEngine, ArenaAllocator *programAllocator = nullptr); + explicit Checker(ThreadSafeArenaAllocator *allocator, util::DiagnosticEngine &diagnosticEngine, + ThreadSafeArenaAllocator *programAllocator = nullptr); virtual ~Checker() = default; NO_COPY_SEMANTIC(Checker); NO_MOVE_SEMANTIC(Checker); - [[nodiscard]] ArenaAllocator *Allocator() noexcept + [[nodiscard]] ThreadSafeArenaAllocator *Allocator() noexcept { - return &allocator_; + return allocator_; } [[nodiscard]] varbinder::Scope *Scope() const noexcept @@ -114,7 +116,7 @@ public: return globalTypes_; } - void SetGlobalTypes(GlobalTypesHolder *globalTypes) noexcept + void SetGlobalTypesHolder(GlobalTypesHolder *globalTypes) { globalTypes_ = globalTypes; } @@ -232,9 +234,9 @@ public: virtual void CleanUp(); - [[nodiscard]] ArenaAllocator *ProgramAllocator() + [[nodiscard]] ThreadSafeArenaAllocator *ProgramAllocator() { - return programAllocator_ == nullptr ? &allocator_ : programAllocator_; + return programAllocator_ == nullptr ? allocator_ : programAllocator_; } protected: @@ -242,8 +244,8 @@ protected: void SetProgram(parser::Program *program); private: - ArenaAllocator allocator_; - ArenaAllocator *programAllocator_ {nullptr}; + ThreadSafeArenaAllocator *allocator_; + ThreadSafeArenaAllocator *programAllocator_ {nullptr}; CheckerContext context_; GlobalTypesHolder *globalTypes_ {nullptr}; TypeRelation *relation_; @@ -253,11 +255,11 @@ private: varbinder::Scope *scope_ {}; util::DiagnosticEngine &diagnosticEngine_; - RelationHolder identicalResults_ {{}, RelationType::IDENTICAL}; - RelationHolder assignableResults_ {{}, RelationType::ASSIGNABLE}; - RelationHolder comparableResults_ {{}, RelationType::COMPARABLE}; - RelationHolder uncheckedCastableResults_ {{}, RelationType::UNCHECKED_CASTABLE}; - RelationHolder supertypeResults_ {{}, RelationType::SUPERTYPE}; + RelationHolder identicalResults_ {Allocator(), RelationType::IDENTICAL}; + RelationHolder assignableResults_ {Allocator(), RelationType::ASSIGNABLE}; + RelationHolder comparableResults_ {Allocator(), RelationType::COMPARABLE}; + RelationHolder uncheckedCastableResults_ {Allocator(), RelationType::UNCHECKED_CASTABLE}; + RelationHolder supertypeResults_ {Allocator(), RelationType::SUPERTYPE}; std::unordered_map typeStack_; std::unordered_set namedTypeStack_; diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index 90abef0f88..f5d2544345 100644 --- a/ets2panda/checker/ets/dynamic.cpp +++ b/ets2panda/checker/ets/dynamic.cpp @@ -365,7 +365,7 @@ ir::ClassDeclaration *ETSChecker::BuildClass(util::StringView name, const ClassB // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *classDecl = ProgramAllocNode(classDef, ProgramAllocator()); - VarBinder()->Program()->Ast()->Statements().push_back(classDecl); + VarBinder()->Program()->Ast()->AddStatement(classDecl); classDecl->SetParent(VarBinder()->Program()->Ast()); auto varBinder = VarBinder()->AsETSBinder(); @@ -597,7 +597,7 @@ void ETSChecker::EmitDynamicModuleClassInitCall() // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *const node = ProgramAllocNode(initCall); node->SetParent(cctorBody); - cctorBody->Statements().push_back(node); + cctorBody->AddStatement(node); ProcessScopesNode(this, node); ProcessCheckerNode(this, node); @@ -620,7 +620,7 @@ void ETSChecker::BuildClassBodyFromDynamicImports(const ArenaVectorAssemblerName() = util::UString(assemblyName, ProgramAllocator()).View(); + import->SetAssemblerName(util::UString(assemblyName, ProgramAllocator()).View()); fields.insert(import->AssemblerName()); imports.push_back(import); diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 167f9e40b2..d1b97e2378 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -229,7 +229,7 @@ static void ResetInferredNode(ETSChecker *checker) auto resetFuncState = [](ir::ArrowFunctionExpression *expr) { auto *func = expr->Function(); func->SetSignature(nullptr); - func->ReturnStatements().clear(); + func->ClearReturnStatements(); expr->SetTsType(nullptr); }; @@ -1098,7 +1098,7 @@ Signature *ETSChecker::ResolvePotentialTrailingLambdaWithReceiver(ir::CallExpres auto *candidateFunctionType = sig->Function()->Params().back()->AsETSParameterExpression()->TypeAnnotation()->AsETSFunctionType(); auto *currentReceiver = candidateFunctionType->Params()[0]; - trailingLambda->Function()->Params().emplace_back(currentReceiver); + trailingLambda->Function()->EmplaceParams(currentReceiver); sigContainLambdaWithReceiverAsParam.emplace_back(sig); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) signature = ValidateSignatures(sigContainLambdaWithReceiverAsParam, callExpr->TypeParams(), arguments, @@ -1108,7 +1108,7 @@ Signature *ETSChecker::ResolvePotentialTrailingLambdaWithReceiver(ir::CallExpres return signature; } sigContainLambdaWithReceiverAsParam.clear(); - trailingLambda->Function()->Params().clear(); + trailingLambda->Function()->ClearParams(); } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return ValidateSignatures(normalSig, callExpr->TypeParams(), arguments, callExpr->Start(), "call", @@ -1224,7 +1224,7 @@ void ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVectorGetOverloadInfo(); + ir::OverloadInfo &ldInfo = method->GetOverloadInfoForUpdate(); ArenaVector overloads(checker->ProgramAllocator()->Adapter()); for (ir::MethodDefinition *const currentFunc : method->Overloads()) { @@ -1236,11 +1236,16 @@ static bool CollectOverload(checker::ETSChecker *checker, ir::MethodDefinition * method->Id()->Variable()->SetTsType(checker->GlobalTypeError()); return false; } - auto *const overloadType = checker->BuildMethodType(currentFunc->Function()); + + auto *const overloadType = currentFunc->TsType() != nullptr ? currentFunc->TsType()->AsETSFunctionType() + : checker->BuildMethodType(currentFunc->Function()); ldInfo.needHelperOverload |= checker->CheckIdenticalOverloads(funcType, overloadType, currentFunc, ldInfo.isDeclare); - currentFunc->SetTsType(overloadType); + if (currentFunc->TsType() == nullptr) { + currentFunc->SetTsType(overloadType); + } + auto overloadSig = currentFunc->Function()->Signature(); funcType->AddCallSignature(overloadSig); if (overloadSig->IsExtensionAccessor()) { @@ -1284,7 +1289,7 @@ checker::Type *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method) if (!CollectOverload(this, method, funcType)) { return GlobalTypeError(); } - ir::OverloadInfo &ldInfo = method->GetOverloadInfo(); + ir::OverloadInfo &ldInfo = method->GetOverloadInfoForUpdate(); ldInfo.needHelperOverload &= ldInfo.isDeclare; if (ldInfo.needHelperOverload) { @@ -1474,6 +1479,10 @@ void ETSChecker::ValidateMainSignature(ir::ScriptFunction *func) void ETSChecker::BuildFunctionSignature(ir::ScriptFunction *func, bool isConstructSig) { bool isArrow = func->IsArrow(); + // note(Ekko): For extenal function overload, need to not change ast tree, for arrow type, need perferred type. + if (func->Signature() != nullptr && !isArrow) { + return; + } auto *nameVar = isArrow ? nullptr : func->Id()->Variable(); auto funcName = nameVar == nullptr ? util::StringView() : nameVar->Name(); @@ -2127,11 +2136,8 @@ void ETSChecker::MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression * } using SFunctionData = ir::ScriptFunction::ScriptFunctionData; -void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr, Signature *sig) +ir::ScriptFunction *ETSChecker::CreateLambdaFunction(ir::BlockStatement *trailingBlock, Signature *sig) { - auto *trailingBlock = callExpr->TrailingBlock(); - ES2PANDA_ASSERT(trailingBlock != nullptr); - auto *funcParamScope = varbinder::LexicalScope(VarBinder()).GetScope(); auto paramCtx = varbinder::LexicalScope::Enter(VarBinder(), funcParamScope, false); @@ -2178,7 +2184,19 @@ void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr, Signatur funcParamScope->BindNode(funcNode); trailingBlock->SetScope(funcScope); - ReplaceScope(funcNode->Body(), trailingBlock, funcScope); + + return funcNode; +} + +void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr, Signature *sig) +{ + auto *trailingBlock = callExpr->TrailingBlock(); + ES2PANDA_ASSERT(trailingBlock != nullptr); + + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto *funcNode = CreateLambdaFunction(trailingBlock, sig); + funcNode->AddFlag(ir::ScriptFunctionFlags::TRAILING_LAMBDA); + ReplaceScope(funcNode->Body(), trailingBlock, funcNode->Scope()); callExpr->SetTrailingBlock(nullptr); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index c799944902..82a6fdb2c2 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1669,6 +1669,9 @@ void ETSChecker::BindingsModuleObjectAddProperty(checker::ETSObjectType *moduleO for (auto [_, var] : bindings) { (void)_; auto [found, aliasedName] = FindSpecifierForModuleObject(importDecl, var->AsLocalVariable()->Name()); + if (!var->AsLocalVariable()->Declaration()->Node()->IsValidInCurrentPhase()) { + continue; + } if ((var->AsLocalVariable()->Declaration()->Node()->IsExported()) && found) { if (!aliasedName.Empty()) { moduleObjType->AddReExportAlias(var->Declaration()->Name(), aliasedName); @@ -2818,6 +2821,7 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty auto classCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), classScope); checker->VarBinder()->AsETSBinder()->ResolveMethodDefinition(method); + method->Function()->ClearFlag(ir::ScriptFunctionFlags::EXTERNAL); functionScope->BindName(classScope->Node()->AsClassDefinition()->InternalName()); method->Check(checker); @@ -2836,7 +2840,7 @@ ir::ClassProperty *GetImplementationClassProp(ETSChecker *checker, ir::ClassProp auto *const classProp = checker->ClassPropToImplementationProp( interfaceProp->Clone(checker->ProgramAllocator(), originalProp->Parent()), scope); classType->AddProperty(classProp->Key()->Variable()->AsLocalVariable()); - classDef->Body().push_back(classProp); + classDef->EmplaceBody(classProp); return classProp; } @@ -2903,7 +2907,7 @@ void ETSChecker::GenerateGetterSetterPropertyAndMethod(ir::ClassProperty *origin // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) ir::MethodDefinition *getter = GenerateDefaultGetterSetter(interfaceProp, classProp, scope, false, this); - classDef->Body().push_back(getter); + classDef->EmplaceBody(getter); const auto &name = getter->Key()->AsIdentifier()->Name(); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index c5724a9d7e..cbf729d09f 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ +#include #include "checker/ETSchecker.h" #include "checker/ets/typeRelationContext.h" #include "checker/types/ets/etsDynamicType.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/etsTupleType.h" #include "checker/types/ets/etsPartialTypeParameter.h" +#include "compiler/lowering/phase.h" #include "ir/base/classDefinition.h" #include "ir/base/classElement.h" #include "ir/base/classProperty.h" @@ -2411,10 +2413,16 @@ void ETSChecker::TransformProperties(ETSObjectType *classType) GenerateGetterSetterPropertyAndMethod(originalProp, classType); } - auto it = classDef->Body().begin(); - while (it != classDef->Body().end()) { + auto &body = classDef->Body(); + if (!std::any_of(body.cbegin(), body.cend(), [](const ir::AstNode *node) { + return node->IsClassProperty() && (node->Modifiers() & ir::ModifierFlags::GETTER_SETTER) != 0U; + })) { + return; + } + auto it = classDef->BodyForUpdate().begin(); + while (it != classDef->BodyForUpdate().end()) { if ((*it)->IsClassProperty() && ((*it)->Modifiers() & ir::ModifierFlags::GETTER_SETTER) != 0U) { - it = classDef->Body().erase(it); + it = classDef->BodyForUpdate().erase(it); } else { ++it; } @@ -2478,14 +2486,18 @@ void ETSChecker::AddElementsToModuleObject(ETSObjectType *moduleObj, const util: // This function computes effective runtime view of type Type *ETSChecker::GetApparentType(Type *type) { - if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) { + auto currChecker = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker(); + auto &apparentTypes = currChecker->apparentTypes_; + + if (auto it = apparentTypes.find(type); LIKELY(it != apparentTypes.end())) { return it->second; } - auto cached = [this, type](Type *res) { + + auto cached = [&apparentTypes, type](Type *res) { if (type != res) { - apparentTypes_.insert({type, res}); + apparentTypes.insert({type, res}); } - apparentTypes_.insert({res, res}); + apparentTypes.insert({res, res}); return res; }; @@ -2526,7 +2538,9 @@ Type *ETSChecker::GetApparentType(Type *type) Type const *ETSChecker::GetApparentType(Type const *type) const { - if (auto it = apparentTypes_.find(type); LIKELY(it != apparentTypes_.end())) { + auto currChecker = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker(); + auto &apparentTypes = currChecker->apparentTypes_; + if (auto it = apparentTypes.find(type); LIKELY(it != apparentTypes.end())) { return it->second; } // Relaxed for some types diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 4c35d829af..53b6838523 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -23,6 +23,8 @@ #include "checker/types/type.h" #include "ir/statements/annotationDeclaration.h" +#include + namespace ark::es2panda::checker { ByteType *ETSChecker::CreateByteType(int8_t value) @@ -448,15 +450,18 @@ std::tuple ETSChecker::CreateBuiltinArraySign Signature *ETSChecker::CreateBuiltinArraySignature(const ETSArrayType *arrayType, size_t dim) { - auto res = globalArraySignatures_.find(arrayType); - if (res != globalArraySignatures_.end()) { + auto currentChecker = + compiler::GetPhaseManager()->Context() != nullptr ? compiler::GetPhaseManager()->Context()->GetChecker() : this; + auto &globalArraySignatures = currentChecker->AsETSChecker()->globalArraySignatures_; + auto res = globalArraySignatures.find(arrayType); + if (res != globalArraySignatures.end()) { return res->second; } auto [internalName, info] = CreateBuiltinArraySignatureInfo(arrayType, dim); auto *signature = CreateSignature(info, GlobalVoidType(), ir::ScriptFunctionFlags::NONE, false); signature->SetInternalName(internalName); - globalArraySignatures_.insert({arrayType, signature}); + globalArraySignatures.insert({arrayType, signature}); return signature; } diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index 00dcde0ae4..f8a63c3124 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -179,7 +179,7 @@ void InstantiationContext::InstantiateType(ETSObjectType *type, ArenaVectorSubstitute(checker_->Relation(), substitution)->AsETSObjectType(); - type->GetInstantiationMap().try_emplace(hash, result_->AsETSObjectType()); + type->InsertInstantiationMap(hash, result_->AsETSObjectType()); result_->AddTypeFlag(TypeFlag::GENERIC); ctScope.TryCheckConstraints(); diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index b2d95bd91d..c77f536455 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -98,7 +98,7 @@ static std::pair GetPartialClassPro ir::AstNode *typeNode) { auto classDefProgram = typeNode->GetTopStatement()->AsETSModule()->Program(); - if (classDefProgram == checker->VarBinder()->Program()) { + if (classDefProgram == checker->VarBinder()->AsETSBinder()->GetGlobalRecordTable()->Program()) { return {classDefProgram, checker->VarBinder()->AsETSBinder()->GetGlobalRecordTable()}; } return {classDefProgram, checker->VarBinder()->AsETSBinder()->GetExternalRecordTable().at(classDefProgram)}; @@ -204,8 +204,11 @@ Type *ETSChecker::HandlePartialInterface(ir::TSInterfaceDeclaration *interfaceDe partialInterDecl->Variable()); } + auto savedScope = VarBinder()->TopScope(); + VarBinder()->ResetTopScope(partialProgram->GlobalScope()); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *partialType = CreatePartialTypeInterfaceDecl(interfaceDecl, typeToBePartial, partialInterDecl); + VarBinder()->ResetTopScope(savedScope); ES2PANDA_ASSERT(partialType != nullptr); NamedTypeStackElement ntse(this, partialType); @@ -465,7 +468,7 @@ void ETSChecker::CreatePartialClassDeclaration(ir::ClassDefinition *const newCla auto *const newProp = CreateNullishProperty(prop->AsClassProperty(), newClassDefinition); // Put the new property into the class declaration - newClassDefinition->Body().emplace_back(newProp); + newClassDefinition->EmplaceBody(newProp); } if (prop->IsMethodDefinition() && (prop->AsMethodDefinition()->Function()->IsGetter() || @@ -476,7 +479,7 @@ void ETSChecker::CreatePartialClassDeclaration(ir::ClassDefinition *const newCla continue; } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - newClassDefinition->Body().emplace_back(CreateNullishPropertyFromAccessor(method, newClassDefinition)); + newClassDefinition->EmplaceBody(CreateNullishPropertyFromAccessor(method, newClassDefinition)); } } if (classDef->IsDeclare()) { @@ -599,10 +602,12 @@ ir::TSInterfaceDeclaration *ETSChecker::CreateInterfaceProto(util::StringView na // Put class declaration in global scope, and in program AST partialInterface->SetParent(interfaceDeclProgram->Ast()); - interfaceDeclProgram->Ast()->Statements().push_back(partialInterface); + interfaceDeclProgram->Ast()->AddStatement(partialInterface); interfaceDeclProgram->GlobalScope()->InsertBinding(name, var); partialInterface->AddModifier(flags); + partialInterface->ClearModifier(ir::ModifierFlags::EXPORTED); + partialInterface->ClearModifier(ir::ModifierFlags::DEFAULT_EXPORT); return partialInterface; } @@ -701,7 +706,7 @@ Type *ETSChecker::CreatePartialTypeInterfaceDecl(ir::TSInterfaceDeclaration *con // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) BuildSuperPartialTypeReference(superPartialType, superPartialRefTypeParams); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - partialInterface->Extends().push_back(ProgramAllocNode(superPartialRef)); + partialInterface->EmplaceExtends(ProgramAllocNode(superPartialRef)); partialInterface->Extends().back()->SetParent(partialInterface); } } @@ -739,7 +744,7 @@ void ETSChecker::CreateConstructorForPartialType(ir::ClassDefinition *const part ctor->Id()->SetVariable(ctorId->Variable()); // Put ctor in partial class body - partialClassDef->Body().emplace_back(ctor); + partialClassDef->EmplaceBody(ctor); } ir::ClassDefinition *ETSChecker::CreateClassPrototype(util::StringView name, parser::Program *const classDeclProgram) @@ -772,7 +777,7 @@ ir::ClassDefinition *ETSChecker::CreateClassPrototype(util::StringView name, par decl->BindNode(classDef); // Put class declaration in global scope, and in program AST - classDeclProgram->Ast()->Statements().push_back(classDecl); + classDeclProgram->Ast()->AddStatement(classDecl); classDeclProgram->GlobalScope()->InsertBinding(name, var); return classDef; @@ -964,7 +969,7 @@ Type *ETSChecker::GetReadonlyType(Type *type) void ETSChecker::MakePropertiesReadonly(ETSObjectType *const classType) { - classType->UpdateTypeProperties(this, [this](auto *property, auto *propType) { + classType->UpdateTypeProperties([this](auto *property, auto *propType) { auto *newDecl = ProgramAllocator()->New(property->Name(), property->Declaration()->Node()); auto *const propCopy = property->Copy(ProgramAllocator(), newDecl); diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h index e1ede4842b..e079ff71a6 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h @@ -23,7 +23,7 @@ class GlobalTypesHolder; class ETSAsyncFuncReturnType : public ETSObjectType { public: - ETSAsyncFuncReturnType(ArenaAllocator *allocator, TypeRelation *relation, ETSObjectType *promiseType) + ETSAsyncFuncReturnType(ThreadSafeArenaAllocator *allocator, TypeRelation *relation, ETSObjectType *promiseType) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_OBJECT, std::make_tuple(nullptr, ETSObjectFlags::ASYNC_FUNC_RETURN_TYPE, relation)), promiseType_(promiseType) diff --git a/ets2panda/checker/types/ets/etsBigIntType.h b/ets2panda/checker/types/ets/etsBigIntType.h index 279c5d0817..8ed5f40ccb 100644 --- a/ets2panda/checker/types/ets/etsBigIntType.h +++ b/ets2panda/checker/types/ets/etsBigIntType.h @@ -21,14 +21,14 @@ namespace ark::es2panda::checker { class ETSBigIntType : public ETSObjectType { public: - explicit ETSBigIntType(ArenaAllocator *allocator, [[maybe_unused]] ETSObjectType *super) + explicit ETSBigIntType(ThreadSafeArenaAllocator *allocator, [[maybe_unused]] ETSObjectType *super) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_BIGINT, nullptr, ETSObjectFlags::CLASS | ETSObjectFlags::BUILTIN_BIGINT | ETSObjectFlags::RESOLVED_SUPER) { SetSuperType(super); } - explicit ETSBigIntType(ArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, + explicit ETSBigIntType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, util::StringView value) : ETSObjectType( allocator, "", compiler::Signatures::BUILTIN_BIGINT, diff --git a/ets2panda/checker/types/ets/etsDynamicType.h b/ets2panda/checker/types/ets/etsDynamicType.h index eea79b4fb9..9506417407 100644 --- a/ets2panda/checker/types/ets/etsDynamicType.h +++ b/ets2panda/checker/types/ets/etsDynamicType.h @@ -28,7 +28,8 @@ class ETSDynamicType : public ETSObjectType { static constexpr auto RELATION = 2; public: - explicit ETSDynamicType(ArenaAllocator *allocator, std::tuple label, + explicit ETSDynamicType(ThreadSafeArenaAllocator *allocator, + std::tuple label, std::tuple info, bool hasDecl) : ETSObjectType(allocator, std::get(label), std::get(label), std::make_tuple(std::get(info), std::get(info) | ETSObjectFlags::DYNAMIC, diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index a5c6bdf33d..99e5b34528 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -24,7 +24,7 @@ namespace ark::es2panda::checker { class ETSEnumType : public ETSObjectType { public: - explicit ETSEnumType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, + explicit ETSEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) : ETSObjectType(allocator, name, internalName, std::make_tuple(declNode, ETSObjectFlags::CLASS | ETSObjectFlags::ENUM_OBJECT, relation)) @@ -49,7 +49,7 @@ public: class ETSIntEnumType : public ETSEnumType { public: - explicit ETSIntEnumType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, + explicit ETSIntEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) : ETSEnumType(allocator, name, internalName, declNode, relation) { @@ -70,8 +70,8 @@ public: class ETSStringEnumType : public ETSEnumType { public: - explicit ETSStringEnumType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, - ir::AstNode *declNode, TypeRelation *relation) + explicit ETSStringEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, + util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) : ETSEnumType(allocator, name, internalName, declNode, relation) { AddTypeFlag(checker::TypeFlag::ETS_STRING_ENUM); diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index 1df9fd28ea..6ee38c6662 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -15,6 +15,7 @@ #include "checker/ETSchecker.h" #include "checker/types/globalTypesHolder.h" +#include "compiler/lowering/phase.h" namespace ark::es2panda::checker { @@ -104,11 +105,16 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, ETSObjectType *ETSFunctionType::ArrowToFunctionalInterface(ETSChecker *checker) { - auto &cached = arrowToFuncInterface_; - if (LIKELY(cached != nullptr)) { - return cached; + auto &cached = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->GetArrowToFuncInterfaces(); + + auto found = cached.find(this); + if (LIKELY(found != cached.end())) { + return found->second; } - return cached = FunctionTypeToFunctionalInterfaceType(checker, ArrowSignature(), ArrowSignature()->MinArgCount()); + return cached + .emplace(this, + FunctionTypeToFunctionalInterfaceType(checker, ArrowSignature(), ArrowSignature()->MinArgCount())) + .first->second; } ETSObjectType *ETSFunctionType::ArrowToFunctionalInterfaceDesiredArity(ETSChecker *checker, size_t arity) @@ -121,13 +127,15 @@ ETSObjectType *ETSFunctionType::ArrowToFunctionalInterfaceDesiredArity(ETSChecke ETSFunctionType *ETSFunctionType::MethodToArrow(ETSChecker *checker) { - auto &cached = invokeToArrowSignature_; - if (LIKELY(cached != nullptr)) { - return cached; + auto &cached = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->GetInvokeToArrowSignatures(); + + auto found = cached.find(this); + if (LIKELY(found != cached.end())) { + return found->second; } ES2PANDA_ASSERT(!IsETSArrowType() && CallSignatures().size() == 1); - return cached = checker->CreateETSArrowType(CallSignatures()[0]); + return cached.emplace(this, checker->CreateETSArrowType(CallSignatures()[0])).first->second; } void ETSFunctionType::AddCallSignature(Signature *signature) diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index f59b65c709..14eea128aa 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -165,8 +165,6 @@ private: ArenaVector extensionAccessorSigs_; util::StringView const name_; util::StringView const assemblerName_; - ETSFunctionType *invokeToArrowSignature_ {}; - ETSObjectType *arrowToFuncInterface_ {}; Signature *helperSignature_ {}; }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 733f658a53..61a6db0141 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -18,6 +18,11 @@ #include "checker/ETSchecker.h" #include "checker/ets/conversion.h" #include "checker/types/globalTypesHolder.h" +#include "checker/types/ets/etsAsyncFuncReturnType.h" +#include "checker/types/ets/etsEnumType.h" +#include "checker/types/ets/etsDynamicFunctionType.h" +#include "compiler/lowering/phase.h" +#include "ir/statements/annotationDeclaration.h" namespace ark::es2panda::checker { @@ -199,9 +204,8 @@ varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(co ETSFunctionType *ETSObjectType::CreateMethodTypeForProp(const util::StringView &name) const { - ES2PANDA_ASSERT(GetRelation() != nullptr && GetRelation()->GetChecker() != nullptr); - auto *checker = GetRelation()->GetChecker()->AsETSChecker(); - return checker->CreateETSMethodType(name, {{}, Allocator()->Adapter()}); + ES2PANDA_ASSERT(GetRelation() != nullptr); + return GetRelation()->GetChecker()->AsETSChecker()->CreateETSMethodType(name, {{}, Allocator()->Adapter()}); } static void AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, @@ -856,6 +860,7 @@ void ETSObjectType::IsGenericSupertypeOf(TypeRelation *relation, ETSObjectType * Type *ETSObjectType::AsSuper(Checker *checker, varbinder::Variable *sourceVar) { + checker = GetETSChecker(); if (sourceVar == nullptr) { return nullptr; } @@ -919,9 +924,10 @@ varbinder::LocalVariable *ETSObjectType::CopyProperty(varbinder::LocalVariable * return copiedProp; } -Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation *const relation, +Type *ETSObjectType::Instantiate(ArenaAllocator *const allocator, TypeRelation *relation, GlobalTypesHolder *const globalTypes) { + relation = relation_; auto *const checker = relation->GetChecker()->AsETSChecker(); std::lock_guard guard {*checker->Mutex()}; auto *const base = GetOriginalBaseType(); @@ -976,7 +982,7 @@ static varbinder::LocalVariable *CopyPropertyWithTypeArguments(varbinder::LocalV auto *const checker = relation->GetChecker()->AsETSChecker(); auto *const varType = ETSChecker::IsVariableGetterSetter(prop) ? prop->TsType() : checker->GetTypeOfVariable(prop); auto *const copiedPropType = SubstituteVariableType(relation, substitution, varType); - auto *const copiedProp = prop->Copy(checker->ProgramAllocator(), prop->Declaration()); + auto *const copiedProp = prop->Copy(checker->Allocator(), prop->Declaration()); // NOTE: some situation copiedPropType we get here are types cached in Checker, // uncontrolled SetVariable will pollute the cache. if (copiedPropType->Variable() == prop || copiedPropType->Variable() == nullptr) { @@ -1036,19 +1042,26 @@ void ETSObjectType::SetCopiedTypeProperties(TypeRelation *const relation, ETSObj copiedType->RemoveObjectFlag(ETSObjectFlags::CHECKED_COMPATIBLE_ABSTRACTS | ETSObjectFlags::INCOMPLETE_INSTANTIATION | ETSObjectFlags::CHECKED_INVOKE_LEGITIMACY); copiedType->SetVariable(variable_); - copiedType->SetBaseType(base); + + // #25295 Need to do some refactor on baseType for partial + if (IsPartial() && HasObjectFlag(ETSObjectFlags::INTERFACE)) { + copiedType->SetBaseType(this); + } else { + copiedType->SetBaseType(base); + } auto const &baseTypeParams = base->TypeArguments(); copiedType->effectiveSubstitution_ = ComputeEffectiveSubstitution(relation, baseTypeParams, newTypeArgs); copiedType->SetTypeArguments(std::move(newTypeArgs)); + ES2PANDA_ASSERT(relation); copiedType->relation_ = relation; } -void ETSObjectType::UpdateTypeProperty(checker::ETSChecker *checker, varbinder::LocalVariable *const prop, - PropertyType fieldType, PropertyProcesser const &func) +void ETSObjectType::UpdateTypeProperty(varbinder::LocalVariable *const prop, PropertyType fieldType, + PropertyProcesser const &func) { - auto const propType = prop->Declaration()->Node()->Check(checker); + auto const propType = prop->Declaration()->Node()->Check(GetETSChecker()); auto *const propCopy = func(prop, propType); if (fieldType == PropertyType::INSTANCE_FIELD) { @@ -1060,36 +1073,128 @@ void ETSObjectType::UpdateTypeProperty(checker::ETSChecker *checker, varbinder:: } } -void ETSObjectType::UpdateTypeProperties(checker::ETSChecker *checker, PropertyProcesser const &func) +void ETSObjectType::UpdateTypeProperties(PropertyProcesser const &func) { AddTypeFlag(TypeFlag::READONLY); for (auto const &prop : InstanceFields()) { - UpdateTypeProperty(checker, prop.second, PropertyType::INSTANCE_FIELD, func); + UpdateTypeProperty(prop.second, PropertyType::INSTANCE_FIELD, func); } for (auto const &prop : StaticFields()) { - UpdateTypeProperty(checker, prop.second, PropertyType::STATIC_FIELD, func); + UpdateTypeProperty(prop.second, PropertyType::STATIC_FIELD, func); } if (SuperType() != nullptr) { - auto *const superProp = SuperType()->Clone(checker)->AsETSObjectType(); - superProp->UpdateTypeProperties(checker, func); + auto *const superProp = + SuperType() + ->Instantiate(allocator_, relation_, relation_->GetChecker()->GetGlobalTypesHolder()) + ->AsETSObjectType(); + superProp->UpdateTypeProperties(func); SetSuperType(superProp); } } +static util::StringView GetHashFromSubstitution(const Substitution *substitution, const bool extensionFuncFlag, + ArenaAllocator *allocator) +{ + std::vector fields; + for (auto [k, v] : *substitution) { + std::stringstream ss; + k->ToString(ss, true); + ss << ":"; + v->ToString(ss, true); + // NOTE (mmartin): change bare address to something more appropriate unique representation + ss << ":" << k << ":" << v; + fields.push_back(ss.str()); + } + std::sort(fields.begin(), fields.end()); + + std::stringstream ss; + for (auto &fstr : fields) { + ss << fstr; + ss << ";"; + } + + if (extensionFuncFlag) { + ss << "extensionFunctionType;"; + } + return util::UString(ss.str(), allocator).View(); +} + +static std::pair GetObjectTypeDeclNames(ir::AstNode *node) +{ + if (node->IsClassDefinition()) { + return {node->AsClassDefinition()->Ident()->Name(), node->AsClassDefinition()->InternalName()}; + } + if (node->IsTSInterfaceDeclaration()) { + return {node->AsTSInterfaceDeclaration()->Id()->Name(), node->AsTSInterfaceDeclaration()->InternalName()}; + } + return {node->AsAnnotationDeclaration()->GetBaseName()->Name(), node->AsAnnotationDeclaration()->InternalName()}; +} + +static std::tuple CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName) +{ + Language lang(Language::Id::ETS); + bool hasDecl = false; + + if (declNode->IsClassDefinition()) { + auto *clsDef = declNode->AsClassDefinition(); + lang = clsDef->Language(); + hasDecl = clsDef->IsDeclare(); + } + + if (declNode->IsTSInterfaceDeclaration()) { + auto *ifaceDecl = declNode->AsTSInterfaceDeclaration(); + lang = ifaceDecl->Language(); + hasDecl = ifaceDecl->IsDeclare(); + } + + auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8()); + if (res) { + lang = *res; + } + + return std::make_tuple(lang, hasDecl); +} + +ETSObjectType *ETSObjectType::CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags) +{ + auto const [name, internalName] = GetObjectTypeDeclNames(declNode); + + if (declNode->IsClassDefinition() && (declNode->AsClassDefinition()->IsEnumTransformed())) { + if (declNode->AsClassDefinition()->IsIntEnumTransformed()) { + return Allocator()->New(Allocator(), name, internalName, declNode, GetRelation()); + } + ES2PANDA_ASSERT(declNode->AsClassDefinition()->IsStringEnumTransformed()); + return Allocator()->New(Allocator(), name, internalName, declNode, GetRelation()); + } + + if (auto [lang, hasDecl] = CheckForDynamicLang(declNode, internalName); lang.IsDynamic()) { + return Allocator()->New(Allocator(), std::make_tuple(name, internalName, lang), + std::make_tuple(declNode, flags, GetRelation()), hasDecl); + } + + if (internalName == compiler::Signatures::BUILTIN_ARRAY) { + return Allocator()->New(Allocator(), name, + std::make_tuple(declNode, flags, GetRelation())); + } + + return Allocator()->New(Allocator(), name, internalName, + std::make_tuple(declNode, flags, GetRelation())); +} + // #22951: remove isExtensionFunctionType flag ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitution *substitution, bool cache, bool isExtensionFunctionType) { + relation = relation_; if (substitution == nullptr || substitution->empty()) { return this; } - auto *const checker = relation->GetChecker()->AsETSChecker(); auto *base = GetOriginalBaseType(); - ArenaVector newTypeArgs {Allocator()->Adapter()}; + ArenaVector newTypeArgs {allocator_->Adapter()}; const bool anyChange = SubstituteTypeArgs(relation, newTypeArgs, substitution); // Lambda types can capture type params in their bodies, normal classes cannot. // NOTE: gogabr. determine precise conditions where we do not need to copy. @@ -1098,7 +1203,7 @@ ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitut return this; } - const util::StringView hash = checker->GetHashFromSubstitution(substitution, isExtensionFunctionType); + const util::StringView hash = GetHashFromSubstitution(substitution, isExtensionFunctionType, allocator_); if (cache) { if (auto *inst = GetInstantiatedType(hash); inst != nullptr) { return inst; @@ -1110,14 +1215,15 @@ ETSObjectType *ETSObjectType::Substitute(TypeRelation *relation, const Substitut } relation->IncreaseTypeRecursionCount(base); - auto *const copiedType = checker->CreateETSObjectType(declNode_, flags_); + auto *const copiedType = CreateETSObjectType(declNode_, flags_); SetCopiedTypeProperties(relation, copiedType, std::move(newTypeArgs), base); if (isExtensionFunctionType) { copiedType->AddObjectFlag(checker::ETSObjectFlags::EXTENSION_FUNCTION); } if (cache) { - GetInstantiationMap().try_emplace(hash, copiedType); + ES2PANDA_ASSERT(copiedType->GetRelation()); + InsertInstantiationMap(hash, copiedType); } if (superType_ != nullptr) { @@ -1157,6 +1263,11 @@ ETSObjectType *ETSObjectType::SubstituteArguments(TypeRelation *relation, ArenaV return Substitute(relation, substitution); } +ETSChecker *ETSObjectType::GetETSChecker() +{ + return relation_->GetChecker()->AsETSChecker(); +} + void ETSObjectType::InstantiateProperties() const { ES2PANDA_ASSERT(relation_ != nullptr); @@ -1355,4 +1466,40 @@ void ETSObjectType::CheckVarianceRecursively(TypeRelation *relation, VarianceFla } } +ETSObjectType *ETSObjectType::GetInstantiatedType(util::StringView hash) +{ + auto &instantiationMap = + compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->GetObjectInstantiationMap(); + auto found = instantiationMap.find(this); + if (found == instantiationMap.end()) { + return nullptr; + } + + auto found2 = instantiationMap.at(this).find(hash); + if (found2 == instantiationMap.at(this).end()) { + return nullptr; + } + + return found2->second; +} + +void ETSObjectType::InsertInstantiationMap(const util::StringView &key, ETSObjectType *value) +{ + auto &instantiationMap = + compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->GetObjectInstantiationMap(); + if (instantiationMap.find(this) == instantiationMap.end()) { + ArenaUnorderedMap instantiation( + compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->Allocator()->Adapter()); + instantiation.emplace(key, value); + instantiationMap.emplace(this, instantiation); + } + compiler::GetPhaseManager() + ->Context() + ->GetChecker() + ->AsETSChecker() + ->GetObjectInstantiationMap() + .at(this) + .try_emplace(key, value); +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index 9a174689dd..20e5811f3d 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -16,6 +16,10 @@ #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H #define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H +#include +#include + +#include "checker/checker.h" #include "checker/types/type.h" #include "checker/types/ets/etsObjectTypeConstants.h" #include "checker/types/signature.h" @@ -37,14 +41,14 @@ public: using PropertyTraverser = std::function; using PropertyHolder = std::array(PropertyType::COUNT)>; - explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, + explicit ETSObjectType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, ir::AstNode *declNode, ETSObjectFlags flags) : ETSObjectType(allocator, name, internalName, std::make_tuple(declNode, flags, nullptr), std::make_index_sequence(PropertyType::COUNT)> {}) { } - explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView internalName, + explicit ETSObjectType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, std::tuple info) : ETSObjectType(allocator, name, internalName, info, std::make_index_sequence(PropertyType::COUNT)> {}) @@ -70,6 +74,8 @@ public: } } + ETSChecker *GetETSChecker(); + void SetSuperType(ETSObjectType *super) { superType_ = super; @@ -92,6 +98,7 @@ public: void SetRelation(TypeRelation *relation) { + ES2PANDA_ASSERT(relation); relation_ = relation; } @@ -158,7 +165,7 @@ public: return interfaces_; } - ArenaVector &Interfaces() + const ArenaVector &Interfaces() { return interfaces_; } @@ -276,15 +283,7 @@ public: return static_cast(flags_ & ETSObjectFlags::UNBOXABLE_TYPE); } - ETSObjectType *GetInstantiatedType(util::StringView hash) - { - auto found = instantiationMap_.find(hash); - if (found != instantiationMap_.end()) { - return found->second; - } - - return nullptr; - } + ETSObjectType *GetInstantiatedType(util::StringView hash); varbinder::Scope *GetTypeArgumentScope() const { @@ -295,10 +294,7 @@ public: return typeParams->Scope(); } - InstantiationMap &GetInstantiationMap() - { - return instantiationMap_; - } + void InsertInstantiationMap(const util::StringView &key, ETSObjectType *value); template varbinder::LocalVariable *GetOwnProperty(const util::StringView &name) const @@ -361,7 +357,7 @@ public: const util::StringView &name, PropertySearchFlags flags) const; bool CheckIdenticalFlags(ETSObjectType *other) const; - + ETSObjectType *CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags); void Iterate(const PropertyTraverser &cb) const; void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; @@ -369,7 +365,7 @@ public: void AssignmentTarget(TypeRelation *relation, Type *source) override; bool IsBoxedPrimitive() const; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - void UpdateTypeProperties(checker::ETSChecker *checker, PropertyProcesser const &func); + void UpdateTypeProperties(PropertyProcesser const &func); ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution) override; ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution, bool cache, bool isExtensionFunctionType = false); @@ -392,7 +388,7 @@ public: const ArenaVector &ReExports() const; bool IsSameBasedGeneric(TypeRelation *relation, Type const *other) const; - ArenaAllocator *Allocator() const + ThreadSafeArenaAllocator *Allocator() const { return allocator_; } @@ -414,7 +410,7 @@ protected: private: template - explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, + explicit ETSObjectType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, std::tuple info, [[maybe_unused]] std::index_sequence s) : Type(TypeFlag::ETS_OBJECT), @@ -426,7 +422,6 @@ private: reExports_(allocator->Adapter()), reExportAlias_(allocator->Adapter()), flags_(std::get(info)), - instantiationMap_(allocator->Adapter()), typeArguments_(allocator->Adapter()), relation_(std::get(info)), constructSignatures_(allocator->Adapter()), @@ -448,7 +443,7 @@ private: void IdenticalUptoTypeArguments(TypeRelation *relation, Type *other); void SubstitutePartialTypes(TypeRelation *relation, Type *other); void IsGenericSupertypeOf(TypeRelation *relation, ETSObjectType *source); - void UpdateTypeProperty(checker::ETSChecker *checker, varbinder::LocalVariable *const prop, PropertyType fieldType, + void UpdateTypeProperty(varbinder::LocalVariable *const prop, PropertyType fieldType, PropertyProcesser const &func); varbinder::LocalVariable *SearchFieldsDecls(const util::StringView &name, PropertySearchFlags flags) const; @@ -464,7 +459,7 @@ private: ir::TSTypeParameterDeclaration *GetTypeParams() const; - ArenaAllocator *const allocator_; + ThreadSafeArenaAllocator *const allocator_; util::StringView const name_; util::StringView const internalName_; ir::AstNode *const declNode_; @@ -472,7 +467,6 @@ private: ArenaVector reExports_; ArenaMap reExportAlias_; ETSObjectFlags flags_; - InstantiationMap instantiationMap_; ArenaVector typeArguments_; ETSObjectType *superType_ {}; ETSObjectType *enclosingType_ {}; diff --git a/ets2panda/checker/types/ets/etsResizableArrayType.h b/ets2panda/checker/types/ets/etsResizableArrayType.h index 43babf404a..1301e72693 100644 --- a/ets2panda/checker/types/ets/etsResizableArrayType.h +++ b/ets2panda/checker/types/ets/etsResizableArrayType.h @@ -23,7 +23,7 @@ namespace ark::es2panda::checker { class ETSResizableArrayType : public ETSObjectType { public: - explicit ETSResizableArrayType(ArenaAllocator *allocator, ETSObjectType *super) + explicit ETSResizableArrayType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_ARRAY, nullptr, ETSObjectFlags::CLASS | ETSObjectFlags::BUILTIN_ARRAY | ETSObjectFlags::RESOLVED_SUPER), element_(nullptr) @@ -31,13 +31,13 @@ public: SetSuperType(super); } - explicit ETSResizableArrayType(ArenaAllocator *allocator, util::StringView name, + explicit ETSResizableArrayType(ThreadSafeArenaAllocator *allocator, util::StringView name, std::tuple info) : ETSObjectType(allocator, name, compiler::Signatures::BUILTIN_ARRAY, info), element_(nullptr) { } - explicit ETSResizableArrayType(ArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, + explicit ETSResizableArrayType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, Type *element) : ETSObjectType( allocator, "", compiler::Signatures::BUILTIN_ARRAY, diff --git a/ets2panda/checker/types/ets/etsStringType.h b/ets2panda/checker/types/ets/etsStringType.h index 09d15090cc..513f4deb52 100644 --- a/ets2panda/checker/types/ets/etsStringType.h +++ b/ets2panda/checker/types/ets/etsStringType.h @@ -21,14 +21,14 @@ namespace ark::es2panda::checker { class ETSStringType : public ETSObjectType { public: - explicit ETSStringType(ArenaAllocator *allocator, ETSObjectType *super) + explicit ETSStringType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_STRING, nullptr, ETSObjectFlags::CLASS | ETSObjectFlags::STRING | ETSObjectFlags::RESOLVED_SUPER) { SetSuperType(super); } - explicit ETSStringType(ArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation) + explicit ETSStringType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_STRING, std::make_tuple(nullptr, ETSObjectFlags::CLASS | ETSObjectFlags::STRING | ETSObjectFlags::RESOLVED_SUPER, @@ -37,7 +37,7 @@ public: SetSuperType(super); } - explicit ETSStringType(ArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, + explicit ETSStringType(ThreadSafeArenaAllocator *allocator, ETSObjectType *super, TypeRelation *relation, util::StringView value) : ETSObjectType(allocator, "", compiler::Signatures::BUILTIN_STRING, std::make_tuple(nullptr, diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 92368135f3..e03343c7f1 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -22,6 +22,8 @@ namespace ark::es2panda::checker { +std::mutex Type::idLock_ {}; + bool Type::IsETSResizableArrayType() const { return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_ARRAY); diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 1a0895b37a..1104cada5f 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_H #define ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_H +#include #include "generated/signatures.h" #include "checker/types/typeMapping.h" #include "checker/types/typeRelation.h" @@ -50,6 +51,7 @@ class Type { public: explicit Type(TypeFlag flag) : typeFlags_(flag) { + std::lock_guard lock(idLock_); static uint64_t typeId = 0; id_ = ++typeId; } @@ -58,6 +60,7 @@ public: NO_MOVE_SEMANTIC(Type); virtual ~Type() = default; + static std::mutex idLock_; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define TYPE_IS_CHECKS(typeFlag, typeName) \ diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index a2fa218eed..6e1ad8cb6d 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_RELATION_H #define ES2PANDA_COMPILER_CHECKER_TYPES_TYPE_RELATION_H +#include #include "lexer/token/sourceLocation.h" #include "generated/tokenType.h" #include "util/ustring.h" @@ -110,11 +111,18 @@ public: RelationType type; }; -using RelationMap = std::unordered_map; +using RelationMap = ArenaUnorderedMap; class RelationHolder { public: + RelationHolder(ThreadSafeArenaAllocator *allocator, RelationType relationType) + : cached(allocator->Adapter()), type(relationType) + { + } + + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) RelationMap cached; + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) RelationType type {}; }; @@ -245,6 +253,7 @@ public: void IncreaseTypeRecursionCount(Type *const type) { + std::lock_guard lock(mtx_); if (const auto foundType = instantiationRecursionMap_.find(type); foundType != instantiationRecursionMap_.end()) { foundType->second += 1; @@ -261,12 +270,14 @@ public: // possible to reference the correct types of it's members and methods. 2 is possibly enough, because if we // chain expressions, every one of them will be rechecked separately, thus allowing another 2 recursion. constexpr auto MAX_RECURSIVE_TYPE_INST = 2; + std::lock_guard lock(mtx_); const auto foundType = instantiationRecursionMap_.find(type); return foundType == instantiationRecursionMap_.end() ? true : (foundType->second < MAX_RECURSIVE_TYPE_INST); } void DecreaseTypeRecursionCount(Type *const type) { + std::lock_guard lock(mtx_); const auto foundType = instantiationRecursionMap_.find(type); if (foundType == instantiationRecursionMap_.end()) { return; @@ -342,6 +353,7 @@ private: RelationResult CacheLookup(const Type *source, const Type *target, const RelationHolder &holder, RelationType type) const; + std::mutex mtx_; Checker *checker_; RelationResult result_ {}; TypeRelationFlag flags_ {}; diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index e539dffc83..004427936c 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -97,7 +97,7 @@ void ETSGen::CompileAndCheck(const ir::Expression *expr) const checker::ETSChecker *ETSGen::Checker() const noexcept { - return Context()->checker->AsETSChecker(); + return Context()->GetChecker()->AsETSChecker(); } const varbinder::ETSBinder *ETSGen::VarBinder() const noexcept diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 98dd37c7b5..8f0b822ef9 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -240,7 +240,7 @@ static std::vector> StoreExportNodes( std::vector> result; for (auto &pair : declGen) { - auto declString = pair.first; + auto declString = std::string {pair.first}; auto *node = pair.second; if (node->IsClassProperty() && node->IsConst()) { StoreEntity(literals, parser::EntityType::CLASS_PROPERTY); @@ -291,7 +291,7 @@ void ETSEmitter::GenAnnotation() if (scriptFunc->IsAsyncFunc()) { std::vector annotations; annotations.push_back(GenAnnotationAsync(scriptFunc)); - func.metadata->SetAnnotations(std::move(annotations)); + func.metadata->AddAnnotations(annotations); } Program()->AddToFunctionTable(std::move(func)); } @@ -303,7 +303,7 @@ void ETSEmitter::GenAnnotation() GenExternalRecord(recordTable, extProg); } - const auto *checker = static_cast(Context()->checker); + const auto *checker = static_cast(Context()->GetChecker()); for (auto [arrType, signature] : checker->GlobalArrayTypes()) { GenGlobalArrayRecord(arrType, signature); @@ -340,7 +340,7 @@ void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const pa GenInterfaceRecord(interfaceDecl, !isGenStdLib); } - for (auto *signature : recordTable->Signatures()) { + for (auto const *signature : recordTable->Signatures()) { auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this); if (!isGenStdLib) { @@ -348,7 +348,7 @@ void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const pa } if (func.metadata->IsForeign() && IsFromSelfHeadFile(func.name, Context()->parserProgram, extProg)) { - return; + continue; } if (Program()->functionStaticTable.find(func.name) == Program()->functionStaticTable.cend()) { @@ -547,7 +547,7 @@ std::vector ETSEmitter::GenAnnotations(const ir::ClassD auto classIdent = classDef->Ident()->Name().Mutf8(); bool isConstruct = classIdent == Signatures::JSNEW_CLASS; if (isConstruct || classIdent == Signatures::JSCALL_CLASS) { - auto *callNames = Context()->checker->AsETSChecker()->DynamicCallNames(isConstruct); + auto *callNames = Context()->GetChecker()->AsETSChecker()->DynamicCallNames(isConstruct); annotations.push_back(GenAnnotationDynamicCall(*callNames)); } @@ -756,7 +756,7 @@ LiteralArrayVector ETSEmitter::CreateLiteralArray(std::string &baseName, const i void ETSEmitter::CreateLiteralArrayProp(const ir::ClassProperty *prop, std::string &baseName, pandasm::Field &field) { - auto *checker = Context()->checker->AsETSChecker(); + auto *checker = Context()->GetChecker()->AsETSChecker(); uint8_t rank = 1; auto *elemType = checker->GetElementTypeOfArray(prop->TsType()); while (elemType->IsETSArrayType() || elemType->IsETSResizableArrayType()) { @@ -874,7 +874,7 @@ pandasm::AnnotationElement ETSEmitter::GenCustomAnnotationElement(const ir::Clas return ProcessETSEnumType(baseName, init, type); } switch (checker::ETSChecker::TypeKind( - Context()->checker->AsETSChecker()->MaybeUnboxType(const_cast(type)))) { + Context()->GetChecker()->AsETSChecker()->MaybeUnboxType(const_cast(type)))) { case checker::TypeFlag::BYTE: case checker::TypeFlag::SHORT: case checker::TypeFlag::INT: @@ -1066,7 +1066,7 @@ ir::MethodDefinition *ETSEmitter::FindAsyncImpl(ir::ScriptFunction *asyncFunc) } ir::MethodDefinition *method = (*it)->AsMethodDefinition(); - auto *checker = static_cast(Context()->checker); + auto *checker = static_cast(Context()->GetChecker()); checker::TypeRelation *typeRel = checker->Relation(); checker::SavedTypeRelationFlagsContext savedFlagsCtx(typeRel, checker::TypeRelationFlag::NO_RETURN_TYPE_CHECK); method->Function()->Signature()->IsSubtypeOf(typeRel, asyncFunc->Signature()); diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index af038f7485..1e5e752ae7 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -88,6 +88,7 @@ static public_lib::Context::CodeGenCb MakeCompileJob() RegSpiller regSpiller; ArenaAllocator allocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); AstCompiler astcompiler; + compiler::SetPhaseManager(context->phaseManager); CodeGen cg(&allocator, ®Spiller, context, std::make_tuple(scope, programElement, &astcompiler)); FunctionEmitter funcEmitter(&cg, programElement); funcEmitter.Generate(); @@ -299,7 +300,18 @@ static void AddExternalPrograms(public_lib::Context *ctx, const CompilationUnit if (gt != nullptr && gt->IsETSObjectType()) { auto *relation = gt->AsETSObjectType()->GetRelation(); if (relation != nullptr) { - relation->SetChecker(ctx->checker); + relation->SetChecker(ctx->GetChecker()); + } + } + } +} + +[[maybe_unused]] static void MarkAsLowered(parser::Program &program) +{ + for (auto &[name, extPrograms] : program.ExternalSources()) { + for (auto &extProgram : extPrograms) { + if (!extProgram->IsASTLowered()) { + extProgram->MarkASTAsLowered(); } } } @@ -373,8 +385,9 @@ static void SavePermanents(public_lib::Context *ctx, parser::Program *program) varbinder->GetGlobalRecordTable()->CleanUp(); varbinder->Functions().clear(); - ctx->transitionMemory->SetGlobalTypes(ctx->checker->GetGlobalTypesHolder()); - ctx->transitionMemory->SetCachechedComputedAbstracts(ctx->checker->AsETSChecker()->GetCachedComputedAbstracts()); + ctx->transitionMemory->SetGlobalTypes(ctx->GetChecker()->GetGlobalTypesHolder()); + ctx->transitionMemory->SetCachechedComputedAbstracts( + ctx->GetChecker()->AsETSChecker()->GetCachedComputedAbstracts()); ctx->transitionMemory->AddCompiledProgram(ctx->parserProgram); } @@ -422,7 +435,9 @@ template allocator); context->config = &config; context->config->options = &unit.options; context->sourceFile = &unit.input; @@ -435,13 +450,13 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp auto parser = Parser(&program, unit.options, unit.diagnosticEngine, static_cast(unit.rawParserStatus)); context->parser = &parser; - auto checker = Checker(unit.diagnosticEngine, context->allocator); - context->checker = &checker; + parser.SetContext(context); + auto checker = Checker(context->allocator, unit.diagnosticEngine, context->allocator); + context->parserProgram = &program; + context->PushChecker(&checker); auto analyzer = Analyzer(&checker); - auto phaseManager = compiler::PhaseManager(unit.ext, context->allocator); checker.SetAnalyzer(&analyzer); - context->analyzer = checker.GetAnalyzer(); - context->parserProgram = &program; + context->PushAnalyzer(checker.GetAnalyzer()); context->codeGenCb = MakeCompileJob(); context->diagnosticEngine = &unit.diagnosticEngine; context->phaseManager = &phaseManager; @@ -450,7 +465,7 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp CreateDebuggerEvaluationPlugin(checker, *context->allocator, &program, unit.options); if (context->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { checker.SetCachedComputedAbstracts(context->transitionMemory->CachedComputedAbstracts()); - checker.SetGlobalTypes(context->transitionMemory->GlobalTypes()); + checker.SetGlobalTypesHolder(context->transitionMemory->GlobalTypes()); checker.AddStatus(ark::es2panda::checker::CheckerStatus::BUILTINS_INITIALIZED); } else { checker.InitCachedComputedAbstracts(); @@ -461,11 +476,13 @@ static pandasm::Program *Compile(const CompilationUnit &unit, CompilerImpl *comp auto *varbinder = program.VarBinder(); varbinder->SetProgram(&program); varbinder->SetContext(context); - context->checker->Initialize(varbinder); + context->GetChecker()->Initialize(varbinder); if (!ExecuteParsingAndCompiling(unit, context)) { return nullptr; } + + MarkAsLowered(program); return EmitProgram(compilerImpl, context, unit); } diff --git a/ets2panda/compiler/core/pandagen.cpp b/ets2panda/compiler/core/pandagen.cpp index 85ab16b545..3438850966 100644 --- a/ets2panda/compiler/core/pandagen.cpp +++ b/ets2panda/compiler/core/pandagen.cpp @@ -1825,7 +1825,7 @@ const checker::Type *PandaGen::GetVRegType(VReg vreg) const { // We assume that all used regs have any type if (vreg.GetIndex() > NextReg().GetIndex()) { - return Context()->checker->GetGlobalTypesHolder()->GlobalAnyType(); + return Context()->GetChecker()->GetGlobalTypesHolder()->GlobalAnyType(); } return nullptr; diff --git a/ets2panda/compiler/lowering/checkerPhase.cpp b/ets2panda/compiler/lowering/checkerPhase.cpp index 019a5ce570..7f820e8168 100644 --- a/ets2panda/compiler/lowering/checkerPhase.cpp +++ b/ets2panda/compiler/lowering/checkerPhase.cpp @@ -15,21 +15,40 @@ #include "checkerPhase.h" #include "checker/checker.h" +#include "checker/ETSchecker.h" namespace ark::es2panda::compiler { +void CheckerPhase::FetchCache(public_lib::Context *ctx, parser::Program *program) +{ + // for ast-cache using + if (program->VarBinder()->Extension() != ScriptExtension::ETS) { + return; + } + ctx->GetChecker()->AsETSChecker()->ReputCheckerData(); +} + +void CheckerPhase::MarkStatementsNoCleanup(parser::Program *program) +{ + for (auto stmt : program->Ast()->Statements()) { + stmt->AddAstNodeFlags(ir::AstNodeFlags::NOCLEANUP); + } +} + bool CheckerPhase::Perform(public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) { + ctx->GetChecker()->Initialize(program->VarBinder()); + FetchCache(ctx, program); for (auto [_, programList] : program->ExternalSources()) { for (auto prog : programList) { - for (auto stmt : prog->Ast()->Statements()) { - stmt->AddAstNodeFlags(ir::AstNodeFlags::NOCLEANUP); + if (!prog->IsASTLowered()) { + MarkStatementsNoCleanup(prog); } } } for (auto stmt : program->Ast()->Statements()) { stmt->AddAstNodeFlags(ir::AstNodeFlags::NOCLEANUP); } - auto checkerResult = ctx->checker->StartChecker(ctx->parserProgram->VarBinder(), *ctx->config->options); + auto checkerResult = ctx->GetChecker()->StartChecker(ctx->parserProgram->VarBinder(), *ctx->config->options); return checkerResult; } diff --git a/ets2panda/compiler/lowering/checkerPhase.h b/ets2panda/compiler/lowering/checkerPhase.h index 03b9e6979b..f9a915da10 100644 --- a/ets2panda/compiler/lowering/checkerPhase.h +++ b/ets2panda/compiler/lowering/checkerPhase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,8 +26,11 @@ public: { return NAME; } + void FetchCache(public_lib::Context *ctx, parser::Program *program) override; bool Perform(public_lib::Context *ctx, parser::Program *program) override; + + void MarkStatementsNoCleanup(parser::Program *program); }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/ambientLowering.cpp b/ets2panda/compiler/lowering/ets/ambientLowering.cpp index b07f25dc9b..3a52acabc8 100644 --- a/ets2panda/compiler/lowering/ets/ambientLowering.cpp +++ b/ets2panda/compiler/lowering/ets/ambientLowering.cpp @@ -92,13 +92,22 @@ ir::AstNode *AmbientLowering::CreateIndexerMethodIfNeeded(ir::AstNode *ast, publ return ast; } - ArenaVector &classBody = + const ArenaVector &classBodyConst = ast->IsClassDefinition() ? ast->AsClassDefinition()->Body() : ast->AsTSInterfaceBody()->Body(); - auto it = classBody.begin(); // Only one DummyNode is allowed in classBody for now - ES2PANDA_ASSERT( - std::count_if(classBody.begin(), classBody.end(), [](ir::AstNode *node) { return node->IsDummyNode(); }) <= 1); + ES2PANDA_ASSERT(std::count_if(classBodyConst.cbegin(), classBodyConst.cend(), + [](const ir::AstNode *node) { return node->IsDummyNode(); }) <= 1); + if (!std::any_of(classBodyConst.cbegin(), classBodyConst.cend(), [](const ir::AstNode *node) { + return node->IsDummyNode() && node->AsDummyNode()->IsDeclareIndexer(); + })) { + return ast; + } + + ArenaVector &classBody = + ast->IsClassDefinition() ? ast->AsClassDefinition()->BodyForUpdate() : ast->AsTSInterfaceBody()->Body(); + + auto it = classBody.begin(); while (it != classBody.end()) { if ((*it)->IsDummyNode() && (*it)->AsDummyNode()->IsDeclareIndexer()) { auto setDefinition = diff --git a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp index a9aa187de8..bf9fea2cc5 100644 --- a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp @@ -231,7 +231,7 @@ bool ArrayLiteralLowering::PerformForModule(public_lib::Context *ctx, parser::Pr { parser_ = ctx->parser->AsETSParser(); varbinder_ = ctx->parserProgram->VarBinder()->AsETSBinder(); - checker_ = ctx->checker->AsETSChecker(); + checker_ = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( [this](ir::AstNode *ast) -> AstNodePtr { if (ast->IsArrayExpression()) { diff --git a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp index d801b5526c..9645a5ff5d 100644 --- a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp +++ b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp @@ -126,7 +126,7 @@ ir::MethodDefinition *CreateAsyncProxy(checker::ETSChecker *checker, ir::MethodD { ir::ScriptFunction *asyncFunc = asyncMethod->Function(); if (!asyncFunc->IsExternal()) { - checker->VarBinder()->AsETSBinder()->GetRecordTable()->Signatures().push_back(asyncFunc->Scope()); + checker->VarBinder()->AsETSBinder()->GetRecordTable()->EmplaceSignatures(asyncFunc->Scope(), asyncFunc); } ir::MethodDefinition *implMethod = CreateAsyncImplMethod(checker, asyncMethod, classDef); @@ -170,7 +170,7 @@ void ComposeAsyncImplMethod(checker::ETSChecker *checker, ir::MethodDefinition * implMethod->Function()->Id()->SetVariable(baseOverloadImplMethod->Function()->Id()->Variable()); baseOverloadImplMethod->AddOverload(implMethod); } else { - classDef->Body().push_back(implMethod); + classDef->EmplaceBody(implMethod); } } @@ -199,7 +199,7 @@ void UpdateClassDefintion(checker::ETSChecker *checker, ir::ClassDefinition *cla bool AsyncMethodLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); ir::NodeTransformer handleClassAsyncMethod = [checker](ir::AstNode *const ast) { if (ast->IsClassDefinition()) { diff --git a/ets2panda/compiler/lowering/ets/bigintLowering.cpp b/ets2panda/compiler/lowering/ets/bigintLowering.cpp index 132656ee5c..6d40b4592f 100644 --- a/ets2panda/compiler/lowering/ets/bigintLowering.cpp +++ b/ets2panda/compiler/lowering/ets/bigintLowering.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -28,7 +28,7 @@ std::string_view BigIntLowering::Name() const ir::Expression *CreateBigInt(public_lib::Context *ctx, ir::BigIntLiteral *literal) { auto parser = ctx->parser->AsETSParser(); - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); // This will change the bigint literal node into the new class instance expression: // 123456n => new BigInt("123456") @@ -90,7 +90,7 @@ bool RemoveConst(ir::BinaryExpression *expr) bool BigIntLowering::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) { - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style diff --git a/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp b/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp index 4c51f695dd..5ad356570b 100644 --- a/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp +++ b/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp @@ -60,20 +60,9 @@ void BoxNumberLiteralArguments(ir::CallExpression *callExpr, PhaseManager *phase } } -bool BoxedTypeLowering::Perform(public_lib::Context *const ctx, parser::Program *const program) +bool BoxedTypeLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - for (const auto &[_, extPrograms] : program->ExternalSources()) { - (void)_; - for (auto *const extProg : extPrograms) { - if (extProg->GetFlag(parser::ProgramFlags::AST_BOXED_TYPE_LOWERED)) { - continue; - } - Perform(ctx, extProg); - extProg->SetFlag(parser::ProgramFlags::AST_BOXED_TYPE_LOWERED); - } - } - - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); auto parser = ctx->parser->AsETSParser(); auto phaseManager = ctx->phaseManager; program->Ast()->TransformChildrenRecursively( @@ -95,7 +84,6 @@ bool BoxedTypeLowering::Perform(public_lib::Context *const ctx, parser::Program return ast; }, Name()); - return true; } diff --git a/ets2panda/compiler/lowering/ets/boxedTypeLowering.h b/ets2panda/compiler/lowering/ets/boxedTypeLowering.h index cf124f55bb..c7d21d52b0 100644 --- a/ets2panda/compiler/lowering/ets/boxedTypeLowering.h +++ b/ets2panda/compiler/lowering/ets/boxedTypeLowering.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,10 +20,11 @@ namespace ark::es2panda::compiler { -class BoxedTypeLowering : public Phase { +class BoxedTypeLowering : public PhaseForDeclarations { public: std::string_view Name() const override; - bool Perform(public_lib::Context *ctx, parser::Program *program) override; + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp index 2f63e74222..a0a8c9534c 100644 --- a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp +++ b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp @@ -119,7 +119,7 @@ static void HandleFunctionParam(public_lib::Context *ctx, ir::ETSParameterExpres ArenaMap *varsMap) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *varBinder = checker->VarBinder(); auto *id = param->Ident()->AsIdentifier(); @@ -128,7 +128,7 @@ static void HandleFunctionParam(public_lib::Context *ctx, ir::ETSParameterExpres auto *func = param->Parent()->AsScriptFunction(); ES2PANDA_ASSERT(func->Body()->IsBlockStatement()); // guaranteed after expressionLambdaLowering auto *body = func->Body()->AsBlockStatement(); - auto &bodyStmts = body->Statements(); + auto &bodyStmts = body->StatementsForUpdates(); auto *scope = body->Scope(); auto *initId = allocator->New(id->Name(), allocator); @@ -177,7 +177,7 @@ static ir::AstNode *HandleVariableDeclarator(public_lib::Context *ctx, ir::Varia ArenaMap *varsMap) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *varBinder = checker->VarBinder(); auto *id = declarator->Id()->AsIdentifier(); @@ -231,7 +231,7 @@ static bool IsBeingDeclared(ir::AstNode *ast) static bool IsPartOfBoxInitializer(public_lib::Context *ctx, ir::AstNode *ast) { ES2PANDA_ASSERT(ast->IsIdentifier()); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *id = ast->AsIdentifier(); // NOTE(gogabr): rely on caching for type instantiations, so we can use pointer comparison. @@ -248,7 +248,7 @@ static bool OnLeftSideOfAssignment(ir::AstNode *ast) static ir::AstNode *HandleReference(public_lib::Context *ctx, ir::Identifier *id, varbinder::Variable *var) { auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); // `as` is needed to account for smart types auto *res = parser->CreateFormattedExpression("@@I1.get() as @@T2", var->Name(), id->TsType()); @@ -279,8 +279,8 @@ static ir::AstNode *HandleAssignment(public_lib::Context *ctx, ir::AssignmentExp ES2PANDA_ASSERT(ass->OperatorType() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION); auto *parser = ctx->parser->AsETSParser(); - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); - auto *checker = ctx->checker->AsETSChecker(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *oldVar = ass->Left()->Variable(); auto *newVar = varsMap.find(oldVar)->second; diff --git a/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp b/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp index 823859d681..0a3374acc2 100644 --- a/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp +++ b/ets2panda/compiler/lowering/ets/cfgBuilderPhase.cpp @@ -28,7 +28,9 @@ bool CFGBuilderPhase::Perform(public_lib::Context *ctx, parser::Program *program for (auto &[_, ext_programs] : program->ExternalSources()) { (void)_; for (auto *extProg : ext_programs) { - Perform(ctx, extProg); + if (!extProg->IsASTLowered()) { + Perform(ctx, extProg); + } } } diff --git a/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp b/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp index 9d232d1db0..3f5c3219af 100644 --- a/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp +++ b/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp @@ -47,7 +47,7 @@ static ir::AstNode *ConvertMemberExpressionToAsExpression(ir::CallExpression *ca bool ConvertPrimitiveCastMethodCall::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) { - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [checker](checker::AstNodePtr ast) -> checker::AstNodePtr { diff --git a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp index 613fcf10d2..c1e53dd59b 100644 --- a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp @@ -24,7 +24,7 @@ namespace ark::es2panda::compiler { void GenerateOverloadHelperParams(public_lib::Context *ctx, uint32_t minArg, size_t maxArg, bool hasRestVar, ArenaVector ¶ms) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *allocator = ctx->allocator; if (!hasRestVar) { @@ -58,9 +58,9 @@ void GenerateOverloadHelperParams(public_lib::Context *ctx, uint32_t minArg, siz void BuildOverloadHelperFunction(public_lib::Context *ctx, ir::MethodDefinition *method) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *allocator = ctx->allocator; - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); auto const &[minArg, maxArg, needHelperOverload, isDeclare, hasRestVar, returnVoid] = method->GetOverloadInfo(); ES2PANDA_ASSERT(needHelperOverload); @@ -107,7 +107,7 @@ void UpdateCallSignature(public_lib::Context *ctx, ir::CallExpression *expr) { ES2PANDA_ASSERT(expr->Signature()->HasSignatureFlag(checker::SignatureFlags::DUPLICATE_ASM)); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); expr->SetTsType(nullptr); expr->Check(checker); } diff --git a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp index d9ede70dc7..bf69507850 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp @@ -185,7 +185,7 @@ static void CreateFunctionOverload(ir::MethodDefinition *method, ArenaVectorSetRange(funcExpression->Range()); if (!method->IsDeclare() && method->Parent()->IsTSInterfaceBody()) { - overloadMethod->Function()->Body()->AsBlockStatement()->Statements().clear(); + overloadMethod->Function()->Body()->AsBlockStatement()->ClearStatements(); } method->AddOverload(overloadMethod); @@ -214,7 +214,15 @@ static void ClearOptionalParameters(public_lib::Context *ctx, ir::ScriptFunction { auto allocator = ctx->allocator; - for (auto *¶m : function->Params()) { + auto const ¶ms = function->Params(); + bool hasOptional = std::any_of(params.cbegin(), params.cend(), + [](ir::Expression *p) { return p->AsETSParameterExpression()->IsOptional(); }); + if (!hasOptional) { + return; + } + + auto ¶msToChange = function->ParamsForUpdate(); + for (auto *¶m : paramsToChange) { auto oldParam = param->AsETSParameterExpression(); if (oldParam->IsOptional()) { param = util::NodeAllocator::ForceSetParent(allocator, oldParam->Ident(), false, diff --git a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp index 55a77785c4..e6bffbeee3 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp @@ -57,13 +57,14 @@ static void TransformDefaultParameters(public_lib::Context *ctx, ir::ScriptFunct auto const body = function->Body()->AsBlockStatement(); auto const allocator = ctx->allocator; auto const parser = ctx->parser->AsETSParser(); + auto &bodyStmt = body->StatementsForUpdates(); - body->Statements().insert(body->Statements().begin(), params.size(), nullptr); + bodyStmt.insert(bodyStmt.begin(), params.size(), nullptr); for (size_t dfltIdx = 0; dfltIdx < params.size(); ++dfltIdx) { auto const param = params.at(dfltIdx); auto stmt = TransformInitializer(allocator, parser, param); - body->Statements()[dfltIdx] = stmt; + bodyStmt[dfltIdx] = stmt; stmt->SetParent(body); } } diff --git a/ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp b/ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp index 8cf9e00c33..b4d6f19d1b 100644 --- a/ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp +++ b/ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp @@ -21,7 +21,7 @@ namespace ark::es2panda::compiler { bool DynamicImportLowering::PerformForModule(public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) { - ctx->checker->AsETSChecker()->BuildDynamicImportClass(); + ctx->GetChecker()->AsETSChecker()->BuildDynamicImportClass(); return true; } diff --git a/ets2panda/compiler/lowering/ets/enumLowering.cpp b/ets2panda/compiler/lowering/ets/enumLowering.cpp index f13666933d..8a503952b4 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumLowering.cpp @@ -60,7 +60,7 @@ ir::MethodDefinition *MakeMethodDef(public_lib::Context *ctx, ir::ClassDefinitio auto *const methodDef = ctx->AllocNode( ir::MethodDefinitionKind::METHOD, identClone, functionExpr, function->Modifiers(), ctx->Allocator(), false); methodDef->SetParent(enumClass); - enumClass->Body().push_back(methodDef); + enumClass->EmplaceBody(methodDef); return methodDef; } @@ -152,7 +152,7 @@ template arrayIdent, arrayExpr, typeAnnotation, ir::ModifierFlags::STATIC | ir::ModifierFlags::PRIVATE | ir::ModifierFlags::READONLY, Allocator(), false); arrayClassProp->SetParent(enumClass); - enumClass->Body().push_back(arrayClassProp); + enumClass->EmplaceBody(arrayClassProp); return arrayIdent; } @@ -208,7 +208,7 @@ void EnumLoweringPhase::CreateEnumItemFields(const ir::TSEnumDeclaration *const return field; }; for (auto *const member : enumDecl->Members()) { - enumClass->Body().push_back(createEnumItemField(member->AsTSEnumMember())); + enumClass->EmplaceBody(createEnumItemField(member->AsTSEnumMember())); } } @@ -316,7 +316,7 @@ void EnumLoweringPhase::CreateCCtorForEnumClass(ir::ClassDefinition *const enumC AllocNode(ir::MethodDefinitionKind::METHOD, identClone, funcExpr, ir::ModifierFlags::PRIVATE | ir::ModifierFlags::STATIC, Allocator(), false); methodDef->SetParent(enumClass); - enumClass->Body().push_back(methodDef); + enumClass->EmplaceBody(methodDef); } ir::ClassProperty *EnumLoweringPhase::CreateOrdinalField(ir::ClassDefinition *const enumClass) @@ -327,7 +327,7 @@ ir::ClassProperty *EnumLoweringPhase::CreateOrdinalField(ir::ClassDefinition *co AllocNode(fieldIdent, nullptr, intTypeAnnotation, ir::ModifierFlags::PRIVATE | ir::ModifierFlags::READONLY, Allocator(), false); - enumClass->Body().push_back(field); + enumClass->EmplaceBody(field); field->SetParent(enumClass); return field; } @@ -377,7 +377,7 @@ ir::ScriptFunction *EnumLoweringPhase::CreateFunctionForCtorOfEnumClass(ir::Clas auto *superConstructorCall = AllocNode(callee, std::move(callArguments), nullptr, false); auto *superCallStatement = AllocNode(superConstructorCall); superCallStatement->SetParent(body); - body->Statements().push_back(superCallStatement); + body->AddStatement(superCallStatement); auto *thisExpr = Allocator()->New(); auto *fieldIdentifier = Allocator()->New(ORDINAL_NAME, Allocator()); @@ -389,7 +389,7 @@ ir::ScriptFunction *EnumLoweringPhase::CreateFunctionForCtorOfEnumClass(ir::Clas AllocNode(leftHandSide, rightHandSide, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); auto initStatement = AllocNode(initializer); initStatement->SetParent(body); - body->Statements().push_back(initStatement); + body->AddStatement(initStatement); return func; } @@ -403,7 +403,7 @@ void EnumLoweringPhase::CreateCtorForEnumClass(ir::ClassDefinition *const enumCl auto *const methodDef = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, identClone, funcExpr, ir::ModifierFlags::PUBLIC, Allocator(), false); methodDef->SetParent(enumClass); - enumClass->Body().push_back(methodDef); + enumClass->EmplaceBody(methodDef); } void EnumLoweringPhase::ProcessEnumClassDeclaration(ir::TSEnumDeclaration *const enumDecl, @@ -539,7 +539,7 @@ bool EnumLoweringPhase::PerformForModule(public_lib::Context *ctx, parser::Progr } context_ = ctx; - checker_ = ctx->checker->AsETSChecker(); + checker_ = ctx->GetChecker()->AsETSChecker(); varbinder_ = ctx->parserProgram->VarBinder()->AsETSBinder(); program_ = program; diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index 6e555c258c..a46a63ea5e 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp @@ -150,7 +150,7 @@ static ir::CallExpression *CreateCallInstanceEnumExpression(public_lib::Context auto *calleeClass = FindEnclosingClass(expr); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *varBinder = checker->VarBinder()->AsETSBinder(); auto *nearestScope = NearestScope(parent); @@ -370,7 +370,7 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars context_ = ctx; parser_ = ctx->parser->AsETSParser(); - checker_ = ctx->checker->AsETSChecker(); + checker_ = ctx->GetChecker()->AsETSChecker(); varbinder_ = ctx->parserProgram->VarBinder()->AsETSBinder(); program->Ast()->TransformChildrenRecursivelyPostorder( diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index dbe2fd35b1..1dccd5d05d 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -42,7 +42,7 @@ ir::Expression *ExpandBracketsPhase::ProcessNewArrayInstanceExpression( { auto *const parser = ctx->parser->AsETSParser(); ES2PANDA_ASSERT(parser != nullptr); - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); ES2PANDA_ASSERT(checker != nullptr); auto *dimension = newInstanceExpression->Dimension(); auto *dimType = dimension->TsType(); @@ -84,7 +84,7 @@ ir::Expression *ExpandBracketsPhase::ProcessNewMultiDimArrayInstanceExpression( { auto *const parser = ctx->parser->AsETSParser(); ES2PANDA_ASSERT(parser != nullptr); - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); ES2PANDA_ASSERT(checker != nullptr); ir::BlockExpression *returnExpression = nullptr; @@ -146,7 +146,7 @@ ir::Expression *ExpandBracketsPhase::CreateNewMultiDimArrayInstanceExpression( newInstanceExpression->SetTsType(nullptr); blockExpression->AddStatement(ctx->AllocNode(newInstanceExpression)); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); InitScopesPhaseETS::RunExternalNode(blockExpression, checker->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(blockExpression, NearestScope(blockExpression)); blockExpression->Check(checker); diff --git a/ets2panda/compiler/lowering/ets/exportAnonymousConst.cpp b/ets2panda/compiler/lowering/ets/exportAnonymousConst.cpp index 3cb3fd1c24..d67d756dec 100644 --- a/ets2panda/compiler/lowering/ets/exportAnonymousConst.cpp +++ b/ets2panda/compiler/lowering/ets/exportAnonymousConst.cpp @@ -57,14 +57,17 @@ static void HandleAnonymousConst(public_lib::Context *const ctx, parser::Program [](auto *specific) { return specific->IsDefault() && specific->GetConstantExpression() != nullptr; }); }; auto module = program->Ast(); - auto iterator = std::find_if(module->Statements().begin(), module->Statements().end(), isExportAnonymousConst); - if (iterator == module->Statements().end()) { + auto iteratorForFind = + std::find_if(module->Statements().begin(), module->Statements().end(), isExportAnonymousConst); + if (iteratorForFind == module->Statements().end()) { return; } + auto &stmt = module->StatementsForUpdates(); + auto iterator = std::find_if(stmt.begin(), stmt.end(), isExportAnonymousConst); auto *anonymousVariableDecl = CreateAnonymousVariableDecl(ctx, (*iterator)->AsExportNamedDeclaration())->AsStatement(); - module->Statements().insert(iterator, anonymousVariableDecl); + stmt.insert(iterator, anonymousVariableDecl); } static void HandleExportDefaultInExportNamedDecl(public_lib::Context *const ctx, parser::Program *const program) @@ -85,12 +88,16 @@ static void HandleExportDefaultInExportNamedDecl(public_lib::Context *const ctx, }; auto module = program->Ast(); - auto iterator = + auto iteratorConst = std::find_if(module->Statements().begin(), module->Statements().end(), exportNamedDeclarationhasDefault); - if (iterator == module->Statements().end()) { + if (iteratorConst == module->Statements().end()) { return; } + auto &stmt = module->StatementsForUpdates(); + + auto iterator = std::find_if(stmt.begin(), stmt.end(), exportNamedDeclarationhasDefault); + auto *allocator = ctx->allocator; auto *exportNamedDeclaration = (*iterator)->AsExportNamedDeclaration(); auto oldSpecifiers = exportNamedDeclaration->Specifiers(); @@ -110,20 +117,13 @@ static void HandleExportDefaultInExportNamedDecl(public_lib::Context *const ctx, newSpecifiers.push_back(specifier); } - module->Statements().insert(iterator, exportDefaulNamedDeclarations.front()); + stmt.insert(iterator, exportDefaulNamedDeclarations.front()); exportNamedDeclaration->ReplaceSpecifiers(newSpecifiers); exportNamedDeclaration->ClearModifier(ir::ModifierFlags::DEFAULT_EXPORT); } -bool ExportAnonymousConstPhase::Perform(public_lib::Context *const ctx, parser::Program *const program) +bool ExportAnonymousConstPhase::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) { - for (auto &[_, ext_programs] : program->ExternalSources()) { - (void)_; - for (auto *extProg : ext_programs) { - Perform(ctx, extProg); - } - } - HandleExportDefaultInExportNamedDecl(ctx, program); HandleAnonymousConst(ctx, program); return true; diff --git a/ets2panda/compiler/lowering/ets/exportAnonymousConst.h b/ets2panda/compiler/lowering/ets/exportAnonymousConst.h index ba1b37d491..13c3e56bc2 100644 --- a/ets2panda/compiler/lowering/ets/exportAnonymousConst.h +++ b/ets2panda/compiler/lowering/ets/exportAnonymousConst.h @@ -20,14 +20,14 @@ namespace ark::es2panda::compiler { -class ExportAnonymousConstPhase : public Phase { +class ExportAnonymousConstPhase : public PhaseForDeclarations { public: std::string_view Name() const override { return "ExportAnonymousConstPhase"; } - bool Perform(public_lib::Context *ctx, parser::Program *program) override; + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp index ab70ff5880..bb3fcbff99 100644 --- a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp @@ -133,7 +133,7 @@ bool ExtensionAccessorPhase::PerformForModule(public_lib::Context *ctx, parser:: return true; } - checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( [&checker](ir::AstNode *const node) -> AstNodePtr { return CheckAndReturnNode(checker, node); }, Name()); return true; diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp index 36ce44662c..1aa0c072ea 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp @@ -91,7 +91,7 @@ void GenericBridgesPhase::AddGenericBridge(ir::ClassDefinition const *const clas bridgeMethod->AddAstNodeFlags(methodDefinition->GetAstNodeFlags()); bridgeMethod->SetParent(const_cast(classDefinition)); - auto *varBinder = context_->checker->VarBinder()->AsETSBinder(); + auto *varBinder = context_->GetChecker()->VarBinder()->AsETSBinder(); auto *scope = NearestScope(methodDefinition); auto scopeGuard = varbinder::LexicalScope::Enter(varBinder, scope); InitScopesPhaseETS::RunExternalNode(bridgeMethod, varBinder); @@ -100,7 +100,7 @@ void GenericBridgesPhase::AddGenericBridge(ir::ClassDefinition const *const clas true}; varBinder->AsETSBinder()->ResolveReferencesForScopeWithContext(bridgeMethod, scope); - auto *checker = context_->checker->AsETSChecker(); + auto *checker = context_->GetChecker()->AsETSChecker(); auto const checkerCtx = checker::SavedCheckerContext(checker, checker::CheckerStatus::IN_CLASS | checker::CheckerStatus::IGNORE_VISIBILITY | @@ -128,7 +128,7 @@ void GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const ir::MethodDefinition *const derivedMethod, Substitutions const &substitutions) const { - auto *const checker = context_->checker->AsETSChecker(); + auto *const checker = context_->GetChecker()->AsETSChecker(); auto *const relation = checker->Relation(); auto const overrides = [checker, relation, classDefinition](checker::Signature const *source, @@ -199,7 +199,7 @@ void GenericBridgesPhase::CreateGenericBridges(ir::ClassDefinition const *const auto const &classBody = classDefinition->Body(); // Collect type parameters defaults/constraints in the derived class - auto *checker = context_->checker->AsETSChecker(); + auto *checker = context_->GetChecker()->AsETSChecker(); substitutions.derivedConstraints = checker->NewSubstitution(); auto const *const classType = classDefinition->TsType()->AsETSObjectType(); @@ -239,7 +239,7 @@ GenericBridgesPhase::Substitutions GenericBridgesPhase::GetSubstitutions( auto const parameterNumber = typeParameters.size(); ES2PANDA_ASSERT(parameterNumber == typeArguments.size()); - auto *checker = context_->checker->AsETSChecker(); + auto *checker = context_->GetChecker()->AsETSChecker(); Substitutions substitutions {}; substitutions.derivedSubstitutions = checker->NewSubstitution(); substitutions.baseConstraints = checker->NewSubstitution(); diff --git a/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.cpp b/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.cpp index d8bd398120..44d8ae95b5 100644 --- a/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.cpp +++ b/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.cpp @@ -98,7 +98,7 @@ static void TryInsertDefaultAnnotation(public_lib::Context *ctx, ir::AstNode *no auto methodFunc = methodDef->Function(); auto defaultAnno = CreateDefaultAnnotationUsageForFunction(ctx, methodFunc); if (defaultAnno != nullptr) { - methodFunc->Annotations().emplace_back(defaultAnno->AsAnnotationUsage()); + methodFunc->EmplaceAnnotations(defaultAnno->AsAnnotationUsage()); defaultAnno->SetParent(methodFunc); RefineSourceRanges(defaultAnno); } diff --git a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp index 7b00e071ae..c88ab3572b 100644 --- a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp @@ -48,7 +48,7 @@ static inline bool IsAbstractClassType(const checker::Type *type) static ir::AstNode *CreateAnonClassImplCtor(public_lib::Context *ctx, ArenaVector &readonlyFields) { - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); auto *const parser = ctx->parser->AsETSParser(); checker::ETSChecker::ClassInitializerBuilder initBuilder = [ctx, checker, parser, readonlyFields](ArenaVector *statements, @@ -204,14 +204,14 @@ static void AnnotateGeneratedAnonClass(checker::ETSChecker *checker, ir::ClassDe annoUsage->AddModifier(ir::ModifierFlags::ANNOTATION_USAGE); annoUsage->SetParent(classDef); annoId->SetParent(annoUsage); - classDef->Annotations().emplace_back(annoUsage); + classDef->AddAnnotations(annoUsage); RefineSourceRanges(annoUsage); CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, annoUsage); } static void GenerateAnonClassTypeFromInterface(public_lib::Context *ctx, ir::TSInterfaceDeclaration *ifaceNode) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); if (ifaceNode->GetAnonClass() != nullptr) { return; @@ -255,7 +255,7 @@ static void GenerateAnonClassTypeFromInterface(public_lib::Context *ctx, ir::TSI auto *classImplements = ctx->AllocNode( ctx->AllocNode(ifaceNode->TsType(), ctx->Allocator())); classImplements->SetParent(classDef); - classDef->Implements().emplace_back(classImplements); + classDef->EmplaceImplements(classImplements); classType->RemoveObjectFlag(checker::ETSObjectFlags::RESOLVED_INTERFACES); checker->GetInterfacesOfClass(classType); @@ -264,7 +264,7 @@ static void GenerateAnonClassTypeFromInterface(public_lib::Context *ctx, ir::TSI static void GenerateAnonClassTypeFromAbstractClass(public_lib::Context *ctx, ir::ClassDefinition *abstractClassNode) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); if (abstractClassNode->GetAnonClass() != nullptr) { return; @@ -341,7 +341,7 @@ static checker::Type *ProcessDeclNode(checker::ETSChecker *checker, checker::ETS static void HandleInterfaceLowering(public_lib::Context *ctx, ir::ObjectExpression *objExpr) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *targetType = objExpr->TsType(); checker->CheckObjectLiteralKeys(objExpr->Properties()); @@ -433,6 +433,9 @@ bool InterfaceObjectLiteralLowering::Perform(public_lib::Context *ctx, parser::P for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { + if (extProg->IsASTLowered()) { + continue; + } auto *savedProgram = varbinder->Program(); auto *savedRecordTable = varbinder->GetRecordTable(); auto *savedTopScope = varbinder->TopScope(); @@ -451,6 +454,9 @@ bool InterfaceObjectLiteralLowering::Perform(public_lib::Context *ctx, parser::P for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { + if (extProg->IsASTLowered()) { + continue; + } TransfromInterfaceLiteral(ctx, extProg); } } diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 15f279ea37..782f6e5c10 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -75,16 +75,19 @@ static bool CheckIfNeedThis(ir::ArrowFunctionExpression *lambda, checker::ETSChe } static size_t g_calleeCount = 0; +static std::mutex g_calleeCountMutex {}; // Make calleeCount behaviour predictable static void ResetCalleeCount() { + std::lock_guard lock(g_calleeCountMutex); g_calleeCount = 0; } static util::StringView CreateCalleeName(ArenaAllocator *allocator) { auto name = util::UString(util::StringView("lambda$invoke$"), allocator); + std::lock_guard lock(g_calleeCountMutex); name.Append(std::to_string(g_calleeCount++)); return name.View(); } @@ -98,7 +101,7 @@ static std::pair Clon } auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *newScope = allocator->New(allocator, enclosingScope); auto newTypeParams = ArenaVector(allocator->Adapter()); @@ -160,8 +163,8 @@ ParamsAndVarMap CreateLambdaCalleeParameters(public_lib::Context *ctx, ir::Arrow varbinder::ParamScope *paramScope, checker::Substitution *substitution) { auto allocator = ctx->allocator; - auto checker = ctx->checker->AsETSChecker(); - auto varBinder = ctx->checker->VarBinder(); + auto checker = ctx->GetChecker()->AsETSChecker(); + auto varBinder = ctx->GetChecker()->VarBinder(); auto resParams = ArenaVector(allocator->Adapter()); auto varMap = ArenaMap(allocator->Adapter()); @@ -261,7 +264,7 @@ static ir::MethodDefinition *SetUpCalleeMethod(public_lib::Context *ctx, LambdaI varbinder::Scope *scopeForMethod) { auto *allocator = ctx->allocator; - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); auto *calleeClass = info->calleeClass; auto *funcScope = func->Scope(); @@ -278,7 +281,7 @@ static ir::MethodDefinition *SetUpCalleeMethod(public_lib::Context *ctx, LambdaI auto *funcExpr = util::NodeAllocator::ForceSetParent(allocator, func); auto *method = util::NodeAllocator::ForceSetParent( allocator, ir::MethodDefinitionKind::METHOD, calleeNameClone, funcExpr, modifierFlags, allocator, false); - calleeClass->Definition()->Body().push_back(method); + calleeClass->Definition()->EmplaceBody(method); method->SetParent(calleeClass->Definition()); auto *var = @@ -300,9 +303,9 @@ static ir::MethodDefinition *SetUpCalleeMethod(public_lib::Context *ctx, LambdaI varbinder::BoundContext bctx {varBinder->GetRecordTable(), calleeClass->Definition(), true}; varBinder->ResolveReferencesForScopeWithContext(func, funcScope); - auto checkerCtx = checker::SavedCheckerContext(ctx->checker, checker::CheckerStatus::IN_CLASS, + auto checkerCtx = checker::SavedCheckerContext(ctx->GetChecker(), checker::CheckerStatus::IN_CLASS, calleeClass->Definition()->TsType()->AsETSObjectType()); - method->Check(ctx->checker->AsETSChecker()); + method->Check(ctx->GetChecker()->AsETSChecker()); return method; } @@ -312,8 +315,8 @@ static ir::MethodDefinition *CreateCalleeMethod(public_lib::Context *ctx, ir::Ar LambdaInfo const *info, CalleeMethodInfo const *cmInfo) { auto *allocator = ctx->allocator; - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); - auto *checker = ctx->checker->AsETSChecker(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *classScope = info->calleeClass->Definition()->Scope()->AsClassScope(); @@ -381,7 +384,7 @@ static ir::MethodDefinition *CreateCallee(public_lib::Context *ctx, ir::ArrowFun LambdaInfo const *info) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *body = lambda->Function()->Body()->AsBlockStatement(); auto calleeName = lambda->Function()->IsAsyncFunc() ? (util::UString {checker::ETSChecker::GetAsyncImplName(info->name), allocator}).View() @@ -420,7 +423,7 @@ static void CreateLambdaClassFields(public_lib::Context *ctx, ir::ClassDefinitio { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto props = ArenaVector(allocator->Adapter()); if (info->callReceiver != nullptr) { @@ -445,7 +448,7 @@ static void CreateLambdaClassConstructor(public_lib::Context *ctx, ir::ClassDefi { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto params = ArenaVector(allocator->Adapter()); auto makeParam = [checker, allocator, substitution, ¶ms](util::StringView name, checker::Type *type) { @@ -491,7 +494,7 @@ static void CreateLambdaClassConstructor(public_lib::Context *ctx, ir::ClassDefi allocator, ir::MethodDefinitionKind::CONSTRUCTOR, constructorId->Clone(allocator, nullptr), funcExpr, ir::ModifierFlags::NONE, allocator, false); - classDefinition->Body().push_back(ctor); + classDefinition->EmplaceBody(ctor); ctor->SetParent(classDefinition); } @@ -506,7 +509,7 @@ static ArenaVector CreateRestArgumentsArrayReall auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *restParameterType = lciInfo->lambdaSignature->RestVar()->TsType(); auto *restParameterSubstituteType = restParameterType->Substitute(checker->Relation(), lciInfo->substitution); @@ -560,14 +563,14 @@ static ArenaVector CreateRestArgumentsArrayReall checker->MaybeBoxType(elementType), restParameterIndex, restParameterIndex); } - return ArenaVector(std::move(args->AsBlockStatement()->Statements())); + return ArenaVector(args->AsBlockStatement()->Statements()); } static void CreateInvokeMethodRestParameter(public_lib::Context *ctx, LambdaClassInvokeInfo *lciInfo, ArenaVector *params) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *anyType = checker->GlobalETSNullishObjectType(); auto *restIdent = Gensym(allocator); @@ -595,7 +598,7 @@ static ArenaVector CreateCallArgumentsForLambdaClassInvoke(pub { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto callArguments = ArenaVector(allocator->Adapter()); for (auto *captured : *info->capturedVars) { @@ -670,7 +673,7 @@ static ir::BlockStatement *CreateLambdaClassInvokeBody(public_lib::Context *ctx, { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *anyType = checker->GlobalETSNullishObjectType(); auto *call = CreateCallForLambdaClassInvoke(ctx, info, lciInfo, wrapToObject); @@ -698,7 +701,7 @@ static void CreateLambdaClassInvokeMethod(public_lib::Context *ctx, LambdaInfo c bool wrapToObject) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *anyType = checker->GlobalETSNullishObjectType(); auto params = ArenaVector(allocator->Adapter()); @@ -738,7 +741,7 @@ static void CreateLambdaClassInvokeMethod(public_lib::Context *ctx, LambdaInfo c false); ES2PANDA_ASSERT(!invokeMethod->IsStatic()); - lciInfo->classDefinition->Body().push_back(invokeMethod); + lciInfo->classDefinition->EmplaceBody(invokeMethod); invokeMethod->SetParent(lciInfo->classDefinition); } @@ -800,8 +803,8 @@ static ir::ClassDeclaration *CreateEmptyLambdaClassDeclaration(public_lib::Conte { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); - auto *checker = ctx->checker->AsETSChecker(); - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *checker = ctx->GetChecker()->AsETSChecker(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); auto lambdaClassName = util::UString {std::string_view {"LambdaObject-"}, allocator}; lambdaClassName.Append(info->calleeClass->Definition()->Ident()->Name()).Append("$").Append(info->name); @@ -822,7 +825,7 @@ static ir::ClassDeclaration *CreateEmptyLambdaClassDeclaration(public_lib::Conte auto *classDefinition = classDeclaration->Definition(); // Adjust the class definition compared to what the parser gives. - classDefinition->Body().clear(); // remove the default empty constructor + classDefinition->ClearBody(); // remove the default empty constructor classDefinition->AddModifier(ir::ModifierFlags::PUBLIC | ir::ModifierFlags::FUNCTIONAL); if (newTypeParams != nullptr) { classDefinition->SetTypeParams(newTypeParams); @@ -830,7 +833,7 @@ static ir::ClassDeclaration *CreateEmptyLambdaClassDeclaration(public_lib::Conte } auto *program = varBinder->GetRecordTable()->Program(); - program->Ast()->Statements().push_back(classDeclaration); + program->Ast()->AddStatement(classDeclaration); classDeclaration->SetParent(program->Ast()); return classDeclaration; @@ -839,8 +842,8 @@ static ir::ClassDeclaration *CreateEmptyLambdaClassDeclaration(public_lib::Conte static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker::ETSFunctionType *fntype, ir::MethodDefinition *callee, LambdaInfo const *info) { - auto *checker = ctx->checker->AsETSChecker(); - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *checker = ctx->GetChecker()->AsETSChecker(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); auto *oldTypeParams = (info->enclosingFunction != nullptr) ? info->enclosingFunction->TypeParams() : nullptr; auto [newTypeParams, subst0] = @@ -895,8 +898,8 @@ static ir::ETSNewClassInstanceExpression *CreateConstructorCall(public_lib::Cont LambdaInfo const *info) { auto *allocator = ctx->allocator; - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); - auto *checker = ctx->checker->AsETSChecker(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto args = ArenaVector(allocator->Adapter()); if (info->callReceiver != nullptr) { @@ -923,9 +926,9 @@ static ir::ETSNewClassInstanceExpression *CreateConstructorCall(public_lib::Cont auto lexScope = varbinder::LexicalScope::Enter(varBinder, nearestScope); varBinder->ResolveReferencesForScopeWithContext(newExpr, nearestScope); - auto checkerCtx = checker::SavedCheckerContext(ctx->checker, checker::CheckerStatus::IN_CLASS, + auto checkerCtx = checker::SavedCheckerContext(ctx->GetChecker(), checker::CheckerStatus::IN_CLASS, info->calleeClass->Definition()->TsType()->AsETSObjectType()); - auto scopeCtx = checker::ScopeContext(ctx->checker, nearestScope); + auto scopeCtx = checker::ScopeContext(ctx->GetChecker(), nearestScope); newExpr->Check(checker); return newExpr; @@ -934,7 +937,7 @@ static ir::ETSNewClassInstanceExpression *CreateConstructorCall(public_lib::Cont static ir::AstNode *ConvertLambda(public_lib::Context *ctx, ir::ArrowFunctionExpression *lambda) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); lambda->Check(checker); ES2PANDA_ASSERT(lambda->TsType()->IsETSFunctionType()); @@ -994,7 +997,7 @@ static ir::ScriptFunction *GetWrappingLambdaParentFunction(public_lib::Context * auto *callExpr = util::NodeAllocator::ForceSetParent(allocator, funcRef, std::move(callArgs), nullptr, false); ir::Statement *stmt; - if (signature->ReturnType() == ctx->checker->AsETSChecker()->GlobalVoidType()) { + if (signature->ReturnType() == ctx->GetChecker()->AsETSChecker()->GlobalVoidType()) { stmt = util::NodeAllocator::ForceSetParent(allocator, callExpr); } else { stmt = util::NodeAllocator::ForceSetParent(allocator, callExpr); @@ -1008,7 +1011,7 @@ static ir::ScriptFunction *GetWrappingLambdaParentFunction(public_lib::Context * static ir::ArrowFunctionExpression *CreateWrappingLambda(public_lib::Context *ctx, ir::Expression *funcRef) { auto *allocator = ctx->allocator; - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); ES2PANDA_ASSERT(funcRef->TsType()->IsETSArrowType()); auto signature = funcRef->TsType()->AsETSFunctionType()->ArrowSignature(); @@ -1025,10 +1028,10 @@ static ir::ArrowFunctionExpression *CreateWrappingLambda(public_lib::Context *ct auto [enclosingClass, _] = FindEnclosingClassAndFunction(parent); - auto checkerCtx = checker::SavedCheckerContext(ctx->checker, checker::CheckerStatus::IN_CLASS, + auto checkerCtx = checker::SavedCheckerContext(ctx->GetChecker(), checker::CheckerStatus::IN_CLASS, enclosingClass->Definition()->TsType()->AsETSObjectType()); - auto scopeCtx = checker::ScopeContext(ctx->checker, nearestScope); - lambda->Check(ctx->checker->AsETSChecker()); + auto scopeCtx = checker::ScopeContext(ctx->GetChecker(), nearestScope); + lambda->Check(ctx->GetChecker()->AsETSChecker()); return lambda; } @@ -1126,7 +1129,7 @@ static bool IsFunctionOrMethodCall(checker::ETSChecker *checker, ir::CallExpress static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpression *call) { auto *allocator = ctx->allocator; - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *varBinder = checker->VarBinder()->AsETSBinder(); auto *oldCallee = call->Callee(); @@ -1142,6 +1145,7 @@ static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpressio oldType->IsETSFunctionType() && oldType->AsETSFunctionType()->ArrowSignature()->HasRestParameter(); util::StringView invokeMethodName = util::UString {checker::FunctionalInterfaceInvokeName(arity, hasRestParam), allocator}.View(); + auto *prop = ifaceType->GetProperty(invokeMethodName, checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | checker::PropertySearchFlags::SEARCH_IN_INTERFACES); ES2PANDA_ASSERT(prop != nullptr); @@ -1245,7 +1249,7 @@ static ir::AstNode *LowerTypeNodeIfNeeded(public_lib::Context *ctx, ir::AstNode } auto allocator = ctx->allocator; - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); auto newTypeNode = allocator->New(type->AsETSFunctionType()->ArrowToFunctionalInterface(checker), allocator); @@ -1255,7 +1259,7 @@ static ir::AstNode *LowerTypeNodeIfNeeded(public_lib::Context *ctx, ir::AstNode bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - auto *varBinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *varBinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); varbinder::RecordTableContext bctx {varBinder, program == ctx->parserProgram ? nullptr : program}; parser::SavedFormattingFileName savedFormattingName(ctx->parser->AsETSParser(), "lambda-conversion"); @@ -1273,7 +1277,7 @@ bool LambdaConversionPhase::PerformForModule(public_lib::Context *ctx, parser::P auto insertInvokeIfNeeded = [ctx](ir::AstNode *node) { if (node->IsCallExpression() && - !IsFunctionOrMethodCall(ctx->checker->AsETSChecker(), node->AsCallExpression()) && + !IsFunctionOrMethodCall(ctx->GetChecker()->AsETSChecker(), node->AsCallExpression()) && !IsRedirectingConstructorCall(node->AsCallExpression())) { return InsertInvokeCall(ctx, node->AsCallExpression()); } diff --git a/ets2panda/compiler/lowering/ets/lateInitialization.cpp b/ets2panda/compiler/lowering/ets/lateInitialization.cpp index a6e6b95098..108d21c318 100644 --- a/ets2panda/compiler/lowering/ets/lateInitialization.cpp +++ b/ets2panda/compiler/lowering/ets/lateInitialization.cpp @@ -27,7 +27,7 @@ using AstNodePtr = ir::AstNode *; ir::ClassProperty *TransformerClassProperty(public_lib::Context *ctx, ir::ClassProperty *property) { - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); auto allocator = ctx->allocator; // Note: This code will be excluded after primitive type refactoring if (property->TsType()->IsETSPrimitiveType()) { @@ -46,9 +46,9 @@ ir::ClassProperty *TransformerClassProperty(public_lib::Context *ctx, ir::ClassP static ir::AstNode *TransformerMemberExpression(ir::MemberExpression *memberExpr, public_lib::Context *ctx) { - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); auto parser = ctx->parser->AsETSParser(); - auto varbinder = ctx->checker->VarBinder()->AsETSBinder(); + auto varbinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); auto allocator = ctx->Allocator(); auto originalType = memberExpr->TsType(); // Note: This code will be excluded after primitive type refactoring diff --git a/ets2panda/compiler/lowering/ets/localClassLowering.cpp b/ets2panda/compiler/lowering/ets/localClassLowering.cpp index a9b4095219..febb95ab47 100644 --- a/ets2panda/compiler/lowering/ets/localClassLowering.cpp +++ b/ets2panda/compiler/lowering/ets/localClassLowering.cpp @@ -29,7 +29,7 @@ static ir::ClassProperty *CreateCapturedField(public_lib::Context *ctx, const va varbinder::ClassScope *scope, size_t &idx) { auto *allocator = ctx->Allocator(); - auto *varBinder = ctx->checker->AsETSChecker()->VarBinder(); + auto *varBinder = ctx->GetChecker()->AsETSChecker()->VarBinder(); // Enter the lambda class instance field scope, every property will be bound to the lambda instance itself auto fieldCtx = varbinder::LexicalScope::Enter(varBinder, scope->InstanceFieldScope()); @@ -103,7 +103,7 @@ ir::ETSParameterExpression *LocalClassConstructionPhase::CreateParam(public_lib: varbinder::FunctionParamScope *scope, util::StringView name, checker::Type *type) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto newParam = checker->AddParam(name, nullptr); newParam->SetTsType(type); newParam->Ident()->SetTsType(type); @@ -126,8 +126,8 @@ void LocalClassConstructionPhase::ModifyConstructorParameters( for (auto *signature : classType->ConstructSignatures()) { LOG(DEBUG, ES2PANDA) << " - Modifying Constructor: " << signature->InternalName(); auto constructor = signature->Function(); - auto ¶meters = constructor->Params(); auto &sigParams = signature->Params(); + auto ¶meters = constructor->ParamsForUpdate(); signature->GetSignatureInfo()->minArgCount += capturedVars.size(); ES2PANDA_ASSERT(signature == constructor->Signature()); @@ -146,7 +146,7 @@ void LocalClassConstructionPhase::ModifyConstructorParameters( sigParams.insert(sigParams.begin(), newParam->Ident()->Variable()->AsLocalVariable()); parameterMap[var] = newParam->Ident()->Variable()->AsLocalVariable(); } - reinterpret_cast(ctx->checker->AsETSChecker()->VarBinder()) + reinterpret_cast(ctx->GetChecker()->AsETSChecker()->VarBinder()) ->BuildFunctionName(constructor); LOG(DEBUG, ES2PANDA) << " Transformed Constructor: " << signature->InternalName(); @@ -170,7 +170,7 @@ void LocalClassConstructionPhase::ModifyConstructorParameters( initStatements.push_back(initStatement); } if (body != nullptr && body->IsBlockStatement()) { - auto &statements = body->AsBlockStatement()->Statements(); + auto &statements = body->AsBlockStatement()->StatementsForUpdates(); statements.insert(statements.begin(), initStatements.begin(), initStatements.end()); } } @@ -235,7 +235,7 @@ void LocalClassConstructionPhase::HandleLocalClass( bool LocalClassConstructionPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); ArenaUnorderedMap> capturedVarsMap { ctx->allocator->Adapter()}; diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp index deefde6145..1f35c823d6 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp @@ -107,7 +107,7 @@ bool ObjectIndexLowering::PerformForModule(public_lib::Context *ctx, parser::Pro { auto *const parser = ctx->parser->AsETSParser(); ES2PANDA_ASSERT(parser != nullptr); - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); ES2PANDA_ASSERT(checker != nullptr); program->Ast()->TransformChildrenRecursively( diff --git a/ets2panda/compiler/lowering/ets/objectIterator.cpp b/ets2panda/compiler/lowering/ets/objectIterator.cpp index cf43ac31d1..c3136f256e 100644 --- a/ets2panda/compiler/lowering/ets/objectIterator.cpp +++ b/ets2panda/compiler/lowering/ets/objectIterator.cpp @@ -54,7 +54,7 @@ void ObjectIteratorLowering::TransferForOfLoopBody(ir::Statement *const forBody, ir::BlockStatement *const whileBody) const noexcept { ES2PANDA_ASSERT(forBody != nullptr && whileBody != nullptr); - auto &whileStatements = whileBody->Statements(); + auto &whileStatements = whileBody->StatementsForUpdates(); // Currently while loop body consists of 2 statements: 'x = it.value!' and 'it = ci.next()' // We need to insert the body of original for-of-loop between them, change their parent and @@ -128,7 +128,7 @@ ir::Statement *ObjectIteratorLowering::ProcessObjectIterator(public_lib::Context // class has required accessible iterator method and all the types and scopes are properly resolved. auto *const allocator = ctx->Allocator(); - auto *const varbinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *const varbinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); ES2PANDA_ASSERT(varbinder != nullptr); auto statementScope = varbinder::LexicalScope::Enter(varbinder, NearestScope(forOfStatement)); @@ -179,7 +179,7 @@ ir::Statement *ObjectIteratorLowering::ProcessObjectIterator(public_lib::Context ->Body() ->AsBlockStatement()); - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); ES2PANDA_ASSERT(checker != nullptr); CheckLoweredNode(varbinder, checker, loweringResult); diff --git a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp index e24fe2ea47..d0f415917d 100644 --- a/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/objectLiteralLowering.cpp @@ -193,7 +193,7 @@ static void GenerateNewStatements(public_lib::Context *ctx, ir::ObjectExpression for (auto *propExpr : objExpr->Properties()) { // Skip possibly invalid properties: if (!propExpr->IsProperty()) { - ES2PANDA_ASSERT(ctx->checker->AsETSChecker()->IsAnyError()); + ES2PANDA_ASSERT(ctx->GetChecker()->AsETSChecker()->IsAnyError()); continue; } @@ -250,9 +250,9 @@ static ir::AstNode *HandleObjectLiteralLowering(public_lib::Context *ctx, ir::Ob return objExpr; } - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); auto *const parser = ctx->parser->AsETSParser(); - auto *const varbinder = ctx->checker->VarBinder()->AsETSBinder(); + auto *const varbinder = ctx->GetChecker()->VarBinder()->AsETSBinder(); checker->CheckObjectLiteralKeys(objExpr->Properties()); diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index 62e38b69c3..2f6c22e715 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -105,7 +105,7 @@ void AdjustBoxingUnboxingFlags(ir::Expression *loweringResult, const ir::Express static ir::OpaqueTypeNode *CreateProxyTypeNode(public_lib::Context *ctx, ir::Expression *expr) { auto *lcType = expr->TsType(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); if (checker->IsExtensionETSFunctionType(lcType) && expr->IsMemberExpression() && expr->AsMemberExpression()->HasMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR)) { lcType = expr->AsMemberExpression()->ExtensionAccessorType(); @@ -285,7 +285,7 @@ static ir::Expression *ConstructOpAssignmentResult(public_lib::Context *ctx, ir: ir::AstNode *HandleOpAssignment(public_lib::Context *ctx, ir::AssignmentExpression *assignment) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); if (assignment->TsType() == nullptr) { // hasn't been through checker return assignment; @@ -367,7 +367,7 @@ static ir::Expression *ConstructUpdateResult(public_lib::Context *ctx, ir::Updat auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); auto *argument = upd->Argument(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); ArgumentInfo argInfo {}; argInfo.objType = checker->GlobalVoidType(); @@ -412,7 +412,7 @@ static ir::AstNode *HandleUpdate(public_lib::Context *ctx, ir::UpdateExpression ir::Expression *loweringResult = ConstructUpdateResult(ctx, upd); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto expressionCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), scope); checker::SavedCheckerContext scc {checker, checker::CheckerStatus::IGNORE_VISIBILITY, ContainingClass(upd)}; diff --git a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp index 701623fc52..94ce179427 100644 --- a/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/optionalArgumentsLowering.cpp @@ -19,6 +19,7 @@ #include "checker/ETSchecker.h" namespace ark::es2panda::compiler { + static void TransformArguments(public_lib::Context *ctx, ir::Expression *callLike, checker::Signature *signature, ArenaVector &arguments); @@ -52,7 +53,7 @@ static void TransformArguments(public_lib::Context *ctx, ir::Expression *callLik ES2PANDA_ASSERT((callLike->IsCallExpression() && callLike->AsCallExpression()->IsTrailingCall()) || arguments.size() >= signature->MinArgCount()); - auto const checker = ctx->checker->AsETSChecker(); + auto const checker = ctx->GetChecker()->AsETSChecker(); auto const allocator = ctx->allocator; size_t missing = signature->ArgCount() - arguments.size(); diff --git a/ets2panda/compiler/lowering/ets/packageImplicitImport.cpp b/ets2panda/compiler/lowering/ets/packageImplicitImport.cpp index fae3b44254..550acfe703 100644 --- a/ets2panda/compiler/lowering/ets/packageImplicitImport.cpp +++ b/ets2panda/compiler/lowering/ets/packageImplicitImport.cpp @@ -32,7 +32,7 @@ static void MergeExternalFilesIntoCompiledProgram(parser::Program *const program // Because same package files must be in one folder, relative path references in an external // source's import declaration certainly will be the same (and can be resolved) from the global program too - program->Ast()->Statements().emplace_back(stmt); + program->Ast()->AddStatement(stmt); } } } diff --git a/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp b/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp index 19f0157be7..a0814250f8 100644 --- a/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp +++ b/ets2panda/compiler/lowering/ets/partialExportClassGen.cpp @@ -24,19 +24,23 @@ static void GeneratePartialDeclForExported(const public_lib::Context *const ctx, { // NOTE (mmartin): handle interfaces if (node->IsClassDeclaration()) { - ctx->checker->AsETSChecker()->CreatePartialType(node->AsClassDeclaration()->Definition()->TsType()); + ctx->GetChecker()->AsETSChecker()->CreatePartialType(node->AsClassDeclaration()->Definition()->TsType()); + } + if (node->IsTSInterfaceDeclaration()) { + ctx->GetChecker()->AsETSChecker()->CreatePartialType(node->AsTSInterfaceDeclaration()->TsType()); } } bool PartialExportClassGen::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) { program->Ast()->TransformChildrenRecursively( - [ctx, &program](ir::AstNode *const ast) { - if ((ast->IsClassDeclaration() || ast->IsTSInterfaceDeclaration()) && ast->IsExported()) { - auto *const savedProg = ctx->checker->VarBinder()->AsETSBinder()->Program(); - ctx->checker->VarBinder()->AsETSBinder()->SetProgram(program); + [ctx, program](ir::AstNode *const ast) { + if ((ast->IsClassDeclaration() || ast->IsTSInterfaceDeclaration()) && + (ast->IsExported() || ast->IsDefaultExported())) { + auto *const savedProg = ctx->GetChecker()->VarBinder()->AsETSBinder()->Program(); + ctx->GetChecker()->VarBinder()->AsETSBinder()->SetProgram(program); GeneratePartialDeclForExported(ctx, ast); - ctx->checker->VarBinder()->AsETSBinder()->SetProgram(savedProg); + ctx->GetChecker()->VarBinder()->AsETSBinder()->SetProgram(savedProg); } return ast; diff --git a/ets2panda/compiler/lowering/ets/partialExportClassGen.h b/ets2panda/compiler/lowering/ets/partialExportClassGen.h index dbe558e0e6..1c8114a448 100644 --- a/ets2panda/compiler/lowering/ets/partialExportClassGen.h +++ b/ets2panda/compiler/lowering/ets/partialExportClassGen.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,7 +20,7 @@ namespace ark::es2panda::compiler { -class PartialExportClassGen : public PhaseForBodies { +class PartialExportClassGen : public PhaseForDeclarations { public: std::string_view Name() const override { diff --git a/ets2panda/compiler/lowering/ets/recordLowering.cpp b/ets2panda/compiler/lowering/ets/recordLowering.cpp index 8897cd7ddb..870a9c2aed 100644 --- a/ets2panda/compiler/lowering/ets/recordLowering.cpp +++ b/ets2panda/compiler/lowering/ets/recordLowering.cpp @@ -92,18 +92,18 @@ void RecordLowering::CheckDuplicateKey(KeySetType &keySet, ir::ObjectExpression (number.IsDouble() && keySet.insert(number.GetDouble()).second)) { continue; } - ctx->checker->AsETSChecker()->LogError(diagnostic::OBJ_LIT_PROP_NAME_COLLISION, {}, expr->Start()); + ctx->GetChecker()->AsETSChecker()->LogError(diagnostic::OBJ_LIT_PROP_NAME_COLLISION, {}, expr->Start()); break; } case ir::AstNodeType::STRING_LITERAL: { if (keySet.insert(prop->Key()->AsStringLiteral()->Str()).second) { continue; } - ctx->checker->AsETSChecker()->LogError(diagnostic::OBJ_LIT_PROP_NAME_COLLISION, {}, expr->Start()); + ctx->GetChecker()->AsETSChecker()->LogError(diagnostic::OBJ_LIT_PROP_NAME_COLLISION, {}, expr->Start()); break; } case ir::AstNodeType::IDENTIFIER: { - ctx->checker->AsETSChecker()->LogError(diagnostic::OBJ_LIT_UNKNOWN_PROP, {}, expr->Start()); + ctx->GetChecker()->AsETSChecker()->LogError(diagnostic::OBJ_LIT_UNKNOWN_PROP, {}, expr->Start()); break; } default: { @@ -122,7 +122,7 @@ void RecordLowering::CheckLiteralsCompleteness(KeySetType &keySet, ir::ObjectExp } for (auto &ct : keyType->AsETSUnionType()->ConstituentTypes()) { if (ct->IsConstantType() && keySet.find(TypeToKey(ct)) == keySet.end()) { - ctx->checker->AsETSChecker()->LogError(diagnostic::OBJ_LIT_NOT_COVERING_UNION, {}, expr->Start()); + ctx->GetChecker()->AsETSChecker()->LogError(diagnostic::OBJ_LIT_NOT_COVERING_UNION, {}, expr->Start()); } } } @@ -154,7 +154,7 @@ ir::Statement *RecordLowering::CreateStatement(const std::string &src, ir::Expre ir::Expression *RecordLowering::UpdateObjectExpression(ir::ObjectExpression *expr, public_lib::Context *ctx) { - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); if (!expr->PreferredType()->IsETSObjectType()) { // Unexpected preferred type @@ -188,7 +188,7 @@ ir::Expression *RecordLowering::UpdateObjectExpression(ir::ObjectExpression *exp block->SetParent(expr->Parent()); // Run checks - InitScopesPhaseETS::RunExternalNode(block, ctx->checker->VarBinder()); + InitScopesPhaseETS::RunExternalNode(block, ctx->GetChecker()->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(block, NearestScope(block)); block->Check(checker); diff --git a/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp b/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp index 12d58293e3..804519f911 100644 --- a/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp +++ b/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp @@ -27,7 +27,7 @@ static ir::AstNode *ConvertToResizableArrayType(ir::TSArrayType *node, public_li auto *parser = ctx->parser->AsETSParser(); ir::TypeNode *typeAnnotation = parser->CreateFormattedTypeAnnotation("Array<" + node->ElementType()->DumpEtsSrc() + ">"); - typeAnnotation->SetAnnotations(std::move(node->Annotations())); + typeAnnotation->SetAnnotations(node->Annotations()); typeAnnotation->SetParent(node->Parent()); typeAnnotation->SetRange(node->Range()); RefineSourceRanges(node); diff --git a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp index 224e980335..a34c623cf9 100644 --- a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp @@ -30,7 +30,7 @@ static ir::BlockExpression *CreateRestArgsBlockExpression(public_lib::Context *c { auto *allocator = context->allocator; auto *parser = context->parser->AsETSParser(); - auto *checker = context->checker->AsETSChecker(); + auto *checker = context->GetChecker()->AsETSChecker(); ArenaVector blockStatements(allocator->Adapter()); const auto arraySymbol = Gensym(allocator); @@ -89,7 +89,7 @@ static ir::Expression *CreateRestArgsArray(public_lib::Context *context, ArenaVe { auto *allocator = context->allocator; auto *parser = context->parser->AsETSParser(); - auto *checker = context->checker->AsETSChecker(); + auto *checker = context->GetChecker()->AsETSChecker(); // Handle single spread element case const size_t extraArgs = arguments.size() - signature->Params().size(); @@ -121,7 +121,7 @@ static ir::CallExpression *RebuildCallExpression(public_lib::Context *context, i checker::Signature *signature, ir::Expression *restArgsArray) { auto *allocator = context->allocator; - auto *varbinder = context->checker->VarBinder()->AsETSBinder(); + auto *varbinder = context->GetChecker()->VarBinder()->AsETSBinder(); ArenaVector newArgs(allocator->Adapter()); for (size_t i = 0; i < signature->Params().size(); ++i) { @@ -143,7 +143,7 @@ static ir::CallExpression *RebuildCallExpression(public_lib::Context *context, i auto *scope = NearestScope(newCall->Parent()); auto bscope = varbinder::LexicalScope::Enter(varbinder, scope); - CheckLoweredNode(context->checker->VarBinder()->AsETSBinder(), context->checker->AsETSChecker(), newCall); + CheckLoweredNode(context->GetChecker()->VarBinder()->AsETSBinder(), context->GetChecker()->AsETSChecker(), newCall); newCall->RemoveAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST); return newCall; } @@ -169,8 +169,9 @@ static ir::ETSNewClassInstanceExpression *RebuildNewClassInstanceExpression( newCall->AddModifier(originalCall->Modifiers()); newCall->AddBoxingUnboxingFlags(originalCall->GetBoxingUnboxingFlags()); auto *scope = NearestScope(newCall->Parent()); - auto bscope = varbinder::LexicalScope::Enter(context->checker->VarBinder()->AsETSBinder(), scope); - CheckLoweredNode(context->checker->VarBinder()->AsETSBinder(), context->checker->AsETSChecker(), newCall); + auto bscope = + varbinder::LexicalScope::Enter(context->GetChecker()->VarBinder()->AsETSBinder(), scope); + CheckLoweredNode(context->GetChecker()->VarBinder()->AsETSBinder(), context->GetChecker()->AsETSChecker(), newCall); return newCall; } diff --git a/ets2panda/compiler/lowering/ets/restTupleLowering.cpp b/ets2panda/compiler/lowering/ets/restTupleLowering.cpp index 7e9724a1bf..36554fe955 100644 --- a/ets2panda/compiler/lowering/ets/restTupleLowering.cpp +++ b/ets2panda/compiler/lowering/ets/restTupleLowering.cpp @@ -368,7 +368,7 @@ void CreateNewMethod(public_lib::Context *ctx, ir::AstNode *node) // Build new methodDefinition auto *const methodDef = CreateNewMethodDefinition(ctx, definition->AsMethodDefinition(), function); - node->AsClassDefinition()->Body().push_back(methodDef); + node->AsClassDefinition()->EmplaceBody(methodDef); } } } diff --git a/ets2panda/compiler/lowering/ets/setJumpTarget.cpp b/ets2panda/compiler/lowering/ets/setJumpTarget.cpp index 95b29ec11e..46b9c961e7 100644 --- a/ets2panda/compiler/lowering/ets/setJumpTarget.cpp +++ b/ets2panda/compiler/lowering/ets/setJumpTarget.cpp @@ -51,7 +51,7 @@ void SetJumpTargetPhase::FindJumpTarget(const public_lib::Context *ctx, ir::AstN var->SetScope(varbinder->GetScope()); label->SetVariable(var); decl->BindNode(label); - label->SetTsType(var->SetTsType(ctx->checker->GetGlobalTypesHolder()->GlobalTypeError())); + label->SetTsType(var->SetTsType(ctx->GetChecker()->GetGlobalTypesHolder()->GlobalTypeError())); } else if (var->Declaration()->IsLabelDecl()) { SetTarget(node, var->Declaration()->Node()); return; @@ -95,21 +95,13 @@ void SetJumpTargetPhase::FindJumpTarget(const public_lib::Context *ctx, ir::AstN SetTarget(node, nullptr); } -bool SetJumpTargetPhase::Perform(public_lib::Context *ctx, parser::Program *program) +bool SetJumpTargetPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - for (auto &[_, ext_programs] : program->ExternalSources()) { - (void)_; - for (auto *extProg : ext_programs) { - Perform(ctx, extProg); - } - } - program->Ast()->IterateRecursivelyPostorder([&](ir::AstNode *const node) -> void { if (node->IsBreakStatement() || node->IsContinueStatement()) { FindJumpTarget(ctx, node); } }); - return true; } diff --git a/ets2panda/compiler/lowering/ets/setJumpTarget.h b/ets2panda/compiler/lowering/ets/setJumpTarget.h index 79eb75efe4..ddef1ff51b 100644 --- a/ets2panda/compiler/lowering/ets/setJumpTarget.h +++ b/ets2panda/compiler/lowering/ets/setJumpTarget.h @@ -20,7 +20,7 @@ namespace ark::es2panda::compiler { -class SetJumpTargetPhase : public Phase { +class SetJumpTargetPhase : public PhaseForDeclarations { public: std::string_view Name() const override { @@ -28,7 +28,8 @@ public: } void FindJumpTarget(const public_lib::Context *ctx, ir::AstNode *const node); - bool Perform(public_lib::Context *ctx, parser::Program *program) override; + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; private: void LogError(const public_lib::Context *ctx, const diagnostic::DiagnosticKind &diagnostic, diff --git a/ets2panda/compiler/lowering/ets/spreadLowering.cpp b/ets2panda/compiler/lowering/ets/spreadLowering.cpp index 1c2f4241cf..8c0c488a32 100644 --- a/ets2panda/compiler/lowering/ets/spreadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/spreadLowering.cpp @@ -82,7 +82,7 @@ static ir::Identifier *CreateNewArrayDeclareStatement(public_lib::Context *ctx, ArenaVector &statements, ir::Identifier *newArrayLengthId) { - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); auto *const allocator = ctx->allocator; auto *const parser = ctx->parser->AsETSParser(); ir::Identifier *newArrayId = Gensym(allocator); @@ -286,7 +286,8 @@ static void CreateNewArrayElementsAssignStatement(public_lib::Context *ctx, ir:: newTupleAssignmentStatements.cend()); } else { ir::Identifier *spreadArrIterator = Gensym(allocator); - checker::Type *arrayElementType = ctx->checker->AsETSChecker()->GetElementTypeOfArray(array->TsType()); + checker::Type *arrayElementType = + ctx->GetChecker()->AsETSChecker()->GetElementTypeOfArray(array->TsType()); statements.emplace_back(CreateElementsAssignStatementBySpreadArr( ctx, spArrIds[spArrIdx++], newArrayAndIndex, spreadArrIterator, arrayElementType)); } @@ -343,7 +344,7 @@ static ir::BlockExpression *CreateLoweredExpressionForArray(public_lib::Context */ static ir::BlockExpression *CreateLoweredExpressionForTuple(public_lib::Context *ctx, ir::ArrayExpression *array) { - auto *const checker = ctx->checker->AsETSChecker(); + auto *const checker = ctx->GetChecker()->AsETSChecker(); auto *const parser = ctx->parser->AsETSParser(); auto *const allocator = ctx->allocator; @@ -356,7 +357,7 @@ static ir::BlockExpression *CreateLoweredExpressionForTuple(public_lib::Context bool SpreadConstructionPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - checker::ETSChecker *const checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *const checker = ctx->GetChecker()->AsETSChecker(); varbinder::ETSBinder *const varbinder = checker->VarBinder()->AsETSBinder(); program->Ast()->TransformChildrenRecursively( diff --git a/ets2panda/compiler/lowering/ets/stringComparison.cpp b/ets2panda/compiler/lowering/ets/stringComparison.cpp index e7f0cb4f16..d10fdb7b50 100644 --- a/ets2panda/compiler/lowering/ets/stringComparison.cpp +++ b/ets2panda/compiler/lowering/ets/stringComparison.cpp @@ -78,7 +78,7 @@ void StringComparisonLowering::ProcessBinaryExpression(ir::BinaryExpression *exp // reset types is any, will re-run checker to set them once again properly expr->SetTsType(nullptr); - checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); ArenaVector callArgs(checker->Allocator()->Adapter()); ir::Expression *accessor = nullptr; auto *zeroExpr = checker->AllocNode(util::StringView("0")); @@ -95,7 +95,7 @@ void StringComparisonLowering::ProcessBinaryExpression(ir::BinaryExpression *exp expr->SetRight(zeroExpr); auto *parent = expr->Parent(); - InitScopesPhaseETS::RunExternalNode(expr, ctx->checker->VarBinder()); + InitScopesPhaseETS::RunExternalNode(expr, ctx->GetChecker()->VarBinder()); checker->VarBinder()->AsETSBinder()->ResolveReferencesForScope(parent, NearestScope(parent)); if (parent->IsBinaryExpression() || parent->IsConditionalExpression()) { @@ -108,7 +108,7 @@ void StringComparisonLowering::ProcessBinaryExpression(ir::BinaryExpression *exp bool StringComparisonLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); [[maybe_unused]] ArenaVector foundNodes(checker->Allocator()->Adapter()); // CC-OFFNXT(G.FMT.14-CPP) project code style program->Ast()->IterateRecursively([&foundNodes, this](ir::AstNode *ast) -> ir::AstNode * { diff --git a/ets2panda/compiler/lowering/ets/stringConstantsLowering.cpp b/ets2panda/compiler/lowering/ets/stringConstantsLowering.cpp index e2bae0b0e6..8f255cb457 100644 --- a/ets2panda/compiler/lowering/ets/stringConstantsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/stringConstantsLowering.cpp @@ -35,19 +35,8 @@ static ir::AstNode *FoldConcat(public_lib::Context *ctx, ir::BinaryExpression *c return resNode; } -bool StringConstantsLowering::Perform(public_lib::Context *ctx, parser::Program *program) +bool StringConstantsLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - for (auto &[_, ext_programs] : program->ExternalSources()) { - (void)_; - for (auto *extProg : ext_programs) { - if (program->GetFlag(parser::ProgramFlags::AST_STRING_CONSTANT_LOWERED)) { - continue; - } - Perform(ctx, extProg); - program->SetFlag(parser::ProgramFlags::AST_STRING_CONSTANT_LOWERED); - } - } - program->Ast()->TransformChildrenRecursivelyPostorder( [ctx](checker::AstNodePtr const node) -> checker::AstNodePtr { if (node->IsBinaryExpression()) { @@ -60,7 +49,6 @@ bool StringConstantsLowering::Perform(public_lib::Context *ctx, parser::Program return node; }, Name()); - return true; } diff --git a/ets2panda/compiler/lowering/ets/stringConstantsLowering.h b/ets2panda/compiler/lowering/ets/stringConstantsLowering.h index d69fcb5339..4b0ce4e6ea 100644 --- a/ets2panda/compiler/lowering/ets/stringConstantsLowering.h +++ b/ets2panda/compiler/lowering/ets/stringConstantsLowering.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,10 +20,11 @@ namespace ark::es2panda::compiler { -class StringConstantsLowering : public Phase { +class StringConstantsLowering : public PhaseForDeclarations { public: std::string_view Name() const override; - bool Perform(public_lib::Context *ctx, parser::Program *program) override; + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp b/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp index 1e4060b5ea..e3c4f2e73f 100644 --- a/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/stringConstructorLowering.cpp @@ -48,7 +48,7 @@ static constexpr char const FORMAT_TO_STRING_EXPRESSION[] = "((@@E1 as Object).t ir::Expression *ReplaceStringConstructor(public_lib::Context *const ctx, ir::ETSNewClassInstanceExpression *newClassInstExpr) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *parser = ctx->parser->AsETSParser(); // Skip missing signatures diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index a914f8ad66..c30b85b05f 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -42,7 +42,7 @@ void GlobalClassHandler::AddStaticBlockToClass(ir::AstNode *node) if (node->IsClassDefinition() && !node->AsClassDefinition()->IsDeclare()) { auto classDef = node->AsClassDefinition(); if (auto staticBlock = CreateStaticBlock(classDef); staticBlock != nullptr) { - classDef->Body().emplace_back(staticBlock); // NOTE(vpukhov): inserted to end for some reason + classDef->EmplaceBody(staticBlock); // NOTE(vpukhov): inserted to end for some reason staticBlock->SetParent(classDef); } } @@ -103,7 +103,7 @@ ir::ClassDeclaration *GlobalClassHandler::CreateTransformedClass(ir::ETSModule * static void InsertInGlobal(ir::ClassDefinition *globalClass, ir::AstNode *node) { - globalClass->Body().insert(globalClass->Body().begin(), node); + globalClass->BodyForUpdate().insert(globalClass->Body().begin(), node); node->SetParent(globalClass); } @@ -165,11 +165,9 @@ void GlobalClassHandler::MergeNamespace(ArenaVector &namespaces parser->LogError(diagnostic::NAMESPACE_ANNOTATION_CONFLICT, {ns->Ident()->Name().Mutf8()}, ns->Start()); } else if (!ns->Annotations().empty()) { ES2PANDA_ASSERT(res->second->Annotations().empty()); - res->second->SetAnnotations(std::move(ns->Annotations())); - } - for (auto *statement : ns->Statements()) { - res->second->Statements().emplace_back(statement); + res->second->SetAnnotations(std::move(ns->AnnotationsForUpdate())); } + res->second->AddStatements(ns->Statements()); namespaces.erase(it); } else { nsMap.insert({ns->Ident()->Name(), ns}); @@ -178,10 +176,10 @@ void GlobalClassHandler::MergeNamespace(ArenaVector &namespaces } } -ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector &namespaces, - parser::Program *program) +ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector &namespaces, + parser::Program *program) { - ArenaVector classDecls {allocator_->Adapter()}; + ArenaVector classDecls {allocator_->Adapter()}; MergeNamespace(namespaces, program); for (auto ns : namespaces) { classDecls.emplace_back(TransformNamespace(ns, program)); @@ -197,7 +195,7 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, ArenaVector immediateInitializers(allocator_->Adapter()); ArenaVector initializerBlock(allocator_->Adapter()); ArenaVector namespaces(allocator_->Adapter()); - auto &body = ns->Statements(); + auto &body = ns->StatementsForUpdates(); for (auto *statement : body) { statement->Iterate([this](ir::AstNode *node) { AddStaticBlockToClass(node); }); } @@ -224,14 +222,14 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, body.erase(end, body.end()); auto globalClasses = TransformNamespaces(namespaces, program); for (auto *cls : globalClasses) { - globalClass->Body().emplace_back(cls); + globalClass->EmplaceBody(cls); cls->SetParent(globalClass); - CollectNamespaceExportedClasses(cls->Definition()); + CollectNamespaceExportedClasses(cls->AsClassDeclaration()->Definition()); } // Add rest statement, such as type declaration for (auto *statement : body) { - globalClass->Body().emplace_back(statement); + globalClass->EmplaceBody(statement); statement->SetParent(globalClass); } body.clear(); @@ -241,10 +239,10 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, void GlobalClassHandler::CollectProgramGlobalClasses(parser::Program *program, ArenaVector namespaces) { auto classDecls = TransformNamespaces(namespaces, program); + program->Ast()->AddStatements(classDecls); for (auto cls : classDecls) { - program->Ast()->Statements().push_back(cls); cls->SetParent(program->Ast()); - CollectNamespaceExportedClasses(cls->Definition()); + CollectNamespaceExportedClasses(cls->AsClassDeclaration()->Definition()); } } @@ -286,9 +284,9 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & ArenaVector initializerBlock(allocator_->Adapter()); ArenaVector namespaces(allocator_->Adapter()); - for (auto program : programs) { + for (auto const program : programs) { program->Ast()->IterateRecursively([this](ir::AstNode *node) { AddStaticBlockToClass(node); }); - auto &body = program->Ast()->Statements(); + auto &body = program->Ast()->StatementsForUpdates(); auto stmts = CollectProgramGlobalStatements(body, globalClass, program->Ast()); auto end = std::remove_if(body.begin(), body.end(), [&namespaces](ir::AstNode *node) { if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { @@ -306,7 +304,7 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & program->SetGlobalClass(globalClass); } - globalProgram->Ast()->Statements().emplace_back(globalDecl); + globalProgram->Ast()->AddStatement(globalDecl); globalDecl->SetParent(globalProgram->Ast()); globalClass->SetGlobalInitialized(); CollectProgramGlobalClasses(globalProgram, namespaces); @@ -367,7 +365,7 @@ void GlobalClassHandler::AddInitializerBlockToStaticBlock(ir::ClassDefinition *g auto *blockBody = staticBlock->Function()->Body()->AsBlockStatement(); initializerStmts->SetParent(blockBody); - blockBody->Statements().emplace_back(initializerStmts); + blockBody->AddStatement(initializerStmts); } void GlobalClassHandler::AddInitCallToStaticBlock(ir::ClassDefinition *globalClass, ir::MethodDefinition *initMethod) @@ -388,7 +386,7 @@ void GlobalClassHandler::AddInitCallToStaticBlock(ir::ClassDefinition *globalCla auto *blockBody = staticBlock->Function()->Body()->AsBlockStatement(); auto exprStmt = NodeAllocator::Alloc(allocator_, callExpr); exprStmt->SetParent(blockBody); - blockBody->Statements().emplace_back(exprStmt); + blockBody->AddStatement(exprStmt); } ir::Identifier *GlobalClassHandler::RefIdent(const util::StringView &name) diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h index ae589327d1..18d7fbbbc4 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h @@ -62,8 +62,8 @@ private: ir::ClassDefinition *globalClass, bool isDeclare); void SetupInitializerBlock(parser::Program *program, ArenaVector> &&initializerBlock, ir::ClassDefinition *globalClass); - ArenaVector TransformNamespaces(ArenaVector &namespaces, - parser::Program *program); + ArenaVector TransformNamespaces(ArenaVector &namespaces, + parser::Program *program); ir::ClassDeclaration *CreateGlobalClass(const parser::Program *globalProgram); ir::ClassStaticBlock *CreateStaticBlock(ir::ClassDefinition *classDef); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp index 8e3afe694c..dc8869fffa 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp @@ -58,7 +58,7 @@ void GlobalDeclTransformer::VisitFunctionDeclaration(ir::FunctionDeclaration *fu allocator_, methodKind, funcDecl->Function()->Id()->Clone(allocator_, nullptr), funcExpr, funcDecl->Function()->Modifiers(), allocator_, false); method->SetRange(funcDecl->Range()); - method->Function()->SetAnnotations(std::move(funcDecl->Annotations())); + method->Function()->SetAnnotations(funcDecl->Annotations()); if (funcDecl->Function()->IsExported() && funcDecl->Function()->HasExportAlias()) { method->AddAstNodeFlags(ir::AstNodeFlags::HAS_EXPORT_ALIAS); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp index aa76dbdc45..fd25d833a5 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp @@ -57,8 +57,10 @@ GlobalClassHandler::ModuleDependencies ImportExportDecls::HandleGlobalStmts(Aren if (!programs.empty()) { std::sort(programs.begin(), programs.end(), ProgramFileNameLessThan); } - for (const auto &program : programs) { - PreMergeNamespaces(program); + for (auto const &program : programs) { + if (!program->IsASTLowered()) { + PreMergeNamespaces(program); + } SavedImportExportDeclsContext savedContext(this, program); ProcessProgramStatements(program, program->Ast()->Statements(), moduleDependencies); VerifyCollectedExportName(program); @@ -318,7 +320,7 @@ void ImportExportDecls::PreMergeNamespaces(parser::Program *program) } ArenaVector namespaces(program->Allocator()->Adapter()); - auto &body = ast->AsETSModule()->Statements(); + auto &body = ast->AsETSModule()->StatementsForUpdates(); auto originalSize = body.size(); auto end = std::remove_if(body.begin(), body.end(), [&namespaces](ir::AstNode *node) { if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp index 28c205ee50..3db02c7218 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp @@ -58,8 +58,10 @@ bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *prog GlobalClassHandler globalClass(ctx->parser->AsETSParser(), ctx->Allocator()); for (auto &[package, extPrograms] : program->ExternalSources()) { - auto moduleDependencies = imports.HandleGlobalStmts(extPrograms); - globalClass.SetupGlobalClass(extPrograms, &moduleDependencies); + if (!extPrograms.front()->IsASTLowered()) { + auto moduleDependencies = imports.HandleGlobalStmts(extPrograms); + globalClass.SetupGlobalClass(extPrograms, &moduleDependencies); + } } ArenaVector mainModule(ctx->Allocator()->Adapter()); diff --git a/ets2panda/compiler/lowering/ets/typeFromLowering.cpp b/ets2panda/compiler/lowering/ets/typeFromLowering.cpp index 2ee7cc83d8..31f98cba35 100644 --- a/ets2panda/compiler/lowering/ets/typeFromLowering.cpp +++ b/ets2panda/compiler/lowering/ets/typeFromLowering.cpp @@ -116,7 +116,7 @@ std::string HandleTypeParameter(ir::Expression *param, checker::ETSChecker *chec ir::Expression *ReplaceTypeFrom(public_lib::Context *ctx, ir::CallExpression *ast) { auto parser = ctx->parser->AsETSParser(); - auto checker = ctx->checker->AsETSChecker(); + auto checker = ctx->GetChecker()->AsETSChecker(); auto *typeParams = ast->AsCallExpression()->TypeParams(); ES2PANDA_ASSERT(typeParams != nullptr && typeParams->Params().size() == 1); diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index 2df65448a0..ecbedb0619 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -32,7 +32,7 @@ static void ReplaceAll(std::string &str, std::string_view substr, std::string_vi } } -static std::string GetAccessClassName(const checker::ETSUnionType *unionType) +std::string GetAccessClassName(const checker::ETSUnionType *unionType) { std::stringstream ss; ss << PREFIX; @@ -47,7 +47,7 @@ static std::string GetAccessClassName(const checker::ETSUnionType *unionType) static ir::ClassDefinition *GetUnionAccessClass(public_lib::Context *ctx, varbinder::VarBinder *varbinder, std::string const &name) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto *allocator = ctx->Allocator(); // Create the name for the synthetic class node if (auto foundVar = checker->Scope()->FindLocal(util::StringView(name), varbinder::ResolveBindingOptions::BINDINGS); @@ -72,7 +72,7 @@ static ir::ClassDefinition *GetUnionAccessClass(public_lib::Context *ctx, varbin auto globalBlock = varbinder->Program()->Ast(); classDecl->SetParent(globalBlock); - globalBlock->Statements().push_back(classDecl); + globalBlock->AddStatement(classDecl); classDecl->Check(checker); return classDef; } @@ -82,7 +82,7 @@ static std::tuple CreateNamedA checker::Signature *signature) { auto *allocator = ctx->Allocator(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto unionType = checker->GetApparentType(checker->GetNonNullishType(expr->Object()->TsType()))->AsETSUnionType(); auto *const accessClass = GetUnionAccessClass(ctx, varbinder, GetAccessClassName(unionType)); @@ -131,7 +131,7 @@ static varbinder::LocalVariable *CreateNamedAccessProperty(public_lib::Context * ir::MemberExpression *expr) { auto *const allocator = ctx->Allocator(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto unionType = checker->GetApparentType(checker->GetNonNullishType(expr->Object()->TsType()))->AsETSUnionType(); auto *const accessClass = GetUnionAccessClass(ctx, varbinder, GetAccessClassName(unionType)); @@ -166,7 +166,7 @@ static varbinder::LocalVariable *CreateNamedAccess(public_lib::Context *ctx, var { auto type = expr->TsType(); auto name = expr->Property()->AsIdentifier()->Name(); - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); auto unionType = checker->GetApparentType(checker->GetNonNullishType(expr->Object()->TsType()))->AsETSUnionType(); auto *const accessClass = GetUnionAccessClass(ctx, varbinder, GetAccessClassName(unionType)); @@ -208,7 +208,7 @@ static ir::TSAsExpression *GenAsExpression(public_lib::Context *ctx, checker::Ty auto *const typeNode = ctx->AllocNode(opaqueType, ctx->Allocator()); auto *const asExpression = ctx->AllocNode(node, typeNode, false); asExpression->SetParent(parent); - asExpression->Check(ctx->checker->AsETSChecker()); + asExpression->Check(ctx->GetChecker()->AsETSChecker()); return asExpression; } @@ -227,7 +227,7 @@ static ir::TSAsExpression *UnionCastToPrimitive(public_lib::Context *ctx, checke static ir::TSAsExpression *HandleUnionCastToPrimitive(public_lib::Context *ctx, ir::TSAsExpression *expr) { - checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); auto *const unionType = expr->Expr()->TsType()->AsETSUnionType(); auto *sourceType = unionType->FindExactOrBoxedType(checker, expr->TsType()); if (sourceType == nullptr) { @@ -262,7 +262,7 @@ static ir::TSAsExpression *HandleUnionCastToPrimitive(public_lib::Context *ctx, bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - checker::ETSChecker *checker = ctx->checker->AsETSChecker(); + checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); program->Ast()->TransformChildrenRecursively( [ctx, checker](checker::AstNodePtr ast) -> checker::AstNodePtr { @@ -290,7 +290,7 @@ bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program * bool UnionLowering::PostconditionForModule(public_lib::Context *ctx, const parser::Program *program) { - auto *checker = ctx->checker->AsETSChecker(); + auto *checker = ctx->GetChecker()->AsETSChecker(); bool current = !program->Ast()->IsAnyChild([checker](ir::AstNode *ast) { if (!ast->IsMemberExpression() || ast->AsMemberExpression()->Object()->TsType() == nullptr) { return false; diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 6cd559f27d..a871d1f962 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -74,67 +74,18 @@ namespace ark::es2panda::compiler { -static CheckerPhase g_checkerPhase; -static SetJumpTargetPhase g_setJumpTargetPhase; -static CFGBuilderPhase g_cfgBuilderPhase; -static ResolveIdentifiers g_resolveIdentifiers {}; -static AmbientLowering g_ambientLowering; -static ArrayLiteralLowering g_arrayLiteralLowering {}; -static BigIntLowering g_bigintLowering; -static StringConstructorLowering g_stringConstructorLowering; -static ConstantExpressionLowering g_constantExpressionLowering; -static InterfacePropertyDeclarationsPhase g_interfacePropDeclPhase; // NOLINT(fuchsia-statically-constructed-objects) -static EnumLoweringPhase g_enumLoweringPhase; -static EnumPostCheckLoweringPhase g_enumPostCheckLoweringPhase; -static RestTupleConstructionPhase g_restTupleConstructionPhase; -static SpreadConstructionPhase g_spreadConstructionPhase; -static ExtensionAccessorPhase g_extensionAccessorPhase; -static ExpressionLambdaConstructionPhase g_expressionLambdaConstructionPhase; -static OpAssignmentLowering g_opAssignmentLowering; -static BoxingForLocals g_boxingForLocals; -static CapturedVariables g_capturedVariables {}; -static LambdaConversionPhase g_lambdaConversionPhase; -static ObjectIndexLowering g_objectIndexLowering; -static ObjectIteratorLowering g_objectIteratorLowering; -static ObjectLiteralLowering g_objectLiteralLowering; -static InterfaceObjectLiteralLowering g_interfaceObjectLiteralLowering; -static UnionLowering g_unionLowering; -static OptionalLowering g_optionalLowering; -static ExpandBracketsPhase g_expandBracketsPhase; -static ExportAnonymousConstPhase g_exportAnonymousConstPhase; -static PromiseVoidInferencePhase g_promiseVoidInferencePhase; -static RecordLowering g_recordLowering; -static DeclareOverloadLowering g_declareOverloadLowering; -static DefaultParametersLowering g_defaultParametersLowering; -static DefaultParametersInConstructorLowering g_defaultParametersInConstructorLowering; -static OptionalArgumentsLowering g_optionalArgumentsLowering; -static TopLevelStatements g_topLevelStatements; -static LocalClassConstructionPhase g_localClassLowering; -static StringComparisonLowering g_stringComparisonLowering; -static StringConstantsLowering g_stringConstantsLowering; -static PartialExportClassGen g_partialExportClassGen; -static PackageImplicitImport g_packageImplicitImport; -static GenericBridgesPhase g_genericBridgesLowering; -static BoxedTypeLowering g_boxedTypeLowering; -static AsyncMethodLowering g_asyncMethodLowering; -static TypeFromLowering g_typeFromLowering; -static ResizableArrayConvert g_resizableArrayConvert; -static RestArgsLowering g_restArgsLowering; -static LateInitializationConvert g_lateInitializationConvert; -static InsertOptionalParametersAnnotation g_insertOptionalParametersAnnotation; -static ConvertPrimitiveCastMethodCall g_convertPrimitiveCastMethodCall; -static PluginPhase g_pluginsAfterParse {"plugins-after-parse", ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}; -static PluginPhase g_pluginsAfterBind {"plugins-after-bind", ES2PANDA_STATE_BOUND, &util::Plugin::AfterBind}; -static PluginPhase g_pluginsAfterCheck {"plugins-after-check", ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}; -static PluginPhase g_pluginsAfterLowerings {"plugins-after-lowering", ES2PANDA_STATE_LOWERED, - &util::Plugin::AfterLowerings}; // NOLINTBEGIN(fuchsia-statically-constructed-objects) +static CheckerPhase g_checkerPhase; static InitScopesPhaseETS g_initScopesPhaseEts; static InitScopesPhaseAS g_initScopesPhaseAs; static InitScopesPhaseTs g_initScopesPhaseTs; static InitScopesPhaseJs g_initScopesPhaseJs; // NOLINTEND(fuchsia-statically-constructed-objects) -static DynamicImportLowering g_dynamicImportLowering; +// static DynamicImportLowering g_dynamicImportLowering; +const static inline char *g_pluginsAfterParse = "plugins-after-parse"; +const static inline char *g_pluginsAfterBind = "plugins-after-bind"; +const static inline char *g_pluginsAfterCheck = "plugins-after-check"; +const static inline char *g_pluginsAfterLowering = "plugins-after-lowering"; // CC-OFFNXT(huge_method, G.FUN.01-CPP) long initialization list std::vector GetETSPhaseList() @@ -142,66 +93,77 @@ std::vector GetETSPhaseList() // clang-format off // NOLINTBEGIN return { - &g_pluginsAfterParse, - &g_stringConstantsLowering, - &g_packageImplicitImport, - &g_exportAnonymousConstPhase, - &g_topLevelStatements, - &g_resizableArrayConvert, - &g_expressionLambdaConstructionPhase, - &g_insertOptionalParametersAnnotation, - &g_defaultParametersInConstructorLowering, - &g_defaultParametersLowering, - &g_ambientLowering, - &g_restTupleConstructionPhase, - &g_initScopesPhaseEts, - &g_optionalLowering, - &g_promiseVoidInferencePhase, - &g_interfacePropDeclPhase, - &g_constantExpressionLowering, - &g_enumLoweringPhase, - &g_resolveIdentifiers, - &g_pluginsAfterBind, - &g_capturedVariables, - &g_setJumpTargetPhase, - &g_cfgBuilderPhase, - &g_checkerPhase, // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck - &g_pluginsAfterCheck, // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them - &g_convertPrimitiveCastMethodCall, - &g_dynamicImportLowering, - &g_asyncMethodLowering, - &g_declareOverloadLowering, - &g_enumPostCheckLoweringPhase, - &g_spreadConstructionPhase, - &g_restArgsLowering, - &g_arrayLiteralLowering, - &g_bigintLowering, - &g_opAssignmentLowering, - &g_lateInitializationConvert, - &g_extensionAccessorPhase, - &g_boxingForLocals, - &g_recordLowering, - &g_boxedTypeLowering, - &g_objectIndexLowering, - &g_objectIteratorLowering, - &g_lambdaConversionPhase, - &g_unionLowering, - &g_expandBracketsPhase, - &g_localClassLowering, - &g_partialExportClassGen, - &g_interfaceObjectLiteralLowering, // this lowering should be put after all classs generated. - &g_objectLiteralLowering, - &g_stringConstructorLowering, - &g_stringComparisonLowering, - &g_optionalArgumentsLowering, // #22952 could be moved to earlier phase - &g_genericBridgesLowering, - &g_typeFromLowering, - &g_pluginsAfterLowerings, // pluginsAfterLowerings has to come at the very end, nothing should go after it + new PluginPhase {g_pluginsAfterParse, ES2PANDA_STATE_PARSED, &util::Plugin::AfterParse}, + new StringConstantsLowering, + new PackageImplicitImport, + new ExportAnonymousConstPhase, + new TopLevelStatements, + new ResizableArrayConvert, + new ExpressionLambdaConstructionPhase, + new InsertOptionalParametersAnnotation, + new DefaultParametersInConstructorLowering, + new DefaultParametersLowering, + new AmbientLowering, + new RestTupleConstructionPhase, + new InitScopesPhaseETS, + new OptionalLowering, + new PromiseVoidInferencePhase, + new InterfacePropertyDeclarationsPhase, + new ConstantExpressionLowering, + new EnumLoweringPhase, + new ResolveIdentifiers, + new PluginPhase {g_pluginsAfterBind, ES2PANDA_STATE_BOUND, &util::Plugin::AfterBind}, + new CapturedVariables, + new SetJumpTargetPhase, + new CFGBuilderPhase, + // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck + new CheckerPhase, + // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them + new PluginPhase {g_pluginsAfterCheck, ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}, + new ConvertPrimitiveCastMethodCall, + new DynamicImportLowering, + new AsyncMethodLowering, + new DeclareOverloadLowering, + new EnumPostCheckLoweringPhase, + new SpreadConstructionPhase, + new RestArgsLowering, + new ArrayLiteralLowering, + new BigIntLowering, + new OpAssignmentLowering, + new LateInitializationConvert, + new ExtensionAccessorPhase, + new BoxingForLocals, + new RecordLowering, + new BoxedTypeLowering, + new ObjectIndexLowering, + new ObjectIteratorLowering, + new LambdaConversionPhase, + new UnionLowering, + new ExpandBracketsPhase, + new LocalClassConstructionPhase, + new PartialExportClassGen, + new InterfaceObjectLiteralLowering, // must be put after all classes are generated. + new ObjectLiteralLowering, + new StringConstructorLowering, + new StringComparisonLowering, + new OptionalArgumentsLowering, // #22952 could be moved to earlier phase + new GenericBridgesPhase, + new TypeFromLowering, + // pluginsAfterLowerings has to come at the very end, nothing should go after it + new PluginPhase{g_pluginsAfterLowering, ES2PANDA_STATE_LOWERED, + &util::Plugin::AfterLowerings}, }; // NOLINTEND // clang-format on } +void DestoryETSPhaseList(std::vector &list) +{ + for (auto *phase : list) { + delete phase; + } +} + std::vector GetASPhaseList() { return { @@ -239,6 +201,16 @@ void SetPhaseManager(PhaseManager *phaseManager) g_phaseManager = phaseManager; } +void PhaseManager::Reset() +{ + prev_ = {0, INVALID_PHASE_ID}; + curr_ = {0, PARSER_PHASE_ID}; + next_ = PARSER_PHASE_ID + 1; + ES2PANDA_ASSERT(next_ == 0); + + SetPhaseManager(this); +} + bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) { SetPhaseManager(ctx->phaseManager); @@ -246,7 +218,7 @@ bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) #ifndef NDEBUG if (!Precondition(ctx, program)) { - ctx->checker->LogError(diagnostic::PRECOND_FAILED, {Name()}, lexer::SourcePosition {}); + ctx->GetChecker()->LogError(diagnostic::PRECOND_FAILED, {Name()}, lexer::SourcePosition {}); return false; } #endif @@ -257,7 +229,7 @@ bool Phase::Apply(public_lib::Context *ctx, parser::Program *program) #ifndef NDEBUG if (!Postcondition(ctx, program)) { - ctx->checker->LogError(diagnostic::POSTCOND_FAILED, {Name()}, lexer::SourcePosition {}); + ctx->GetChecker()->LogError(diagnostic::POSTCOND_FAILED, {Name()}, lexer::SourcePosition {}); return false; } #endif @@ -270,6 +242,9 @@ bool PhaseForDeclarations::Precondition(public_lib::Context *ctx, const parser:: for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { + if (extProg->IsASTLowered()) { + continue; + } if (!Precondition(ctx, extProg)) { return false; } @@ -281,11 +256,14 @@ bool PhaseForDeclarations::Precondition(public_lib::Context *ctx, const parser:: bool PhaseForDeclarations::Perform(public_lib::Context *ctx, parser::Program *program) { + FetchCache(ctx, program); bool result = true; for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { - result &= Perform(ctx, extProg); + if (!extProg->IsASTLowered()) { + result &= Perform(ctx, extProg); + } } } @@ -298,6 +276,9 @@ bool PhaseForDeclarations::Postcondition(public_lib::Context *ctx, const parser: for (auto &[_, extPrograms] : program->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { + if (extProg->IsASTLowered()) { + continue; + } if (!Postcondition(ctx, extProg)) { return false; } @@ -330,17 +311,27 @@ bool PhaseForBodies::Precondition(public_lib::Context *ctx, const parser::Progra return PreconditionForModule(ctx, program); } -bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) +bool PhaseForBodies::ProcessExternalPrograms(public_lib::Context *ctx, parser::Program *program) { bool result = true; - if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { - for (auto &[_, extPrograms] : program->ExternalSources()) { - (void)_; - for (auto *extProg : extPrograms) { + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *extProg : extPrograms) { + if (!extProg->IsASTLowered()) { result &= Perform(ctx, extProg); } } } + return result; +} + +bool PhaseForBodies::Perform(public_lib::Context *ctx, parser::Program *program) +{ + FetchCache(ctx, program); + bool result = true; + if (ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB) { + result &= ProcessExternalPrograms(ctx, program); + } result &= PerformForModule(ctx, program); return result; @@ -369,6 +360,13 @@ bool PhaseForBodies::Postcondition(public_lib::Context *ctx, const parser::Progr return PostconditionForModule(ctx, program); } +PhaseManager::~PhaseManager() +{ + if (ScriptExtension::ETS == ext_) { + DestoryETSPhaseList(phases_); + } +} + void PhaseManager::InitializePhases() { switch (ext_) { @@ -390,6 +388,19 @@ void PhaseManager::InitializePhases() int id = 0; for (auto phase : phases_) { + // js side UI plugin needs an extra phaseID, which is different from c++ side plugin phase + if (phase->Name() == std::string(g_pluginsAfterParse)) { + jsPluginAfterParse_ = id++; + } + if (phase->Name() == std::string(g_pluginsAfterBind)) { + jsPluginAfterBind_ = id++; + } + if (phase->Name() == std::string(g_pluginsAfterCheck)) { + jsPluginAfterCheck_ = id++; + } + if (phase->Name() == std::string(g_pluginsAfterLowering)) { + jsPluginAfterLower_ = id++; + } phase->id_ = id++; } } @@ -403,21 +414,36 @@ std::vector PhaseManager::AllPhases() std::vector PhaseManager::RebindPhases() { ES2PANDA_ASSERT(IsInitialized()); - return { - &g_initScopesPhaseEts, - &g_resolveIdentifiers, - }; + return GetSubPhases({ScopesInitPhase::NAME, ResolveIdentifiers::NAME}); +} + +std::vector PhaseManager::GetSubPhases(const std::vector &phaseNames) +{ + std::vector phases; + for (auto &phaseName : phaseNames) { + for (auto phase : phases_) { + if (phase->Name() == phaseName) { + phases.emplace_back(phase); + } + } + } + return phases; } std::vector PhaseManager::RecheckPhases() { ES2PANDA_ASSERT(IsInitialized()); - return { - &g_initScopesPhaseEts, - &g_resolveIdentifiers, - &g_capturedVariables, - &g_checkerPhase, - }; + return GetSubPhases({ScopesInitPhase::NAME, ResolveIdentifiers::NAME, "CapturedVariables", CheckerPhase::NAME}); +} + +int32_t PhaseManager::GetCurrentMajor() const +{ + return curr_.major; +} + +int32_t PhaseManager::GetCurrentMinor() const +{ + return curr_.minor; } } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/phase.h b/ets2panda/compiler/lowering/phase.h index e1ff9c3885..63c3e493f4 100644 --- a/ets2panda/compiler/lowering/phase.h +++ b/ets2panda/compiler/lowering/phase.h @@ -16,21 +16,28 @@ #ifndef ES2PANDA_COMPILER_LOWERING_PHASE_H #define ES2PANDA_COMPILER_LOWERING_PHASE_H +#include "macros.h" #include "parser/program/program.h" #include "public/public.h" +#include "phase_id.h" namespace ark::es2panda::compiler { -constexpr int32_t INVALID_PHASE_ID = -2; -constexpr int32_t PARSER_PHASE_ID = -1; - class Phase { public: /* If Apply returns false, processing is stopped. */ bool Apply(public_lib::Context *ctx, parser::Program *program); + virtual ~Phase() = default; + Phase() = default; + + NO_COPY_SEMANTIC(Phase); + NO_MOVE_SEMANTIC(Phase); + virtual std::string_view Name() const = 0; + virtual void FetchCache([[maybe_unused]] public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) {} + virtual bool Precondition([[maybe_unused]] public_lib::Context *ctx, [[maybe_unused]] const parser::Program *program) { @@ -73,6 +80,7 @@ class PhaseForDeclarations : public Phase { */ class PhaseForBodies : public Phase { bool Precondition(public_lib::Context *ctx, const parser::Program *program) override; + bool ProcessExternalPrograms(public_lib::Context *ctx, parser::Program *program); bool Perform(public_lib::Context *ctx, parser::Program *program) override; bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; @@ -95,23 +103,46 @@ public: PhaseManager(ScriptExtension ext, ArenaAllocator *allocator) : allocator_ {allocator}, ext_ {ext} { InitializePhases(); - Restart(); + Reset(); + } + + PhaseManager(public_lib::Context *context, ScriptExtension ext, ArenaAllocator *allocator) + : PhaseManager(ext, allocator) + { + context_ = context; + } + + NO_COPY_SEMANTIC(PhaseManager); + NO_MOVE_SEMANTIC(PhaseManager); + + ~PhaseManager(); + + public_lib::Context *Context() + { + return context_; } - int32_t PreviousPhaseId() const + PhaseId PreviousPhaseId() const { return prev_; } - int32_t CurrentPhaseId() const + PhaseId CurrentPhaseId() const { return curr_; } void SetCurrentPhaseId(int32_t phaseId) { + if (phaseId == curr_.minor) { + return; + } prev_ = curr_; - curr_ = phaseId; + + if (curr_.minor > phaseId) { + curr_.major++; + } + curr_.minor = phaseId; } ArenaAllocator *Allocator() const @@ -124,13 +155,7 @@ public: return allocator_ != nullptr && ext_ != ScriptExtension::INVALID; } - void Restart() - { - prev_ = INVALID_PHASE_ID; - curr_ = PARSER_PHASE_ID; - next_ = PARSER_PHASE_ID + 1; - ES2PANDA_ASSERT(next_ == 0); - } + void Reset(); Phase *NextPhase() { @@ -144,20 +169,47 @@ public: std::vector RebindPhases(); std::vector RecheckPhases(); + void SetCurrentPhaseIdToAfterParse() + { + GetPhaseManager()->SetCurrentPhaseId(jsPluginAfterParse_); + } + + void SetCurrentPhaseIdToAfterBind() + { + GetPhaseManager()->SetCurrentPhaseId(jsPluginAfterBind_); + } + + void SetCurrentPhaseIdToAfterCheck() + { + GetPhaseManager()->SetCurrentPhaseId(jsPluginAfterCheck_); + } + + void SetCurrentPhaseIdToAfterLower() + { + GetPhaseManager()->SetCurrentPhaseId(jsPluginAfterLower_); + } + + int32_t GetCurrentMajor() const; + int32_t GetCurrentMinor() const; + + std::vector GetSubPhases(const std::vector &phaseNames); + private: void InitializePhases(); - int32_t prev_ {INVALID_PHASE_ID}; - int32_t curr_ {INVALID_PHASE_ID}; + PhaseId prev_ {0, INVALID_PHASE_ID}; + PhaseId curr_ {0, INVALID_PHASE_ID}; int32_t next_ {INVALID_PHASE_ID}; + int32_t jsPluginAfterParse_ {0}; + int32_t jsPluginAfterBind_ {0}; + int32_t jsPluginAfterCheck_ {0}; + int32_t jsPluginAfterLower_ {0}; ArenaAllocator *allocator_ {nullptr}; + public_lib::Context *context_ {nullptr}; ScriptExtension ext_ {ScriptExtension::INVALID}; std::vector phases_; }; -PhaseManager *GetPhaseManager(); -void SetPhaseManager(PhaseManager *phaseManager); - } // namespace ark::es2panda::compiler #endif diff --git a/ets2panda/compiler/lowering/phase_id.h b/ets2panda/compiler/lowering/phase_id.h new file mode 100644 index 0000000000..a3ba46c8f5 --- /dev/null +++ b/ets2panda/compiler/lowering/phase_id.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_PHASE_ID_H +#define ES2PANDA_COMPILER_LOWERING_PHASE_ID_H + +namespace ark::es2panda::compiler { + +constexpr int32_t INVALID_PHASE_ID = -2; +constexpr int32_t PARSER_PHASE_ID = -1; + +struct PhaseId { + int32_t major; // NOLINT(misc-non-private-member-variables-in-classes) + int32_t minor; // NOLINT(misc-non-private-member-variables-in-classes) + + bool operator<(const PhaseId &other) const + { + return major == other.major ? minor < other.minor : major < other.major; + } + + bool operator<=(const PhaseId &other) const + { + return major == other.major ? minor <= other.minor : major <= other.major; + } + + bool operator==(const PhaseId &other) const + { + return major == other.major && minor == other.minor; + } + + bool operator>=(const PhaseId &other) const + { + return major == other.major ? minor >= other.minor : major >= other.major; + } + + bool operator>(const PhaseId &other) const + { + return major == other.major ? minor > other.minor : major > other.major; + } +}; + +} // namespace ark::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/plugin_phase.cpp b/ets2panda/compiler/lowering/plugin_phase.cpp index 14f72aa7f0..f4dcbebf93 100644 --- a/ets2panda/compiler/lowering/plugin_phase.cpp +++ b/ets2panda/compiler/lowering/plugin_phase.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -28,7 +28,7 @@ bool PluginPhase::Perform(public_lib::Context *ctx, [[maybe_unused]] parser::Pro for (auto &plugin : *(ctx->plugins)) { (plugin.*methodCall_)(reinterpret_cast(ctx)); if (ctx->state == ES2PANDA_STATE_ERROR) { - ctx->checker->LogTypeError(ctx->errorMessage, ctx->errorPos); + ctx->GetChecker()->LogTypeError(ctx->errorMessage, ctx->errorPos); return false; } } diff --git a/ets2panda/compiler/lowering/resolveIdentifiers.cpp b/ets2panda/compiler/lowering/resolveIdentifiers.cpp index cc13b62ce3..541af34dee 100644 --- a/ets2panda/compiler/lowering/resolveIdentifiers.cpp +++ b/ets2panda/compiler/lowering/resolveIdentifiers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -19,12 +19,45 @@ #include "util/options.h" namespace ark::es2panda::compiler { + +void ResolveIdentifiers::InsertReExported(parser::Program *program, varbinder::ETSBinder *pVarBinder, + parser::Program *extProgram) +{ + auto etsBinder = extProgram->VarBinder()->AsETSBinder(); + auto &reExportedImports = pVarBinder->ReExportImports(); + for (auto &it : etsBinder->ReExportImports()) { + if (it->GetTopStatement()->AsETSModule()->Program()->SourceFile().GetPath() != + program->SourceFile().GetPath()) { + reExportedImports.insert(it); + } + } + + auto &aliasMap = pVarBinder->GetSelectiveExportAliasMultimap(); + aliasMap.insert(etsBinder->GetSelectiveExportAliasMultimap().begin(), + etsBinder->GetSelectiveExportAliasMultimap().end()); +} + +void ResolveIdentifiers::FetchCache([[maybe_unused]] public_lib::Context *ctx, + [[maybe_unused]] parser::Program *program) +{ + auto pVarBinder = program->VarBinder()->AsETSBinder(); + for (auto &[package, extPrograms] : program->ExternalSources()) { + auto *extProgram = extPrograms.front(); + if (!extProgram->IsStdLib() && extProgram->IsASTLowered()) { + InsertReExported(program, pVarBinder, extProgram); + } + } +} + bool ResolveIdentifiers::Perform(public_lib::Context *ctx, [[maybe_unused]] parser::Program *program) { + FetchCache(ctx, program); auto const *options = ctx->config->options; auto *varbinder = ctx->parserProgram->VarBinder()->AsETSBinder(); - if (options->IsDumpAst()) { + static bool firstDump = true; + if (options->IsDumpAst() && firstDump) { + firstDump = false; std::cout << varbinder->Program()->Dump() << std::endl; } diff --git a/ets2panda/compiler/lowering/resolveIdentifiers.h b/ets2panda/compiler/lowering/resolveIdentifiers.h index 186363fbb0..1b7f962edb 100644 --- a/ets2panda/compiler/lowering/resolveIdentifiers.h +++ b/ets2panda/compiler/lowering/resolveIdentifiers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -23,12 +23,16 @@ class ResolveIdentifiers : public Phase { public: static constexpr std::string_view NAME = "ResolveIdentifiers"; + void FetchCache(public_lib::Context *ctx, parser::Program *program) override; + std::string_view Name() const override { return "ResolveIdentifiers"; } bool Perform(public_lib::Context *ctx, parser::Program *program) override; + + void InsertReExported(parser::Program *program, varbinder::ETSBinder *pVarBinder, parser::Program *extProgram); }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/scopesInit/savedBindingsCtx.cpp b/ets2panda/compiler/lowering/scopesInit/savedBindingsCtx.cpp index 56aa8c8318..8d4ee9e016 100644 --- a/ets2panda/compiler/lowering/scopesInit/savedBindingsCtx.cpp +++ b/ets2panda/compiler/lowering/scopesInit/savedBindingsCtx.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -55,7 +55,7 @@ void ExportDeclarationContext::BindExportDecl(ir::AstNode *exportDecl) util::StringView(DEFAULT_EXPORT), rhs->AsFunctionDeclaration()->Function()); } else { - VarBinder()->AddDecl(rhs->Start(), util::StringView(DEFAULT_EXPORT)); + VarBinder()->AddDecl(rhs->Start(), util::StringView(DEFAULT_EXPORT), rhs); } } } diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 49bec80f6e..b0c239c381 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -841,6 +841,9 @@ void InitScopesPhaseETS::HandleProgram(parser::Program *program) (void)_; auto savedTopScope(program->VarBinder()->TopScope()); auto mainProg = progList.front(); + if (mainProg->IsASTLowered()) { + continue; + } mainProg->VarBinder()->InitTopScope(); AddGlobalToBinder(mainProg); BindScopeNode(mainProg->VarBinder()->GetScope(), mainProg->Ast()); @@ -1251,7 +1254,9 @@ void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef) auto classCtx = LexicalScopeCreateOrEnter(VarBinder(), classDef); IterateNoTParams(classDef); - FilterOverloads(classDef->Body()); + + // Will generate new node when compiling decl, so when compiling main file, will not generate new history in decl. + FilterOverloads(classDef->BodyForUpdate()); auto *classScope = classCtx.GetScope(); BindScopeNode(classScope, classDef); } @@ -1378,7 +1383,7 @@ void InitScopesPhaseETS::ParseGlobalClass(ir::ClassDefinition *global) CallNode(decl); } CallNode(global->Annotations()); - FilterOverloads(global->Body()); + FilterOverloads(global->BodyForUpdate()); } void InitScopesPhaseETS::AddGlobalDeclaration(ir::AstNode *node) diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index 09fe048e25..dfddc8ba92 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -52,7 +52,13 @@ ir::Identifier *Gensym(ArenaAllocator *const allocator) util::UString GenName(ArenaAllocator *const allocator) { static std::size_t gensymCounter = 0U; - return util::UString {std::string(GENSYM_CORE) + std::to_string(++gensymCounter), allocator}; + static std::mutex gensymCounterMutex {}; + std::size_t individualGensym = 0; + { + std::lock_guard lock(gensymCounterMutex); + individualGensym = ++gensymCounter; + } + return util::UString {std::string(GENSYM_CORE) + std::to_string(individualGensym), allocator}; } void SetSourceRangesRecursively(ir::AstNode *node, const lexer::SourceRange &range) @@ -69,7 +75,7 @@ ir::AstNode *RefineSourceRanges(ir::AstNode *node) }; auto const refine = [isDummyLoc](ir::AstNode *ast) { - if (isDummyLoc(ast->Range(), ast) && ast->Parent() != nullptr) { + if (ast->Parent() != nullptr && isDummyLoc(ast->Range(), ast)) { ast->SetRange(ast->Parent()->Range()); } }; @@ -167,7 +173,7 @@ static void ClearHelper(parser::Program *prog) { ResetGlobalClass(prog); // #24256 Should be removed when code refactoring on checker is done and no ast node allocated in checker. - auto &stmts = prog->Ast()->Statements(); + auto &stmts = prog->Ast()->StatementsForUpdates(); // clang-format off stmts.erase(std::remove_if(stmts.begin(), stmts.end(), [](ir::AstNode *ast) -> bool { @@ -216,31 +222,56 @@ varbinder::Scope *Rebind(PhaseManager *phaseManager, varbinder::ETSBinder *varBi return scope; } +void HandleExternalProgram(varbinder::ETSBinder *newVarbinder, parser::Program *program) +{ + for (auto [_, program_list] : program->ExternalSources()) { + for (auto prog : program_list) { + if (!prog->IsASTLowered()) { + ClearHelper(prog); + prog->PushVarBinder(newVarbinder); + } + } + } +} + // Rerun varbinder and checker on the node. void Recheck(PhaseManager *phaseManager, varbinder::ETSBinder *varBinder, checker::ETSChecker *checker, ir::AstNode *node) { RefineSourceRanges(node); if (node->IsProgram()) { + auto ctx = varBinder->GetContext(); + phaseManager->SetCurrentPhaseId(0); auto program = node->AsETSModule()->Program(); - if (program->IsPackage()) { - return; - } - for (auto [_, program_list] : program->ExternalSources()) { - for (auto prog : program_list) { - ClearHelper(prog); - } - } + auto newVarbinder = ctx->allocator->New(ctx->allocator); + newVarbinder->SetProgram(program); + newVarbinder->SetContext(ctx); + program->PushVarBinder(newVarbinder); + varBinder->CopyTo(newVarbinder); + HandleExternalProgram(newVarbinder, program); ClearHelper(program); - varBinder->CleanUp(); - varBinder->GetContext()->checker->CleanUp(); + auto newChecker = + ctx->allocator->New(ctx->allocator, *ctx->diagnosticEngine, ctx->allocator); + auto analyzer = ctx->allocator->New(newChecker); + + ctx->PushAnalyzer(analyzer); + newChecker->SetAnalyzer(analyzer); + newChecker->Initialize(newVarbinder); + ctx->PushChecker(newChecker); + for (auto [_, program_list] : program->ExternalSources()) { + if (auto prog = program_list.front(); prog->IsASTLowered()) { + newChecker->SetGlobalTypesHolder(prog->Checker()->GetGlobalTypesHolder()); + break; + } + } for (auto *phase : phaseManager->RecheckPhases()) { - phase->Apply(varBinder->GetContext(), program); + phase->Apply(ctx, program); } + phaseManager->SetCurrentPhaseIdToAfterCheck(); return; } diff --git a/ets2panda/declgen_ets2ts/main.cpp b/ets2panda/declgen_ets2ts/main.cpp index d55467fc90..385e9f37c8 100644 --- a/ets2panda/declgen_ets2ts/main.cpp +++ b/ets2panda/declgen_ets2ts/main.cpp @@ -105,7 +105,7 @@ static int Run(int argc, const char **argv) impl->CreateContextFromString(cfg, parserInputCStr, cfgImpl->options->SourceFileName().c_str()); auto *ctxImpl = reinterpret_cast(ctx); - auto *checker = reinterpret_cast(ctxImpl->checker); + auto *checker = reinterpret_cast(ctxImpl->GetChecker()); auto *isolatedDeclgenChecker = reinterpret_cast(ctxImpl->isolatedDeclgenChecker); impl->ProceedToState(ctx, ES2PANDA_STATE_BOUND); diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 99fad43361..5d374555e6 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -17,10 +17,17 @@ import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; import * as child_process from 'child_process'; +import * as crypto from 'crypto'; + + import cluster, { Cluster, - Worker + Worker, } from 'cluster'; +import { + Worker as ThreadWorker, + workerData +} from 'worker_threads'; import { ABC_SUFFIX, ARKTSCONFIG_JSON_FILE, @@ -59,13 +66,18 @@ import { CompileFileInfo, DependencyFileConfig, DependentModuleConfig, + JobInfo, + KPointer, ModuleInfo } from '../types'; import { ArkTSConfigGenerator } from './generate_arktsconfig'; import { SetupClusterOptions } from '../types'; +import { create } from 'domain'; +import { emitKeypressEvents } from 'readline'; export abstract class BaseMode { buildConfig: BuildConfig; entryFiles: Set; + allFiles: Map; compileFiles: Map; outputDir: string; cacheDir: string; @@ -93,6 +105,7 @@ export abstract class BaseMode { isCacheFileExists: boolean; dependencyFileMap: DependencyFileConfig | null; isBuildConfigModified: boolean | undefined; + hasCleanWorker: boolean; constructor(buildConfig: BuildConfig) { this.buildConfig = buildConfig; @@ -121,12 +134,14 @@ export abstract class BaseMode { this.moduleInfos = new Map(); this.compileFiles = new Map(); + this.allFiles = new Map(); this.mergedAbcFile = path.resolve(this.outputDir, MERGED_ABC_FILE); this.dependencyJsonFile = path.resolve(this.cacheDir, DEPENDENCY_JSON_FILE); this.abcLinkerCmd = ['"' + this.buildConfig.abcLinkerPath + '"']; this.dependencyAnalyzerCmd = ['"' + this.buildConfig.dependencyAnalyzerPath + '"']; this.logger = Logger.getInstance(); + this.hasCleanWorker = false; } public declgen(fileInfo: CompileFileInfo): void { @@ -465,8 +480,17 @@ export abstract class BaseMode { const filePathFromModuleRoot = path.relative(moduleInfo.moduleRootPath, file); const filePathInCache = path.join(this.cacheDir, moduleInfo.packageName, filePathFromModuleRoot); const abcFilePath = path.resolve(changeFileExtension(filePathInCache, ABC_SUFFIX)); - this.abcFiles.add(abcFilePath); + + const fileInfo: CompileFileInfo = { + filePath: file, + dependentFiles: this.dependencyFileMap?.dependants[file] || [], + abcFilePath, + arktsConfigFile: moduleInfo.arktsConfigFile, + packageName: moduleInfo.packageName + }; + this.allFiles.set(file, fileInfo); + if (this.isBuildConfigModified || this.isFileChanged(file, abcFilePath)) { compileFiles.add(file); queue.push(file); @@ -541,7 +565,7 @@ export abstract class BaseMode { } protected collectCompileFiles(): void { - if (!this.isBuildConfigModified && this.isCacheFileExists && !this.enableDeclgenEts2Ts) { + if (!this.enableDeclgenEts2Ts) { this.collectDependentCompileFiles(); return; } @@ -554,19 +578,16 @@ export abstract class BaseMode { let filePathInCache: string = path.join(this.cacheDir, moduleInfo.packageName, filePathFromModuleRoot); let abcFilePath: string = path.resolve(changeFileExtension(filePathInCache, ABC_SUFFIX)); this.abcFiles.add(abcFilePath); - if (!this.isBuildConfigModified && this.shouldSkipFile(file, moduleInfo, filePathFromModuleRoot, abcFilePath)) { - return; - } this.hashCache[file] = getFileHash(file); let fileInfo: CompileFileInfo = { - filePath: file, + filePath: path.resolve(file), dependentFiles: [], abcFilePath: abcFilePath, arktsConfigFile: moduleInfo.arktsConfigFile, packageName: moduleInfo.packageName }; moduleInfo.compileFileInfos.push(fileInfo); - this.compileFiles.set(file, fileInfo); + this.compileFiles.set(path.resolve(file), fileInfo); return; } const logData: LogData = LogDataFactory.newInstance( @@ -615,6 +636,7 @@ export abstract class BaseMode { this.mergeAbcFiles(); } + // -- runParallell code begins -- private terminateAllWorkers(): void { Object.values(cluster.workers || {}).forEach(worker => { worker?.kill(); @@ -622,7 +644,7 @@ export abstract class BaseMode { }; public generatedependencyFileMap(): void { - if (this.isBuildConfigModified || !this.isCacheFileExists || this.enableDeclgenEts2Ts) { + if (this.enableDeclgenEts2Ts) { return; } let dependencyInputFile: string = path.join(this.cacheDir, DEPENDENCY_INPUT_FILE); @@ -808,7 +830,6 @@ export abstract class BaseMode { }); return JSON.parse(jsonStr); } - setupCluster(cluster: Cluster, options: SetupClusterOptions): void { const { clearExitListeners, @@ -825,4 +846,488 @@ export abstract class BaseMode { execArgv: execArgs, }); } + // -- runParallell code ends -- + + + // -- runConcurrent code begins -- + + private findStronglyConnectedComponents(graph: DependencyFileConfig): Map> { + const adjacencyList: Record = {}; + const reverseAdjacencyList: Record = {}; + const allNodes = new Set(); + + for (const node in graph.dependencies) { + allNodes.add(node); + graph.dependencies[node].forEach(dep => allNodes.add(dep)); + } + for (const node in graph.dependants) { + allNodes.add(node); + graph.dependants[node].forEach(dep => allNodes.add(dep)); + } + + Array.from(allNodes).forEach(node => { + adjacencyList[node] = graph.dependencies[node] || []; + reverseAdjacencyList[node] = graph.dependants[node] || []; + }); + + const visited = new Set(); + const order: string[] = []; + + function dfs(node: string): void { + visited.add(node); + for (const neighbor of adjacencyList[node]) { + if (!visited.has(neighbor)) { + dfs(neighbor); + } + } + order.push(node); + } + + Array.from(allNodes).forEach(node => { + if (!visited.has(node)) { + dfs(node); + } + }); + + visited.clear(); + const components = new Map>(); + + function reverseDfs(node: string, component: Set): void { + visited.add(node); + component.add(node); + for (const neighbor of reverseAdjacencyList[node]) { + if (!visited.has(neighbor)) { + reverseDfs(neighbor, component); + } + } + } + + for (let i = order.length - 1; i >= 0; i--) { + const node = order[i]; + if (!visited.has(node)) { + const component = new Set(); + reverseDfs(node, component); + if (component.size > 1) { + const sortedFiles = Array.from(component).sort(); + const hashKey = createHash(sortedFiles.join('|')); + components.set(hashKey, component); + } + + } + } + + return components; + } + + + private getJobDependencies(fileDeps: string[], cycleFiles: Map): Set { + let depJobList: Set = new Set(); + fileDeps.forEach((file) => { + if (!cycleFiles.has(file)) { + depJobList.add(this.getExternalProgramJobId(file)); + } else { + cycleFiles.get(file)?.forEach((f) => { + depJobList.add(f); + }); + } + }); + + return depJobList; + } + + private getAbcJobId(file: string): string { + return '1' + file; + } + + private getExternalProgramJobId(file: string): string { + return '0' + file; + } + + private getJobDependants(fileDeps: string[], cycleFiles: Map): Set { + let depJobList: Set = new Set(); + fileDeps.forEach((file) => { + if (!file.endsWith(DECL_ETS_SUFFIX)) { + depJobList.add(this.getAbcJobId(file)); + } + if (cycleFiles.has(file)) { + cycleFiles.get(file)?.forEach((f) => { + depJobList.add(f); + }); + } else { + depJobList.add(this.getExternalProgramJobId(file)); + } + }); + + return depJobList; + } + + private collectCompileJobs(jobs: Record): void { + let fileDepsInfo: DependencyFileConfig = this.dependencyFileMap!; + Object.keys(fileDepsInfo.dependants).forEach((file) => { + if (!(file in fileDepsInfo.dependencies)) { + fileDepsInfo.dependencies[file] = []; + } + }); + + const cycleGroups = this.findStronglyConnectedComponents(fileDepsInfo); + let cycleFiles: Map = new Map(); + cycleGroups.forEach((value: Set, key: string) => { + value.forEach((file) => { + cycleFiles.set(file, [key]); + }); + }); + + Object.entries(fileDepsInfo.dependencies).forEach(([key, value]) => { + if (this.entryFiles.has(key) && !this.compileFiles.has(key)) { + return; + } + let dependencies = this.getJobDependencies(value, cycleFiles); + + if (!key.endsWith(DECL_ETS_SUFFIX)) { + let abcJobId: string = this.getAbcJobId(key); + jobs[abcJobId] = { + id: abcJobId, + isDeclFile: false, + isInCycle: cycleFiles.has(key), + isAbcJob: true, + fileList: [key], + dependencies: Array.from(dependencies), // 依赖external program + dependants: [] + }; + } + + if (cycleFiles.has(key)) { + const externalProgramJobIds = cycleFiles.get(key)!; + externalProgramJobIds.forEach((id) => { + let fileList: string[] = Array.from(cycleGroups.get(id)!); + this.createExternalProgramJob(id, fileList, jobs, dependencies, true); + }); + } else { + const id = this.getExternalProgramJobId(key); + let fileList: string[] = [key]; + this.createExternalProgramJob(id, fileList, jobs, dependencies); + } + + if (key.endsWith(DECL_ETS_SUFFIX)) { + let fileInfo: CompileFileInfo = { + filePath: key, + dependentFiles: [], + abcFilePath: '', + arktsConfigFile: this.moduleInfos.get(this.packageName)!.arktsConfigFile, + packageName: this.moduleInfos.get(this.packageName)!.packageName + }; + + if (!this.allFiles.has(key)) { + this.allFiles.set(key, fileInfo); + } + } + }); + + Object.entries(fileDepsInfo.dependants).forEach(([key, value]) => { + if (this.entryFiles.has(key) && !this.compileFiles.has(key)) { + return; + } + let dependants = this.getJobDependants(value, cycleFiles); + + this.dealWithDependants(cycleFiles, key, jobs, dependants); + }); + } + + private dealWithDependants(cycleFiles: Map, key: string, jobs: Record, dependants: Set): void { + if (cycleFiles.has(key)) { + const externalProgramJobIds = cycleFiles.get(key)!; + externalProgramJobIds.forEach((id) => { + jobs[id].dependants.forEach(dep => { + dependants.add(dep); + }); + if (dependants.has(id)) { + dependants.delete(id); + } + + jobs[id].dependants = Array.from(dependants); + }); + } else { + const id = this.getExternalProgramJobId(key); + jobs[id].dependants.forEach(dep => { + dependants.add(dep); + }); + if (dependants.has(id)) { + dependants.delete(id); + } + jobs[id].dependants = Array.from(dependants); + } + } + + private createExternalProgramJob(id: string, fileList: string[], jobs: Record, dependencies: Set, isInCycle?: boolean): void { + if (dependencies.has(id)) { + dependencies.delete(id); + } + + // TODO: can be duplicated ids + if (jobs[id]) { + // If job already exists, merge the file lists and dependencies + const existingJob = jobs[id]; + const mergedDependencies = new Set([ + ...existingJob.dependencies, + ...Array.from(dependencies) + ]); + jobs[id] = { + ...existingJob, + dependencies: Array.from(mergedDependencies) + }; + } else { + jobs[id] = { + id, + fileList, + isDeclFile: true, + isInCycle, + isAbcJob: false, + dependencies: Array.from(dependencies), // 依赖external program + dependants: [] + }; + } + } + + private addJobToQueues(job: Job, queues: Queues): void { + if (queues.externalProgramQueue.some(j => j.id === job.id) || + queues.abcQueue.some(j => j.id === job.id)) { + return; + } + + if (!job.isAbcJob) { + queues.externalProgramQueue.push(job); + } else { + queues.abcQueue.push(job); + } + } + + private initCompileQueues(jobs: Record, queues: Queues): void { + this.collectCompileJobs(jobs); + Object.values(jobs).forEach(job => { + if (job.dependencies.length === 0) { + this.addJobToQueues(job, queues); + } + }); + } + + private checkAllTasksDone(queues: Queues, workerPool: WorkerInfo[]): boolean { + if (queues.externalProgramQueue.length === 0) { + for (let i = 0; i < workerPool.length; i++) { + if (!workerPool[i].isIdle) { + return false; + } + } + return true; + } + return false; + } + + private processAfterCompile(config: KPointer, globalContext: KPointer): void { + + if (this.hasCleanWorker) { + return; + } + this.hasCleanWorker = true; + let arktsGlobal = this.buildConfig.arktsGlobal; + let arkts = this.buildConfig.arkts; + + arktsGlobal.es2panda._DestroyGlobalContext(globalContext); + arkts.destroyConfig(config); + arktsGlobal.es2panda._MemFinalize(); + + this.mergeAbcFiles(); + } + + // CC-OFFNXT(huge_depth) + private async invokeWorkers(jobs: Record, queues: Queues, processingJobs: Set, workers: ThreadWorker[]): Promise { + return new Promise((resolve) => { + const numWorkers = 1; + + let files: string[] = []; + + Object.entries(jobs).forEach(([key, job]) => { + for (let i = 0; i < job.fileList.length; i++) { + files.push(job.fileList[i]); + } + }); + + let arkts = this.buildConfig.arkts; + let fileInfo = this.compileFiles.values().next().value!; + + let ets2pandaCmd: string[] = [ + '_', + '--extension', + 'ets', + '--arktsconfig', + fileInfo.arktsConfigFile, + '--output', + fileInfo.abcFilePath, + ]; + + if (this.isDebug) { + ets2pandaCmd.push('--debug-info'); + } + ets2pandaCmd.push(fileInfo.filePath); + + arkts.MemInitialize(); + + let config = arkts.Config.create(ets2pandaCmd).peer; + + let globalContextPtr = arkts.CreateGlobalContext(config, files, files.length, false); + const serializableConfig = this.getSerializableConfig(); + + const workerPool: WorkerInfo[] = []; + for (let i = 0; i < numWorkers; i++) { + const worker = new ThreadWorker( + path.resolve(__dirname, 'compile_thread_worker.js'), + { workerData: { workerId: i } } + ); + + workers.push(worker); + workerPool.push({ worker, isIdle: true }); + this.assignTaskToIdleWorker(workerPool[i], queues, processingJobs, serializableConfig, globalContextPtr); + worker.on('message', (msg) => { + if (msg.type === 'TASK_FINISH') { + const workerInfo = workerPool.find(w => w.worker === worker); + if (workerInfo) { + workerInfo.isIdle = true; + } + const jobId = msg.jobId; + finishedJob.push(jobId); + processingJobs.delete(jobId); + const completedJob = jobs[jobId]; + completedJob.dependants.forEach(depJobId => { + const depJob = jobs[depJobId]; + if (!depJob) { + return; + } + const depIndex = depJob.dependencies.indexOf(jobId); + if (depIndex !== -1) { + depJob.dependencies.splice(depIndex, 1); + if (depJob.dependencies.length === 0) { + this.addJobToQueues(depJob, queues); + } + } + }); + for (let j = 0; j < workerPool.length; j++) { + if (workerPool[j].isIdle) { + this.assignTaskToIdleWorker(workerPool[j], queues, processingJobs, serializableConfig, globalContextPtr); + } + } + } + if (this.checkAllTasksDone(queues, workerPool)) { + workers.forEach(worker => worker.postMessage({ type: 'EXIT' })); + this.processAfterCompile(config, globalContextPtr); + resolve(); + } + }); + } + }); + } + + private updateDependantJobs(jobId: string, processingJobs: Set, jobs: Record, queues: Queues): void { + finishedJob.push(jobId); + processingJobs.delete(jobId); + const completedJob = jobs[jobId]; + completedJob.dependants.forEach(depJobId => { + const depJob = jobs[depJobId]; + // During incremental compilation, the dependants task does not necessarily exist + if (!depJob) { + return; + } + const depIndex = depJob.dependencies.indexOf(jobId); + if (depIndex !== -1) { + depJob.dependencies.splice(depIndex, 1); + if (depJob.dependencies.length === 0) { + this.addJobToQueues(depJob, queues); + } + } + }); + } + + private assignTaskToIdleWorker( + workerInfo: WorkerInfo, + queues: Queues, + processingJobs: Set, + serializableConfig: Object, + globalContextPtr: KPointer): void { + let job: Job | undefined; + let jobInfo: JobInfo | undefined; + + if (queues.externalProgramQueue.length > 0) { + job = queues.externalProgramQueue.shift()!; + jobInfo = { + id: job.id, + isCompileAbc: false, + compileFileInfo: this.allFiles.get(job.fileList[0])!, + buildConfig: serializableConfig, + globalContextPtr: globalContextPtr + }; + } + else if (queues.abcQueue.length > 0) { + job = queues.abcQueue.shift()!; + jobInfo = { + id: job.id, + isCompileAbc: true, + compileFileInfo: this.allFiles.get(job.fileList[0])!, + buildConfig: serializableConfig, + globalContextPtr: globalContextPtr + }; + } + + if (job) { + processingJobs.add(job.id); + workerInfo.worker.postMessage({ type: 'ASSIGN_TASK', jobInfo }); + workerInfo.isIdle = false; + } + } + + public async runConcunrent(): Promise { + this.generateModuleInfos(); + if (this.compileFiles.size === 0) { + return; + } + this.generateArkTSConfigForModules(); + + const jobs: Record = {}; + const queues: Queues = { + externalProgramQueue: [], + abcQueue: [], + }; + this.initCompileQueues(jobs, queues); + + const processingJobs = new Set(); + const workers: ThreadWorker[] = []; + await this.invokeWorkers(jobs, queues, processingJobs, workers); + } +} + +interface WorkerInfo { + worker: ThreadWorker; + isIdle: boolean; } + +interface Job { + id: string; + isDeclFile: boolean; + isInCycle?: boolean; + fileList: string[]; + dependencies: string[]; + dependants: string[]; + isAbcJob: boolean; +} + +interface Queues { + externalProgramQueue: Job[]; + abcQueue: Job[]; +} + +function createHash(str: string): string { + const hash = crypto.createHash('sha256'); + hash.update(str); + return hash.digest('hex'); +} + + // -- runConcurrent code ends -- + +let finishedJob: string[] = []; \ No newline at end of file diff --git a/ets2panda/driver/build_system/src/build/build_mode.ts b/ets2panda/driver/build_system/src/build/build_mode.ts index 59bdb759ab..accdafbcca 100644 --- a/ets2panda/driver/build_system/src/build/build_mode.ts +++ b/ets2panda/driver/build_system/src/build/build_mode.ts @@ -26,6 +26,6 @@ export class BuildMode extends BaseMode { } public async run(): Promise { - await super.runParallell(); + await super.runConcunrent(); } } \ No newline at end of file diff --git a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts new file mode 100644 index 0000000000..c8aaed5662 --- /dev/null +++ b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { parentPort, workerData } from 'worker_threads'; +import { CompileFileInfo, JobInfo } from '../types'; +import * as fs from 'fs'; +import * as path from 'path'; +import { ensurePathExists } from '../utils'; +import { KOALA_WRAPPER_PATH_FROM_SDK } from '../pre_define'; +import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; +import { + BuildConfig, +} from '../types'; +import { + BUILD_MODE +} from '../pre_define'; +import { + LogData, + LogDataFactory, + Logger +} from '../logger'; +import { ErrorCode } from '../error_code'; + +const { workerId } = workerData; + +function compileAbc(jobInfo: JobInfo): void { + let config = jobInfo.buildConfig as BuildConfig; + Logger.getInstance(config); + PluginDriver.getInstance().initPlugins(config); + const koalaWrapperPath = path.resolve(config.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); + let { arkts, arktsGlobal } = require(koalaWrapperPath); + const isDebug = config.buildMode === BUILD_MODE.DEBUG; + + let errorStatus = false; + try { + let fileInfo = jobInfo.compileFileInfo; + ensurePathExists(fileInfo.abcFilePath); + + const ets2pandaCmd = [ + '_', '--extension', 'ets', + '--arktsconfig', fileInfo.arktsConfigFile, + '--output', fileInfo.abcFilePath, + ]; + + if (isDebug) { + ets2pandaCmd.push('--debug-info'); + } + ets2pandaCmd.push(fileInfo.filePath); + + let config = arkts.Config.create(ets2pandaCmd).peer; + arktsGlobal.config = config; + + let context = arkts.Context.createCacheContextFromFile(config, fileInfo.filePath, jobInfo.globalContextPtr, false).peer; + + PluginDriver.getInstance().getPluginContext().setContextPtr(context); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, context); + + PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, context); + + PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, context); + } catch (error) { + errorStatus = true; + if (error instanceof Error) { + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_COMPILE_ABC_FAIL, + 'Compile abc files failed.', + error.message + ); + Logger.getInstance().printError(logData); + } + } finally { + if (!errorStatus) { + // when error occur,wrapper will destroy context. + arktsGlobal.es2panda._DestroyContext(arktsGlobal.compilerContext.peer); + } + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + arkts.destroyConfig(arktsGlobal.config); + } +} + +function compileExternalProgram(jobInfo: JobInfo): void { + let config = jobInfo.buildConfig as BuildConfig; + Logger.getInstance(config); + PluginDriver.getInstance().initPlugins(config); + const koalaWrapperPath = path.resolve(config.buildSdkPath, KOALA_WRAPPER_PATH_FROM_SDK); + let { arkts, arktsGlobal } = require(koalaWrapperPath); + const isDebug = config.buildMode === BUILD_MODE.DEBUG; + + let errorStatus = false; + try { + let fileInfo = jobInfo.compileFileInfo; + const ets2pandaCmd = ['-', '--extension', 'ets', '--arktsconfig', fileInfo.arktsConfigFile]; + + if (isDebug) { + ets2pandaCmd.push('--debug-info'); + } + ets2pandaCmd.push(fileInfo.filePath); + + let config = arkts.Config.create(ets2pandaCmd).peer; + arktsGlobal.config = config; + + let context = arkts.Context.createCacheContextFromFile(config, fileInfo.filePath, jobInfo.globalContextPtr, true).peer; + + PluginDriver.getInstance().getPluginContext().setContextPtr(context); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, context); + + PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, context); + + PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); + + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_LOWERED, context); + } catch (error) { + errorStatus = true; + if (error instanceof Error) { + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_COMPILE_ABC_FAIL, + 'Compile external program files failed.', + error.message + ); + Logger.getInstance().printError(logData); + } + } finally { + if (!errorStatus) { + // when error occur,wrapper will destroy context. + arktsGlobal.es2panda._DestroyContext(arktsGlobal.compilerContext.peer); + } + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + arkts.destroyConfig(arktsGlobal.config); + } +} + +parentPort?.on('message', (msg) => { + if (msg.type === 'ASSIGN_TASK') { + const job = msg.jobInfo; + + if (job.isCompileAbc) { + compileAbc(job); + } else { + compileExternalProgram(job); + } + + parentPort?.postMessage({ + type: 'TASK_FINISH', + jobId: job.id, + workerId, + }); + } else if (msg.type === 'EXIT') { + process.exit(0); + } +}); diff --git a/ets2panda/driver/build_system/src/entry.ts b/ets2panda/driver/build_system/src/entry.ts index c0a0542d9d..f6cd7ef78e 100644 --- a/ets2panda/driver/build_system/src/entry.ts +++ b/ets2panda/driver/build_system/src/entry.ts @@ -29,6 +29,7 @@ export async function build(projectConfig: BuildConfig): Promise { let logger: Logger = Logger.getInstance(projectConfig); let buildConfig: BuildConfig = processBuildConfig(projectConfig); + buildConfig.entryFiles = buildConfig.compileFiles; if (projectConfig.frameworkMode === true) { let buildframeworkMode: BuildFrameworkMode = new BuildFrameworkMode(buildConfig); await buildframeworkMode.run(); @@ -54,8 +55,6 @@ function clean(): void { } function main(): void { - console.log(process.argv); - const buildConfigPath: string = path.resolve(process.argv[2]); const projectConfig: BuildConfig = JSON.parse(fs.readFileSync(buildConfigPath, 'utf-8')); diff --git a/ets2panda/driver/build_system/src/plugins/FileManager.ts b/ets2panda/driver/build_system/src/plugins/FileManager.ts index 8548c8d092..9a2c8b4e18 100644 --- a/ets2panda/driver/build_system/src/plugins/FileManager.ts +++ b/ets2panda/driver/build_system/src/plugins/FileManager.ts @@ -14,11 +14,10 @@ */ import * as path from 'path'; -import * as fs from 'fs'; -import { BuildConfig, DependentModuleConfig } from "../types"; +import { BuildConfig, DependentModuleConfig } from '../types'; import { toUnixPath } from '../utils'; import { ETS_1_1, ETS_1_1_INTEROP, LANGUAGE_VERSION } from '../pre_define'; -import { readFirstLineSync } from '../utils' +import { readFirstLineSync } from '../utils'; export class FileManager { private static instance: FileManager | undefined = undefined; @@ -52,7 +51,7 @@ export class FileManager { static initSDK(externalApiPath: Set, buildSDKPath: string): void { externalApiPath?.forEach(path => { FileManager.staticApiPath.add(toUnixPath(path)); - }) + }); const etsPath = path.resolve(buildSDKPath, '../'); @@ -73,7 +72,7 @@ export class FileManager { declFilesPath: module.declFilesPath ? toUnixPath(module.declFilesPath) : undefined, }; convertedMap.set(module.packageName, convertedModule); - }) + }); this.arkTSModuleMap = convertedMap; } @@ -101,7 +100,7 @@ export class FileManager { if (!path.startsWith(moduleInfo.modulePath)) { continue; } - if (moduleInfo.language != LANGUAGE_VERSION.ARKTS_HYBRID) { + if (moduleInfo.language !== LANGUAGE_VERSION.ARKTS_HYBRID) { return moduleInfo.language; } /** diff --git a/ets2panda/driver/build_system/src/plugins/plugins_driver.ts b/ets2panda/driver/build_system/src/plugins/plugins_driver.ts index eb556eb023..67203f601d 100644 --- a/ets2panda/driver/build_system/src/plugins/plugins_driver.ts +++ b/ets2panda/driver/build_system/src/plugins/plugins_driver.ts @@ -71,12 +71,14 @@ class PluginContext { private program: object | undefined; private projectConfig: object | undefined; private fileManager: FileManager | undefined; + private contextPtr: number | undefined; constructor() { this.ast = undefined; this.program = undefined; this.projectConfig = undefined; this.fileManager = undefined; + this.contextPtr = undefined; } public setArkTSAst(ast: object): void { @@ -96,15 +98,6 @@ class PluginContext { } public setProjectConfig(projectConfig: object): void { - if (this.projectConfig) { - const logData: LogData = LogDataFactory.newInstance( - ErrorCode.BUILDSYSTEM_PLUGIN_CONTEXT_RESET_PROJECT_CONFIG, - 'Trying to reset projectConfig in PluginContext, abort compiling.', - 'projectConfig in PluginContext can only be set once.' - ); - Logger.getInstance().printErrorAndExit(logData); - return; - } this.projectConfig = projectConfig; } @@ -112,16 +105,24 @@ class PluginContext { return this.projectConfig; } - public setFileManager(projectConfig: BuildConfig):void{ - if(!this.fileManager){ + public setFileManager(projectConfig: BuildConfig): void { + if (!this.fileManager) { FileManager.init(projectConfig); this.fileManager = FileManager.getInstance(); } } - public getFileManager():FileManager| undefined{ + public getFileManager(): FileManager | undefined{ return this.fileManager; } + + public setContextPtr(ptr: number): void { + this.contextPtr = ptr; + } + + public getContextPtr(): number | undefined { + return this.contextPtr; + } } export class PluginDriver { diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index 0d0d0d38ac..91255055f1 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -37,6 +37,10 @@ export interface ArkTSGlobal { }; es2panda: { _DestroyContext: Function; + _MemInitialize: Function; + _MemFinalize: Function; + _CreateGlobalContext: Function; + _DestroyGlobalContext: Function; } } @@ -54,6 +58,8 @@ export interface ArkTS { generateTsDeclarationsFromContext: Function; destroyConfig: Function; Es2pandaContextState: typeof Es2pandaContextState; + MemInitialize: Function; + CreateGlobalContext: Function; } export enum Es2pandaContextState { @@ -133,6 +139,7 @@ export interface DependentModuleConfig { export interface BuildConfig extends BuildBaseConfig, DeclgenConfig, LoggerConfig, ModuleConfig, PathConfig, FrameworkConfig { plugins: PluginsConfig; compileFiles: string[]; + entryFiles?: string[]; dependentModuleList: DependentModuleConfig[]; } // ProjectConfig ends @@ -178,4 +185,14 @@ export interface DependencyFileConfig { dependencies: { [filePath: string]: string[]; } -} \ No newline at end of file +} + +export interface JobInfo { + id: string; + isCompileAbc: boolean; + compileFileInfo: CompileFileInfo; + buildConfig: Object; + globalContextPtr?: KPointer; +} + +export type KPointer = number | bigint; \ No newline at end of file diff --git a/ets2panda/driver/build_system/test/demo_hap/entry/a.ets b/ets2panda/driver/build_system/test/demo_hap/entry/a.ets index 76a66d7bbf..03e10fb47a 100644 --- a/ets2panda/driver/build_system/test/demo_hap/entry/a.ets +++ b/ets2panda/driver/build_system/test/demo_hap/entry/a.ets @@ -13,7 +13,22 @@ * limitations under the License. */ + +import {str, strd} from './c' +import {strA} from 'harA' +import {strB} from 'harB' + function main() { let a: string = "hello world" console.log(a) + + console.log(strd); + + console.log(strA); + console.log(strB); + + console.log("end hello world a.ets") } + +let stra = "hello world from a" +export {stra} \ No newline at end of file diff --git a/ets2panda/driver/build_system/test/demo_hap/entry/c.ets b/ets2panda/driver/build_system/test/demo_hap/entry/c.ets index bfbc0dd50e..1fd443aa1f 100644 --- a/ets2panda/driver/build_system/test/demo_hap/entry/c.ets +++ b/ets2panda/driver/build_system/test/demo_hap/entry/c.ets @@ -13,7 +13,9 @@ * limitations under the License. */ -import {strd} from './d' +import {strd, strArr} from './d' + +let d: string[] = strArr; export let str: string = "hello world from c!"; export {strd} \ No newline at end of file diff --git a/ets2panda/driver/build_system/test/demo_hap/entry/d.ets b/ets2panda/driver/build_system/test/demo_hap/entry/d.ets index 0cd8a43084..a880df3c2a 100644 --- a/ets2panda/driver/build_system/test/demo_hap/entry/d.ets +++ b/ets2panda/driver/build_system/test/demo_hap/entry/d.ets @@ -13,4 +13,9 @@ * limitations under the License. */ -export let strd: string = "hello world from d!"; \ No newline at end of file +// import {foo} from './b'; + +// foo(); + +export let strd: string = "hello world from d!"; +export let strArr: string[] = ['1', '2']; \ No newline at end of file diff --git a/ets2panda/driver/dependency_analyzer/dep_analyzer.cpp b/ets2panda/driver/dependency_analyzer/dep_analyzer.cpp index 1ddb8ad777..1ea40a4e2b 100644 --- a/ets2panda/driver/dependency_analyzer/dep_analyzer.cpp +++ b/ets2panda/driver/dependency_analyzer/dep_analyzer.cpp @@ -146,6 +146,8 @@ int DepAnalyzer::AnalyzeDepsForMultiFiles(const char *exec, std::vector parsedFileList; const auto *impl = es2panda_GetImpl(ES2PANDA_LIB_VERSION); + impl->MemInitialize(); + for (auto &file : fileList) { if (parsedFileList.count(file) != 0U || fileDirectDependencies_.count(file) != 0U) { continue; @@ -173,8 +175,8 @@ int DepAnalyzer::AnalyzeDepsForMultiFiles(const char *exec, std::vectorProceedToState(ctx, ES2PANDA_STATE_PARSED); if (ctxImpl->state == ES2PANDA_STATE_ERROR) { - ctxImpl->checker->LogTypeError(std::string("Parse Failed: ").append(ctxImpl->errorMessage), - ctxImpl->errorPos); + ctxImpl->GetChecker()->LogTypeError(std::string("Parse Failed: ").append(ctxImpl->errorMessage), + ctxImpl->errorPos); impl->DestroyContext(ctx); impl->DestroyConfig(cfg); return 1; @@ -188,6 +190,8 @@ int DepAnalyzer::AnalyzeDepsForMultiFiles(const char *exec, std::vectorDestroyContext(ctx); impl->DestroyConfig(cfg); } + + impl->MemFinalize(); return 0; } @@ -230,6 +234,7 @@ std::optional ParseArguments(ark::Span args) int DepAnalyzer::AnalyzeDeps(int argc, const char **argv) { + // NOLINTBEGIN int minArgCount = 2; if (argc < minArgCount) { std::cerr << "No file has been entered for analysis" << std::endl; @@ -241,4 +246,5 @@ int DepAnalyzer::AnalyzeDeps(int argc, const char **argv) return 1; } return 0; + // NOLINTEND } diff --git a/ets2panda/es2panda.cpp b/ets2panda/es2panda.cpp index aadd815b18..b2b63e0635 100644 --- a/ets2panda/es2panda.cpp +++ b/ets2panda/es2panda.cpp @@ -87,7 +87,7 @@ pandasm::Program *Compiler::Compile(const SourceFile &input, const util::Options util::DiagnosticEngine &diagnosticEngine, uint32_t parseStatus) { public_lib::Context context; - ArenaAllocator allocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + ThreadSafeArenaAllocator allocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); context.allocator = &allocator; context.compilingState = public_lib::CompilingState::SINGLE_COMPILING; @@ -105,7 +105,7 @@ unsigned int Compiler::CompileM(std::vector &inputs, util::Options & { public_lib::Context context; context.transitionMemory = - new public_lib::TransitionMemory(new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true)); + new public_lib::TransitionMemory(new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true)); context.allocator = context.transitionMemory->PermanentAllocator(); context.compilingState = public_lib::CompilingState::MULTI_COMPILING_INIT; @@ -138,6 +138,6 @@ void Compiler::DumpAsm(const pandasm::Program *prog) compiler::CompilerImpl::DumpAsm(prog); } -util::DiagnosticEngine *g_diagnosticEngine = nullptr; - +// When compiling multi thread, this is need by each thread indenpengdentlt +thread_local util::DiagnosticEngine *g_diagnosticEngine = nullptr; } // namespace ark::es2panda diff --git a/ets2panda/es2panda.h b/ets2panda/es2panda.h index 21c202e405..39cdbf9e1b 100644 --- a/ets2panda/es2panda.h +++ b/ets2panda/es2panda.h @@ -140,7 +140,7 @@ private: // g_diagnosticEngine used only for flush diagnostic before unexpected process termination: // - inside SIGSEGV handler -extern util::DiagnosticEngine *g_diagnosticEngine; +thread_local extern util::DiagnosticEngine *g_diagnosticEngine; } // namespace ark::es2panda #endif diff --git a/ets2panda/evaluate/debugInfoDeserialization/classBuilder.cpp b/ets2panda/evaluate/debugInfoDeserialization/classBuilder.cpp index e78fd348d3..e1101e2b00 100644 --- a/ets2panda/evaluate/debugInfoDeserialization/classBuilder.cpp +++ b/ets2panda/evaluate/debugInfoDeserialization/classBuilder.cpp @@ -68,7 +68,7 @@ ir::ClassDeclaration *ClassBuilder::Build(parser::Program *program) && classDecl->SetParent(programAst); // Here we assume that global statements of the passed `program` are not currently checked, so that // insertion is safe. - programAst->Statements().push_back(classDecl); + programAst->AddStatement(classDecl); return classDecl; } diff --git a/ets2panda/evaluate/scopedDebugInfoPlugin.cpp b/ets2panda/evaluate/scopedDebugInfoPlugin.cpp index fc8666dc9e..16b6396f9f 100644 --- a/ets2panda/evaluate/scopedDebugInfoPlugin.cpp +++ b/ets2panda/evaluate/scopedDebugInfoPlugin.cpp @@ -149,7 +149,7 @@ bool ScopedDebugInfoPlugin::InsertReturnStatement() // which will also modify method signature's return type. auto *evalMethodStatements = context_.methodStatements; - auto &statementsList = evalMethodStatements->Statements(); + auto &statementsList = evalMethodStatements->StatementsForUpdates(); // Omit the emplaced `DebuggerAPI.setLocal<>` calls and find the original last statement. auto lastStatementIter = std::find(statementsList.rbegin(), statementsList.rend(), lastStatement); ES2PANDA_ASSERT(lastStatementIter != statementsList.rend()); @@ -195,7 +195,7 @@ void ScopedDebugInfoPlugin::AddPrologueEpilogue(ir::BlockStatement *block) } // Prepend prologue. - auto &statements = block->Statements(); + auto &statements = block->StatementsForUpdates(); for (auto *stmt : iter->second.first) { statements.insert(statements.begin(), stmt); } diff --git a/ets2panda/ir/annotationAllowed.h b/ets2panda/ir/annotationAllowed.h index 0053c073dc..90eea9d954 100644 --- a/ets2panda/ir/annotationAllowed.h +++ b/ets2panda/ir/annotationAllowed.h @@ -19,6 +19,7 @@ #include "ir/astNode.h" #include "ir/statement.h" #include "ir/statements/annotationUsage.h" +#include "util/es2pandaMacros.h" namespace ark::es2panda::ir { @@ -31,24 +32,77 @@ public: NO_COPY_OPERATOR(AnnotationAllowed); NO_MOVE_SEMANTIC(AnnotationAllowed); - [[nodiscard]] ArenaVector &Annotations() noexcept + void EmplaceAnnotations(AnnotationUsage *source) { - return annotations_; + auto newNode = reinterpret_cast *>(this->GetOrCreateHistoryNode()); + newNode->annotations_.emplace_back(source); + } + + void ClearAnnotations() + { + auto newNode = reinterpret_cast *>(this->GetOrCreateHistoryNode()); + newNode->annotations_.clear(); + } + + void SetValueAnnotations(AnnotationUsage *source, size_t index) + { + auto newNode = reinterpret_cast *>(this->GetOrCreateHistoryNode()); + auto &arenaVector = newNode->annotations_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; + }; + + void TransformAnnotations(const NodeTransformer &cb, std::string_view const transformationName) + { + auto &annotations = Annotations(); + for (size_t ix = 0; ix < annotations.size(); ix++) { + if (auto *transformedNode = cb(annotations[ix]); annotations[ix] != transformedNode) { + annotations[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueAnnotations(transformedNode->AsAnnotationUsage(), ix); + } + } + } + + ArenaVector &AnnotationsForUpdate() + { + return AstNode::GetOrCreateHistoryNodeAs>()->annotations_; + } + + const ArenaVector &Annotations() + { + return AstNode::GetHistoryNodeAs>()->annotations_; } [[nodiscard]] const ArenaVector &Annotations() const noexcept { - return annotations_; + return AstNode::GetHistoryNodeAs>()->annotations_; } - void SetAnnotations(ArenaVector &&annotations) + void SetAnnotations(const ArenaVector &&annotationList) { - annotations_ = std::move(annotations); - for (ir::AnnotationUsage *anno : annotations_) { - anno->SetParent(this); + auto &annotations = AstNode::GetOrCreateHistoryNodeAs>()->annotations_; + annotations = ArenaVector {annotationList}; + + for (auto annotation : Annotations()) { + annotation->SetParent(this); + } + } + + void SetAnnotations(const ArenaVector &annotationList) + { + auto &annotations = AstNode::GetOrCreateHistoryNodeAs>()->annotations_; + annotations = annotationList; + + for (auto annotation : Annotations()) { + annotation->SetParent(this); } } + void AddAnnotations(AnnotationUsage *annotations) + { + AstNode::GetOrCreateHistoryNodeAs>()->annotations_.emplace_back(annotations); + } + protected: explicit AnnotationAllowed(Expression const &other, ArenaAllocator *allocator) : T(other), annotations_(allocator->Adapter()) @@ -82,11 +136,6 @@ protected: { } - void AddAnnotations(AnnotationUsage *const annotations) - { - annotations_.emplace_back(annotations); - } - AnnotationAllowed(AnnotationAllowed const &other) : T(static_cast(other)), annotations_(other.annotations_.get_allocator()) { diff --git a/ets2panda/ir/as/namedType.cpp b/ets2panda/ir/as/namedType.cpp index 7bf5f66ecb..48880e1589 100644 --- a/ets2panda/ir/as/namedType.cpp +++ b/ets2panda/ir/as/namedType.cpp @@ -45,12 +45,7 @@ void NamedType::TransformChildren(const NodeTransformer &cb, std::string_view co } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void NamedType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 9d920eeac2..3b8a45b1bc 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -14,7 +14,9 @@ */ #include "astNode.h" +#include "compiler/lowering/phase.h" #include "ir/astDump.h" +#include "ir/astNodeHistory.h" #include "ir/srcDump.h" #include "ir/typed.h" @@ -22,50 +24,51 @@ namespace ark::es2panda::ir { AstNode::AstNode(AstNode const &other) { - range_ = other.range_; - type_ = other.type_; - if (other.variable_ != nullptr) { - variable_ = other.variable_; + auto otherHistoryNode = other.GetHistoryNode(); + range_ = otherHistoryNode->range_; + type_ = otherHistoryNode->type_; + if (otherHistoryNode->variable_ != nullptr) { + variable_ = otherHistoryNode->variable_; } - flags_ = other.flags_; - astNodeFlags_ = other.astNodeFlags_; + flags_ = otherHistoryNode->flags_; + astNodeFlags_ = otherHistoryNode->astNodeFlags_; // boxing_unboxing_flags_ {}; leave default value! } [[nodiscard]] bool AstNode::IsExported() const noexcept { if (UNLIKELY(IsClassDefinition())) { - return parent_->IsExported(); + return GetHistoryNode()->parent_->IsExported(); } - return (flags_ & ModifierFlags::EXPORT) != 0; + return (Modifiers() & ModifierFlags::EXPORT) != 0; } [[nodiscard]] bool AstNode::IsDefaultExported() const noexcept { if (UNLIKELY(IsClassDefinition())) { - return parent_->IsDefaultExported(); + return GetHistoryNode()->parent_->IsDefaultExported(); } - return (flags_ & ModifierFlags::DEFAULT_EXPORT) != 0; + return (Modifiers() & ModifierFlags::DEFAULT_EXPORT) != 0; } [[nodiscard]] bool AstNode::IsExportedType() const noexcept { if (UNLIKELY(IsClassDefinition())) { - return this->parent_->IsExportedType(); + return GetHistoryNode()->parent_->IsExportedType(); } - return (flags_ & ModifierFlags::EXPORT_TYPE) != 0; + return (Modifiers() & ModifierFlags::EXPORT_TYPE) != 0; } [[nodiscard]] bool AstNode::HasExportAlias() const noexcept { if (UNLIKELY(IsClassDefinition())) { - return parent_->HasExportAlias(); + return GetHistoryNode()->parent_->HasExportAlias(); } - return (astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; + return (GetHistoryNode()->astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; } bool AstNode::IsScopeBearer() const noexcept @@ -247,18 +250,28 @@ std::string AstNode::IsolatedDumpDecl() const void AstNode::SetOriginalNode(AstNode *originalNode) noexcept { - originalNode_ = originalNode; + if (OriginalNode() != originalNode) { + GetOrCreateHistoryNode()->originalNode_ = originalNode; + } } AstNode *AstNode::OriginalNode() const noexcept { - return originalNode_; + return GetHistoryNode()->originalNode_; +} + +const std::optional> &AstNode::TransformedNode() const noexcept +{ + return GetHistoryNode()->transformedNode_; } void AstNode::SetTransformedNode(std::string_view const transformationName, AstNode *transformedNode) { - transformedNode->SetOriginalNode(this); - transformedNode_ = std::make_optional(std::make_pair(transformationName, transformedNode)); + if (transformedNode != nullptr) { + transformedNode->SetOriginalNode(this); + GetOrCreateHistoryNode()->transformedNode_ = + std::make_optional(std::make_pair(transformationName, transformedNode)); + } } void AstNode::CleanUp() @@ -274,33 +287,33 @@ void AstNode::CleanUp() bool AstNode::IsReadonly() const noexcept { - return (flags_ & ModifierFlags::READONLY) != 0; + return (Modifiers() & ModifierFlags::READONLY) != 0; } // NOTE: For readonly parameter type bool AstNode::IsReadonlyType() const noexcept { - return (flags_ & ModifierFlags::READONLY_PARAMETER) != 0; + return (Modifiers() & ModifierFlags::READONLY_PARAMETER) != 0; } bool AstNode::IsOptionalDeclaration() const noexcept { - return (flags_ & ModifierFlags::OPTIONAL) != 0; + return (Modifiers() & ModifierFlags::OPTIONAL) != 0; } bool AstNode::IsDefinite() const noexcept { - return (flags_ & ModifierFlags::DEFINITE) != 0; + return (Modifiers() & ModifierFlags::DEFINITE) != 0; } bool AstNode::IsConstructor() const noexcept { - return (flags_ & ModifierFlags::CONSTRUCTOR) != 0; + return (Modifiers() & ModifierFlags::CONSTRUCTOR) != 0; } bool AstNode::IsOverride() const noexcept { - return (flags_ & ModifierFlags::OVERRIDE) != 0; + return (Modifiers() & ModifierFlags::OVERRIDE) != 0; } AstNode *AstNode::ShallowClone(ArenaAllocator *allocator) @@ -319,6 +332,7 @@ void AstNode::CopyTo(AstNode *other) const other->flags_ = flags_; other->astNodeFlags_ = astNodeFlags_; other->boxingUnboxingFlags_ = boxingUnboxingFlags_; + other->history_ = history_; other->variable_ = variable_; other->originalNode_ = originalNode_; other->transformedNode_ = transformedNode_; @@ -328,4 +342,80 @@ AstNode *AstNode::Construct([[maybe_unused]] ArenaAllocator *allocator) { ES2PANDA_UNREACHABLE(); } + +bool AstNode::IsValidInCurrentPhase() const +{ + if (!HistoryInitialized()) { + return true; + } + return compiler::GetPhaseManager()->CurrentPhaseId() >= GetFirstCreated(); +} + +compiler::PhaseId AstNode::GetFirstCreated() const +{ + return history_->FirstCreated(); +} + +AstNode *AstNode::GetHistoryNode() const +{ + AstNode *node = nullptr; + + if (HistoryInitialized()) { + node = history_->Get(compiler::GetPhaseManager()->CurrentPhaseId()); + } else { + node = const_cast(this); + } + + ES2PANDA_ASSERT(node != nullptr); + return node; +} + +AstNode *AstNode::GetOrCreateHistoryNode() const +{ + AstNode *node = nullptr; + + if (HistoryInitialized()) { + node = history_->At(compiler::GetPhaseManager()->CurrentPhaseId()); + if (node == nullptr) { + node = history_->Get(compiler::GetPhaseManager()->PreviousPhaseId()); + ES2PANDA_ASSERT(node != nullptr); + node = node->ShallowClone(compiler::GetPhaseManager()->Allocator()); + history_->Set(node, compiler::GetPhaseManager()->CurrentPhaseId()); + } + } else { + node = const_cast(this); + } + + return node; +} + +void AstNode::AddModifier(ModifierFlags const flags) noexcept +{ + if (!All(Modifiers(), flags)) { + GetOrCreateHistoryNode()->flags_ |= flags; + } +} + +void AstNode::ClearModifier(ModifierFlags const flags) noexcept +{ + if (Any(Modifiers(), flags)) { + GetOrCreateHistoryNode()->flags_ &= ~flags; + } +} + +void AstNode::InitHistory() +{ + if (!g_enableContextHistory || HistoryInitialized()) { + return; + } + + history_ = compiler::GetPhaseManager()->Allocator()->New( + this, compiler::GetPhaseManager()->CurrentPhaseId(), compiler::GetPhaseManager()->Allocator()); +} + +bool AstNode::HistoryInitialized() const +{ + return history_ != nullptr; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index c8f07a0c75..5489ceb5f6 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -19,6 +19,7 @@ #include "es2panda.h" #include "astNodeFlags.h" #include "astNodeMapping.h" +#include "compiler/lowering/phase_id.h" #include "ir/visitor/AstVisitor.h" #include "lexer/token/sourceLocation.h" #include "util/es2pandaMacros.h" @@ -41,6 +42,20 @@ class Scope; } // namespace ark::es2panda::varbinder namespace ark::es2panda::ir { + +inline thread_local bool g_enableContextHistory; +// CC-OFFNXT(G.INC.10) +[[maybe_unused]] static void DisableContextHistory() +{ + g_enableContextHistory = false; +} + +// CC-OFFNXT(G.INC.10) +[[maybe_unused]] static void EnableContextHistory() +{ + g_enableContextHistory = true; +} + // NOLINTBEGIN(modernize-avoid-c-arrays) inline constexpr char const CLONE_ALLOCATION_ERROR[] = "Unsuccessful allocation during cloning."; // NOLINTEND(modernize-avoid-c-arrays) @@ -96,6 +111,7 @@ inline std::string_view ToString(AstNodeType nodeType) #undef STRING_FROM_NODE_TYPE // Forward declarations +class AstNodeHistory; class AstDumper; class Expression; class SrcDumper; @@ -127,31 +143,31 @@ public: bool IsProgram() const { - return parent_ == nullptr; + return GetHistoryNode()->parent_ == nullptr; } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define DECLARE_IS_CHECKS(nodeType, className) \ - bool Is##className() const \ - { \ - /* CC-OFFNXT(G.PRE.02) name part*/ \ - /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return type_ == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ +#define DECLARE_IS_CHECKS(nodeType, className) \ + bool Is##className() const \ + { \ + /* CC-OFFNXT(G.PRE.02) name part*/ \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ + return GetHistoryNode()->type_ == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \ - bool Is##baseClass() const \ - { \ - /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return type_ == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ - } \ - bool Is##reinterpretClass() const \ - { \ - /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return type_ == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ +#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \ + bool Is##baseClass() const \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ + return GetHistoryNode()->type_ == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ + } \ + bool Is##reinterpretClass() const \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ + return GetHistoryNode()->type_ == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS @@ -265,62 +281,72 @@ public: void SetRange(const lexer::SourceRange &loc) noexcept { - range_ = loc; + if (GetHistoryNode()->range_ != loc) { + GetOrCreateHistoryNode()->range_ = loc; + } } void SetStart(const lexer::SourcePosition &start) noexcept { - range_.start = start; + if (GetHistoryNode()->range_.start != start) { + GetOrCreateHistoryNode()->range_.start = start; + } } void SetEnd(const lexer::SourcePosition &end) noexcept { - range_.end = end; + if (GetHistoryNode()->range_.end != end) { + GetOrCreateHistoryNode()->range_.end = end; + } } [[nodiscard]] const lexer::SourcePosition &Start() const noexcept { - return range_.start; + return GetHistoryNode()->range_.start; } [[nodiscard]] const lexer::SourcePosition &End() const noexcept { - return range_.end; + return GetHistoryNode()->range_.end; } [[nodiscard]] const lexer::SourceRange &Range() const noexcept { - return range_; + return GetHistoryNode()->range_; } [[nodiscard]] AstNodeType Type() const noexcept { - return type_; + return GetHistoryNode()->type_; } [[nodiscard]] AstNode *Parent() noexcept { - return parent_; + return GetHistoryNode()->parent_; } [[nodiscard]] const AstNode *Parent() const noexcept { - return parent_; + return GetHistoryNode()->parent_; } void SetParent(AstNode *const parent) noexcept { - parent_ = parent; + if (GetHistoryNode()->parent_ != parent) { + GetOrCreateHistoryNode()->parent_ = parent; + } } [[nodiscard]] varbinder::Variable *Variable() const noexcept { - return variable_; + return GetHistoryNode()->variable_; } void SetVariable(varbinder::Variable *variable) noexcept { - variable_ = variable; + if (GetHistoryNode()->variable_ != variable) { + GetOrCreateHistoryNode()->variable_ = variable; + } } // When no decorators are allowed, we cannot return a reference to an empty vector. @@ -354,62 +380,62 @@ public: void SetOverride() noexcept { - flags_ |= ModifierFlags::OVERRIDE; + AddModifier(ModifierFlags::OVERRIDE); } [[nodiscard]] bool IsAsync() const noexcept { - return (flags_ & ModifierFlags::ASYNC) != 0; + return (Modifiers() & ModifierFlags::ASYNC) != 0; } [[nodiscard]] bool IsSynchronized() const noexcept { - return (flags_ & ModifierFlags::SYNCHRONIZED) != 0; + return (Modifiers() & ModifierFlags::SYNCHRONIZED) != 0; } [[nodiscard]] bool IsNative() const noexcept { - return (flags_ & ModifierFlags::NATIVE) != 0; + return (Modifiers() & ModifierFlags::NATIVE) != 0; } [[nodiscard]] bool IsConst() const noexcept { - return (flags_ & ModifierFlags::CONST) != 0; + return (Modifiers() & ModifierFlags::CONST) != 0; } [[nodiscard]] bool IsStatic() const noexcept { - return (flags_ & ModifierFlags::STATIC) != 0; + return (Modifiers() & ModifierFlags::STATIC) != 0; } [[nodiscard]] bool IsFinal() const noexcept { - return (flags_ & ModifierFlags::FINAL) != 0U; + return (Modifiers() & ModifierFlags::FINAL) != 0U; } [[nodiscard]] bool IsAbstract() const noexcept { - return (flags_ & ModifierFlags::ABSTRACT) != 0; + return (Modifiers() & ModifierFlags::ABSTRACT) != 0; } [[nodiscard]] bool IsPublic() const noexcept { - return (flags_ & ModifierFlags::PUBLIC) != 0; + return (Modifiers() & ModifierFlags::PUBLIC) != 0; } [[nodiscard]] bool IsProtected() const noexcept { - return (flags_ & ModifierFlags::PROTECTED) != 0; + return (Modifiers() & ModifierFlags::PROTECTED) != 0; } [[nodiscard]] bool IsPrivate() const noexcept { - return (flags_ & ModifierFlags::PRIVATE) != 0; + return (Modifiers() & ModifierFlags::PRIVATE) != 0; } [[nodiscard]] bool IsInternal() const noexcept { - return (flags_ & ModifierFlags::INTERNAL) != 0; + return (Modifiers() & ModifierFlags::INTERNAL) != 0; } [[nodiscard]] bool IsExported() const noexcept; @@ -420,42 +446,36 @@ public: [[nodiscard]] bool IsDeclare() const noexcept { - return (flags_ & ModifierFlags::DECLARE) != 0; + return (Modifiers() & ModifierFlags::DECLARE) != 0; } [[nodiscard]] bool IsIn() const noexcept { - return (flags_ & ModifierFlags::IN) != 0; + return (Modifiers() & ModifierFlags::IN) != 0; } [[nodiscard]] bool IsOut() const noexcept { - return (flags_ & ModifierFlags::OUT) != 0; + return (Modifiers() & ModifierFlags::OUT) != 0; } [[nodiscard]] bool IsSetter() const noexcept { - return (flags_ & ModifierFlags::SETTER) != 0; + return (Modifiers() & ModifierFlags::SETTER) != 0; } - void AddModifier(ModifierFlags const flags) noexcept - { - flags_ |= flags; - } + void AddModifier(ModifierFlags const flags) noexcept; - void ClearModifier(ModifierFlags const flags) noexcept - { - flags_ &= ~flags; - } + void ClearModifier(ModifierFlags const flags) noexcept; [[nodiscard]] ModifierFlags Modifiers() noexcept { - return flags_; + return GetHistoryNode()->flags_; } [[nodiscard]] ModifierFlags Modifiers() const noexcept { - return flags_; + return GetHistoryNode()->flags_; } [[nodiscard]] bool HasExportAlias() const noexcept; @@ -464,28 +484,34 @@ public: #define DECLARE_FLAG_OPERATIONS(flag_type, member_name) \ void Set##flag_type(flag_type flags) const noexcept \ { \ - (member_name) = flags; \ + if (GetHistoryNode()->member_name != flags) { \ + GetOrCreateHistoryNode()->member_name = flags; \ + } \ } \ \ void Add##flag_type(flag_type flag) const noexcept \ { \ - (member_name) |= flag; \ + if (!All(GetHistoryNode()->member_name, flag)) { \ + GetOrCreateHistoryNode()->member_name |= flag; \ + } \ } \ \ [[nodiscard]] flag_type Get##flag_type() const noexcept \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ - return (member_name); \ + return GetHistoryNode()->member_name; \ } \ \ bool Has##flag_type(flag_type flag) const noexcept \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ - return ((member_name)&flag) != 0U; \ + return (GetHistoryNode()->member_name & flag) != 0U; \ } \ void Remove##flag_type(flag_type flag) const noexcept \ { \ - (member_name) &= ~flag; \ + if (Any(GetHistoryNode()->member_name, flag)) { \ + GetOrCreateHistoryNode()->member_name &= ~flag; \ + } \ } DECLARE_FLAG_OPERATIONS(BoxingUnboxingFlags, boxingUnboxingFlags_); @@ -552,6 +578,11 @@ public: AstNode *ShallowClone(ArenaAllocator *allocator); + bool IsValidInCurrentPhase() const; + + AstNode *GetHistoryNode() const; + AstNode *GetOrCreateHistoryNode() const; + protected: AstNode(AstNode const &other); @@ -561,7 +592,24 @@ protected: void SetType(AstNodeType const type) noexcept { - type_ = type; + if (Type() != type) { + GetOrCreateHistoryNode()->type_ = type; + } + } + + void InitHistory(); + bool HistoryInitialized() const; + + template + T *GetHistoryNodeAs() const + { + return reinterpret_cast(GetHistoryNode()); + } + + template + T *GetOrCreateHistoryNodeAs() const + { + return reinterpret_cast(GetOrCreateHistoryNode()); } friend class SizeOfNodeTest; @@ -572,11 +620,15 @@ protected: ModifierFlags flags_ {}; mutable AstNodeFlags astNodeFlags_ {}; mutable BoxingUnboxingFlags boxingUnboxingFlags_ {}; + AstNodeHistory *history_ {nullptr}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: + compiler::PhaseId GetFirstCreated() const; AstNode &operator=(const AstNode &) = default; + const std::optional> &TransformedNode() const noexcept; + varbinder::Variable *variable_ {}; AstNode *originalNode_ = nullptr; // {lowering_phase_name, new_generated_node} @@ -594,12 +646,14 @@ public: [[nodiscard]] TypeNode *TypeAnnotation() const noexcept { - return typeAnnotation_; + return AstNode::GetHistoryNodeAs>()->typeAnnotation_; } void SetTsTypeAnnotation(TypeNode *const typeAnnotation) noexcept { - typeAnnotation_ = typeAnnotation; + if (TypeAnnotation() != typeAnnotation) { + AstNode::GetOrCreateHistoryNodeAs>()->typeAnnotation_ = typeAnnotation; + } } void CopyTo(AstNode *other) const override diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index 110cd9fcb8..617e3e42f8 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -105,6 +105,8 @@ enum class ScriptFunctionFlags : uint32_t { ASYNC_IMPL = 1U << 19U, EXTERNAL_OVERLOAD = 1U << 20U, HAS_THROW = 1U << 21U, + IN_RECORD = 1U << 22U, + TRAILING_LAMBDA = 1U << 23U, }; enum class TSOperatorType { READONLY, KEYOF, UNIQUE }; diff --git a/ets2panda/ir/astNodeHistory.cpp b/ets2panda/ir/astNodeHistory.cpp index c27d68e8d2..5d46aea8b2 100644 --- a/ets2panda/ir/astNodeHistory.cpp +++ b/ets2panda/ir/astNodeHistory.cpp @@ -18,12 +18,12 @@ namespace ark::es2panda::ir { -AstNodeHistory::AstNodeHistory(AstNode *node, int32_t phaseId, ArenaAllocator *allocator) : list_ {allocator} +AstNodeHistory::AstNodeHistory(AstNode *node, compiler::PhaseId phaseId, ArenaAllocator *allocator) : list_ {allocator} { Set(node, phaseId); } -AstNode *AstNodeHistory::FindBackwardEquals(int32_t phaseId) +AstNode *AstNodeHistory::FindBackwardEquals(compiler::PhaseId phaseId) { auto item = item_; @@ -37,7 +37,7 @@ AstNode *AstNodeHistory::FindBackwardEquals(int32_t phaseId) return nullptr; } -AstNode *AstNodeHistory::FindForwardEquals(int32_t phaseId) +AstNode *AstNodeHistory::FindForwardEquals(compiler::PhaseId phaseId) { auto item = item_; @@ -53,8 +53,9 @@ AstNode *AstNodeHistory::FindForwardEquals(int32_t phaseId) // Find node state precisely at phase with a given ID // (e.g. find the node history record with `phaseId` equal to a given value) -AstNode *AstNodeHistory::At(int32_t phaseId) +AstNode *AstNodeHistory::At(compiler::PhaseId phaseId) { + std::lock_guard lock(itemMutex_); if (LIKELY(item_->data.phaseId == phaseId)) { // Start searching with last accessed item // In most cases last accessed item is the one we are looking for @@ -70,8 +71,9 @@ AstNode *AstNodeHistory::At(int32_t phaseId) // Find node state at phase with a given ID // (e.g. find last node history record with `phaseId` less or equal to a given value) -AstNode *AstNodeHistory::Get(int32_t phaseId) +AstNode *AstNodeHistory::Get(compiler::PhaseId phaseId) { + std::lock_guard lock(itemMutex_); auto found = FindLessOrEquals(phaseId); if (LIKELY(found != nullptr)) { item_ = found; @@ -82,8 +84,9 @@ AstNode *AstNodeHistory::Get(int32_t phaseId) } // Find node state at phase with a given ID and set its new value, insert new history record if not found -void AstNodeHistory::Set(AstNode *node, int32_t phaseId) +void AstNodeHistory::Set(AstNode *node, compiler::PhaseId phaseId) { + std::lock_guard lock(itemMutex_); HistoryRecord record {node, phaseId}; if (LIKELY(list_.Empty() || list_.Tail()->data.phaseId < phaseId)) { item_ = list_.Append(record); @@ -105,7 +108,7 @@ void AstNodeHistory::Set(AstNode *node, int32_t phaseId) // Find node state at phase with a given ID // (e.g. find last node history record with `phaseId` less or equal to a given value) -AstNodeHistory::HistoryList::Item *AstNodeHistory::FindLessOrEquals(int32_t phaseId) +AstNodeHistory::HistoryList::Item *AstNodeHistory::FindLessOrEquals(compiler::PhaseId phaseId) { // Start searching with last accessed item auto item = item_; @@ -136,6 +139,10 @@ AstNodeHistory::HistoryList::Item *AstNodeHistory::FindLessOrEquals(int32_t phas if (item->data.phaseId <= phaseId) { return item; } + if (item->data.phaseId > phaseId && item->prev != nullptr) { + item = item->prev; + return item; + } } return nullptr; diff --git a/ets2panda/ir/astNodeHistory.h b/ets2panda/ir/astNodeHistory.h index 8aebde4a7a..e424046403 100644 --- a/ets2panda/ir/astNodeHistory.h +++ b/ets2panda/ir/astNodeHistory.h @@ -16,33 +16,41 @@ #ifndef ES2PANDA_IR_AST_NODE_HISTORY_H #define ES2PANDA_IR_AST_NODE_HISTORY_H +#include + #include "ir/astNode.h" +#include "compiler/lowering/phase_id.h" #include "util/doubleLinkedList.h" namespace ark::es2panda::ir { class AstNodeHistory { public: - AstNodeHistory(AstNode *node, int32_t phaseId, ArenaAllocator *allocator); + AstNodeHistory(AstNode *node, compiler::PhaseId phaseId, ArenaAllocator *allocator); - AstNode *At(int32_t phaseId); - AstNode *Get(int32_t phaseId); - void Set(AstNode *node, int32_t phaseId); + AstNode *At(compiler::PhaseId phaseId); + AstNode *Get(compiler::PhaseId phaseId); + void Set(AstNode *node, compiler::PhaseId phaseId); + compiler::PhaseId FirstCreated() + { + return list_.Head()->data.phaseId; + } private: struct HistoryRecord { AstNode *node; - int32_t phaseId; + compiler::PhaseId phaseId; }; using HistoryList = util::ArenaDoubleLinkedList; - AstNode *FindBackwardEquals(int32_t phaseId); - AstNode *FindForwardEquals(int32_t phaseId); - HistoryList::Item *FindLessOrEquals(int32_t phaseId); + AstNode *FindBackwardEquals(compiler::PhaseId phaseId); + AstNode *FindForwardEquals(compiler::PhaseId phaseId); + HistoryList::Item *FindLessOrEquals(compiler::PhaseId phaseId); HistoryList list_; // Node history list HistoryList::Item *item_ {nullptr}; // Last accessed history record + std::mutex itemMutex_ {}; }; } // namespace ark::es2panda::ir #endif diff --git a/ets2panda/ir/base/classDefinition.cpp b/ets2panda/ir/base/classDefinition.cpp index 2c88bf449e..5fe57979b3 100644 --- a/ets2panda/ir/base/classDefinition.cpp +++ b/ets2panda/ir/base/classDefinition.cpp @@ -28,28 +28,142 @@ #include "ir/ts/tsClassImplements.h" namespace ark::es2panda::ir { + +void ClassDefinition::SetCtor(MethodDefinition *ctor) +{ + this->GetOrCreateHistoryNodeAs()->ctor_ = ctor; +} + +void ClassDefinition::SetTypeParams(TSTypeParameterDeclaration *typeParams) +{ + this->GetOrCreateHistoryNodeAs()->typeParams_ = typeParams; +} + +void ClassDefinition::SetOrigEnumDecl(TSEnumDeclaration *origEnumDecl) +{ + this->GetOrCreateHistoryNodeAs()->origEnumDecl_ = origEnumDecl; +} + +void ClassDefinition::SetAnonClass(ClassDeclaration *anonClass) +{ + this->GetOrCreateHistoryNodeAs()->anonClass_ = anonClass; +} + +void ClassDefinition::SetSuperClass(Expression *superClass) +{ + this->GetOrCreateHistoryNodeAs()->superClass_ = superClass; +} + +void ClassDefinition::SetSuperTypeParams(TSTypeParameterInstantiation *superTypeParams) +{ + this->GetOrCreateHistoryNodeAs()->superTypeParams_ = superTypeParams; +} + +void ClassDefinition::SetScope(varbinder::LocalScope *scope) +{ + this->GetOrCreateHistoryNodeAs()->scope_ = scope; +} + +void ClassDefinition::SetModifiers(ClassDefinitionModifiers modifiers) +{ + this->GetOrCreateHistoryNodeAs()->modifiers_ = modifiers; +} + +void ClassDefinition::SetInternalName(util::StringView internalName) +{ + this->GetOrCreateHistoryNodeAs()->internalName_ = internalName; +} + +void ClassDefinition::EmplaceBody(AstNode *body) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->body_.emplace_back(body); +} + +void ClassDefinition::ClearBody() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->body_.clear(); +} + +void ClassDefinition::SetValueBody(AstNode *body, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->body_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = body; +} + +[[nodiscard]] const ArenaVector &ClassDefinition::Body() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->body_; +} + +[[nodiscard]] ArenaVector &ClassDefinition::BodyForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->body_; +} + +void ClassDefinition::EmplaceImplements(TSClassImplements *implements) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->implements_.emplace_back(implements); +} + +void ClassDefinition::ClearImplements() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->implements_.clear(); +} + +void ClassDefinition::SetValueImplements(TSClassImplements *implements, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->implements_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = implements; +} + +[[nodiscard]] const ArenaVector &ClassDefinition::Implements() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->implements_; +} + +[[nodiscard]] ArenaVector &ClassDefinition::ImplementsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->implements_; +} + const FunctionExpression *ClassDefinition::Ctor() const { - return ctor_ != nullptr ? ctor_->Value()->AsFunctionExpression() : nullptr; + auto const newNode = GetHistoryNode()->AsClassDefinition(); + return newNode->ctor_ != nullptr ? newNode->ctor_->Value()->AsFunctionExpression() : nullptr; } bool ClassDefinition::HasPrivateMethod() const { - return std::any_of(body_.cbegin(), body_.cend(), [](auto *element) { + auto const body = Body(); + return std::any_of(body.cbegin(), body.cend(), [](auto const *element) { return element->IsMethodDefinition() && element->AsClassElement()->IsPrivateElement(); }); } bool ClassDefinition::HasNativeMethod() const { - return std::any_of(body_.cbegin(), body_.cend(), [](auto *element) { + auto const body = Body(); + return std::any_of(body.cbegin(), body.cend(), [](auto const *element) { return element->IsMethodDefinition() && element->AsMethodDefinition()->IsNative(); }); } bool ClassDefinition::HasComputedInstanceField() const { - return std::any_of(body_.cbegin(), body_.cend(), [](auto *element) { + auto const body = Body(); + return std::any_of(body.cbegin(), body.cend(), [](auto *element) { return element->IsClassProperty() && element->AsClassElement()->IsComputed() && !(element->AsClassElement()->Modifiers() & ir::ModifierFlags::STATIC); }); @@ -57,115 +171,131 @@ bool ClassDefinition::HasComputedInstanceField() const bool ClassDefinition::HasMatchingPrivateKey(const util::StringView &name) const { - return std::any_of(body_.cbegin(), body_.cend(), [&name](auto *element) { + auto const body = Body(); + return std::any_of(body.cbegin(), body.cend(), [&name](auto *element) { return element->AsClassElement()->IsPrivateElement() && element->AsClassElement()->Id()->Name() == name; }); } -void ClassDefinition::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) +void ClassDefinition::TransformBase(const NodeTransformer &cb, std::string_view transformationName) { - if (ident_ != nullptr) { - if (auto *transformedNode = cb(ident_); ident_ != transformedNode) { - ident_->SetTransformedNode(transformationName, transformedNode); - ident_ = transformedNode->AsIdentifier(); + auto const ident = Ident(); + if (ident != nullptr) { + if (auto *transformedNode = cb(ident); ident != transformedNode) { + ident->SetTransformedNode(transformationName, transformedNode); + SetIdent(transformedNode->AsIdentifier()); } } - if (typeParams_ != nullptr) { - if (auto *transformedNode = cb(typeParams_); typeParams_ != transformedNode) { - typeParams_->SetTransformedNode(transformationName, transformedNode); - typeParams_ = transformedNode->AsTSTypeParameterDeclaration(); + auto const typeParam = TypeParams(); + if (typeParam != nullptr) { + if (auto *transformedNode = cb(typeParam); typeParam != transformedNode) { + typeParam->SetTransformedNode(transformationName, transformedNode); + SetTypeParams(transformedNode->AsTSTypeParameterDeclaration()); } } - if (superClass_ != nullptr) { - if (auto *transformedNode = cb(superClass_); superClass_ != transformedNode) { - superClass_->SetTransformedNode(transformationName, transformedNode); - superClass_ = transformedNode->AsExpression(); + auto const superClass = SuperClass(); + if (superClass != nullptr) { + if (auto *transformedNode = cb(superClass); superClass != transformedNode) { + superClass->SetTransformedNode(transformationName, transformedNode); + SetSuperClass(transformedNode->AsExpression()); } } - if (superTypeParams_ != nullptr) { - if (auto *transformedNode = cb(superTypeParams_); superTypeParams_ != transformedNode) { - superTypeParams_->SetTransformedNode(transformationName, transformedNode); - superTypeParams_ = transformedNode->AsTSTypeParameterInstantiation(); + auto const superTypeParam = SuperTypeParams(); + if (superTypeParam != nullptr) { + if (auto *transformedNode = cb(superTypeParam); superTypeParam != transformedNode) { + superTypeParam->SetTransformedNode(transformationName, transformedNode); + SetSuperTypeParams(transformedNode->AsTSTypeParameterInstantiation()); } } +} - for (auto *&it : VectorIterationGuard(implements_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsTSClassImplements(); - } - } +void ClassDefinition::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) +{ + TransformBase(cb, transformationName); - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + auto const &implement = Implements(); + for (size_t ix = 0; ix < implement.size(); ix++) { + if (auto *transformedNode = cb(implement[ix]); implement[ix] != transformedNode) { + implement[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueImplements(transformedNode->AsTSClassImplements(), ix); } } - if (ctor_ != nullptr) { - if (auto *transformedNode = cb(ctor_); ctor_ != transformedNode) { - ctor_->SetTransformedNode(transformationName, transformedNode); - ctor_ = transformedNode->AsMethodDefinition(); + TransformAnnotations(cb, transformationName); + + auto const &ctor = Ctor(); + if (ctor != nullptr) { + if (auto *transformedNode = cb(ctor); ctor != transformedNode) { + ctor->SetTransformedNode(transformationName, transformedNode); + SetCtor(transformedNode->AsMethodDefinition()); } } // Survives adding new elements to the end // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < body_.size(); ix++) { - if (auto *transformedNode = cb(body_[ix]); body_[ix] != transformedNode) { - body_[ix]->SetTransformedNode(transformationName, transformedNode); - body_[ix] = transformedNode; + auto const &body = Body(); + for (size_t ix = 0; ix < body.size(); ix++) { + if (auto *transformedNode = cb(body[ix]); body[ix] != transformedNode) { + body[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueBody(transformedNode, ix); } } } void ClassDefinition::Iterate(const NodeTraverser &cb) const { - if (ident_ != nullptr) { - cb(ident_); + auto const ident = GetHistoryNodeAs()->ident_; + if (ident != nullptr) { + cb(ident); } - if (typeParams_ != nullptr) { - cb(typeParams_); + auto const typeParams = GetHistoryNodeAs()->typeParams_; + if (typeParams != nullptr) { + cb(typeParams); } - if (superClass_ != nullptr) { - cb(superClass_); + auto const superClass = GetHistoryNodeAs()->superClass_; + if (superClass != nullptr) { + cb(superClass); } - if (superTypeParams_ != nullptr) { - cb(superTypeParams_); + auto const superTypeParams = GetHistoryNodeAs()->superTypeParams_; + if (superTypeParams != nullptr) { + cb(superTypeParams); } // Survives adding new elements to the end // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < implements_.size(); ix++) { - cb(implements_[ix]); + auto const &implements = GetHistoryNodeAs()->implements_; + for (auto implement : implements) { + cb(implement); } for (auto *it : VectorIterationGuard(Annotations())) { cb(it); } - if (ctor_ != nullptr) { - cb(ctor_); + auto const ctor = GetHistoryNodeAs()->ctor_; + if (ctor != nullptr) { + cb(ctor); } + auto const &body = GetHistoryNodeAs()->body_; // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < body_.size(); ix++) { - cb(body_[ix]); + for (size_t ix = 0; ix < body.size(); ix++) { + cb(body[ix]); } } void ClassDefinition::SetIdent(ir::Identifier *ident) noexcept { - ident_ = ident; - if (ident_ != nullptr) { - ident_->SetParent(this); + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->ident_ = ident; + if (ident != nullptr) { + ident->SetParent(this); } } @@ -174,26 +304,27 @@ void ClassDefinition::Dump(ir::AstDumper *dumper) const auto propFilter = [](AstNode *prop) -> bool { return !prop->IsClassStaticBlock() || !prop->AsClassStaticBlock()->Function()->IsHidden(); }; - dumper->Add({{"id", AstDumper::Nullish(ident_)}, - {"typeParameters", AstDumper::Optional(typeParams_)}, - {"superClass", AstDumper::Nullish(superClass_)}, - {"superTypeParameters", AstDumper::Optional(superTypeParams_)}, - {"implements", implements_}, + auto ctor = GetHistoryNodeAs()->ctor_; + dumper->Add({{"id", AstDumper::Nullish(Ident())}, + {"typeParameters", AstDumper::Optional(TypeParams())}, + {"superClass", AstDumper::Nullish(SuperClass())}, + {"superTypeParameters", AstDumper::Optional(SuperTypeParams())}, + {"implements", Implements()}, {"annotations", AstDumper::Optional(Annotations())}, - {"constructor", AstDumper::Optional(ctor_)}, - {"body", body_, propFilter}}); + {"constructor", AstDumper::Optional(ctor)}, + {"body", Body(), propFilter}}); } void ClassDefinition::DumpGlobalClass(ir::SrcDumper *dumper) const { ES2PANDA_ASSERT(IsGlobal()); - for (auto elem : body_) { + for (auto elem : Body()) { if (elem->IsClassProperty()) { elem->Dump(dumper); dumper->Endl(); } } - for (auto elem : body_) { + for (auto elem : Body()) { if (elem->IsMethodDefinition()) { elem->Dump(dumper); dumper->Endl(); @@ -204,13 +335,14 @@ void ClassDefinition::DumpGlobalClass(ir::SrcDumper *dumper) const // This method is needed by OHOS CI code checker void ClassDefinition::DumpBody(ir::SrcDumper *dumper) const { + auto const body = Body(); dumper->Add(" {"); - if (!body_.empty()) { + if (!body.empty()) { dumper->IncrIndent(); dumper->Endl(); - for (auto elem : body_) { + for (auto elem : body) { elem->Dump(dumper); - if (elem == body_.back()) { + if (elem == body.back()) { dumper->DecrIndent(); } dumper->Endl(); @@ -270,7 +402,8 @@ bool ClassDefinition::RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const void ClassDefinition::Dump(ir::SrcDumper *dumper) const { // NOTE: plugin API fails - if ((ident_->Name().StartsWith("$dynmodule")) || (ident_->Name().StartsWith("$jscall"))) { + auto const ident = Ident(); + if ((ident->Name().StartsWith("$dynmodule")) || (ident->Name().StartsWith("$jscall"))) { return; } @@ -292,19 +425,20 @@ void ClassDefinition::Dump(ir::SrcDumper *dumper) const DumpPrefix(dumper); ident_->Dump(dumper); - if (typeParams_ != nullptr) { + if (TypeParams() != nullptr) { dumper->Add("<"); - typeParams_->Dump(dumper); + TypeParams()->Dump(dumper); dumper->Add("> "); } - if (superClass_ != nullptr) { + if (SuperClass() != nullptr) { dumper->Add(" extends "); - superClass_->Dump(dumper); + SuperClass()->Dump(dumper); } - DumpItems(dumper, " implements ", implements_); - if (!IsDeclare() || !body_.empty()) { + DumpItems(dumper, " implements ", Implements()); + + if (!IsDeclare() || !Body().empty()) { DumpBody(dumper); } if (IsLocal()) { @@ -337,7 +471,7 @@ ClassDefinition *ClassDefinition::Construct(ArenaAllocator *allocator) { ArenaVector body {allocator->Adapter()}; return allocator->New(allocator, nullptr, std::move(body), ClassDefinitionModifiers::NONE, - ModifierFlags::NONE, Language::Id::COUNT); + ModifierFlags::NONE, Language::Id::COUNT, history_); } void ClassDefinition::CopyTo(AstNode *other) const @@ -367,6 +501,6 @@ void ClassDefinition::CopyTo(AstNode *other) const JsDocAllowed>::CopyTo(other); } -int ClassDefinition::classCounter_ = 0; +std::atomic ClassDefinition::classCounter_ = 0; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index 2eb349f8cc..7a8c0ed2ef 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -21,6 +21,7 @@ #include "ir/srcDump.h" #include "ir/annotationAllowed.h" #include "ir/astNode.h" +#include "ir/astNodeHistory.h" #include "ir/expressions/identifier.h" #include "ir/jsDocAllowed.h" #include "ir/statements/annotationUsage.h" @@ -101,6 +102,7 @@ public: localPrefix_("$" + std::to_string(localIndex_)), exportedClasses_(body_.get_allocator()) { + InitHistory(); } // CC-OFFNXT(G.FUN.01-CPP) solid logic explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ArenaVector &&body, @@ -117,6 +119,7 @@ public: localPrefix_("$" + std::to_string(localIndex_)), exportedClasses_(body_.get_allocator()) { + InitHistory(); } explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ClassDefinitionModifiers modifiers, @@ -133,116 +136,130 @@ public: localPrefix_("$" + std::to_string(localIndex_)), exportedClasses_(body_.get_allocator()) { + InitHistory(); } - [[nodiscard]] bool IsScopeBearer() const noexcept override + // CC-OFFNXT(G.FUN.01-CPP) solid logic + explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ArenaVector &&body, + ClassDefinitionModifiers modifiers, ModifierFlags flags, Language lang, + AstNodeHistory *history) + : JsDocAllowed>(AstNodeType::CLASS_DEFINITION, flags, allocator), + ident_(ident), + implements_(allocator->Adapter()), + body_(std::move(body)), + modifiers_(modifiers), + lang_(lang), + capturedVars_(allocator->Adapter()), + localVariableIsNeeded_(allocator->Adapter()), + localIndex_(classCounter_++), + localPrefix_("$" + std::to_string(localIndex_)), + exportedClasses_(body_.get_allocator()) { - return true; + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } - [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override + [[nodiscard]] bool IsScopeBearer() const noexcept override { - return scope_; + return true; } - void SetScope(varbinder::LocalScope *scope) + [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override { - ES2PANDA_ASSERT(scope_ == nullptr); - scope_ = scope; + return GetHistoryNodeAs()->scope_; } void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } [[nodiscard]] const Identifier *Ident() const noexcept { - return ident_; + return GetHistoryNodeAs()->ident_; } [[nodiscard]] Identifier *Ident() noexcept { - return ident_; + return GetHistoryNodeAs()->ident_; } void SetIdent(ir::Identifier *ident) noexcept; [[nodiscard]] const util::StringView &InternalName() const noexcept { - return internalName_; - } - - void SetInternalName(util::StringView internalName) noexcept - { - internalName_ = internalName; + return GetHistoryNodeAs()->internalName_; } [[nodiscard]] Expression *Super() noexcept { - return superClass_; + return GetHistoryNodeAs()->superClass_; } [[nodiscard]] const Expression *Super() const noexcept { - return superClass_; + return GetHistoryNodeAs()->superClass_; } void SetSuper(Expression *superClass) { - superClass_ = superClass; - if (superClass_ != nullptr) { - superClass_->SetParent(this); + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->superClass_ = superClass; + if (newNode->superClass_ != nullptr) { + newNode->superClass_->SetParent(this); } } [[nodiscard]] bool IsGlobal() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::GLOBAL) != 0; + return (Modifiers() & ClassDefinitionModifiers::GLOBAL) != 0; } [[nodiscard]] bool IsLocal() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::LOCAL) != 0; + return (Modifiers() & ClassDefinitionModifiers::LOCAL) != 0; } [[nodiscard]] bool IsExtern() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::EXTERN) != 0; + return (Modifiers() & ClassDefinitionModifiers::EXTERN) != 0; } [[nodiscard]] bool IsFromExternal() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::FROM_EXTERNAL) != 0; + return (Modifiers() & ClassDefinitionModifiers::FROM_EXTERNAL) != 0; } [[nodiscard]] bool IsInner() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::INNER) != 0; + return (Modifiers() & ClassDefinitionModifiers::INNER) != 0; } [[nodiscard]] bool IsGlobalInitialized() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::GLOBAL_INITIALIZED) != 0; + return (Modifiers() & ClassDefinitionModifiers::GLOBAL_INITIALIZED) != 0; } [[nodiscard]] bool IsClassDefinitionChecked() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::CLASSDEFINITION_CHECKED) != 0; + return (Modifiers() & ClassDefinitionModifiers::CLASSDEFINITION_CHECKED) != 0; } [[nodiscard]] bool IsAnonymous() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::ANONYMOUS) != 0; + return (Modifiers() & ClassDefinitionModifiers::ANONYMOUS) != 0; } [[nodiscard]] bool IsIntEnumTransformed() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::INT_ENUM_TRANSFORMED) != 0; + return (Modifiers() & ClassDefinitionModifiers::INT_ENUM_TRANSFORMED) != 0; } [[nodiscard]] bool IsStringEnumTransformed() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED) != 0; + return (Modifiers() & ClassDefinitionModifiers::STRING_ENUM_TRANSFORMED) != 0; } [[nodiscard]] bool IsEnumTransformed() const noexcept @@ -252,12 +269,12 @@ public: [[nodiscard]] bool IsNamespaceTransformed() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::NAMESPACE_TRANSFORMED) != 0; + return (Modifiers() & ClassDefinitionModifiers::NAMESPACE_TRANSFORMED) != 0; } [[nodiscard]] bool IsFromStruct() const noexcept { - return (modifiers_ & ClassDefinitionModifiers::FROM_STRUCT) != 0; + return (Modifiers() & ClassDefinitionModifiers::FROM_STRUCT) != 0; } [[nodiscard]] bool IsModule() const noexcept @@ -267,47 +284,42 @@ public: [[nodiscard]] es2panda::Language Language() const noexcept { - return lang_; + return GetHistoryNodeAs()->lang_; } void SetGlobalInitialized() noexcept { - modifiers_ |= ClassDefinitionModifiers::GLOBAL_INITIALIZED; + AddClassModifiers(ClassDefinitionModifiers::GLOBAL_INITIALIZED); } void SetInnerModifier() noexcept { - modifiers_ |= ClassDefinitionModifiers::INNER; + AddClassModifiers(ClassDefinitionModifiers::INNER); } void SetClassDefinitionChecked() noexcept { - modifiers_ |= ClassDefinitionModifiers::CLASSDEFINITION_CHECKED; + AddClassModifiers(ClassDefinitionModifiers::CLASSDEFINITION_CHECKED); } void SetAnonymousModifier() noexcept { - modifiers_ |= ClassDefinitionModifiers::ANONYMOUS; + AddClassModifiers(ClassDefinitionModifiers::ANONYMOUS); } void SetNamespaceTransformed() noexcept { - modifiers_ |= ClassDefinitionModifiers::NAMESPACE_TRANSFORMED; + AddClassModifiers(ClassDefinitionModifiers::NAMESPACE_TRANSFORMED); } void SetFromStructModifier() noexcept { - modifiers_ |= ClassDefinitionModifiers::FROM_STRUCT; + AddClassModifiers(ClassDefinitionModifiers::FROM_STRUCT); } [[nodiscard]] ClassDefinitionModifiers Modifiers() const noexcept { - return modifiers_; - } - - void SetModifiers(ClassDefinitionModifiers modifiers) noexcept - { - modifiers_ = modifiers; + return GetHistoryNodeAs()->modifiers_; } void AddProperties(ArenaVector &&body) @@ -316,64 +328,46 @@ public: prop->SetParent(this); } - body_.insert(body_.end(), body.begin(), body.end()); - } - - [[nodiscard]] ArenaVector &Body() noexcept - { - return body_; + auto newNode = GetOrCreateHistoryNode()->AsClassDefinition(); + newNode->body_.insert(newNode->body_.end(), body.begin(), body.end()); } [[nodiscard]] const ArenaVector &Body() const noexcept { - return body_; + return GetHistoryNodeAs()->body_; } [[nodiscard]] MethodDefinition *Ctor() noexcept { - return ctor_; - } - - void SetCtor(MethodDefinition *ctor) - { - ctor_ = ctor; - } - - [[nodiscard]] ArenaVector &Implements() noexcept - { - return implements_; + return GetHistoryNodeAs()->ctor_; } [[nodiscard]] const ArenaVector &Implements() const noexcept { - return implements_; + return GetHistoryNodeAs()->implements_; } [[nodiscard]] const ir::TSTypeParameterDeclaration *TypeParams() const noexcept { - return typeParams_; + return GetHistoryNodeAs()->typeParams_; } [[nodiscard]] ir::TSTypeParameterDeclaration *TypeParams() noexcept { - return typeParams_; - } - - void SetTypeParams(ir::TSTypeParameterDeclaration *typeParams) - { - typeParams_ = typeParams; + return GetHistoryNodeAs()->typeParams_; } const TSTypeParameterInstantiation *SuperTypeParams() const { - return superTypeParams_; + return GetHistoryNodeAs()->superTypeParams_; } TSTypeParameterInstantiation *SuperTypeParams() { - return superTypeParams_; + return GetHistoryNodeAs()->superTypeParams_; } + // ekkoruse: dangerous count for cache here [[nodiscard]] static int LocalTypeCounter() noexcept { return classCounter_; @@ -381,7 +375,7 @@ public: [[nodiscard]] int LocalIndex() const noexcept { - return localIndex_; + return GetHistoryNodeAs()->localIndex_; } [[nodiscard]] util::StringView FunctionalReferenceReferencedMethod() const noexcept @@ -396,52 +390,46 @@ public: [[nodiscard]] const std::string &LocalPrefix() const noexcept { - return localPrefix_; + return GetHistoryNodeAs()->localPrefix_; } bool CaptureVariable(varbinder::Variable *var) { - return capturedVars_.insert(var).second; + auto newNode = GetOrCreateHistoryNode()->AsClassDefinition(); + return newNode->capturedVars_.insert(var).second; } bool AddToLocalVariableIsNeeded(varbinder::Variable *var) { - return localVariableIsNeeded_.insert(var).second; + auto newNode = GetOrCreateHistoryNode()->AsClassDefinition(); + return newNode->localVariableIsNeeded_.insert(var).second; } bool IsLocalVariableNeeded(varbinder::Variable *var) const { - return localVariableIsNeeded_.find(var) != localVariableIsNeeded_.end(); + auto const newNode = GetHistoryNode()->AsClassDefinition(); + return newNode->localVariableIsNeeded_.find(var) != newNode->localVariableIsNeeded_.end(); } [[nodiscard]] const ArenaSet &CapturedVariables() const noexcept { - return capturedVars_; + return GetHistoryNodeAs()->capturedVars_; } bool EraseCapturedVariable(varbinder::Variable *var) { - return capturedVars_.erase(var) != 0; - } - - void SetOrigEnumDecl(ir::TSEnumDeclaration *enumDecl) - { - origEnumDecl_ = enumDecl; + auto newNode = GetOrCreateHistoryNode()->AsClassDefinition(); + return newNode->capturedVars_.erase(var) != 0; } ir::TSEnumDeclaration *OrigEnumDecl() const { - return origEnumDecl_; + return GetHistoryNodeAs()->origEnumDecl_; } ClassDeclaration *GetAnonClass() noexcept { - return anonClass_; - } - - void SetAnonClass(ClassDeclaration *anonClass) noexcept - { - anonClass_ = anonClass; + return GetHistoryNodeAs()->anonClass_; } const FunctionExpression *Ctor() const; @@ -450,6 +438,7 @@ public: bool HasComputedInstanceField() const; bool HasMatchingPrivateKey(const util::StringView &name) const; + void TransformBase(const NodeTransformer &cb, std::string_view transformationName); void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; void Iterate(const NodeTraverser &cb) const override; @@ -483,26 +472,74 @@ public: void CleanUp() override { AstNode::CleanUp(); - modifiers_ &= ~(ClassDefinitionModifiers::CLASSDEFINITION_CHECKED); + ClearClassModifiers(ClassDefinitionModifiers::CLASSDEFINITION_CHECKED); } void AddToExportedClasses(const ir::ClassDeclaration *cls) { ES2PANDA_ASSERT(cls->IsExported()); - exportedClasses_.push_back(cls); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->exportedClasses_.emplace_back(cls); } [[nodiscard]] const ArenaVector &ExportedClasses() const noexcept { - return exportedClasses_; + return GetHistoryNodeAs()->exportedClasses_; } + void SetScope(varbinder::LocalScope *scope); + void SetModifiers(ClassDefinitionModifiers modifiers); + + void EmplaceBody(AstNode *body); + void ClearBody(); + void SetValueBody(AstNode *body, size_t index); + const ArenaVector &Body(); + [[nodiscard]] ArenaVector &BodyForUpdate(); + + void EmplaceImplements(TSClassImplements *implements); + void ClearImplements(); + void SetValueImplements(TSClassImplements *implements, size_t index); + const ArenaVector &Implements(); + ArenaVector &ImplementsForUpdate(); + + void SetCtor(MethodDefinition *ctor); + void SetTypeParams(TSTypeParameterDeclaration *typeParams); + void SetOrigEnumDecl(TSEnumDeclaration *origEnumDecl); + void SetAnonClass(ClassDeclaration *anonClass); + void SetInternalName(util::StringView internalName); protected: ClassDefinition *Construct(ArenaAllocator *allocator) override; + void AddClassModifiers(ClassDefinitionModifiers const flags) noexcept + { + if (!All(Modifiers(), flags)) { + GetOrCreateHistoryNodeAs()->modifiers_ |= flags; + } + } + + void ClearClassModifiers(ClassDefinitionModifiers const flags) noexcept + { + if (Any(Modifiers(), flags)) { + GetOrCreateHistoryNodeAs()->modifiers_ &= ~flags; + } + } + void CopyTo(AstNode *other) const override; private: + void SetSuperClass(Expression *superClass); + void SetSuperTypeParams(TSTypeParameterInstantiation *superTypeParams); + + [[nodiscard]] Expression *SuperClass() + { + return GetHistoryNodeAs()->superClass_; + } + + [[nodiscard]] const Expression *SuperClass() const + { + return GetHistoryNodeAs()->superClass_; + } + void CompileStaticFieldInitializers(compiler::PandaGen *pg, compiler::VReg classReg, const std::vector &staticComputedFieldKeys) const; @@ -528,7 +565,7 @@ private: ArenaSet localVariableIsNeeded_; TSEnumDeclaration *origEnumDecl_ {}; ClassDeclaration *anonClass_ {nullptr}; - static int classCounter_; + static std::atomic classCounter_; int localIndex_ {}; std::string localPrefix_ {}; util::StringView functionalReferenceReferencedMethod_ {}; diff --git a/ets2panda/ir/base/classElement.cpp b/ets2panda/ir/base/classElement.cpp index 9c54368dd8..24c42eeb71 100644 --- a/ets2panda/ir/base/classElement.cpp +++ b/ets2panda/ir/base/classElement.cpp @@ -20,22 +20,70 @@ namespace ark::es2panda::ir { +void ClassElement::SetOrigEnumMember(TSEnumMember *enumMember) +{ + this->GetOrCreateHistoryNodeAs()->enumMember_ = enumMember; +} + +void ClassElement::SetKey(Expression *key) +{ + this->GetOrCreateHistoryNodeAs()->key_ = key; +} + +void ClassElement::EmplaceDecorators(Decorator *decorators) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(decorators); +} + +void ClassElement::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void ClassElement::SetValueDecorators(Decorator *decorators, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = decorators; +} + +[[nodiscard]] const ArenaVector &ClassElement::Decorators() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->decorators_; +} + +[[nodiscard]] ArenaVector &ClassElement::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + void ClassElement::SetValue(Expression *value) noexcept { + if (Value() == value) { + return; + } + if (value != nullptr) { value->SetParent(this); } - value_ = value; + this->GetOrCreateHistoryNodeAs()->value_ = value; } Identifier *ClassElement::Id() noexcept { - return key_ != nullptr && key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; + auto const key = GetHistoryNode()->AsClassElement()->key_; + return key != nullptr && key->IsIdentifier() ? key->AsIdentifier() : nullptr; } const Identifier *ClassElement::Id() const noexcept { - return key_ != nullptr && key_->IsIdentifier() ? key_->AsIdentifier() : nullptr; + auto const key = GetHistoryNode()->AsClassElement()->key_; + return key != nullptr && key->IsIdentifier() ? key->AsIdentifier() : nullptr; } bool ClassElement::IsPrivateElement() const noexcept @@ -44,7 +92,8 @@ bool ClassElement::IsPrivateElement() const noexcept return false; } - return key_->IsIdentifier() && key_->AsIdentifier()->IsPrivateIdent(); + auto const key = GetHistoryNode()->AsClassElement()->key_; + return key->IsIdentifier() && key->AsIdentifier()->IsPrivateIdent(); } void ClassElement::CopyTo(AstNode *other) const diff --git a/ets2panda/ir/base/classElement.h b/ets2panda/ir/base/classElement.h index fc372f8dc2..45101a888b 100644 --- a/ets2panda/ir/base/classElement.h +++ b/ets2panda/ir/base/classElement.h @@ -38,6 +38,24 @@ public: decorators_(allocator->Adapter()), isComputed_(isComputed) { + InitHistory(); + } + + // CC-OFFNXT(G.FUN.01-CPP) solid logic + explicit ClassElement(AstNodeType const elementType, Expression *const key, Expression *const value, + ModifierFlags const modifiers, ArenaAllocator *const allocator, bool const isComputed, + AstNodeHistory *history) + : TypedStatement(elementType, modifiers), + key_(key), + value_(value), + decorators_(allocator->Adapter()), + isComputed_(isComputed) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } [[nodiscard]] Identifier *Id() noexcept; @@ -46,62 +64,56 @@ public: [[nodiscard]] Expression *Key() noexcept { - return key_; + return GetHistoryNodeAs()->key_; } [[nodiscard]] const Expression *Key() const noexcept { - return key_; + return GetHistoryNodeAs()->key_; } [[nodiscard]] Expression *Value() noexcept { - return value_; + return GetHistoryNodeAs()->value_; } void SetValue(Expression *value) noexcept; [[nodiscard]] const Expression *Value() const noexcept { - return value_; + return GetHistoryNodeAs()->value_; } [[nodiscard]] const TSEnumMember *OriginEnumMember() const noexcept { - return enumMember_; + return GetHistoryNodeAs()->enumMember_; } - void SetOrigEnumMember(ir::TSEnumMember *enumMember) - { - enumMember_ = enumMember; - } + void SetOrigEnumMember(ir::TSEnumMember *enumMember); [[nodiscard]] bool IsPrivateElement() const noexcept; [[nodiscard]] const ArenaVector &Decorators() const noexcept { - return decorators_; - } - - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); + return GetHistoryNodeAs()->decorators_; } [[nodiscard]] bool IsComputed() const noexcept { - return isComputed_; + return GetHistoryNodeAs()->isComputed_; } void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = reinterpret_cast(GetOrCreateHistoryNode()); + newNode->decorators_ = std::move(decorators); } void AddDecorator(ir::Decorator *const decorator) { if (decorator != nullptr) { - decorators_.emplace_back(decorator); + auto newNode = reinterpret_cast(GetOrCreateHistoryNode()); + newNode->decorators_.emplace_back(decorator); } } @@ -114,8 +126,18 @@ public: void CopyTo(AstNode *other) const override; + void EmplaceDecorators(Decorator *decorators); + void ClearDecorators(); + void SetValueDecorators(Decorator *decorators, size_t index); + const ArenaVector &Decorators(); + ArenaVector &DecoratorsForUpdate(); + protected: friend class SizeOfNodeTest; + +protected: + void SetKey(Expression *key); + // NOLINTBEGIN(misc-non-private-member-variables-in-classes) Expression *key_; Expression *value_; diff --git a/ets2panda/ir/base/classProperty.cpp b/ets2panda/ir/base/classProperty.cpp index 0ec31492bc..2bacec57d1 100644 --- a/ets2panda/ir/base/classProperty.cpp +++ b/ets2panda/ir/base/classProperty.cpp @@ -23,55 +23,75 @@ #include "compiler/lowering/util.h" namespace ark::es2panda::ir { + +void ClassProperty::SetTypeAnnotation(TypeNode *typeAnnotation) +{ + this->GetOrCreateHistoryNodeAs()->typeAnnotation_ = typeAnnotation; +} + +void ClassProperty::SetDefaultAccessModifier(bool isDefault) +{ + this->GetOrCreateHistoryNodeAs()->isDefault_ = isDefault; +} + void ClassProperty::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (auto *transformedNode = cb(key_); key_ != transformedNode) { - key_->SetTransformedNode(transformationName, transformedNode); - key_ = transformedNode->AsExpression(); + auto *key = Key(); + if (key != nullptr) { + if (auto *transformedNode = cb(key); key != transformedNode) { + key->SetTransformedNode(transformationName, transformedNode); + SetKey(transformedNode->AsExpression()); + } } - if (value_ != nullptr) { - if (auto *transformedNode = cb(value_); value_ != transformedNode) { - value_->SetTransformedNode(transformationName, transformedNode); - value_ = transformedNode->AsExpression(); + auto *value = Value(); + if (value != nullptr) { + if (auto *transformedNode = cb(value); value != transformedNode) { + value->SetTransformedNode(transformationName, transformedNode); + SetValue(transformedNode->AsExpression()); } } - if (typeAnnotation_ != nullptr) { - if (auto *transformedNode = cb(typeAnnotation_); typeAnnotation_ != transformedNode) { - typeAnnotation_->SetTransformedNode(transformationName, transformedNode); - typeAnnotation_ = static_cast(transformedNode); + auto *typeAnnotation = TypeAnnotation(); + if (typeAnnotation != nullptr) { + if (auto *transformedNode = cb(typeAnnotation); typeAnnotation != transformedNode) { + typeAnnotation->SetTransformedNode(transformationName, transformedNode); + SetTypeAnnotation(static_cast(transformedNode)); } } - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - for (auto *&it : Annotations()) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + auto const &annotations = Annotations(); + for (size_t ix = 0; ix < annotations.size(); ix++) { + if (auto *transformedNode = cb(annotations[ix]); annotations[ix] != transformedNode) { + annotations[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueAnnotations(transformedNode->AsAnnotationUsage(), ix); } } } void ClassProperty::Iterate(const NodeTraverser &cb) const { - cb(key_); + auto const key = GetHistoryNode()->AsClassProperty()->key_; + cb(key); - if (value_ != nullptr) { - cb(value_); + auto const value = GetHistoryNode()->AsClassProperty()->value_; + if (value != nullptr) { + cb(value); } - if (typeAnnotation_ != nullptr) { - cb(typeAnnotation_); + if (TypeAnnotation() != nullptr) { + cb(TypeAnnotation()); } - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } @@ -83,17 +103,17 @@ void ClassProperty::Iterate(const NodeTraverser &cb) const void ClassProperty::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "ClassProperty"}, - {"key", key_}, - {"value", AstDumper::Optional(value_)}, - {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(flags_))}, + {"key", Key()}, + {"value", AstDumper::Optional(Value())}, + {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(Modifiers()))}, {"static", IsStatic()}, {"readonly", IsReadonly()}, {"declare", IsDeclare()}, {"optional", IsOptionalDeclaration()}, - {"computed", isComputed_}, - {"typeAnnotation", AstDumper::Optional(typeAnnotation_)}, + {"computed", IsComputed()}, + {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, {"definite", IsDefinite()}, - {"decorators", decorators_}, + {"decorators", Decorators()}, {"annotations", AstDumper::Optional(Annotations())}}); } @@ -224,8 +244,8 @@ void ClassProperty::Dump(ir::SrcDumper *dumper) const } DumpPrefix(dumper); - if (key_ != nullptr) { - key_->Dump(dumper); + if (Key() != nullptr) { + Key()->Dump(dumper); } if (IsOptionalDeclaration()) { @@ -238,14 +258,14 @@ void ClassProperty::Dump(ir::SrcDumper *dumper) const if (typeAnnotation_ != nullptr && !dumper->IsDeclgen()) { dumper->Add(": "); - typeAnnotation_->Dump(dumper); + TypeAnnotation()->Dump(dumper); } DumpCheckerTypeForDeclGen(dumper); if (value_ != nullptr && !dumper->IsDeclgen()) { dumper->Add(" = "); - value_->Dump(dumper); + Value()->Dump(dumper); } dumper->Add(";"); @@ -274,11 +294,11 @@ checker::VerifiedType ClassProperty::Check(checker::ETSChecker *checker) ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_->Clone(allocator, nullptr)->AsExpression(); - auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr; - auto *const typeAnnotation = typeAnnotation_ != nullptr ? typeAnnotation_->Clone(allocator, nullptr) : nullptr; + auto *const key = Key()->Clone(allocator, nullptr)->AsExpression(); + auto *const value = Value() != nullptr ? Value()->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const typeAnnotation = TypeAnnotation() != nullptr ? TypeAnnotation()->Clone(allocator, nullptr) : nullptr; - auto *const clone = allocator->New(key, value, typeAnnotation, flags_, allocator, isComputed_); + auto *const clone = allocator->New(key, value, typeAnnotation, Modifiers(), allocator, IsComputed()); if (parent != nullptr) { clone->SetParent(parent); @@ -286,7 +306,7 @@ ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *co key->SetParent(clone); if (value != nullptr) { - value->SetTsType(value_->TsType()); + value->SetTsType(Value()->TsType()); value->SetParent(clone); } if (typeAnnotation != nullptr) { @@ -294,7 +314,7 @@ ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *co typeAnnotation->SetParent(clone); } - for (auto *const decorator : decorators_) { + for (auto *const decorator : Decorators()) { clone->AddDecorator(decorator->Clone(allocator, clone)); } @@ -306,7 +326,7 @@ ClassProperty *ClassProperty::Clone(ArenaAllocator *const allocator, AstNode *co clone->SetAnnotations(std::move(annotationUsages)); } - clone->SetRange(range_); + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/base/classProperty.h b/ets2panda/ir/base/classProperty.h index 9725118c57..ebdd968dc4 100644 --- a/ets2panda/ir/base/classProperty.h +++ b/ets2panda/ir/base/classProperty.h @@ -47,23 +47,17 @@ public: [[nodiscard]] bool IsDefaultAccessModifier() const noexcept { - return isDefault_; + return GetHistoryNodeAs()->isDefault_; } - void SetDefaultAccessModifier(bool isDefault) - { - isDefault_ = isDefault; - } + void SetDefaultAccessModifier(bool isDefault); [[nodiscard]] TypeNode *TypeAnnotation() const noexcept { - return typeAnnotation_; + return GetHistoryNodeAs()->typeAnnotation_; } - void SetTypeAnnotation(TypeNode *typeAnnotation) noexcept - { - typeAnnotation_ = typeAnnotation; - } + void SetTypeAnnotation(TypeNode *typeAnnotation); [[nodiscard]] PrivateFieldKind ToPrivateFieldKind(bool const isStatic) const override { diff --git a/ets2panda/ir/base/classStaticBlock.cpp b/ets2panda/ir/base/classStaticBlock.cpp index d912d1532b..f8b01d54a7 100644 --- a/ets2panda/ir/base/classStaticBlock.cpp +++ b/ets2panda/ir/base/classStaticBlock.cpp @@ -30,20 +30,22 @@ namespace ark::es2panda::ir { void ClassStaticBlock::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - if (auto *transformedNode = cb(value_); value_ != transformedNode) { - value_->SetTransformedNode(transformationName, transformedNode); - value_ = transformedNode->AsExpression(); + auto const value = Value(); + if (auto *transformedNode = cb(value); value != transformedNode) { + value->SetTransformedNode(transformationName, transformedNode); + SetValue(transformedNode->AsExpression()); } } void ClassStaticBlock::Iterate(const NodeTraverser &cb) const { - cb(value_); + auto const value = reinterpret_cast(GetHistoryNode())->value_; + cb(value); } void ClassStaticBlock::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ClassStaticBlock"}, {"value", value_}}); + dumper->Add({{"type", "ClassStaticBlock"}, {"value", Value()}}); } void ClassStaticBlock::Dump([[maybe_unused]] ir::SrcDumper *dumper) const @@ -84,12 +86,12 @@ checker::VerifiedType ClassStaticBlock::Check(checker::ETSChecker *checker) ir::ScriptFunction *ClassStaticBlock::Function() { - return value_->AsFunctionExpression()->Function(); + return Value()->AsFunctionExpression()->Function(); } const ir::ScriptFunction *ClassStaticBlock::Function() const { - return value_->AsFunctionExpression()->Function(); + return Value()->AsFunctionExpression()->Function(); } const util::StringView &ClassStaticBlock::Name() const diff --git a/ets2panda/ir/base/classStaticBlock.h b/ets2panda/ir/base/classStaticBlock.h index a1a1030b75..63ffc33f16 100644 --- a/ets2panda/ir/base/classStaticBlock.h +++ b/ets2panda/ir/base/classStaticBlock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,6 +26,7 @@ public: explicit ClassStaticBlock(Expression *value, ArenaAllocator *allocator) : ClassElement(AstNodeType::CLASS_STATIC_BLOCK, nullptr, value, ModifierFlags::NONE, allocator, false) { + InitHistory(); } PrivateFieldKind ToPrivateFieldKind([[maybe_unused]] bool isStatic) const override @@ -51,6 +52,16 @@ public: v->Accept(this); } + ClassStaticBlock *Construct(ArenaAllocator *allocator) override + { + return allocator->New(nullptr, allocator); + } + + void CopyTo(AstNode *other) const override + { + ClassElement::CopyTo(other); + }; + private: }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/methodDefinition.cpp b/ets2panda/ir/base/methodDefinition.cpp index cf497838fb..6f705a2f97 100644 --- a/ets2panda/ir/base/methodDefinition.cpp +++ b/ets2panda/ir/base/methodDefinition.cpp @@ -24,19 +24,36 @@ namespace ark::es2panda::ir { +void MethodDefinition::SetDefaultAccessModifier(bool isDefault) +{ + this->GetOrCreateHistoryNodeAs()->isDefault_ = isDefault; +} + +void MethodDefinition::SetBaseOverloadMethod(MethodDefinition *baseOverloadMethod) +{ + this->GetOrCreateHistoryNodeAs()->baseOverloadMethod_ = baseOverloadMethod; +} + +void MethodDefinition::SetAsyncPairMethod(MethodDefinition *asyncPairMethod) +{ + this->GetOrCreateHistoryNodeAs()->asyncPairMethod_ = asyncPairMethod; +} + ScriptFunction *MethodDefinition::Function() { - return value_->IsFunctionExpression() ? value_->AsFunctionExpression()->Function() : nullptr; + auto const value = Value(); + return value->IsFunctionExpression() ? value->AsFunctionExpression()->Function() : nullptr; } const ScriptFunction *MethodDefinition::Function() const { - return value_->IsFunctionExpression() ? value_->AsFunctionExpression()->Function() : nullptr; + auto const value = Value(); + return value->IsFunctionExpression() ? value->AsFunctionExpression()->Function() : nullptr; } PrivateFieldKind MethodDefinition::ToPrivateFieldKind(bool const isStatic) const { - switch (kind_) { + switch (Kind()) { case MethodDefinitionKind::METHOD: { return isStatic ? PrivateFieldKind::STATIC_METHOD : PrivateFieldKind::METHOD; } @@ -54,57 +71,65 @@ PrivateFieldKind MethodDefinition::ToPrivateFieldKind(bool const isStatic) const void MethodDefinition::ResolveReferences(const NodeTraverser &cb) const { - cb(key_); - cb(value_); + auto key = GetHistoryNode()->AsMethodDefinition()->key_; + auto value = GetHistoryNode()->AsMethodDefinition()->value_; + cb(key); + cb(value); - for (auto *it : VectorIterationGuard(overloads_)) { + for (auto *it : VectorIterationGuard(Overloads())) { cb(it); } - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } } void MethodDefinition::Iterate(const NodeTraverser &cb) const { - cb(key_); - cb(value_); + auto key = GetHistoryNode()->AsMethodDefinition()->key_; + auto value = GetHistoryNode()->AsMethodDefinition()->value_; + cb(key); + cb(value); - for (auto *it : overloads_) { + for (auto *it : Overloads()) { if (it->Parent() == this) { cb(it); } } - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } } void MethodDefinition::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (auto *transformedNode = cb(key_); key_ != transformedNode) { - key_->SetTransformedNode(transformationName, transformedNode); - key_ = transformedNode->AsExpression(); + auto *key = Key(); + if (auto *transformedNode = cb(key); key != transformedNode) { + key->SetTransformedNode(transformationName, transformedNode); + SetKey(transformedNode->AsExpression()); } - if (auto *transformedNode = cb(value_); value_ != transformedNode) { - value_->SetTransformedNode(transformationName, transformedNode); - value_ = transformedNode->AsExpression(); + auto *value = Value(); + if (auto *transformedNode = cb(value); value != transformedNode) { + value->SetTransformedNode(transformationName, transformedNode); + SetValue(transformedNode->AsExpression()); } - for (auto *&it : VectorIterationGuard(overloads_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsMethodDefinition(); + auto const &overloads = Overloads(); + for (size_t ix = 0; ix < overloads.size(); ix++) { + if (auto *transformedNode = cb(overloads[ix]); overloads[ix] != transformedNode) { + overloads[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueOverloads(transformedNode->AsMethodDefinition(), ix); } } - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } } @@ -113,7 +138,7 @@ void MethodDefinition::Dump(ir::AstDumper *dumper) const { const char *kind = nullptr; - switch (kind_) { + switch (Kind()) { case MethodDefinitionKind::CONSTRUCTOR: { kind = "constructor"; break; @@ -148,15 +173,15 @@ void MethodDefinition::Dump(ir::AstDumper *dumper) const } dumper->Add({{"type", "MethodDefinition"}, - {"key", key_}, + {"key", Key()}, {"kind", kind}, - {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(flags_))}, + {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(Modifiers()))}, {"static", IsStatic()}, {"optional", IsOptionalDeclaration()}, - {"computed", isComputed_}, - {"value", value_}, - {"overloads", overloads_}, - {"decorators", decorators_}}); + {"computed", IsComputed()}, + {"value", Value()}, + {"overloads", Overloads()}, + {"decorators", Decorators()}}); } void MethodDefinition::DumpModifierPrefix(ir::SrcDumper *dumper) const @@ -306,12 +331,13 @@ void MethodDefinition::Dump(ir::SrcDumper *dumper) const return; } - for (auto method : overloads_) { + for (auto method : Overloads()) { method->Dump(dumper); dumper->Endl(); } - for (auto *anno : value_->AsFunctionExpression()->Function()->Annotations()) { + auto value = Value(); + for (auto *anno : value->AsFunctionExpression()->Function()->Annotations()) { // NOTE(zhelyapov): workaround, see #26031 if (anno->GetBaseName()->Name() != compiler::Signatures::DEFAULT_ANNO_FOR_FUNC) { anno->Dump(dumper); @@ -319,12 +345,13 @@ void MethodDefinition::Dump(ir::SrcDumper *dumper) const } DumpPrefix(dumper); - if (key_ != nullptr) { - key_->Dump(dumper); + auto key = Key(); + if (key != nullptr) { + key->Dump(dumper); } - if (value_ != nullptr) { - value_->Dump(dumper); + if (value != nullptr) { + value->Dump(dumper); } } @@ -350,9 +377,9 @@ checker::VerifiedType MethodDefinition::Check(checker::ETSChecker *checker) MethodDefinition *MethodDefinition::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const key = key_->Clone(allocator, nullptr)->AsExpression(); - auto *const value = value_->Clone(allocator, nullptr)->AsExpression(); - auto *const clone = allocator->New(kind_, key, value, flags_, allocator, isComputed_); + auto *const key = Key()->Clone(allocator, nullptr)->AsExpression(); + auto *const value = Value()->Clone(allocator, nullptr)->AsExpression(); + auto *const clone = allocator->New(Kind(), key, value, Modifiers(), allocator, IsComputed()); if (parent != nullptr) { clone->SetParent(parent); @@ -361,13 +388,13 @@ MethodDefinition *MethodDefinition::Clone(ArenaAllocator *const allocator, AstNo key->SetParent(clone); value->SetParent(clone); - for (auto *const decorator : decorators_) { + for (auto *const decorator : Decorators()) { clone->AddDecorator(decorator->Clone(allocator, clone)); } - clone->baseOverloadMethod_ = baseOverloadMethod_; + clone->SetBaseOverloadMethod(BaseOverloadMethod()); - for (auto *const overloads : overloads_) { + for (auto *const overloads : Overloads()) { clone->AddOverload(overloads->Clone(allocator, clone)); } @@ -378,19 +405,16 @@ void MethodDefinition::InitializeOverloadInfo() { ES2PANDA_ASSERT(this->Function() != nullptr); - overloadInfo_ = {this->Function()->Signature()->MinArgCount(), - this->Function()->Signature()->ArgCount(), - false, - this->IsDeclare(), - (this->Function()->Signature()->RestVar() != nullptr), - this->Function()->Signature()->ReturnType()->IsETSVoidType()}; + SetOverloadInfo({this->Function()->Signature()->MinArgCount(), this->Function()->Signature()->ArgCount(), false, + this->IsDeclare(), (this->Function()->Signature()->RestVar() != nullptr), + this->Function()->Signature()->ReturnType()->IsETSVoidType()}); } void MethodDefinition::ResetOverloads() { - auto baseOverloadMethod = baseOverloadMethod_; - baseOverloadMethod_ = nullptr; - for (auto *overload : overloads_) { + auto baseOverloadMethod = BaseOverloadMethod(); + SetBaseOverloadMethod(nullptr); + for (auto *overload : Overloads()) { overload->CleanUp(); } ClearOverloads(); @@ -419,7 +443,8 @@ void MethodDefinition::ResetOverloads() } } - body.emplace_back(this); + parent->IsClassDefinition() ? parent->AsClassDefinition()->EmplaceBody(this) + : parent->AsTSInterfaceBody()->Body().push_back(this); } void MethodDefinition::CleanUp() @@ -448,4 +473,30 @@ void MethodDefinition::CopyTo(AstNode *other) const ClassElement::CopyTo(other); } +void MethodDefinition::EmplaceOverloads(MethodDefinition *overloads) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->overloads_.emplace_back(overloads); +} + +void MethodDefinition::ClearOverloads() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->overloads_.clear(); +} + +void MethodDefinition::SetValueOverloads(MethodDefinition *overloads, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->overloads_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = overloads; +} + +[[nodiscard]] ArenaVector &MethodDefinition::OverloadsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->overloads_; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/methodDefinition.h b/ets2panda/ir/base/methodDefinition.h index 22b5321129..af54efb580 100644 --- a/ets2panda/ir/base/methodDefinition.h +++ b/ets2panda/ir/base/methodDefinition.h @@ -66,6 +66,24 @@ public: baseOverloadMethod_(nullptr), asyncPairMethod_(nullptr) { + InitHistory(); + } + + // CC-OFFNXT(G.FUN.01-CPP) solid logic + explicit MethodDefinition(MethodDefinitionKind const kind, Expression *const key, Expression *const value, + ModifierFlags const modifiers, ArenaAllocator *const allocator, bool const isComputed, + AstNodeHistory *history) + : ClassElement(AstNodeType::METHOD_DEFINITION, key, value, modifiers, allocator, isComputed), + kind_(kind), + overloads_(allocator->Adapter()), + baseOverloadMethod_(nullptr), + asyncPairMethod_(nullptr) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } // NOTE (csabahurton): these friend relationships can be removed once there are getters for private fields @@ -73,106 +91,120 @@ public: MethodDefinitionKind Kind() const { - return kind_; + return GetHistoryNodeAs()->kind_; } [[nodiscard]] bool IsConstructor() const noexcept { - return kind_ == MethodDefinitionKind::CONSTRUCTOR; + return Kind() == MethodDefinitionKind::CONSTRUCTOR; } [[nodiscard]] bool IsMethod() const noexcept { - return kind_ == MethodDefinitionKind::METHOD; + return Kind() == MethodDefinitionKind::METHOD; } [[nodiscard]] bool IsExtensionMethod() const noexcept { - return (kind_ == MethodDefinitionKind::EXTENSION_METHOD) || (kind_ == MethodDefinitionKind::EXTENSION_GET) || - (kind_ == MethodDefinitionKind::EXTENSION_SET); + auto const kind = Kind(); + return (kind == MethodDefinitionKind::EXTENSION_METHOD) || (kind == MethodDefinitionKind::EXTENSION_GET) || + (kind == MethodDefinitionKind::EXTENSION_SET); } [[nodiscard]] bool IsGetter() const noexcept { - return kind_ == MethodDefinitionKind::GET; + return Kind() == MethodDefinitionKind::GET; } [[nodiscard]] bool IsSetter() const noexcept { - return kind_ == MethodDefinitionKind::SET; + return Kind() == MethodDefinitionKind::SET; } [[nodiscard]] bool IsDefaultAccessModifier() const noexcept { - return isDefault_; + return GetHistoryNodeAs()->isDefault_; } - void SetDefaultAccessModifier(bool isDefault) - { - isDefault_ = isDefault; - } + void SetDefaultAccessModifier(bool isDefault); [[nodiscard]] const OverloadsT &Overloads() const noexcept { - return overloads_; + return GetHistoryNodeAs()->overloads_; } [[nodiscard]] const MethodDefinition *BaseOverloadMethod() const noexcept { - return baseOverloadMethod_; + return GetHistoryNodeAs()->baseOverloadMethod_; } [[nodiscard]] MethodDefinition *BaseOverloadMethod() noexcept { - return baseOverloadMethod_; + return GetHistoryNodeAs()->baseOverloadMethod_; } [[nodiscard]] const MethodDefinition *AsyncPairMethod() const noexcept { - return asyncPairMethod_; + return GetHistoryNodeAs()->asyncPairMethod_; } [[nodiscard]] MethodDefinition *AsyncPairMethod() noexcept { - return asyncPairMethod_; + return GetHistoryNodeAs()->asyncPairMethod_; } - [[nodiscard]] OverloadInfo &GetOverloadInfo() noexcept + [[nodiscard]] const OverloadInfo &GetOverloadInfo() noexcept { - return overloadInfo_; + auto newNode = this->GetHistoryNode()->AsMethodDefinition(); + return newNode->overloadInfo_; } - void SetOverloads(OverloadsT &&overloads) + [[nodiscard]] OverloadInfo &GetOverloadInfoForUpdate() noexcept { - overloads_ = std::move(overloads); + auto newNode = this->GetOrCreateHistoryNode()->AsMethodDefinition(); + return newNode->overloadInfo_; } - void ClearOverloads() + [[nodiscard]] const OverloadInfo &GetOverloadInfo() const noexcept { - overloads_.clear(); + return GetHistoryNodeAs()->overloadInfo_; } - void AddOverload(MethodDefinition *const overload) + void SetOverloadInfo(OverloadInfo &&overloadInfo) { - ES2PANDA_ASSERT(overload != nullptr); - overloads_.emplace_back(overload); - overload->Function()->AddFlag((ir::ScriptFunctionFlags::OVERLOAD)); - overload->SetBaseOverloadMethod(this); + auto newNode = this->GetOrCreateHistoryNode()->AsMethodDefinition(); + newNode->overloadInfo_ = overloadInfo; } - void SetBaseOverloadMethod(MethodDefinition *const baseOverloadMethod) + void SetOverloadInfo(OverloadInfo &overloadInfo) + { + auto newNode = this->GetOrCreateHistoryNode()->AsMethodDefinition(); + newNode->overloadInfo_ = overloadInfo; + } + + void SetOverloads(OverloadsT &&overloads) { - baseOverloadMethod_ = baseOverloadMethod; + auto newNode = this->GetOrCreateHistoryNode()->AsMethodDefinition(); + newNode->overloads_ = std::move(overloads); } - void SetAsyncPairMethod(MethodDefinition *const method) + void AddOverload(MethodDefinition *const overload) { - asyncPairMethod_ = method; + ES2PANDA_ASSERT(overload != nullptr); + auto newNode = this->GetOrCreateHistoryNode()->AsMethodDefinition(); + newNode->overloads_.emplace_back(overload); + overload->Function()->AddFlag((ir::ScriptFunctionFlags::OVERLOAD)); + overload->SetBaseOverloadMethod(this); } + void SetBaseOverloadMethod(MethodDefinition *const baseOverloadMethod); + + void SetAsyncPairMethod(MethodDefinition *const asyncPairMethod); + [[nodiscard]] bool HasOverload(MethodDefinition *overload) noexcept { - return std::find(overloads_.begin(), overloads_.end(), overload) != overloads_.end(); + auto const overloads = Overloads(); + return std::find(overloads.begin(), overloads.end(), overload) != overloads.end(); } ScriptFunction *Function(); @@ -201,6 +233,11 @@ public: void CleanUp() override; + void EmplaceOverloads(MethodDefinition *overloads); + void ClearOverloads(); + void SetValueOverloads(MethodDefinition *overloads, size_t index); + [[nodiscard]] ArenaVector &OverloadsForUpdate(); + protected: MethodDefinition *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; diff --git a/ets2panda/ir/base/scriptFunction.cpp b/ets2panda/ir/base/scriptFunction.cpp index 0eb77cd6c8..73ef90390f 100644 --- a/ets2panda/ir/base/scriptFunction.cpp +++ b/ets2panda/ir/base/scriptFunction.cpp @@ -25,6 +25,90 @@ namespace ark::es2panda::ir { +void ScriptFunction::SetBody(AstNode *body) +{ + this->GetOrCreateHistoryNodeAs()->body_ = body; +} + +void ScriptFunction::SetSignature(checker::Signature *signature) +{ + this->GetOrCreateHistoryNodeAs()->signature_ = signature; +} + +void ScriptFunction::SetScope(varbinder::FunctionScope *scope) +{ + this->GetOrCreateHistoryNodeAs()->scope_ = scope; +} + +void ScriptFunction::SetPreferredReturnType(checker::Type *preferredReturnType) +{ + this->GetOrCreateHistoryNodeAs()->preferredReturnType_ = preferredReturnType; +} + +void ScriptFunction::EmplaceParams(Expression *params) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->irSignature_.Params().emplace_back(params); +} + +void ScriptFunction::ClearParams() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->irSignature_.Params().clear(); +} + +void ScriptFunction::SetValueParams(Expression *params, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->irSignature_.Params(); + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = params; +} + +[[nodiscard]] const ArenaVector &ScriptFunction::Params() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->irSignature_.Params(); +} + +[[nodiscard]] ArenaVector &ScriptFunction::ParamsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->irSignature_.Params(); +} + +void ScriptFunction::EmplaceReturnStatements(ReturnStatement *returnStatements) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->returnStatements_.emplace_back(returnStatements); +} + +void ScriptFunction::ClearReturnStatements() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->returnStatements_.clear(); +} + +void ScriptFunction::SetValueReturnStatements(ReturnStatement *returnStatements, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->returnStatements_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = returnStatements; +} + +[[nodiscard]] const ArenaVector &ScriptFunction::ReturnStatements() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->returnStatements_; +} + +[[nodiscard]] ArenaVector &ScriptFunction::ReturnStatementsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->returnStatements_; +} + ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data) : JsDocAllowed>(AstNodeType::SCRIPT_FUNCTION, data.flags, allocator), irSignature_(std::move(data.signature)), @@ -44,13 +128,40 @@ ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&d if (auto *typeParams = irSignature_.TypeParams(); typeParams != nullptr) { typeParams->SetParent(this); } + InitHistory(); +} + +ScriptFunction::ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data, AstNodeHistory *history) + : JsDocAllowed>(AstNodeType::SCRIPT_FUNCTION, data.flags, allocator), + irSignature_(std::move(data.signature)), + body_(data.body), + funcFlags_(data.funcFlags), + lang_(data.lang), + returnStatements_(allocator->Adapter()) +{ + for (auto *param : irSignature_.Params()) { + param->SetParent(this); + } + + if (auto *returnType = irSignature_.ReturnType(); returnType != nullptr) { + returnType->SetParent(this); + } + + if (auto *typeParams = irSignature_.TypeParams(); typeParams != nullptr) { + typeParams->SetParent(this); + } + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } std::size_t ScriptFunction::FormalParamsLength() const noexcept { std::size_t length = 0U; - for (const auto *param : irSignature_.Params()) { + for (const auto *param : Params()) { if (param->IsRestElement() || param->IsAssignmentPattern()) { break; } @@ -63,8 +174,8 @@ std::size_t ScriptFunction::FormalParamsLength() const noexcept void ScriptFunction::SetIdent(Identifier *id) noexcept { - id_ = id; - id_->SetParent(this); + this->GetOrCreateHistoryNodeAs()->id_ = id; + id->SetParent(this); } ScriptFunction *ScriptFunction::Clone(ArenaAllocator *allocator, AstNode *parent) @@ -80,7 +191,7 @@ ScriptFunction *ScriptFunction::Clone(ArenaAllocator *allocator, AstNode *parent auto *res = util::NodeAllocator::ForceSetParent( allocator, allocator, ScriptFunctionData { - body_ != nullptr ? body_->Clone(allocator, nullptr) : nullptr, + Body() != nullptr ? Body()->Clone(allocator, nullptr) : nullptr, FunctionSignature { TypeParams() != nullptr ? TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterDeclaration() : nullptr, @@ -88,7 +199,7 @@ ScriptFunction *ScriptFunction::Clone(ArenaAllocator *allocator, AstNode *parent ReturnTypeAnnotation() != nullptr ? ReturnTypeAnnotation()->Clone(allocator, nullptr)->AsTypeNode() : nullptr, HasReceiver()}, - funcFlags_, flags_, lang_}); + Flags(), Modifiers(), Language()}); res->SetParent(parent); res->SetAnnotations(std::move(annotationUsages)); return res; @@ -96,38 +207,38 @@ ScriptFunction *ScriptFunction::Clone(ArenaAllocator *allocator, AstNode *parent void ScriptFunction::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (id_ != nullptr) { - if (auto *transformedNode = cb(id_); id_ != transformedNode) { - id_->SetTransformedNode(transformationName, transformedNode); - id_ = transformedNode->AsIdentifier(); + auto const id = Id(); + if (id != nullptr) { + if (auto *transformedNode = cb(id); id != transformedNode) { + id->SetTransformedNode(transformationName, transformedNode); + SetIdent(transformedNode->AsIdentifier()); } } - irSignature_.TransformChildren(cb, transformationName); + GetOrCreateHistoryNode()->AsScriptFunction()->irSignature_.TransformChildren(cb, transformationName); - if (body_ != nullptr) { - if (auto *transformedNode = cb(body_); body_ != transformedNode) { - body_->SetTransformedNode(transformationName, transformedNode); - body_ = transformedNode; + auto const &body = Body(); + if (body != nullptr) { + if (auto *transformedNode = cb(body); body != transformedNode) { + body->SetTransformedNode(transformationName, transformedNode); + SetBody(transformedNode); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ScriptFunction::Iterate(const NodeTraverser &cb) const { - if (id_ != nullptr) { - cb(id_); + auto id = GetHistoryNode()->AsScriptFunction()->id_; + if (id != nullptr) { + cb(id); } - irSignature_.Iterate(cb); - if (body_ != nullptr) { - cb(body_); + GetHistoryNode()->AsScriptFunction()->irSignature_.Iterate(cb); + + auto body = GetHistoryNode()->AsScriptFunction()->body_; + if (body != nullptr) { + cb(body); } for (auto *it : VectorIterationGuard(Annotations())) { cb(it); @@ -136,7 +247,8 @@ void ScriptFunction::Iterate(const NodeTraverser &cb) const void ScriptFunction::SetReturnTypeAnnotation(TypeNode *node) noexcept { - irSignature_.SetReturnType(node); + auto newNode = GetOrCreateHistoryNode()->AsScriptFunction(); + newNode->irSignature_.SetReturnType(node); if (node != nullptr) { node->SetParent(this); } @@ -151,15 +263,15 @@ void ScriptFunction::Dump(ir::AstDumper *dumper) const throwMarker = "rethrows"; } dumper->Add({{"type", "ScriptFunction"}, - {"id", AstDumper::Nullish(id_)}, + {"id", AstDumper::Nullish(Id())}, {"generator", IsGenerator()}, {"async", IsAsyncFunc()}, - {"expression", ((funcFlags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0)}, - {"params", irSignature_.Params()}, - {"returnType", AstDumper::Optional(irSignature_.ReturnType())}, - {"typeParameters", AstDumper::Optional(irSignature_.TypeParams())}, + {"expression", ((Flags() & ir::ScriptFunctionFlags::EXPRESSION) != 0)}, + {"params", Params()}, + {"returnType", AstDumper::Optional(ReturnTypeAnnotation())}, + {"typeParameters", AstDumper::Optional(TypeParams())}, {"declare", AstDumper::Optional(IsDeclare())}, - {"body", AstDumper::Optional(body_)}, + {"body", AstDumper::Optional(Body())}, {"annotations", AstDumper::Optional(Annotations())}, {"throwMarker", AstDumper::Optional(throwMarker)}}); } diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index 5651635642..e5a246ebb6 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -56,136 +56,130 @@ public: explicit ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data); + explicit ScriptFunction(ArenaAllocator *allocator, ScriptFunctionData &&data, AstNodeHistory *history); + [[nodiscard]] const Identifier *Id() const noexcept { - return id_; + return GetHistoryNodeAs()->id_; } [[nodiscard]] Identifier *Id() noexcept { - return id_; + return GetHistoryNodeAs()->id_; } [[nodiscard]] const checker::Signature *Signature() const noexcept { - return signature_; + return GetHistoryNodeAs()->signature_; } [[nodiscard]] checker::Signature *Signature() noexcept { - return signature_; + return GetHistoryNodeAs()->signature_; } [[nodiscard]] const ArenaVector &Params() const noexcept { - return irSignature_.Params(); + return GetHistoryNodeAs()->irSignature_.Params(); } - [[nodiscard]] ArenaVector &Params() noexcept - { - return irSignature_.Params(); - } + [[nodiscard]] const ArenaVector &Params(); const ArenaVector &ReturnStatements() const { - return returnStatements_; + return GetHistoryNodeAs()->returnStatements_; } - ArenaVector &ReturnStatements() - { - return returnStatements_; - } + [[nodiscard]] const ArenaVector &ReturnStatements(); + [[nodiscard]] ArenaVector &ReturnStatementsForUpdate(); [[nodiscard]] const TSTypeParameterDeclaration *TypeParams() const noexcept { - return irSignature_.TypeParams(); + return GetHistoryNodeAs()->irSignature_.TypeParams(); } [[nodiscard]] TSTypeParameterDeclaration *TypeParams() noexcept { - return irSignature_.TypeParams(); + return GetHistoryNode()->AsScriptFunction()->irSignature_.TypeParams(); } [[nodiscard]] const AstNode *Body() const noexcept { - return body_; + return GetHistoryNodeAs()->body_; } [[nodiscard]] AstNode *Body() noexcept { - return body_; + return GetHistoryNodeAs()->body_; } void AddReturnStatement(ReturnStatement *returnStatement) { - returnStatements_.push_back(returnStatement); + EmplaceReturnStatements(returnStatement); } - void SetBody(AstNode *body) noexcept - { - body_ = body; - } + void SetBody(AstNode *body); [[nodiscard]] const TypeNode *ReturnTypeAnnotation() const noexcept { - return irSignature_.ReturnType(); + return GetHistoryNodeAs()->irSignature_.ReturnType(); } [[nodiscard]] TypeNode *ReturnTypeAnnotation() noexcept { - return irSignature_.ReturnType(); + return GetHistoryNode()->AsScriptFunction()->irSignature_.ReturnType(); } void SetReturnTypeAnnotation(TypeNode *node) noexcept; [[nodiscard]] bool IsEntryPoint() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::ENTRY_POINT) != 0; + return (Flags() & ir::ScriptFunctionFlags::ENTRY_POINT) != 0; } [[nodiscard]] bool IsGenerator() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::GENERATOR) != 0; + return (Flags() & ir::ScriptFunctionFlags::GENERATOR) != 0; } [[nodiscard]] bool IsAsyncFunc() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::ASYNC) != 0; + return (Flags() & ir::ScriptFunctionFlags::ASYNC) != 0; } [[nodiscard]] bool IsAsyncImplFunc() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::ASYNC_IMPL) != 0; + return (Flags() & ir::ScriptFunctionFlags::ASYNC_IMPL) != 0; } [[nodiscard]] bool IsArrow() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::ARROW) != 0; + return (Flags() & ir::ScriptFunctionFlags::ARROW) != 0; } [[nodiscard]] bool IsOverload() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::OVERLOAD) != 0; + return (Flags() & ir::ScriptFunctionFlags::OVERLOAD) != 0; } [[nodiscard]] bool IsExternalOverload() const { - return (funcFlags_ & ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD) != 0; + return (Flags() & ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD) != 0; } [[nodiscard]] bool IsConstructor() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::CONSTRUCTOR) != 0; + return (Flags() & ir::ScriptFunctionFlags::CONSTRUCTOR) != 0; } [[nodiscard]] bool IsGetter() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::GETTER) != 0; + return (Flags() & ir::ScriptFunctionFlags::GETTER) != 0; } [[nodiscard]] bool IsSetter() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::SETTER) != 0; + return (Flags() & ir::ScriptFunctionFlags::SETTER) != 0; } [[nodiscard]] bool IsExtensionAccessor() const noexcept @@ -195,72 +189,77 @@ public: [[nodiscard]] bool IsMethod() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::METHOD) != 0; + return (Flags() & ir::ScriptFunctionFlags::METHOD) != 0; } [[nodiscard]] bool IsProxy() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::PROXY) != 0; + return (Flags() & ir::ScriptFunctionFlags::PROXY) != 0; } [[nodiscard]] bool IsStaticBlock() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::STATIC_BLOCK) != 0; + return (Flags() & ir::ScriptFunctionFlags::STATIC_BLOCK) != 0; } [[nodiscard]] bool IsEnum() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::ENUM) != 0; + return (Flags() & ir::ScriptFunctionFlags::ENUM) != 0; } [[nodiscard]] bool IsHidden() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::HIDDEN) != 0; + return (Flags() & ir::ScriptFunctionFlags::HIDDEN) != 0; } [[nodiscard]] bool IsExternal() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::EXTERNAL) != 0; + return (Flags() & ir::ScriptFunctionFlags::EXTERNAL) != 0; } [[nodiscard]] bool IsImplicitSuperCallNeeded() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED) != 0; + return (Flags() & ir::ScriptFunctionFlags::IMPLICIT_SUPER_CALL_NEEDED) != 0; } [[nodiscard]] bool HasBody() const noexcept { - return body_ != nullptr; + return Body() != nullptr; } [[nodiscard]] bool HasRestParameter() const noexcept { - return signature_->RestVar() != nullptr; + return Signature()->RestVar() != nullptr; } [[nodiscard]] bool HasReturnStatement() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::HAS_RETURN) != 0; + return (Flags() & ir::ScriptFunctionFlags::HAS_RETURN) != 0; } [[nodiscard]] bool HasThrowStatement() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::HAS_THROW) != 0; + return (Flags() & ir::ScriptFunctionFlags::HAS_THROW) != 0; } [[nodiscard]] bool IsThrowing() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::THROWS) != 0; + return (Flags() & ir::ScriptFunctionFlags::THROWS) != 0; } [[nodiscard]] bool IsRethrowing() const noexcept { - return (funcFlags_ & ir::ScriptFunctionFlags::RETHROWS) != 0; + return (Flags() & ir::ScriptFunctionFlags::RETHROWS) != 0; + } + + [[nodiscard]] bool IsTrailingLambda() const noexcept + { + return (Flags() & ir::ScriptFunctionFlags::TRAILING_LAMBDA) != 0; } [[nodiscard]] bool IsDynamic() const noexcept { - return lang_.IsDynamic(); + return Language().IsDynamic(); } // Note: This method has been written into CAPI, cannot remove it simply. @@ -271,34 +270,30 @@ public: [[nodiscard]] ir::ScriptFunctionFlags Flags() const noexcept { - return funcFlags_; + return GetHistoryNodeAs()->funcFlags_; } [[nodiscard]] bool HasReceiver() const noexcept { - return irSignature_.HasReceiver(); + return GetHistoryNodeAs()->irSignature_.HasReceiver(); } void SetIdent(Identifier *id) noexcept; - void SetSignature(checker::Signature *signature) noexcept - { - signature_ = signature; - } + void SetSignature(checker::Signature *signature); void AddFlag(ir::ScriptFunctionFlags flags) noexcept { - funcFlags_ |= flags; + if (!All(Flags(), flags)) { + GetOrCreateHistoryNode()->AsScriptFunction()->funcFlags_ |= flags; + } } void ClearFlag(ir::ScriptFunctionFlags flags) noexcept { - funcFlags_ &= (~flags); - } - - void AddModifier(ir::ModifierFlags flags) noexcept - { - flags_ |= flags; + if (Any(Flags(), flags)) { + GetOrCreateHistoryNode()->AsScriptFunction()->funcFlags_ &= ~flags; + } } [[nodiscard]] std::size_t FormalParamsLength() const noexcept; @@ -310,37 +305,31 @@ public: [[nodiscard]] varbinder::FunctionScope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } - void SetScope(varbinder::FunctionScope *scope) noexcept - { - scope_ = scope; - } + void SetScope(varbinder::FunctionScope *scope); void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } [[nodiscard]] es2panda::Language Language() const noexcept { - return lang_; + return GetHistoryNodeAs()->lang_; } - void SetPreferredReturnType(checker::Type *preferredReturnType) noexcept - { - preferredReturnType_ = preferredReturnType; - } + void SetPreferredReturnType(checker::Type *preferredReturnType); [[nodiscard]] checker::Type *GetPreferredReturnType() noexcept { - return preferredReturnType_; + return GetHistoryNodeAs()->preferredReturnType_; } [[nodiscard]] checker::Type const *GetPreferredReturnType() const noexcept { - return preferredReturnType_; + return GetHistoryNodeAs()->preferredReturnType_; } [[nodiscard]] ScriptFunction *Clone(ArenaAllocator *allocator, AstNode *parent) override; @@ -373,9 +362,17 @@ public: void CleanUp() override { AstNode::CleanUp(); - signature_ = nullptr; - preferredReturnType_ = nullptr; + SetSignature(nullptr); + SetPreferredReturnType(nullptr); } + void EmplaceReturnStatements(ReturnStatement *returnStatements); + void ClearReturnStatements(); + void SetValueReturnStatements(ReturnStatement *returnStatements, size_t index); + + void EmplaceParams(Expression *params); + void ClearParams(); + void SetValueParams(Expression *params, size_t index); + ArenaVector &ParamsForUpdate(); protected: ScriptFunction *Construct(ArenaAllocator *allocator) override; diff --git a/ets2panda/ir/base/scriptFunctionSignature.h b/ets2panda/ir/base/scriptFunctionSignature.h index b3918b5fbe..65b977c962 100644 --- a/ets2panda/ir/base/scriptFunctionSignature.h +++ b/ets2panda/ir/base/scriptFunctionSignature.h @@ -24,6 +24,7 @@ namespace ark::es2panda::ir { class TSTypeParameterDeclaration; class TypeNode; class ScriptFunction; +class ETSFunctionType; class FunctionSignature { public: @@ -93,6 +94,7 @@ private: bool hasReceiver_; friend class ScriptFunction; + friend class ETSFunctionType; void CopyFrom(const FunctionSignature &other) { typeParams_ = other.typeParams_; diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index 1f69ae5286..a841793031 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -143,7 +143,7 @@ void SpreadElement::Dump(ir::SrcDumper *dumper) const dumper->Add("..."); argument_->Dump(dumper); auto type = TypeAnnotation(); - if (type != nullptr) { + if (type != nullptr && type->IsValidInCurrentPhase()) { dumper->Add(": "); type->Dump(dumper); } diff --git a/ets2panda/ir/base/spreadElement.h b/ets2panda/ir/base/spreadElement.h index 803e8e32a4..f9eefb502c 100644 --- a/ets2panda/ir/base/spreadElement.h +++ b/ets2panda/ir/base/spreadElement.h @@ -59,11 +59,6 @@ public: return decorators_; } - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); - } - void AddDecorators(ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index da4e93b20c..f2d459dce3 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -23,18 +23,13 @@ namespace ark::es2panda::ir { void ETSFunctionType::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - signature_.TransformChildren(cb, transformationName); - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + GetHistoryNodeAs()->signature_.TransformChildren(cb, transformationName); + TransformAnnotations(cb, transformationName); } void ETSFunctionType::Iterate(const NodeTraverser &cb) const { - signature_.Iterate(cb); + GetHistoryNodeAs()->signature_.Iterate(cb); for (auto *it : VectorIterationGuard(Annotations())) { cb(it); } @@ -49,9 +44,9 @@ void ETSFunctionType::Dump(ir::AstDumper *dumper) const throwMarker = "rethrows"; } dumper->Add({{"type", "ETSFunctionType"}, - {"params", signature_.Params()}, - {"typeParameters", AstDumper::Optional(signature_.TypeParams())}, - {"returnType", signature_.ReturnType()}, + {"params", Params()}, + {"typeParameters", AstDumper::Optional(TypeParams())}, + {"returnType", ReturnType()}, {"throwMarker", AstDumper::Optional(throwMarker)}, {"annotations", AstDumper::Optional(Annotations())}}); } @@ -122,19 +117,17 @@ ETSFunctionType *ETSFunctionType::Clone(ArenaAllocator *const allocator, AstNode { ArenaVector paramsClone(allocator->Adapter()); - for (auto *const param : signature_.Params()) { + for (auto *const param : Params()) { paramsClone.emplace_back(param->Clone(allocator, nullptr)->AsExpression()); } auto *const typeParamsClone = - signature_.TypeParams() != nullptr - ? signature_.TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterDeclaration() - : nullptr; + TypeParams() != nullptr ? TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterDeclaration() : nullptr; auto *const returnTypeClone = - signature_.ReturnType() != nullptr ? signature_.ReturnType()->Clone(allocator, nullptr)->AsTypeNode() : nullptr; + ReturnType() != nullptr ? ReturnType()->Clone(allocator, nullptr)->AsTypeNode() : nullptr; auto *const clone = allocator->New( - FunctionSignature(typeParamsClone, std::move(paramsClone), returnTypeClone), funcFlags_, allocator); + FunctionSignature(typeParamsClone, std::move(paramsClone), returnTypeClone), Flags(), allocator); if (typeParamsClone != nullptr) { typeParamsClone->SetParent(clone); @@ -162,8 +155,28 @@ ETSFunctionType *ETSFunctionType::Clone(ArenaAllocator *const allocator, AstNode // If the scope is set to empty, it will result in the inability to retrieve the scope after clone, // and an error cannot find type will be reported - clone->SetScope(this->scope_); + clone->SetScope(Scope()); return clone; } + +ETSFunctionType *ETSFunctionType::Construct(ArenaAllocator *allocator) +{ + auto adapter = allocator->Adapter(); + return allocator->New(FunctionSignature(nullptr, ArenaVector(adapter), nullptr), + ScriptFunctionFlags::NONE, allocator); +} + +void ETSFunctionType::CopyTo(AstNode *other) const +{ + auto otherImpl = reinterpret_cast(other); + + otherImpl->scope_ = scope_; + otherImpl->signature_.CopyFrom(signature_); + otherImpl->functionalInterface_ = functionalInterface_; + otherImpl->funcFlags_ = funcFlags_; + + TypeNode::CopyTo(other); +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsFunctionType.h b/ets2panda/ir/ets/etsFunctionType.h index b6ae35203b..142e16671c 100644 --- a/ets2panda/ir/ets/etsFunctionType.h +++ b/ets2panda/ir/ets/etsFunctionType.h @@ -32,6 +32,7 @@ public: ArenaAllocator *const allocator) noexcept : TypeNode(AstNodeType::ETS_FUNCTION_TYPE, allocator), signature_(std::move(signature)), funcFlags_(funcFlags) { + InitHistory(); } ETSFunctionType() = delete; @@ -46,77 +47,82 @@ public: [[nodiscard]] varbinder::Scope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } void SetScope(varbinder::Scope *scope) { - scope_ = scope; + GetOrCreateHistoryNodeAs()->scope_ = scope; } void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } const TSTypeParameterDeclaration *TypeParams() const { - return signature_.TypeParams(); + return GetHistoryNodeAs()->signature_.TypeParams(); } TSTypeParameterDeclaration *TypeParams() { - return signature_.TypeParams(); + return GetHistoryNodeAs()->signature_.TypeParams(); } const ArenaVector &Params() const { - return signature_.Params(); + return GetHistoryNodeAs()->signature_.Params(); } const TypeNode *ReturnType() const { - return signature_.ReturnType(); + return GetHistoryNodeAs()->signature_.ReturnType(); } TypeNode *ReturnType() { - return signature_.ReturnType(); + return GetHistoryNodeAs()->signature_.ReturnType(); } ir::TSInterfaceDeclaration *FunctionalInterface() { - return functionalInterface_; + return GetHistoryNodeAs()->functionalInterface_; } const ir::TSInterfaceDeclaration *FunctionalInterface() const { - return functionalInterface_; + return GetHistoryNodeAs()->functionalInterface_; } void SetFunctionalInterface(ir::TSInterfaceDeclaration *functionalInterface) { - functionalInterface_ = functionalInterface; + GetOrCreateHistoryNodeAs()->functionalInterface_ = functionalInterface; } ir::ScriptFunctionFlags Flags() { - return funcFlags_; + return GetHistoryNodeAs()->funcFlags_; + } + + ir::ScriptFunctionFlags Flags() const + { + return GetHistoryNodeAs()->funcFlags_; } bool IsThrowing() const { - return (funcFlags_ & ir::ScriptFunctionFlags::THROWS) != 0; + return (Flags() & ir::ScriptFunctionFlags::THROWS) != 0; } bool IsRethrowing() const { - return (funcFlags_ & ir::ScriptFunctionFlags::RETHROWS) != 0; + return (Flags() & ir::ScriptFunctionFlags::RETHROWS) != 0; } bool IsExtensionFunction() const { - return signature_.HasReceiver(); + return GetHistoryNodeAs()->signature_.HasReceiver(); } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -137,6 +143,10 @@ public: [[nodiscard]] ETSFunctionType *Clone(ArenaAllocator *allocator, AstNode *parent) override; +protected: + ETSFunctionType *Construct(ArenaAllocator *allocator) override; + void CopyTo(AstNode *other) const override; + private: varbinder::Scope *scope_ {}; FunctionSignature signature_; diff --git a/ets2panda/ir/ets/etsImportDeclaration.h b/ets2panda/ir/ets/etsImportDeclaration.h index 4abdaff764..7f7e56683b 100644 --- a/ets2panda/ir/ets/etsImportDeclaration.h +++ b/ets2panda/ir/ets/etsImportDeclaration.h @@ -44,31 +44,32 @@ public: void SetImportMetadata(util::ImportFlags importFlags, Language::Id lang, std::string_view resolvedSource, std::string_view declPath, std::string_view ohmUrl) { - importMetadata_.importFlags = importFlags; - importMetadata_.lang = lang; - importMetadata_.resolvedSource = resolvedSource; - importMetadata_.declPath = declPath; - importMetadata_.ohmUrl = ohmUrl; + auto node = GetOrCreateHistoryNode()->AsETSImportDeclaration(); + node->importMetadata_.importFlags = importFlags; + node->importMetadata_.lang = lang; + node->importMetadata_.resolvedSource = resolvedSource; + node->importMetadata_.declPath = declPath; + node->importMetadata_.ohmUrl = ohmUrl; } es2panda::Language Language() const { - return es2panda::Language {importMetadata_.lang}; + return es2panda::Language {ImportMetadata().lang}; } std::string_view DeclPath() const { - return importMetadata_.declPath; + return ImportMetadata().declPath; } std::string_view OhmUrl() const { - return importMetadata_.ohmUrl; + return ImportMetadata().ohmUrl; } bool IsValid() const { - return (Source()->Str() != ERROR_LITERAL) && importMetadata_.IsValid(); + return (Source()->Str() != ERROR_LITERAL) && ImportMetadata().IsValid(); } bool IsPureDynamic() const @@ -76,24 +77,24 @@ public: return IsValid() && DeclPath().empty() && Language().IsDynamic(); } - util::StringView &AssemblerName() + void SetAssemblerName(util::StringView assemblerName) { - return assemblerName_; + GetOrCreateHistoryNode()->AsETSImportDeclaration()->assemblerName_ = assemblerName; } const util::StringView &AssemblerName() const { - return assemblerName_; + return GetHistoryNode()->AsETSImportDeclaration()->assemblerName_; } std::string_view ResolvedSource() const { - return importMetadata_.resolvedSource; + return ImportMetadata().resolvedSource; } - const auto &ImportMetadata() const + const util::ImportPathManager::ImportMetadata &ImportMetadata() const { - return importMetadata_; + return GetHistoryNode()->AsETSImportDeclaration()->importMetadata_; } void Accept(ASTVisitorT *v) override @@ -101,6 +102,22 @@ public: v->Accept(this); } + ETSImportDeclaration *Construct(ArenaAllocator *allocator) override + { + ArenaVector specifiers(allocator->Adapter()); + return allocator->New(nullptr, std::move(specifiers)); + } + + void CopyTo(AstNode *other) const override + { + auto otherImpl = other->AsETSImportDeclaration(); + + otherImpl->importMetadata_ = importMetadata_; + otherImpl->assemblerName_ = assemblerName_; + + ImportDeclaration::CopyTo(other); + }; + private: util::ImportPathManager::ImportMetadata importMetadata_; util::StringView assemblerName_ {}; diff --git a/ets2panda/ir/ets/etsModule.cpp b/ets2panda/ir/ets/etsModule.cpp index 3fea029e81..4891a53166 100644 --- a/ets2panda/ir/ets/etsModule.cpp +++ b/ets2panda/ir/ets/etsModule.cpp @@ -34,7 +34,7 @@ void ETSModule::Dump(ir::SrcDumper *dumper) const } dumper->Add("namespace "); - ident_->Dump(dumper); + Ident()->Dump(dumper); dumper->Add(" {"); dumper->IncrIndent(); } @@ -67,6 +67,7 @@ void ETSModule::CopyTo(AstNode *other) const otherImpl->ident_ = ident_; otherImpl->flag_ = flag_; otherImpl->program_ = program_; + otherImpl->globalClass_ = globalClass_; JsDocAllowed>::CopyTo(other); } diff --git a/ets2panda/ir/ets/etsModule.h b/ets2panda/ir/ets/etsModule.h index 0c967d8d24..8f2bb0ecd8 100644 --- a/ets2panda/ir/ets/etsModule.h +++ b/ets2panda/ir/ets/etsModule.h @@ -54,47 +54,81 @@ public: program_(program) { type_ = AstNodeType::ETS_MODULE; + InitHistory(); + } + + // CC-OFFNXT(G.FUN.01-CPP) solid logic + explicit ETSModule(ArenaAllocator *allocator, ArenaVector &&statementList, Identifier *ident, + ModuleFlag flag, parser::Program *program, AstNodeHistory *history) + : JsDocAllowed>(allocator, std::move(statementList)), + ident_(ident), + flag_(flag), + program_(program) + { + type_ = AstNodeType::ETS_MODULE; + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } ir::Identifier *Ident() { - return ident_; + return GetHistoryNodeAs()->ident_; } const ir::Identifier *Ident() const { - return ident_; + return GetHistoryNodeAs()->ident_; } parser::Program *Program() { - return program_; + return GetHistoryNodeAs()->program_; + } + + const ir::ClassDefinition *GlobalClass() const + { + return GetHistoryNodeAs()->globalClass_; + } + + ir::ClassDefinition *GlobalClass() + { + return GetHistoryNodeAs()->globalClass_; + } + + void SetGlobalClass(ir::ClassDefinition *globalClass) + { + if (globalClass != GlobalClass()) { + GetOrCreateHistoryNode()->AsETSModule()->globalClass_ = globalClass; + } } [[nodiscard]] bool IsETSScript() const noexcept { - return (flag_ & ModuleFlag::ETSSCRIPT) != 0; + return (ModuleFlags() & ModuleFlag::ETSSCRIPT) != 0; } [[nodiscard]] bool IsNamespace() const noexcept { - return (flag_ & ModuleFlag::NAMESPACE) != 0; + return (ModuleFlags() & ModuleFlag::NAMESPACE) != 0; } [[nodiscard]] bool IsNamespaceChainLastNode() const noexcept { - return (flag_ & ModuleFlag::NAMESPACE_CHAIN_LAST_NODE) != 0; + return (ModuleFlags() & ModuleFlag::NAMESPACE_CHAIN_LAST_NODE) != 0; } void SetNamespaceChainLastNode() noexcept { ES2PANDA_ASSERT(IsNamespace()); - flag_ |= ModuleFlag::NAMESPACE_CHAIN_LAST_NODE; + AddModuleFlag(ModuleFlag::NAMESPACE_CHAIN_LAST_NODE); } const parser::Program *Program() const { - return program_; + return GetHistoryNodeAs()->program_; } void Dump(ir::SrcDumper *dumper) const override; void Accept(ASTVisitorT *v) override @@ -107,9 +141,29 @@ public: private: friend class SizeOfNodeTest; + ModuleFlag ModuleFlags() const + { + return GetHistoryNodeAs()->flag_; + } + + void AddModuleFlag(ModuleFlag flag) noexcept + { + if (!All(ModuleFlags(), flag)) { + GetOrCreateHistoryNode()->AsETSModule()->flag_ |= flag; + } + } + + void ClearModuleFlag(ModuleFlag flag) noexcept + { + if (Any(ModuleFlags(), flag)) { + GetOrCreateHistoryNode()->AsETSModule()->flag_ &= ~flag; + } + } + Identifier *ident_; ModuleFlag flag_; parser::Program *program_; + ir::ClassDefinition *globalClass_ {}; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsNeverType.cpp b/ets2panda/ir/ets/etsNeverType.cpp index 79284dd1f7..3f40e34750 100644 --- a/ets2panda/ir/ets/etsNeverType.cpp +++ b/ets2panda/ir/ets/etsNeverType.cpp @@ -21,12 +21,7 @@ namespace ark::es2panda::ir { void ETSNeverType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSNeverType::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ets/etsNullishTypes.cpp b/ets2panda/ir/ets/etsNullishTypes.cpp index e3e9e79836..0957d162a4 100644 --- a/ets2panda/ir/ets/etsNullishTypes.cpp +++ b/ets2panda/ir/ets/etsNullishTypes.cpp @@ -21,12 +21,7 @@ namespace ark::es2panda::ir { void ETSUndefinedType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSUndefinedType::Iterate([[maybe_unused]] const NodeTraverser &cb) const @@ -92,12 +87,7 @@ ETSUndefinedType *ETSUndefinedType::Clone(ArenaAllocator *allocator, AstNode *pa void ETSNullType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSNullType::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ets/etsParameterExpression.cpp b/ets2panda/ir/ets/etsParameterExpression.cpp index 382a8a6f11..672d060e2a 100644 --- a/ets2panda/ir/ets/etsParameterExpression.cpp +++ b/ets2panda/ir/ets/etsParameterExpression.cpp @@ -22,8 +22,29 @@ namespace ark::es2panda::ir { +void ETSParameterExpression::SetRequiredParams(size_t extraValue) +{ + this->GetOrCreateHistoryNodeAs()->extraValue_ = extraValue; +} + +void ETSParameterExpression::SetLexerSaved(util::StringView savedLexer) +{ + this->GetOrCreateHistoryNodeAs()->savedLexer_ = savedLexer; +} + +void ETSParameterExpression::SetSpread(SpreadElement *spread) +{ + this->GetOrCreateHistoryNodeAs()->spread_ = spread; +} + ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, bool isOptional, ArenaAllocator *const allocator) + : ETSParameterExpression(identOrSpread, isOptional, allocator, nullptr) +{ +} + +ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, bool isOptional, + ArenaAllocator *const allocator, AstNodeHistory *history) : AnnotationAllowed(AstNodeType::ETS_PARAMETER_EXPRESSION, allocator) { SetOptional(isOptional); @@ -43,125 +64,140 @@ ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identO } else { ES2PANDA_UNREACHABLE(); } + + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, ir::Expression *initializer, ArenaAllocator *const allocator) + : ETSParameterExpression(identOrSpread, initializer, allocator, nullptr) +{ +} + +ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, ir::Expression *initializer, + ArenaAllocator *const allocator, AstNodeHistory *history) : ETSParameterExpression(identOrSpread, true, allocator) { SetInitializer(initializer); + + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } const util::StringView &ETSParameterExpression::Name() const noexcept { - return ident_->Name(); + return Ident()->Name(); } const Identifier *ETSParameterExpression::Ident() const noexcept { - return ident_; + return GetHistoryNodeAs()->ident_; } Identifier *ETSParameterExpression::Ident() noexcept { - return ident_; + return GetHistoryNodeAs()->ident_; } const SpreadElement *ETSParameterExpression::RestParameter() const noexcept { - return spread_; + return GetHistoryNodeAs()->spread_; } SpreadElement *ETSParameterExpression::RestParameter() noexcept { - return spread_; + return GetHistoryNodeAs()->spread_; } const Expression *ETSParameterExpression::Initializer() const noexcept { - return initializer_; + return GetHistoryNodeAs()->initializer_; } Expression *ETSParameterExpression::Initializer() noexcept { - return initializer_; + return GetHistoryNodeAs()->initializer_; } varbinder::Variable *ETSParameterExpression::Variable() const noexcept { - return ident_->Variable(); + return Ident()->Variable(); } TypeNode const *ETSParameterExpression::TypeAnnotation() const noexcept { - return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation(); + return !IsRestParameter() ? Ident()->TypeAnnotation() : Spread()->TypeAnnotation(); } TypeNode *ETSParameterExpression::TypeAnnotation() noexcept { - return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation(); + return !IsRestParameter() ? Ident()->TypeAnnotation() : Spread()->TypeAnnotation(); } void ETSParameterExpression::SetTypeAnnotation(TypeNode *typeNode) noexcept { - !IsRestParameter() ? ident_->SetTsTypeAnnotation(typeNode) : spread_->SetTsTypeAnnotation(typeNode); + !IsRestParameter() ? Ident()->SetTsTypeAnnotation(typeNode) : Spread()->SetTsTypeAnnotation(typeNode); } void ETSParameterExpression::SetVariable(varbinder::Variable *const variable) noexcept { - ident_->SetVariable(variable); -} - -void ETSParameterExpression::SetLexerSaved(util::StringView s) noexcept -{ - savedLexer_ = s; + Ident()->SetVariable(variable); } util::StringView ETSParameterExpression::LexerSaved() const noexcept { - return savedLexer_; + return GetHistoryNodeAs()->savedLexer_; } void ETSParameterExpression::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { + auto const spread = Spread(); + auto const ident = Ident(); + auto newNode = GetOrCreateHistoryNodeAs(); if (IsRestParameter()) { - if (auto *transformedNode = cb(spread_); spread_ != transformedNode) { - spread_->SetTransformedNode(transformationName, transformedNode); - spread_ = transformedNode->AsRestElement(); + if (auto *transformedNode = cb(spread); spread != transformedNode) { + spread->SetTransformedNode(transformationName, transformedNode); + SetSpread(transformedNode->AsRestElement()); } - ident_ = spread_->Argument()->AsIdentifier(); + newNode->ident_ = Spread()->Argument()->AsIdentifier(); } else { - if (auto *transformedNode = cb(ident_); ident_ != transformedNode) { - ident_->SetTransformedNode(transformationName, transformedNode); - ident_ = transformedNode->AsIdentifier(); + if (auto *transformedNode = cb(ident); ident != transformedNode) { + ident->SetTransformedNode(transformationName, transformedNode); + SetIdent(transformedNode->AsIdentifier()); } } - if (initializer_ != nullptr) { - if (auto *transformedNode = cb(initializer_); initializer_ != transformedNode) { - initializer_->SetTransformedNode(transformationName, transformedNode); - initializer_ = transformedNode->AsExpression(); + auto const initializer = Initializer(); + if (initializer != nullptr) { + if (auto *transformedNode = cb(initializer); initializer != transformedNode) { + initializer->SetTransformedNode(transformationName, transformedNode); + SetInitializer(transformedNode->AsExpression()); } } - for (auto *&it : Annotations()) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSParameterExpression::Iterate(const NodeTraverser &cb) const { if (IsRestParameter()) { - cb(spread_); + auto const spread = GetHistoryNode()->AsETSParameterExpression()->spread_; + cb(spread); } else { - cb(ident_); + auto const ident = GetHistoryNode()->AsETSParameterExpression()->ident_; + cb(ident); } - if (initializer_ != nullptr) { - cb(initializer_); + auto const initializer = GetHistoryNode()->AsETSParameterExpression()->initializer_; + if (initializer != nullptr) { + cb(initializer); } for (auto *it : Annotations()) { @@ -173,12 +209,12 @@ void ETSParameterExpression::Dump(ir::AstDumper *const dumper) const { if (!IsRestParameter()) { dumper->Add({{"type", "ETSParameterExpression"}, - {"name", ident_}, - {"initializer", AstDumper::Optional(initializer_)}, + {"name", Ident()}, + {"initializer", AstDumper::Optional(Initializer())}, {"annotations", AstDumper::Optional(Annotations())}}); } else { dumper->Add({{"type", "ETSParameterExpression"}, - {"rest parameter", spread_}, + {"rest parameter", Spread()}, {"annotations", AstDumper::Optional(Annotations())}}); } } @@ -190,23 +226,25 @@ void ETSParameterExpression::Dump(ir::SrcDumper *const dumper) const } if (IsRestParameter()) { - spread_->Dump(dumper); + Spread()->Dump(dumper); } else { - if (ident_ != nullptr) { + auto const ident = Ident(); + auto const initializer = Initializer(); + if (ident != nullptr) { ES2PANDA_ASSERT(ident_->IsAnnotatedExpression()); - ident_->Dump(dumper); - if (isOptional_ && initializer_ == nullptr) { + ident->Dump(dumper); + if (IsOptional() && initializer == nullptr) { dumper->Add("?"); } - auto typeAnnotation = ident_->AsAnnotatedExpression()->TypeAnnotation(); + auto typeAnnotation = ident->AsAnnotatedExpression()->TypeAnnotation(); if (typeAnnotation != nullptr) { dumper->Add(": "); typeAnnotation->Dump(dumper); } } - if (initializer_ != nullptr) { + if (initializer != nullptr) { dumper->Add(" = "); - initializer_->Dump(dumper); + initializer->Dump(dumper); } } } @@ -233,14 +271,15 @@ checker::VerifiedType ETSParameterExpression::Check(checker::ETSChecker *const c ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const identOrSpread = spread_ != nullptr ? spread_->Clone(allocator, nullptr)->AsAnnotatedExpression() - : ident_->Clone(allocator, nullptr)->AsAnnotatedExpression(); + auto *const identOrSpread = Spread() != nullptr ? Spread()->Clone(allocator, nullptr)->AsAnnotatedExpression() + : Ident()->Clone(allocator, nullptr)->AsAnnotatedExpression(); auto *const initializer = - initializer_ != nullptr ? initializer_->Clone(allocator, nullptr)->AsExpression() : nullptr; + Initializer() != nullptr ? Initializer()->Clone(allocator, nullptr)->AsExpression() : nullptr; - auto *const clone = initializer_ != nullptr + auto *const clone = Initializer() != nullptr ? allocator->New(identOrSpread, initializer, allocator) - : allocator->New(identOrSpread, isOptional_, allocator); + : allocator->New(identOrSpread, IsOptional(), allocator); + ES2PANDA_ASSERT(identOrSpread != nullptr); identOrSpread->SetParent(clone); if (initializer != nullptr) { @@ -251,7 +290,7 @@ ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allo clone->SetParent(parent); } - clone->SetRequiredParams(extraValue_); + clone->SetRequiredParams(GetRequiredParams()); if (!Annotations().empty()) { ArenaVector annotationUsages {allocator->Adapter()}; diff --git a/ets2panda/ir/ets/etsParameterExpression.h b/ets2panda/ir/ets/etsParameterExpression.h index a38f760c79..976e54149f 100644 --- a/ets2panda/ir/ets/etsParameterExpression.h +++ b/ets2panda/ir/ets/etsParameterExpression.h @@ -38,9 +38,15 @@ public: explicit ETSParameterExpression(AnnotatedExpression *identOrSpread, bool isOptional, ArenaAllocator *const allocator); + explicit ETSParameterExpression(AnnotatedExpression *identOrSpread, bool isOptional, + ArenaAllocator *const allocator, AstNodeHistory *history); + explicit ETSParameterExpression(AnnotatedExpression *identOrSpread, ir::Expression *initializer, ArenaAllocator *const allocator); + explicit ETSParameterExpression(AnnotatedExpression *identOrSpread, ir::Expression *initializer, + ArenaAllocator *const allocator, AstNodeHistory *history); + [[nodiscard]] const util::StringView &Name() const noexcept; [[nodiscard]] const Identifier *Ident() const noexcept; @@ -48,8 +54,8 @@ public: void SetIdent(Identifier *ident) noexcept { - ident_ = ident; - ident_->SetParent(this); + this->GetOrCreateHistoryNodeAs()->ident_ = ident; + ident->SetParent(this); } [[nodiscard]] const SpreadElement *RestParameter() const noexcept; @@ -58,7 +64,7 @@ public: [[nodiscard]] const Expression *Initializer() const noexcept; [[nodiscard]] Expression *Initializer() noexcept; - void SetLexerSaved(util::StringView s) noexcept; + void SetLexerSaved(util::StringView savedLexer); [[nodiscard]] util::StringView LexerSaved() const noexcept; [[nodiscard]] varbinder::Variable *Variable() const noexcept; @@ -71,35 +77,32 @@ public: [[nodiscard]] bool IsOptional() const noexcept { - return isOptional_; + return GetHistoryNodeAs()->isOptional_; } void SetOptional(bool value) noexcept { - isOptional_ = value; - ES2PANDA_ASSERT(isOptional_ || initializer_ == nullptr); + this->GetOrCreateHistoryNodeAs()->isOptional_ = value; + ES2PANDA_ASSERT(IsOptional() || Initializer() == nullptr); } void SetInitializer(Expression *initExpr) noexcept { - initializer_ = initExpr; - ES2PANDA_ASSERT(isOptional_ || initializer_ == nullptr); + this->GetOrCreateHistoryNodeAs()->initializer_ = initExpr; + ES2PANDA_ASSERT(IsOptional() || Initializer() == nullptr); } [[nodiscard]] bool IsRestParameter() const noexcept { - return spread_ != nullptr; + return Spread() != nullptr; } [[nodiscard]] std::size_t GetRequiredParams() const noexcept { - return extraValue_; + return GetHistoryNodeAs()->extraValue_; } - void SetRequiredParams(std::size_t const value) noexcept - { - extraValue_ = value; - } + void SetRequiredParams(std::size_t const extraValue); [[nodiscard]] ETSParameterExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; @@ -122,6 +125,18 @@ public: private: friend class SizeOfNodeTest; + SpreadElement *Spread() noexcept + { + return GetHistoryNodeAs()->spread_; + } + + const SpreadElement *Spread() const noexcept + { + return GetHistoryNodeAs()->spread_; + } + + void SetSpread(SpreadElement *spread); + Identifier *ident_; Expression *initializer_ = nullptr; SpreadElement *spread_ = nullptr; diff --git a/ets2panda/ir/ets/etsPrimitiveType.cpp b/ets2panda/ir/ets/etsPrimitiveType.cpp index c18f743502..c4d18a628d 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.cpp +++ b/ets2panda/ir/ets/etsPrimitiveType.cpp @@ -24,12 +24,7 @@ namespace ark::es2panda::ir { void ETSPrimitiveType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSPrimitiveType::Iterate([[maybe_unused]] const NodeTraverser &cb) const @@ -109,7 +104,7 @@ checker::VerifiedType ETSPrimitiveType::Check(checker::ETSChecker *checker) checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *checker) { - switch (type_) { + switch (GetPrimitiveType()) { case PrimitiveType::BYTE: { SetTsType(checker->GlobalByteType()); return TsType(); @@ -158,7 +153,7 @@ checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *c ETSPrimitiveType *ETSPrimitiveType::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const clone = allocator->New(type_, allocator); + auto *const clone = allocator->New(GetPrimitiveType(), allocator); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/ets/etsPrimitiveType.h b/ets2panda/ir/ets/etsPrimitiveType.h index 49e9d73cc3..e26ae82974 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.h +++ b/ets2panda/ir/ets/etsPrimitiveType.h @@ -16,6 +16,7 @@ #ifndef ES2PANDA_IR_ETS_PRIMITIVE_TYPE_H #define ES2PANDA_IR_ETS_PRIMITIVE_TYPE_H +#include "ir/base/methodDefinition.h" #include "ir/typeNode.h" namespace ark::es2panda::ir { @@ -26,11 +27,12 @@ public: explicit ETSPrimitiveType(PrimitiveType type, ArenaAllocator *const allocator) : TypeNode(AstNodeType::ETS_PRIMITIVE_TYPE, allocator), type_(type) { + InitHistory(); } PrimitiveType GetPrimitiveType() const { - return type_; + return GetHistoryNodeAs()->type_; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -51,6 +53,21 @@ public: [[nodiscard]] ETSPrimitiveType *Clone(ArenaAllocator *allocator, AstNode *parent) override; +protected: + ETSPrimitiveType *Construct(ArenaAllocator *allocator) override + { + return allocator->New(PrimitiveType::VOID, allocator); + } + + void CopyTo(AstNode *other) const override + { + auto otherImpl = reinterpret_cast(other); + + otherImpl->type_ = type_; + + TypeNode::CopyTo(other); + } + private: PrimitiveType type_; }; diff --git a/ets2panda/ir/ets/etsReExportDeclaration.cpp b/ets2panda/ir/ets/etsReExportDeclaration.cpp index c5df1d644b..4475c8b08c 100644 --- a/ets2panda/ir/ets/etsReExportDeclaration.cpp +++ b/ets2panda/ir/ets/etsReExportDeclaration.cpp @@ -19,6 +19,11 @@ namespace ark::es2panda::ir { +void ETSReExportDeclaration::SetETSImportDeclarations(ETSImportDeclaration *etsImportDeclarations) +{ + this->GetOrCreateHistoryNodeAs()->etsImportDeclarations_ = etsImportDeclarations; +} + ETSReExportDeclaration::ETSReExportDeclaration(ETSImportDeclaration *etsImportDeclarations, const std::vector &userPaths, util::StringView programPath, ArenaAllocator *allocator) @@ -30,26 +35,29 @@ ETSReExportDeclaration::ETSReExportDeclaration(ETSImportDeclaration *etsImportDe for (const auto &path : userPaths) { userPaths_.emplace_back(util::UString(path, allocator).View()); } + InitHistory(); } void ETSReExportDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (etsImportDeclarations_ != nullptr) { - if (auto *transformedNode = cb(etsImportDeclarations_); etsImportDeclarations_ != transformedNode) { - etsImportDeclarations_->SetTransformedNode(transformationName, transformedNode); - etsImportDeclarations_ = transformedNode->AsETSImportDeclaration(); + auto const etsImportDecl = GetETSImportDeclarations(); + if (etsImportDecl != nullptr) { + if (auto *transformedNode = cb(etsImportDecl); etsImportDecl != transformedNode) { + etsImportDecl->SetTransformedNode(transformationName, transformedNode); + SetETSImportDeclarations(transformedNode->AsETSImportDeclaration()); } } + InitHistory(); } void ETSReExportDeclaration::Iterate(const NodeTraverser &cb) const { - etsImportDeclarations_->Iterate(cb); + GetETSImportDeclarations()->Iterate(cb); } void ETSReExportDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ETSReExportDeclaration"}, {"ets_import_declarations", etsImportDeclarations_}}); + dumper->Add({{"type", "ETSReExportDeclaration"}, {"ets_import_declarations", GetETSImportDeclarations()}}); } void ETSReExportDeclaration::Dump([[maybe_unused]] ir::SrcDumper *dumper) const @@ -82,14 +90,16 @@ checker::VerifiedType ETSReExportDeclaration::Check(checker::ETSChecker * /*chec return {this, nullptr}; } -AstNode *ETSReExportDeclaration::Construct(ArenaAllocator *allocator) +ETSReExportDeclaration *ETSReExportDeclaration::Construct(ArenaAllocator *allocator) { - return allocator->New(nullptr, std::vector {}, util::StringView {}, allocator); + std::vector userPaths; + return allocator->New(nullptr, std::move(userPaths), + util::UString(std::string(), allocator).View(), allocator); } void ETSReExportDeclaration::CopyTo(AstNode *other) const { - auto otherImpl = other->AsETSReExportDeclaration(); + auto otherImpl = reinterpret_cast(other); otherImpl->etsImportDeclarations_ = etsImportDeclarations_; otherImpl->userPaths_ = userPaths_; diff --git a/ets2panda/ir/ets/etsReExportDeclaration.h b/ets2panda/ir/ets/etsReExportDeclaration.h index 48d7e65459..cb43dc8708 100644 --- a/ets2panda/ir/ets/etsReExportDeclaration.h +++ b/ets2panda/ir/ets/etsReExportDeclaration.h @@ -31,22 +31,22 @@ public: ETSImportDeclaration *GetETSImportDeclarations() const { - return etsImportDeclarations_; + return GetHistoryNodeAs()->etsImportDeclarations_; } ETSImportDeclaration *GetETSImportDeclarations() { - return etsImportDeclarations_; + return GetHistoryNodeAs()->etsImportDeclarations_; } const ArenaVector &GetUserPaths() const { - return userPaths_; + return GetHistoryNodeAs()->userPaths_; } util::StringView const &GetProgramPath() const { - return programPath_; + return GetHistoryNodeAs()->programPath_; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -73,8 +73,9 @@ public: } protected: - AstNode *Construct(ArenaAllocator *allocator) override; + ETSReExportDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; + void SetETSImportDeclarations(ETSImportDeclaration *etsImportDeclarations); private: friend class SizeOfNodeTest; diff --git a/ets2panda/ir/ets/etsStringLiteralType.cpp b/ets2panda/ir/ets/etsStringLiteralType.cpp index d6227f2673..178160de40 100644 --- a/ets2panda/ir/ets/etsStringLiteralType.cpp +++ b/ets2panda/ir/ets/etsStringLiteralType.cpp @@ -21,12 +21,7 @@ namespace ark::es2panda::ir { void ETSStringLiteralType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSStringLiteralType::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ets/etsStructDeclaration.h b/ets2panda/ir/ets/etsStructDeclaration.h index 538797da5d..1ee72040a3 100644 --- a/ets2panda/ir/ets/etsStructDeclaration.h +++ b/ets2panda/ir/ets/etsStructDeclaration.h @@ -30,6 +30,17 @@ public: explicit ETSStructDeclaration(ClassDefinition *const def, ArenaAllocator *const allocator) : ClassDeclaration(AstNodeType::STRUCT_DECLARATION, def, allocator) { + InitHistory(); + } + + explicit ETSStructDeclaration(ClassDefinition *const def, ArenaAllocator *const allocator, AstNodeHistory *history) + : ClassDeclaration(AstNodeType::STRUCT_DECLARATION, def, allocator) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } void Dump(ir::AstDumper *dumper) const override; @@ -42,6 +53,16 @@ public: { v->Accept(this); } + + ETSStructDeclaration *Construct(ArenaAllocator *allocator) override + { + return allocator->New(nullptr, allocator); + } + + void CopyTo(AstNode *other) const override + { + ClassDeclaration::CopyTo(other); + }; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index b79654c62e..79b9e906fb 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -29,12 +29,7 @@ void ETSTuple::TransformChildren(const NodeTransformer &cb, std::string_view con } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ETSTuple::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index 21db7e1814..7986198c72 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -21,23 +21,27 @@ #include "compiler/core/pandagen.h" namespace ark::es2panda::ir { + +void ETSTypeReference::SetPart(ETSTypeReferencePart *part) +{ + this->GetOrCreateHistoryNodeAs()->part_ = part; +} + void ETSTypeReference::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (auto *transformedNode = cb(part_); part_ != transformedNode) { - part_->SetTransformedNode(transformationName, transformedNode); - part_ = transformedNode->AsETSTypeReferencePart(); - } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } + auto const part = Part(); + if (auto *transformedNode = cb(part); part != transformedNode) { + part->SetTransformedNode(transformationName, transformedNode); + SetPart(transformedNode->AsETSTypeReferencePart()); } + + TransformAnnotations(cb, transformationName); } void ETSTypeReference::Iterate(const NodeTraverser &cb) const { - cb(part_); + auto const part = GetHistoryNodeAs()->part_; + cb(part); for (auto *it : VectorIterationGuard(Annotations())) { cb(it); } @@ -45,7 +49,7 @@ void ETSTypeReference::Iterate(const NodeTraverser &cb) const ir::Identifier *ETSTypeReference::BaseName() const { - ir::ETSTypeReferencePart *partIter = part_; + ir::ETSTypeReferencePart *partIter = Part(); while (partIter->Previous() != nullptr) { partIter = partIter->Previous(); @@ -68,7 +72,7 @@ ir::Identifier *ETSTypeReference::BaseName() const void ETSTypeReference::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ETSTypeReference"}, {"part", part_}, {"annotations", AstDumper::Optional(Annotations())}}); + dumper->Add({{"type", "ETSTypeReference"}, {"part", Part()}, {"annotations", AstDumper::Optional(Annotations())}}); } void ETSTypeReference::Dump(ir::SrcDumper *dumper) const @@ -76,8 +80,8 @@ void ETSTypeReference::Dump(ir::SrcDumper *dumper) const for (auto *anno : Annotations()) { anno->Dump(dumper); } - ES2PANDA_ASSERT(part_ != nullptr); - part_->Dump(dumper); + ES2PANDA_ASSERT(Part() != nullptr); + Part()->Dump(dumper); } void ETSTypeReference::Compile(compiler::PandaGen *pg) const @@ -103,7 +107,7 @@ checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) if (TsType() != nullptr) { return TsType(); } - auto *type = part_->GetType(checker); + auto *type = Part()->GetType(checker); if (IsReadonlyType()) { type = checker->GetReadonlyType(type); } @@ -112,14 +116,14 @@ checker::Type *ETSTypeReference::GetType(checker::ETSChecker *checker) ETSTypeReference *ETSTypeReference::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const partClone = part_ != nullptr ? part_->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; + auto *const partClone = Part() != nullptr ? Part()->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; auto *const clone = allocator->New(partClone, allocator); if (partClone != nullptr) { partClone->SetParent(clone); } - clone->flags_ = flags_; + clone->flags_ = Modifiers(); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/ets/etsTypeReference.h b/ets2panda/ir/ets/etsTypeReference.h index f100af2e56..a69e3679fe 100644 --- a/ets2panda/ir/ets/etsTypeReference.h +++ b/ets2panda/ir/ets/etsTypeReference.h @@ -25,16 +25,27 @@ public: explicit ETSTypeReference(ir::ETSTypeReferencePart *part, ArenaAllocator *const allocator) : TypeNode(AstNodeType::ETS_TYPE_REFERENCE, allocator), part_(part) { + InitHistory(); + } + + explicit ETSTypeReference(ir::ETSTypeReferencePart *part, ArenaAllocator *const allocator, AstNodeHistory *history) + : TypeNode(AstNodeType::ETS_TYPE_REFERENCE, allocator), part_(part) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } ir::ETSTypeReferencePart *Part() { - return part_; + return GetHistoryNodeAs()->part_; } ir::ETSTypeReferencePart *Part() const { - return part_; + return GetHistoryNodeAs()->part_; } ir::Identifier *BaseName() const; @@ -61,6 +72,8 @@ public: private: friend class SizeOfNodeTest; + void SetPart(ETSTypeReferencePart *part); + ir::ETSTypeReferencePart *part_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index e0686ef076..befb996682 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -22,55 +22,79 @@ #include "compiler/core/pandagen.h" namespace ark::es2panda::ir { + +void ETSTypeReferencePart::SetName(Expression *name) +{ + this->GetOrCreateHistoryNodeAs()->name_ = name; +} + +void ETSTypeReferencePart::SetTypeParams(TSTypeParameterInstantiation *typeParams) +{ + this->GetOrCreateHistoryNodeAs()->typeParams_ = typeParams; +} + +void ETSTypeReferencePart::SetPrevious(ETSTypeReferencePart *prev) +{ + this->GetOrCreateHistoryNodeAs()->prev_ = prev; +} + void ETSTypeReferencePart::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - if (auto *transformedNode = cb(name_); name_ != transformedNode) { - name_->SetTransformedNode(transformationName, transformedNode); - name_ = transformedNode->AsExpression(); + auto const name = Name(); + if (name != nullptr) { + if (auto *transformedNode = cb(name); name != transformedNode) { + name->SetTransformedNode(transformationName, transformedNode); + SetName(transformedNode->AsExpression()); + } } - if (typeParams_ != nullptr) { - if (auto *transformedNode = cb(typeParams_); typeParams_ != transformedNode) { - typeParams_->SetTransformedNode(transformationName, transformedNode); - typeParams_ = transformedNode->AsTSTypeParameterInstantiation(); + auto const typeParams = TypeParams(); + if (typeParams != nullptr) { + if (auto *transformedNode = cb(typeParams); typeParams != transformedNode) { + typeParams->SetTransformedNode(transformationName, transformedNode); + SetTypeParams(transformedNode->AsTSTypeParameterInstantiation()); } } - if (prev_ != nullptr) { - if (auto *transformedNode = cb(prev_); prev_ != transformedNode) { - prev_->SetTransformedNode(transformationName, transformedNode); - prev_ = transformedNode->AsETSTypeReferencePart(); + auto const prev = Previous(); + if (prev != nullptr) { + if (auto *transformedNode = cb(prev); prev != transformedNode) { + prev->SetTransformedNode(transformationName, transformedNode); + SetPrevious(transformedNode->AsETSTypeReferencePart()); } } } void ETSTypeReferencePart::Iterate(const NodeTraverser &cb) const { - cb(name_); + auto const name = GetHistoryNodeAs()->name_; + cb(name); - if (typeParams_ != nullptr) { - cb(typeParams_); + auto const typeParams = GetHistoryNodeAs()->typeParams_; + if (typeParams != nullptr) { + cb(typeParams); } - if (prev_ != nullptr) { - cb(prev_); + auto const prev = GetHistoryNodeAs()->prev_; + if (prev != nullptr) { + cb(prev); } } void ETSTypeReferencePart::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "ETSTypeReferencePart"}, - {"name", name_}, - {"typeParams", AstDumper::Optional(typeParams_)}, - {"previous", AstDumper::Optional(prev_)}}); + {"name", Name()}, + {"typeParams", AstDumper::Optional(TypeParams())}, + {"previous", AstDumper::Optional(Previous())}}); } void ETSTypeReferencePart::Dump(ir::SrcDumper *dumper) const { - ES2PANDA_ASSERT(name_ != nullptr); - name_->Dump(dumper); - if (typeParams_ != nullptr) { - typeParams_->Dump(dumper); + ES2PANDA_ASSERT(Name() != nullptr); + Name()->Dump(dumper); + if (TypeParams() != nullptr) { + TypeParams()->Dump(dumper); } } @@ -95,24 +119,25 @@ checker::VerifiedType ETSTypeReferencePart::Check(checker::ETSChecker *checker) checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *const checker) { - ES2PANDA_ASSERT(name_->IsIdentifier() || name_->IsTSQualifiedName()); + auto const name = Name(); + ES2PANDA_ASSERT(name->IsIdentifier() || name->IsTSQualifiedName()); Identifier *ident = GetIdent(); varbinder::Variable *variable = nullptr; - if (name_->IsIdentifier()) { + if (name->IsIdentifier()) { variable = ident->Variable(); } else { - if (name_->AsTSQualifiedName()->Left()->Variable() != nullptr && - name_->AsTSQualifiedName()->Left()->Variable()->TsType() != nullptr && - name_->AsTSQualifiedName()->Left()->Variable()->TsType()->IsETSObjectType()) { - variable = name_->AsTSQualifiedName()->Left()->Variable()->TsType()->AsETSObjectType()->GetProperty( + if (name->AsTSQualifiedName()->Left()->Variable() != nullptr && + name->AsTSQualifiedName()->Left()->Variable()->TsType() != nullptr && + name->AsTSQualifiedName()->Left()->Variable()->TsType()->IsETSObjectType()) { + variable = name->AsTSQualifiedName()->Left()->Variable()->TsType()->AsETSObjectType()->GetProperty( ident->Name(), checker::PropertySearchFlags::SEARCH_DECL); } } if (variable != nullptr && variable->Declaration()->IsTypeAliasDecl()) { - return checker->HandleTypeAlias(name_, typeParams_, + return checker->HandleTypeAlias(name, TypeParams(), variable->Declaration()->AsTypeAliasDecl()->Node()->AsTSTypeAliasDeclaration()); } @@ -130,7 +155,7 @@ checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *co if (ident->Name() == compiler::Signatures::READONLY_TYPE_NAME || ident->Name() == compiler::Signatures::REQUIRED_TYPE_NAME) { - return checker->HandleUtilityTypeParameterNode(typeParams_, ident); + return checker->HandleUtilityTypeParameterNode(TypeParams(), ident); } if (ident->Name() == compiler::Signatures::PARTIAL_TYPE_NAME) { @@ -150,11 +175,12 @@ checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *co checker::Type *ETSTypeReferencePart::HandleFixedArrayType(checker::ETSChecker *const checker) { - if (typeParams_ == nullptr || typeParams_->Params().size() != 1) { + auto const typeParams = TypeParams(); + if (typeParams == nullptr || typeParams->Params().size() != 1) { checker->LogError(diagnostic::FIXED_ARRAY_PARAM_ERROR, {}, Start()); return checker->GlobalTypeError(); } - checker::Type *type = checker->CreateETSArrayType(typeParams_->Params()[0]->GetType(checker), IsReadonlyType()); + checker::Type *type = checker->CreateETSArrayType(typeParams->Params()[0]->GetType(checker), IsReadonlyType()); SetTsType(type); return type; } @@ -162,14 +188,15 @@ checker::Type *ETSTypeReferencePart::HandleFixedArrayType(checker::ETSChecker *c checker::Type *ETSTypeReferencePart::HandlePartialType(checker::ETSChecker *const checker, const Identifier *const ident) { - auto *baseType = checker->HandleUtilityTypeParameterNode(typeParams_, ident); + auto const typeParams = TypeParams(); + auto *baseType = checker->HandleUtilityTypeParameterNode(typeParams, ident); if (baseType != nullptr && baseType->IsETSObjectType() && !baseType->AsETSObjectType()->TypeArguments().empty()) { // we treat Partial> class as a different copy from A now, // but not a generic type param for Partial<> - if (typeParams_ != nullptr) { - for (auto &typeRef : typeParams_->Params()) { + if (typeParams != nullptr) { + for (auto &typeRef : typeParams->Params()) { checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), - typeRef->AsETSTypeReference()->Part()->typeParams_, Start()); + typeRef->AsETSTypeReference()->Part()->TypeParams(), Start()); baseType = ctx.Result(); } } @@ -187,35 +214,37 @@ checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) } } } - if (prev_ == nullptr) { - if (name_->IsIdentifier() || name_->IsTSQualifiedName()) { + auto const name = Name(); + if (Previous() == nullptr) { + if (name->IsIdentifier() || name->IsTSQualifiedName()) { SetTsType(HandleInternalTypes(checker)); } if (TsType() == nullptr) { - checker::Type *baseType = checker->GetReferencedTypeBase(name_); + checker::Type *baseType = checker->GetReferencedTypeBase(name); ES2PANDA_ASSERT(baseType != nullptr); if (baseType->IsETSObjectType()) { - checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), typeParams_, Start()); + checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), TypeParams(), Start()); SetTsType(ctx.Result()); } else { SetTsType(baseType); } } } else { - checker::Type *baseType = prev_->GetType(checker); - SetTsType(checker->GetReferencedTypeFromBase(baseType, name_)); + checker::Type *baseType = Previous()->GetType(checker); + SetTsType(checker->GetReferencedTypeFromBase(baseType, name)); } return TsType(); } ETSTypeReferencePart *ETSTypeReferencePart::Clone(ArenaAllocator *const allocator, AstNode *const parent) { - auto *const nameClone = name_ != nullptr ? name_->Clone(allocator, nullptr)->AsExpression() : nullptr; + auto *const nameClone = Name() != nullptr ? Name()->Clone(allocator, nullptr)->AsExpression() : nullptr; auto *const typeParamsClone = - typeParams_ != nullptr ? typeParams_->Clone(allocator, nullptr)->AsTSTypeParameterInstantiation() : nullptr; - auto *const prevClone = prev_ != nullptr ? prev_->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; + TypeParams() != nullptr ? TypeParams()->Clone(allocator, nullptr)->AsTSTypeParameterInstantiation() : nullptr; + auto *const prevClone = + Previous() != nullptr ? Previous()->Clone(allocator, nullptr)->AsETSTypeReferencePart() : nullptr; auto *const clone = allocator->New(nameClone, typeParamsClone, prevClone, allocator); if (nameClone != nullptr) { @@ -240,12 +269,13 @@ ETSTypeReferencePart *ETSTypeReferencePart::Clone(ArenaAllocator *const allocato ir::Identifier *ETSTypeReferencePart::GetIdent() { - if (name_->IsTSQualifiedName()) { - auto ident = name_->AsTSQualifiedName()->Right(); + auto const name = Name(); + if (name->IsTSQualifiedName()) { + auto ident = name->AsTSQualifiedName()->Right(); ES2PANDA_ASSERT(ident->IsIdentifier()); return ident->AsIdentifier(); } - return name_->AsIdentifier(); + return name->AsIdentifier(); } ETSTypeReferencePart *ETSTypeReferencePart::Construct(ArenaAllocator *allocator) diff --git a/ets2panda/ir/ets/etsTypeReferencePart.h b/ets2panda/ir/ets/etsTypeReferencePart.h index 4b1e6aba37..54a2156b99 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.h +++ b/ets2panda/ir/ets/etsTypeReferencePart.h @@ -26,36 +26,65 @@ public: ir::ETSTypeReferencePart *prev, ArenaAllocator *const allocator) : TypeNode(AstNodeType::ETS_TYPE_REFERENCE_PART, allocator), name_(name), typeParams_(typeParams), prev_(prev) { + InitHistory(); } explicit ETSTypeReferencePart(ir::Expression *name, ArenaAllocator *const allocator) : TypeNode(AstNodeType::ETS_TYPE_REFERENCE_PART, allocator), name_(name) { + InitHistory(); + } + + explicit ETSTypeReferencePart(ir::Expression *name, ArenaAllocator *const allocator, AstNodeHistory *history) + : TypeNode(AstNodeType::ETS_TYPE_REFERENCE_PART, allocator), name_(name) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } + } + + explicit ETSTypeReferencePart(ir::Expression *name, ir::TSTypeParameterInstantiation *typeParams, + ir::ETSTypeReferencePart *prev, ArenaAllocator *const allocator, + AstNodeHistory *history) + : TypeNode(AstNodeType::ETS_TYPE_REFERENCE_PART, allocator), name_(name), typeParams_(typeParams), prev_(prev) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } ir::ETSTypeReferencePart *Previous() { - return prev_; + return GetHistoryNodeAs()->prev_; } const ir::ETSTypeReferencePart *Previous() const { - return prev_; + return GetHistoryNodeAs()->prev_; } ir::Expression *Name() { - return name_; + return GetHistoryNodeAs()->name_; } ir::TSTypeParameterInstantiation *TypeParams() { - return typeParams_; + return GetHistoryNodeAs()->typeParams_; + } + + const ir::TSTypeParameterInstantiation *TypeParams() const + { + return GetHistoryNodeAs()->typeParams_; } const ir::Expression *Name() const { - return name_; + return GetHistoryNodeAs()->name_; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -85,6 +114,10 @@ private: checker::Type *HandleFixedArrayType(checker::ETSChecker *const checker); friend class SizeOfNodeTest; + void SetName(ir::Expression *name); + void SetTypeParams(ir::TSTypeParameterInstantiation *typeParams); + void SetPrevious(ir::ETSTypeReferencePart *prev); + ir::Expression *name_; ir::TSTypeParameterInstantiation *typeParams_ {}; ir::ETSTypeReferencePart *prev_ {}; diff --git a/ets2panda/ir/ets/etsUnionType.cpp b/ets2panda/ir/ets/etsUnionType.cpp index 39860832e4..de035bcd61 100644 --- a/ets2panda/ir/ets/etsUnionType.cpp +++ b/ets2panda/ir/ets/etsUnionType.cpp @@ -20,23 +20,20 @@ namespace ark::es2panda::ir { void ETSUnionType::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(types_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = static_cast(transformedNode); - } - } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + auto const &types = Types(); + for (size_t ix = 0; ix < types.size(); ix++) { + if (auto *transformedNode = cb(types[ix]); types[ix] != transformedNode) { + types[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueTypes(static_cast(transformedNode), ix); } } + + TransformAnnotations(cb, transformationName); } void ETSUnionType::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(types_)) { + for (auto *it : VectorIterationGuard(Types())) { cb(it); } @@ -47,7 +44,7 @@ void ETSUnionType::Iterate(const NodeTraverser &cb) const void ETSUnionType::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ETSUnionType"}, {"types", types_}, {"annotations", AstDumper::Optional(Annotations())}}); + dumper->Add({{"type", "ETSUnionType"}, {"types", Types()}, {"annotations", AstDumper::Optional(Annotations())}}); } void ETSUnionType::Dump(ir::SrcDumper *dumper) const @@ -55,9 +52,9 @@ void ETSUnionType::Dump(ir::SrcDumper *dumper) const for (auto *anno : Annotations()) { anno->Dump(dumper); } - for (auto type : types_) { + for (auto type : Types()) { type->Dump(dumper); - if (type != types_.back()) { + if (type != Types().back()) { dumper->Add(" | "); } } @@ -72,7 +69,7 @@ checker::Type *ETSUnionType::Check([[maybe_unused]] checker::TSChecker *checker) checker::VerifiedType ETSUnionType::Check(checker::ETSChecker *checker) { - for (auto *it : types_) { + for (auto *it : Types()) { it->Check(checker); } @@ -98,7 +95,7 @@ checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker) ArenaVector types(checker->Allocator()->Adapter()); - for (auto *it : types_) { + for (auto *it : Types()) { types.push_back(it->GetType(checker)); } @@ -115,7 +112,7 @@ checker::Type *ETSUnionType::GetType(checker::ETSChecker *checker) ETSUnionType *ETSUnionType::Clone(ArenaAllocator *const allocator, AstNode *const parent) { ArenaVector types(allocator->Adapter()); - for (auto *it : types_) { + for (auto *it : Types()) { auto *type = it->Clone(allocator, nullptr); types.push_back(type); } @@ -131,7 +128,7 @@ ETSUnionType *ETSUnionType::Clone(ArenaAllocator *const allocator, AstNode *cons } clone->SetAnnotations(std::move(annotationUsages)); } - for (auto *it : clone->types_) { + for (auto *it : clone->Types()) { it->SetParent(clone); } diff --git a/ets2panda/ir/ets/etsUnionType.h b/ets2panda/ir/ets/etsUnionType.h index 4bc14986b3..21a06d8ef1 100644 --- a/ets2panda/ir/ets/etsUnionType.h +++ b/ets2panda/ir/ets/etsUnionType.h @@ -24,11 +24,17 @@ public: explicit ETSUnionType(ArenaVector &&types, ArenaAllocator *const allocator) : TypeNode(AstNodeType::ETS_UNION_TYPE, allocator), types_(std::move(types)) { + InitHistory(); } const ArenaVector &Types() const { - return types_; + return GetHistoryNodeAs()->types_; + } + + void SetValueTypes(TypeNode *type, size_t index) const + { + GetOrCreateHistoryNodeAs()->types_[index] = type; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -47,6 +53,22 @@ public: [[nodiscard]] ETSUnionType *Clone(ArenaAllocator *allocator, AstNode *parent) override; +protected: + ETSUnionType *Construct(ArenaAllocator *allocator) override + { + ArenaVector types(allocator->Adapter()); + return allocator->New(std::move(types), allocator); + } + + void CopyTo(AstNode *other) const override + { + auto otherImpl = reinterpret_cast(other); + + otherImpl->types_ = types_; + + TypeNode::CopyTo(other); + } + private: ArenaVector types_; }; diff --git a/ets2panda/ir/ets/etsWildcardType.cpp b/ets2panda/ir/ets/etsWildcardType.cpp index 24000a8aa5..ab5ffc9e50 100644 --- a/ets2panda/ir/ets/etsWildcardType.cpp +++ b/ets2panda/ir/ets/etsWildcardType.cpp @@ -32,12 +32,8 @@ void ETSWildcardType::TransformChildren(const NodeTransformer &cb, std::string_v typeReference_ = transformedNode->AsETSTypeReference(); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void ETSWildcardType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/expression.h b/ets2panda/ir/expression.h index 52b74a8329..00c10eaec8 100644 --- a/ets2panda/ir/expression.h +++ b/ets2panda/ir/expression.h @@ -33,24 +33,26 @@ public: [[nodiscard]] bool IsGrouped() const noexcept { - return grouped_; + return AstNode::GetHistoryNodeAs()->grouped_; } void SetGrouped() noexcept { - grouped_ = true; + if (!IsGrouped()) { + AstNode::GetOrCreateHistoryNodeAs()->grouped_ = true; + } } [[nodiscard]] const Literal *AsLiteral() const { ES2PANDA_ASSERT(IsLiteral()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } [[nodiscard]] Literal *AsLiteral() { ES2PANDA_ASSERT(IsLiteral()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } [[nodiscard]] virtual bool IsLiteral() const noexcept @@ -76,25 +78,25 @@ public: [[nodiscard]] TypeNode *AsTypeNode() { ES2PANDA_ASSERT(IsTypeNode()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } [[nodiscard]] const TypeNode *AsTypeNode() const { ES2PANDA_ASSERT(IsTypeNode()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } [[nodiscard]] AnnotatedExpression *AsAnnotatedExpression() { ES2PANDA_ASSERT(IsAnnotatedExpression()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } [[nodiscard]] const AnnotatedExpression *AsAnnotatedExpression() const { ES2PANDA_ASSERT(IsAnnotatedExpression()); - return reinterpret_cast(this); + return reinterpret_cast(GetHistoryNodeAs()); } bool IsBrokenExpression() const noexcept; @@ -109,7 +111,7 @@ protected: Expression(Expression const &other) : TypedAstNode(static_cast(other)) { - grouped_ = other.grouped_; + grouped_ = other.IsGrouped(); } private: @@ -150,12 +152,12 @@ public: [[nodiscard]] bool IsOptional() const noexcept { - return optional_; + return GetHistoryNodeAs()->optional_; } void ClearOptional() noexcept { - optional_ = false; + GetOrCreateHistoryNodeAs()->optional_ = false; } protected: diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 2cc1924a89..2af3767f2b 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -119,11 +119,6 @@ public: return decorators_; } - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); - } - void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/expressions/arrowFunctionExpression.cpp b/ets2panda/ir/expressions/arrowFunctionExpression.cpp index c4941954ec..772cf69fc0 100644 --- a/ets2panda/ir/expressions/arrowFunctionExpression.cpp +++ b/ets2panda/ir/expressions/arrowFunctionExpression.cpp @@ -28,12 +28,7 @@ void ArrowFunctionExpression::TransformChildren(const NodeTransformer &cb, std:: func_ = transformedNode->AsScriptFunction(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void ArrowFunctionExpression::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/expressions/callExpression.h b/ets2panda/ir/expressions/callExpression.h index 3d7f231a15..1dc57dca97 100644 --- a/ets2panda/ir/expressions/callExpression.h +++ b/ets2panda/ir/expressions/callExpression.h @@ -17,7 +17,9 @@ #define ES2PANDA_IR_EXPRESSION_CALL_EXPRESSION_H #include "varbinder/variable.h" +#include "ir/base/scriptFunction.h" #include "ir/expression.h" +#include "ir/expressions/arrowFunctionExpression.h" namespace ark::es2panda::checker { class ETSAnalyzer; @@ -184,6 +186,9 @@ public: AstNode::CleanUp(); signature_ = nullptr; uncheckedType_ = nullptr; + if (IsTransformedFromTrailingCall()) { + RetrieveTrailingBlock(); + } } private: @@ -193,6 +198,19 @@ private: bool isBlockInNewLine {false}; }; + bool IsTransformedFromTrailingCall() + { + return !arguments_.empty() && arguments_.back()->IsArrowFunctionExpression() && + arguments_.back()->AsArrowFunctionExpression()->Function()->IsTrailingLambda(); + } + + void RetrieveTrailingBlock() + { + SetTrailingBlock(arguments_.back()->AsArrowFunctionExpression()->Function()->Body()->AsBlockStatement()); + trailingLambdaInfo_.isTrailingCall = false; + arguments_.pop_back(); + } + protected: // NOLINTBEGIN(misc-non-private-member-variables-in-classes) Expression *callee_; diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index ad06be7bfb..b5c0e1b6ed 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -30,11 +30,13 @@ Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, for (auto *decorator : other.decorators_) { decorators_.emplace_back(decorator->Clone(allocator, this)); } + InitHistory(); } Identifier::Identifier(ArenaAllocator *const allocator) : Identifier(ERROR_LITERAL, allocator) { flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + InitHistory(); } Identifier::Identifier(util::StringView const name, ArenaAllocator *const allocator) @@ -43,6 +45,7 @@ Identifier::Identifier(util::StringView const name, ArenaAllocator *const alloca if (name == ERROR_LITERAL) { flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; } + InitHistory(); } Identifier::Identifier(util::StringView const name, TypeNode *const typeAnnotation, ArenaAllocator *const allocator) @@ -51,12 +54,13 @@ Identifier::Identifier(util::StringView const name, TypeNode *const typeAnnotati if (name == ERROR_LITERAL) { flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; } + InitHistory(); } void Identifier::SetName(const util::StringView &newName) noexcept { ES2PANDA_ASSERT(newName != ERROR_LITERAL); - name_ = newName; + GetOrCreateHistoryNodeAs()->name_ = newName; } Identifier *Identifier::Clone(ArenaAllocator *const allocator, AstNode *const parent) @@ -72,6 +76,13 @@ Identifier *Identifier::Clone(ArenaAllocator *const allocator, AstNode *const pa return clone; } +void Identifier::SetValueDecorators(Decorator *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + arenaVector[index] = source; +} + Identifier *Identifier::CloneReference(ArenaAllocator *const allocator, AstNode *const parent) { auto *const clone = Clone(allocator, parent); @@ -90,10 +101,11 @@ void Identifier::TransformChildren(const NodeTransformer &cb, std::string_view c } } - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } } @@ -104,14 +116,14 @@ void Identifier::Iterate(const NodeTraverser &cb) const cb(TypeAnnotation()); } - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } } ValidationInfo Identifier::ValidateExpression() { - if ((flags_ & IdentifierFlags::OPTIONAL) != 0U) { + if ((IdFlags() & IdentifierFlags::OPTIONAL) != 0U) { return {"Unexpected token '?'.", Start()}; } @@ -126,10 +138,10 @@ ValidationInfo Identifier::ValidateExpression() void Identifier::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", IsPrivateIdent() ? "PrivateIdentifier" : "Identifier"}, - {"name", name_}, + {"name", Name()}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, {"optional", AstDumper::Optional(IsOptional())}, - {"decorators", decorators_}}); + {"decorators", Decorators()}}); } void Identifier::Dump(ir::SrcDumper *dumper) const @@ -143,7 +155,7 @@ void Identifier::Dump(ir::SrcDumper *dumper) const dumper->Add("private "); } - auto name = std::string(name_); + auto name = std::string(Name()); std::string propertyStr = compiler::Signatures::PROPERTY.data(); if (UNLIKELY(name.find(propertyStr) != std::string::npos)) { name.replace(name.find(propertyStr), propertyStr.length(), "_$property$_"); diff --git a/ets2panda/ir/expressions/identifier.h b/ets2panda/ir/expressions/identifier.h index da71df56cc..6f8814018b 100644 --- a/ets2panda/ir/expressions/identifier.h +++ b/ets2panda/ir/expressions/identifier.h @@ -68,42 +68,39 @@ public: [[nodiscard]] const util::StringView &Name() const noexcept { - return name_; + return GetHistoryNodeAs()->name_; } [[nodiscard]] util::StringView &Name() noexcept { - return name_; + return GetHistoryNodeAs()->name_; } void SetName(const util::StringView &newName) noexcept; - [[nodiscard]] const ArenaVector &Decorators() const noexcept - { - return decorators_; - } + void SetValueDecorators(Decorator *source, size_t index); - const ArenaVector *DecoratorsPtr() const override + [[nodiscard]] const ArenaVector &Decorators() const noexcept { - return &Decorators(); + return GetHistoryNodeAs()->decorators_; } bool IsErrorPlaceHolder() const noexcept { - return (flags_ & IdentifierFlags::ERROR_PLACEHOLDER) != 0; + return (IdFlags() & IdentifierFlags::ERROR_PLACEHOLDER) != 0; } [[nodiscard]] bool IsOptional() const noexcept { - return (flags_ & IdentifierFlags::OPTIONAL) != 0; + return (IdFlags() & IdentifierFlags::OPTIONAL) != 0; } void SetOptional(bool const optional) noexcept { if (optional) { - flags_ |= IdentifierFlags::OPTIONAL; + AddIdFlags(IdentifierFlags::OPTIONAL); } else { - flags_ &= ~IdentifierFlags::OPTIONAL; + ClearIdFlags(IdentifierFlags::OPTIONAL); } } @@ -114,86 +111,86 @@ public: [[nodiscard]] bool IsTdz() const noexcept { - return (flags_ & IdentifierFlags::TDZ) != 0; + return (IdFlags() & IdentifierFlags::TDZ) != 0; } void SetTdz() noexcept { - flags_ |= IdentifierFlags::TDZ; + AddIdFlags(IdentifierFlags::TDZ); } void SetAccessor() noexcept { - flags_ |= IdentifierFlags::GET; + AddIdFlags(IdentifierFlags::GET); } [[nodiscard]] bool IsAccessor() const noexcept { - return (flags_ & IdentifierFlags::GET) != 0; + return (IdFlags() & IdentifierFlags::GET) != 0; } void SetMutator() noexcept { - flags_ |= IdentifierFlags::SET; + AddIdFlags(IdentifierFlags::SET); } [[nodiscard]] bool IsMutator() const noexcept { - return (flags_ & IdentifierFlags::SET) != 0; + return (IdFlags() & IdentifierFlags::SET) != 0; } [[nodiscard]] bool IsReceiver() const noexcept { - return name_ == varbinder::VarBinder::MANDATORY_PARAM_THIS; + return Name() == varbinder::VarBinder::MANDATORY_PARAM_THIS; } [[nodiscard]] bool IsPrivateIdent() const noexcept { - return (flags_ & IdentifierFlags::PRIVATE) != 0; + return (IdFlags() & IdentifierFlags::PRIVATE) != 0; } void SetPrivate(bool const isPrivate) noexcept { if (isPrivate) { - flags_ |= IdentifierFlags::PRIVATE; + AddIdFlags(IdentifierFlags::PRIVATE); } else { - flags_ &= ~IdentifierFlags::PRIVATE; + ClearIdFlags(IdentifierFlags::PRIVATE); } } [[nodiscard]] bool IsIgnoreBox() const noexcept { - return (flags_ & IdentifierFlags::IGNORE_BOX) != 0; + return (IdFlags() & IdentifierFlags::IGNORE_BOX) != 0; } void SetIgnoreBox() noexcept { - flags_ |= IdentifierFlags::IGNORE_BOX; + AddIdFlags(IdentifierFlags::IGNORE_BOX); } [[nodiscard]] bool IsAnnotationDecl() const noexcept { - return (flags_ & IdentifierFlags::ANNOTATIONDECL) != 0; + return (IdFlags() & IdentifierFlags::ANNOTATIONDECL) != 0; } void SetAnnotationDecl() noexcept { - flags_ |= IdentifierFlags::ANNOTATIONDECL; + AddIdFlags(IdentifierFlags::ANNOTATIONDECL); } [[nodiscard]] bool IsAnnotationUsage() const noexcept { - return (flags_ & IdentifierFlags::ANNOTATIONUSAGE) != 0; + return (IdFlags() & IdentifierFlags::ANNOTATIONUSAGE) != 0; } void SetAnnotationUsage() noexcept { - flags_ |= IdentifierFlags::ANNOTATIONUSAGE; + AddIdFlags(IdentifierFlags::ANNOTATIONUSAGE); } void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + GetOrCreateHistoryNodeAs()->decorators_ = std::move(decorators); } [[nodiscard]] Identifier *Clone(ArenaAllocator *allocator, AstNode *parent) override; @@ -222,7 +219,42 @@ public: v->Accept(this); } + Identifier *Construct(ArenaAllocator *allocator) override + { + return allocator->New(allocator); + } + + void CopyTo(AstNode *other) const override + { + auto otherImpl = other->AsIdentifier(); + + otherImpl->name_ = name_; + otherImpl->flags_ = flags_; + otherImpl->decorators_ = decorators_; + + AnnotatedExpression::CopyTo(other); + }; + private: + IdentifierFlags IdFlags() const + { + return GetHistoryNodeAs()->flags_; + } + + void AddIdFlags(IdentifierFlags const flags) noexcept + { + if (!All(IdFlags(), flags)) { + GetOrCreateHistoryNodeAs()->flags_ |= flags; + } + } + + void ClearIdFlags(IdentifierFlags const flags) noexcept + { + if (Any(IdFlags(), flags)) { + GetOrCreateHistoryNodeAs()->flags_ &= ~flags; + } + } + bool CheckDeclarationsPart2(const ir::AstNode *parent, ScriptExtension ext) const; bool CheckDeclarationsPart1(const ir::AstNode *parent, ScriptExtension ext) const; bool CheckNotDeclarations(const ir::AstNode *parent, ScriptExtension ext) const; diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 7f7e05007f..45e893cb51 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -81,11 +81,6 @@ public: return decorators_; } - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); - } - void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { decorators_ = std::move(decorators); diff --git a/ets2panda/ir/module/importDeclaration.cpp b/ets2panda/ir/module/importDeclaration.cpp index d48246d887..161970f5f5 100644 --- a/ets2panda/ir/module/importDeclaration.cpp +++ b/ets2panda/ir/module/importDeclaration.cpp @@ -24,46 +24,55 @@ namespace ark::es2panda::ir { +void ImportDeclaration::SetSource(StringLiteral *source) +{ + this->GetOrCreateHistoryNodeAs()->source_ = source; +} + void ImportDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - if (auto *transformedNode = cb(source_); source_ != transformedNode) { - source_->SetTransformedNode(transformationName, transformedNode); - source_ = transformedNode->AsStringLiteral(); + auto const source = Source(); + if (auto *transformedNode = cb(source); source != transformedNode) { + source->SetTransformedNode(transformationName, transformedNode); + SetSource(transformedNode->AsStringLiteral()); } - for (auto *&it : VectorIterationGuard(specifiers_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode; + auto const &specifiers = Specifiers(); + for (size_t index = 0; index < specifiers.size(); ++index) { + if (auto *transformedNode = cb(specifiers[index]); specifiers[index] != transformedNode) { + specifiers[index]->SetTransformedNode(transformationName, transformedNode); + SetValueSpecifiers(transformedNode, index); } } } void ImportDeclaration::Iterate(const NodeTraverser &cb) const { - cb(source_); + auto source = GetHistoryNodeAs()->source_; + cb(source); - for (auto *it : VectorIterationGuard(specifiers_)) { + for (auto *it : VectorIterationGuard(Specifiers())) { cb(it); } } void ImportDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ImportDeclaration"}, {"source", source_}, {"specifiers", specifiers_}}); + dumper->Add({{"type", "ImportDeclaration"}, {"source", Source()}, {"specifiers", Specifiers()}}); } void ImportDeclaration::Dump(ir::SrcDumper *dumper) const { dumper->Add("import "); - if (specifiers_.size() == 1 && - (specifiers_[0]->IsImportNamespaceSpecifier() || specifiers_[0]->IsImportDefaultSpecifier())) { - specifiers_[0]->Dump(dumper); + auto const &specifiers = Specifiers(); + if (specifiers.size() == 1 && + (specifiers[0]->IsImportNamespaceSpecifier() || specifiers[0]->IsImportDefaultSpecifier())) { + specifiers[0]->Dump(dumper); } else { dumper->Add("{ "); - for (auto specifier : specifiers_) { + for (auto specifier : specifiers) { specifier->Dump(dumper); - if (specifier != specifiers_.back()) { + if (specifier != specifiers.back()) { dumper->Add(", "); } } @@ -71,7 +80,7 @@ void ImportDeclaration::Dump(ir::SrcDumper *dumper) const } dumper->Add(" from "); - source_->Dump(dumper); + Source()->Dump(dumper); dumper->Add(";"); dumper->Endl(); } @@ -104,7 +113,7 @@ ImportDeclaration *ImportDeclaration::Construct(ArenaAllocator *allocator) void ImportDeclaration::CopyTo(AstNode *other) const { - auto otherImpl = other->AsImportDeclaration(); + auto otherImpl = static_cast(other); otherImpl->source_ = source_; otherImpl->specifiers_ = specifiers_; @@ -113,4 +122,30 @@ void ImportDeclaration::CopyTo(AstNode *other) const Statement::CopyTo(other); } +void ImportDeclaration::EmplaceSpecifiers(AstNode *source) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->specifiers_.emplace_back(source); +} + +void ImportDeclaration::ClearSpecifiers() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->specifiers_.clear(); +} + +void ImportDeclaration::SetValueSpecifiers(AstNode *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->specifiers_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; +} + +[[nodiscard]] ArenaVector &ImportDeclaration::SpecifiersForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->specifiers_; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/module/importDeclaration.h b/ets2panda/ir/module/importDeclaration.h index c3f28438e2..2da6374989 100644 --- a/ets2panda/ir/module/importDeclaration.h +++ b/ets2panda/ir/module/importDeclaration.h @@ -25,6 +25,11 @@ enum class ImportKinds { ALL, TYPES }; class ImportDeclaration : public Statement { public: + void EmplaceSpecifiers(AstNode *source); + void ClearSpecifiers(); + void SetValueSpecifiers(AstNode *source, size_t index); + [[nodiscard]] ArenaVector &SpecifiersForUpdate(); + explicit ImportDeclaration(StringLiteral *source, ArenaVector &&specifiers, const ImportKinds importKinds = ImportKinds::ALL) : Statement(AstNodeType::IMPORT_DECLARATION), @@ -32,26 +37,36 @@ public: specifiers_(std::move(specifiers)), importKinds_(importKinds) { + InitHistory(); } - const StringLiteral *Source() const + explicit ImportDeclaration(StringLiteral *source, ArenaVector &&specifiers, + const ImportKinds importKinds, AstNodeHistory *history) + : Statement(AstNodeType::IMPORT_DECLARATION), + source_(source), + specifiers_(std::move(specifiers)), + importKinds_(importKinds) { - return source_; + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } - StringLiteral *Source() + const StringLiteral *Source() const { - return source_; + return GetHistoryNodeAs()->source_; } - const ArenaVector &Specifiers() const + StringLiteral *Source() { - return specifiers_; + return GetHistoryNodeAs()->source_; } - ArenaVector &Specifiers() + const ArenaVector &Specifiers() const { - return specifiers_; + return GetHistoryNodeAs()->specifiers_; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -70,7 +85,7 @@ public: bool IsTypeKind() const { - return importKinds_ == ImportKinds::TYPES; + return GetHistoryNodeAs()->importKinds_ == ImportKinds::TYPES; } ImportDeclaration *Construct(ArenaAllocator *allocator) override; @@ -78,6 +93,8 @@ public: private: friend class SizeOfNodeTest; + void SetSource(StringLiteral *source); + StringLiteral *source_; ArenaVector specifiers_; ImportKinds importKinds_; diff --git a/ets2panda/ir/opaqueTypeNode.cpp b/ets2panda/ir/opaqueTypeNode.cpp index b76b69d868..4a74b38975 100644 --- a/ets2panda/ir/opaqueTypeNode.cpp +++ b/ets2panda/ir/opaqueTypeNode.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void OpaqueTypeNode::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void OpaqueTypeNode::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/statements/annotationDeclaration.cpp b/ets2panda/ir/statements/annotationDeclaration.cpp index aab66f2db2..f353444a46 100644 --- a/ets2panda/ir/statements/annotationDeclaration.cpp +++ b/ets2panda/ir/statements/annotationDeclaration.cpp @@ -21,36 +21,77 @@ #include "ir/srcDump.h" namespace ark::es2panda::ir { + +void AnnotationDeclaration::SetInternalName(util::StringView internalName) +{ + this->GetOrCreateHistoryNodeAs()->internalName_ = internalName; +} + +void AnnotationDeclaration::SetExpr(Expression *expr) +{ + this->GetOrCreateHistoryNodeAs()->expr_ = expr; +} + +void AnnotationDeclaration::EmplaceProperties(AstNode *properties) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->properties_.emplace_back(properties); +} + +void AnnotationDeclaration::ClearProperties() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->properties_.clear(); +} + +void AnnotationDeclaration::SetValueProperties(AstNode *properties, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->properties_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = properties; +} + +[[nodiscard]] const ArenaVector &AnnotationDeclaration::Properties() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->properties_; +} + +[[nodiscard]] ArenaVector &AnnotationDeclaration::PropertiesForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->properties_; +} + void AnnotationDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(properties_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode; + auto const &properties = Properties(); + for (size_t ix = 0; ix < properties.size(); ix++) { + if (auto *transformedNode = cb(properties[ix]); properties[ix] != transformedNode) { + properties[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueProperties(transformedNode->AsTSClassImplements(), ix); } } - if (expr_ != nullptr) { - if (auto *transformedNode = cb(expr_); expr_ != transformedNode) { - expr_->SetTransformedNode(transformationName, transformedNode); - expr_ = transformedNode->AsIdentifier(); + auto const expr = Expr(); + if (expr != nullptr) { + if (auto *transformedNode = cb(expr); expr != transformedNode) { + expr->SetTransformedNode(transformationName, transformedNode); + SetExpr(transformedNode->AsIdentifier()); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void AnnotationDeclaration::Iterate(const NodeTraverser &cb) const { - if (expr_ != nullptr) { - cb(expr_); + auto const expr = GetHistoryNodeAs()->expr_; + if (expr != nullptr) { + cb(expr); } - for (auto *it : VectorIterationGuard(properties_)) { + for (auto *it : VectorIterationGuard(Properties())) { cb(it); } @@ -61,24 +102,25 @@ void AnnotationDeclaration::Iterate(const NodeTraverser &cb) const void AnnotationDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"Expr", expr_}, {"properties", properties_}, {"annotations", AstDumper::Optional(Annotations())}}); + dumper->Add({{"Expr", Expr()}, {"properties", Properties()}, {"annotations", AstDumper::Optional(Annotations())}}); } void AnnotationDeclaration::Dump(ir::SrcDumper *dumper) const { // re-understand for (auto *anno : Annotations()) { anno->Dump(dumper); } - ES2PANDA_ASSERT(expr_ != nullptr); + ES2PANDA_ASSERT(Expr() != nullptr); dumper->Add("@interface "); - expr_->Dump(dumper); + Expr()->Dump(dumper); dumper->Add(" {"); - if (!properties_.empty()) { + auto const properties = Properties(); + if (!properties.empty()) { dumper->IncrIndent(); dumper->Endl(); - for (auto elem : properties_) { + for (auto elem : properties) { elem->Dump(dumper); - if (elem == properties_.back()) { + if (elem == properties.back()) { dumper->DecrIndent(); } } @@ -108,14 +150,13 @@ checker::VerifiedType AnnotationDeclaration::Check(checker::ETSChecker *checker) Identifier *AnnotationDeclaration::GetBaseName() const { - if (expr_->IsIdentifier()) { - return expr_->AsIdentifier(); + if (Expr()->IsIdentifier()) { + return GetHistoryNodeAs()->expr_->AsIdentifier(); } - auto *part = expr_->AsETSTypeReference()->Part(); + auto *part = Expr()->AsETSTypeReference()->Part(); return part->Name()->AsTSQualifiedName()->Right(); } - -AstNode *AnnotationDeclaration::Construct(ArenaAllocator *allocator) +AnnotationDeclaration *AnnotationDeclaration::Construct(ArenaAllocator *allocator) { return allocator->New(nullptr, allocator); } diff --git a/ets2panda/ir/statements/annotationDeclaration.h b/ets2panda/ir/statements/annotationDeclaration.h index f55f591444..c3d3b8f2f2 100644 --- a/ets2panda/ir/statements/annotationDeclaration.h +++ b/ets2panda/ir/statements/annotationDeclaration.h @@ -42,42 +42,39 @@ public: expr_(expr), properties_(allocator->Adapter()) { + InitHistory(); } explicit AnnotationDeclaration(Expression *expr, ArenaVector &&properties, ArenaAllocator *allocator) : AnnotationAllowed(AstNodeType::ANNOTATION_DECLARATION, allocator), expr_(expr), properties_(std::move(properties)) { + InitHistory(); } const util::StringView &InternalName() const { - return internalName_; + return GetHistoryNodeAs()->internalName_; } - void SetInternalName(util::StringView internalName) - { - internalName_ = internalName; - } + void SetInternalName(util::StringView internalName); [[nodiscard]] const Expression *Expr() const noexcept { - return expr_; + return GetHistoryNodeAs()->expr_; } [[nodiscard]] Expression *Expr() noexcept { - return expr_; + return GetHistoryNodeAs()->expr_; } - [[nodiscard]] ArenaVector &Properties() noexcept - { - return properties_; - } + [[nodiscard]] const ArenaVector &Properties(); + [[nodiscard]] ArenaVector &PropertiesForUpdate(); [[nodiscard]] const ArenaVector &Properties() const noexcept { - return properties_; + return GetHistoryNodeAs()->properties_; } [[nodiscard]] const ArenaVector *PropertiesPtr() const @@ -87,37 +84,38 @@ public: void AddProperties(ArenaVector &&properties) { - properties_ = std::move(properties); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->properties_ = std::move(properties); } [[nodiscard]] bool IsSourceRetention() const noexcept { - return (policy_ & RetentionPolicy::SOURCE) != 0; + return (Policy() & RetentionPolicy::SOURCE) != 0; } [[nodiscard]] bool IsBytecodeRetention() const noexcept { - return (policy_ & RetentionPolicy::BYTECODE) != 0; + return (Policy() & RetentionPolicy::BYTECODE) != 0; } [[nodiscard]] bool IsRuntimeRetention() const noexcept { - return (policy_ & RetentionPolicy::RUNTIME) != 0; + return (Policy() & RetentionPolicy::RUNTIME) != 0; } void SetSourceRetention() noexcept { - policy_ = RetentionPolicy::SOURCE; + GetOrCreateHistoryNodeAs()->policy_ = RetentionPolicy::SOURCE; } void SetBytecodeRetention() noexcept { - policy_ = RetentionPolicy::BYTECODE; + GetOrCreateHistoryNodeAs()->policy_ = RetentionPolicy::BYTECODE; } void SetRuntimeRetention() noexcept { - policy_ = RetentionPolicy::RUNTIME; + GetOrCreateHistoryNodeAs()->policy_ = RetentionPolicy::RUNTIME; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -141,28 +139,38 @@ public: [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } void SetScope(varbinder::LocalScope *scope) { ES2PANDA_ASSERT(scope_ == nullptr); - scope_ = scope; + GetOrCreateHistoryNodeAs()->scope_ = scope; } void ClearScope() noexcept override { - scope_ = nullptr; + GetOrCreateHistoryNodeAs()->scope_ = nullptr; } Identifier *GetBaseName() const; -protected: - AstNode *Construct(ArenaAllocator *allocator) override; + void EmplaceProperties(AstNode *properties); + void ClearProperties(); + void SetValueProperties(AstNode *properties, size_t index); + + AnnotationDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; private: friend class SizeOfNodeTest; + RetentionPolicy Policy() const + { + return GetHistoryNodeAs()->policy_; + } + + void SetExpr(Expression *expr); + util::StringView internalName_ {}; varbinder::LocalScope *scope_ {}; Expression *expr_; diff --git a/ets2panda/ir/statements/blockStatement.cpp b/ets2panda/ir/statements/blockStatement.cpp index 63cc1287f0..abbe7d12b0 100644 --- a/ets2panda/ir/statements/blockStatement.cpp +++ b/ets2panda/ir/statements/blockStatement.cpp @@ -28,11 +28,13 @@ namespace ark::es2panda::ir { void BlockStatement::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { // This will survive pushing element to the back of statements_ in the process - // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < statements_.size(); ix++) { - if (auto *transformedNode = cb(statements_[ix]); statements_[ix] != transformedNode) { - statements_[ix]->SetTransformedNode(transformationName, transformedNode); - statements_[ix] = transformedNode->AsStatement(); + auto const &constStatements = Statements(); + for (size_t index = 0; index < constStatements.size(); index++) { + auto statement = constStatements[index]; + if (auto *transformedNode = cb(statement); statement != transformedNode) { + statement->SetTransformedNode(transformationName, transformedNode); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + statements[index] = transformedNode->AsStatement(); } } } @@ -41,7 +43,7 @@ AstNode *BlockStatement::Clone(ArenaAllocator *const allocator, AstNode *const p { ArenaVector statements(allocator->Adapter()); - for (auto *statement : this->statements_) { + for (auto *statement : Statements()) { statements.push_back(statement->Clone(allocator, parent)->AsStatement()); } @@ -54,35 +56,37 @@ AstNode *BlockStatement::Clone(ArenaAllocator *const allocator, AstNode *const p void BlockStatement::Iterate(const NodeTraverser &cb) const { // This will survive pushing element to the back of statements_ in the process + auto const &statements = Statements(); // NOLINTNEXTLINE(modernize-loop-convert) - for (size_t ix = 0; ix < statements_.size(); ix++) { - cb(statements_[ix]); + for (size_t ix = 0; ix < statements.size(); ix++) { + cb(statements[ix]); } } void BlockStatement::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", IsProgram() ? "Program" : "BlockStatement"}, {"statements", statements_}}); + dumper->Add({{"type", IsProgram() ? "Program" : "BlockStatement"}, {"statements", Statements()}}); } void BlockStatement::Dump(ir::SrcDumper *dumper) const { + auto const &statements = Statements(); // NOTE(nsizov): trailing blocks if (Parent() != nullptr && (Parent()->IsBlockStatement() || Parent()->IsCallExpression())) { dumper->Add("{"); - if (!statements_.empty()) { + if (!statements.empty()) { dumper->IncrIndent(); dumper->Endl(); } } - for (auto statement : statements_) { + for (auto statement : statements) { statement->Dump(dumper); - if (statement != statements_.back()) { + if (statement != statements.back()) { dumper->Endl(); } } if (Parent() != nullptr && (Parent()->IsBlockStatement() || Parent()->IsCallExpression())) { - if (!statements_.empty()) { + if (!statements.empty()) { dumper->DecrIndent(); dumper->Endl(); } @@ -118,7 +122,7 @@ BlockStatement *BlockStatement::Construct(ArenaAllocator *allocator) void BlockStatement::CopyTo(AstNode *other) const { - auto otherImpl = other->AsBlockStatement(); + auto otherImpl = static_cast(other); otherImpl->scope_ = scope_; otherImpl->statements_ = statements_; diff --git a/ets2panda/ir/statements/blockStatement.h b/ets2panda/ir/statements/blockStatement.h index 81745d7f37..e47670c061 100644 --- a/ets2panda/ir/statements/blockStatement.h +++ b/ets2panda/ir/statements/blockStatement.h @@ -31,11 +31,9 @@ public: statements_(std::move(statementList)), trailingBlocks_(allocator->Adapter()) { + InitHistory(); } - // NOTE (somas): this friend relationship can be removed once there are getters for private fields - friend class checker::ETSAnalyzer; - [[nodiscard]] bool IsScopeBearer() const noexcept override { return true; @@ -43,55 +41,91 @@ public: [[nodiscard]] varbinder::Scope *Scope() const noexcept override { - return scope_; + return AstNode::GetHistoryNodeAs()->scope_; } void SetScope(varbinder::Scope *scope) noexcept { - scope_ = scope; + if (Scope() != scope) { + AstNode::GetOrCreateHistoryNodeAs()->scope_ = scope; + } } void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } - const ArenaVector &Statements() const + ArenaVector &StatementsForUpdates() { - return statements_; + return AstNode::GetOrCreateHistoryNodeAs()->statements_; } - ArenaVector &Statements() + const ArenaVector &Statements() { - return statements_; + return AstNode::GetHistoryNodeAs()->statements_; + } + + const ArenaVector &Statements() const + { + return AstNode::GetHistoryNodeAs()->statements_; } void SetStatements(ArenaVector &&statementList) { - statements_ = std::move(statementList); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + statements = std::move(statementList); - for (auto *statement : statements_) { + for (auto *statement : Statements()) { statement->SetParent(this); } } - void AddStatement(Statement *stmt) + void AddStatements(const ArenaVector &statementList) { - stmt->SetParent(this); - statements_.emplace_back(stmt); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + + for (auto statement : statementList) { + statement->SetParent(this); + statements.emplace_back(statement); + } } - void AddStatements(ArenaVector &stmts) + void ClearStatements() { - for (auto *stmt : stmts) { - stmt->SetParent(this); - } - statements_.insert(statements_.end(), stmts.begin(), stmts.end()); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + statements.clear(); + } + + void AddStatement(Statement *statement) + { + statement->SetParent(this); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + statements.emplace_back(statement); + } + + void AddStatement(std::size_t idx, Statement *statement) + { + statement->SetParent(this); + auto &statements = AstNode::GetOrCreateHistoryNodeAs()->statements_; + statements.emplace(std::next(statements.begin() + idx), statement); } void AddTrailingBlock(AstNode *stmt, BlockStatement *trailingBlock) { - trailingBlocks_.emplace(stmt, trailingBlock); + AstNode::GetOrCreateHistoryNodeAs()->trailingBlocks_.emplace(stmt, trailingBlock); + } + + BlockStatement *SearchStatementInTrailingBlock(Statement *item) + { + auto &trailingBlock = AstNode::GetHistoryNodeAs()->trailingBlocks_; + auto nowNode = item->GetHistoryNode(); + for (auto &it : trailingBlock) { + if (it.first->GetHistoryNode() == nowNode) { + return it.second; + } + } + return nullptr; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; diff --git a/ets2panda/ir/statements/classDeclaration.cpp b/ets2panda/ir/statements/classDeclaration.cpp index d459bc5e20..398e74f231 100644 --- a/ets2panda/ir/statements/classDeclaration.cpp +++ b/ets2panda/ir/statements/classDeclaration.cpp @@ -24,14 +24,46 @@ namespace ark::es2panda::ir { +void ClassDeclaration::SetDefinition(ClassDefinition *def) +{ + this->GetOrCreateHistoryNodeAs()->def_ = def; +} + ClassDeclaration *ClassDeclaration::Construct(ArenaAllocator *allocator) { return allocator->New(nullptr, allocator); } +void ClassDeclaration::EmplaceDecorators(Decorator *decorators) +{ + this->GetOrCreateHistoryNodeAs()->decorators_.emplace_back(decorators); +} + +void ClassDeclaration::ClearDecorators() +{ + this->GetOrCreateHistoryNodeAs()->decorators_.clear(); +} + +void ClassDeclaration::SetValueDecorators(Decorator *decorators, size_t index) +{ + auto &arenaVector = this->GetOrCreateHistoryNodeAs()->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = decorators; +} + +[[nodiscard]] const ArenaVector &ClassDeclaration::Decorators() +{ + return this->GetHistoryNodeAs()->decorators_; +} + +[[nodiscard]] ArenaVector &ClassDeclaration::DecoratorsForUpdate() +{ + return this->GetOrCreateHistoryNodeAs()->decorators_; +} + void ClassDeclaration::CopyTo(AstNode *other) const { - auto otherImpl = other->AsClassDeclaration(); + auto otherImpl = reinterpret_cast(other); otherImpl->def_ = def_; otherImpl->decorators_ = decorators_; @@ -41,40 +73,45 @@ void ClassDeclaration::CopyTo(AstNode *other) const void ClassDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - if (auto *transformedNode = cb(def_); def_ != transformedNode) { - def_->SetTransformedNode(transformationName, transformedNode); - def_ = transformedNode->AsClassDefinition(); + auto const def = Definition(); + if (auto *transformedNode = cb(def); def != transformedNode) { + def->SetTransformedNode(transformationName, transformedNode); + SetDefinition(transformedNode->AsClassDefinition()); } } void ClassDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } - cb(def_); + auto def = GetHistoryNodeAs()->def_; + cb(def); } void ClassDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "ClassDeclaration"}, {"definition", def_}, {"decorators", AstDumper::Optional(decorators_)}}); + dumper->Add({{"type", "ClassDeclaration"}, + {"definition", Definition()}, + {"decorators", AstDumper::Optional(Decorators())}}); } void ClassDeclaration::Dump(ir::SrcDumper *dumper) const { - if (def_ != nullptr) { - def_->Dump(dumper); + if (Definition() != nullptr) { + Definition()->Dump(dumper); } // NOTE(nsizov): support decorators when supported in ArkTS - ES2PANDA_ASSERT(decorators_.empty()); + ES2PANDA_ASSERT(Decorators().empty()); } void ClassDeclaration::Compile(compiler::PandaGen *pg) const diff --git a/ets2panda/ir/statements/classDeclaration.h b/ets2panda/ir/statements/classDeclaration.h index 72a5afe51f..5ea6d0e8d0 100644 --- a/ets2panda/ir/statements/classDeclaration.h +++ b/ets2panda/ir/statements/classDeclaration.h @@ -24,31 +24,38 @@ public: explicit ClassDeclaration(ClassDefinition *def, ArenaAllocator *allocator) : Statement(AstNodeType::CLASS_DECLARATION), def_(def), decorators_(allocator->Adapter()) { + InitHistory(); } - ClassDefinition *Definition() + explicit ClassDeclaration(ClassDefinition *def, ArenaAllocator *allocator, AstNodeHistory *history) + : Statement(AstNodeType::CLASS_DECLARATION), def_(def), decorators_(allocator->Adapter()) { - return def_; + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } - const ClassDefinition *Definition() const + ClassDefinition *Definition() { - return def_; + return GetHistoryNodeAs()->def_; } - const ArenaVector &Decorators() const + const ClassDefinition *Definition() const { - return decorators_; + return GetHistoryNodeAs()->def_; } - const ArenaVector *DecoratorsPtr() const override + const ArenaVector &Decorators() const { - return &Decorators(); + return GetHistoryNodeAs()->decorators_; } void AddDecorators(ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = GetOrCreateHistoryNodeAs(); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -71,10 +78,19 @@ public: v->Accept(this); } + void EmplaceDecorators(Decorator *decorators); + void ClearDecorators(); + void SetValueDecorators(Decorator *decorators, size_t index); + const ArenaVector &Decorators(); + ArenaVector &DecoratorsForUpdate(); + + void SetDefinition(ClassDefinition *def); + protected: explicit ClassDeclaration(AstNodeType type, ClassDefinition *const def, ArenaAllocator *const allocator) : Statement(type), def_(def), decorators_(allocator->Adapter()) { + InitHistory(); } ClassDeclaration *Construct(ArenaAllocator *allocator) override; diff --git a/ets2panda/ir/statements/functionDeclaration.cpp b/ets2panda/ir/statements/functionDeclaration.cpp index 21fb0d5f85..be0f1341c4 100644 --- a/ets2panda/ir/statements/functionDeclaration.cpp +++ b/ets2panda/ir/statements/functionDeclaration.cpp @@ -23,31 +23,34 @@ #include "compiler/core/pandagen.h" namespace ark::es2panda::ir { + +void FunctionDeclaration::SetFunction(ScriptFunction *func) +{ + this->GetOrCreateHistoryNodeAs()->func_ = func; +} + void FunctionDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); - if (auto *transformedNode = cb(func_); func_ != transformedNode) { - func_->SetTransformedNode(transformationName, transformedNode); - func_ = transformedNode->AsScriptFunction(); + auto const func = Function(); + if (auto *transformedNode = cb(func); func != transformedNode) { + func->SetTransformedNode(transformationName, transformedNode); + SetFunction(transformedNode->AsScriptFunction()); } } void FunctionDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } @@ -55,15 +58,16 @@ void FunctionDeclaration::Iterate(const NodeTraverser &cb) const cb(it); } - cb(func_); + auto func = GetHistoryNode()->AsFunctionDeclaration()->func_; + cb(func); } void FunctionDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", func_->IsOverload() ? "TSDeclareFunction" : "FunctionDeclaration"}, - {"decorators", AstDumper::Optional(decorators_)}, + dumper->Add({{"type", Function()->IsOverload() ? "TSDeclareFunction" : "FunctionDeclaration"}, + {"decorators", AstDumper::Optional(Decorators())}, {"annotations", AstDumper::Optional(Annotations())}, - {"function", func_}}); + {"function", Function()}}); } void FunctionDeclaration::Dump(ir::SrcDumper *dumper) const @@ -71,19 +75,20 @@ void FunctionDeclaration::Dump(ir::SrcDumper *dumper) const for (auto *anno : Annotations()) { anno->Dump(dumper); } - if (func_->IsNative()) { + auto func = Function(); + if (func->IsNative()) { dumper->Add("native "); } - if (func_->IsDeclare()) { + if (func->IsDeclare()) { dumper->Add("declare "); } - if (func_->IsAsyncFunc()) { + if (func->IsAsyncFunc()) { dumper->Add("async "); } dumper->Add("function "); - func_->Id()->Dump(dumper); - func_->Dump(dumper); + func->Id()->Dump(dumper); + func->Dump(dumper); } void FunctionDeclaration::Compile(compiler::PandaGen *pg) const @@ -122,4 +127,30 @@ void FunctionDeclaration::CopyTo(AstNode *other) const JsDocAllowed>::CopyTo(other); } +void FunctionDeclaration::EmplaceDecorators(Decorator *decorators) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(decorators); +} + +void FunctionDeclaration::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void FunctionDeclaration::SetValueDecorators(Decorator *decorators, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = decorators; +} + +[[nodiscard]] ArenaVector &FunctionDeclaration::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/statements/functionDeclaration.h b/ets2panda/ir/statements/functionDeclaration.h index 55a3443f02..25a69766e6 100644 --- a/ets2panda/ir/statements/functionDeclaration.h +++ b/ets2panda/ir/statements/functionDeclaration.h @@ -36,7 +36,10 @@ public: func_(func), isAnonymous_(isAnonymous) { - flags_ = func->Modifiers(); + InitHistory(); + if (func != nullptr) { + flags_ = func->Modifiers(); + } } explicit FunctionDeclaration(ArenaAllocator *allocator, ScriptFunction *func, bool isAnonymous = false) @@ -45,27 +48,45 @@ public: func_(func), isAnonymous_(isAnonymous) { - flags_ = func->Modifiers(); + InitHistory(); + if (func != nullptr) { + flags_ = func->Modifiers(); + } + } + + explicit FunctionDeclaration(ArenaAllocator *allocator, ScriptFunction *func, bool isAnonymous, + AstNodeHistory *history) + : JsDocAllowed>(AstNodeType::FUNCTION_DECLARATION, allocator), + decorators_(allocator->Adapter()), + func_(func), + isAnonymous_(isAnonymous) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } ScriptFunction *Function() { - return func_; + return GetHistoryNodeAs()->func_; } bool IsAnonymous() const { - return isAnonymous_; + return GetHistoryNodeAs()->isAnonymous_; } const ScriptFunction *Function() const { - return func_; + return GetHistoryNodeAs()->func_; } void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = this->GetOrCreateHistoryNode()->AsFunctionDeclaration(); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -90,8 +111,19 @@ public: FunctionDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; + [[nodiscard]] const ArenaVector &Decorators() const + { + return GetHistoryNodeAs()->decorators_; + }; + private: friend class SizeOfNodeTest; + void SetFunction(ScriptFunction *func); + void EmplaceDecorators(Decorator *decorators); + void ClearDecorators(); + void SetValueDecorators(Decorator *decorators, size_t index); + [[nodiscard]] ArenaVector &DecoratorsForUpdate(); + ArenaVector decorators_; ScriptFunction *func_; bool isAnonymous_; diff --git a/ets2panda/ir/statements/variableDeclaration.cpp b/ets2panda/ir/statements/variableDeclaration.cpp index 56934876cf..adbe853c54 100644 --- a/ets2panda/ir/statements/variableDeclaration.cpp +++ b/ets2panda/ir/statements/variableDeclaration.cpp @@ -22,33 +22,101 @@ #include "utils/arena_containers.h" namespace ark::es2panda::ir { + +void VariableDeclaration::EmplaceDecorators(Decorator *source) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(source); +} + +void VariableDeclaration::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void VariableDeclaration::SetValueDecorators(Decorator *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; +} + +[[nodiscard]] const ArenaVector &VariableDeclaration::Decorators() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->decorators_; +} + +[[nodiscard]] ArenaVector &VariableDeclaration::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + +void VariableDeclaration::EmplaceDeclarators(VariableDeclarator *source) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->declarators_.emplace_back(source); +} + +void VariableDeclaration::ClearDeclarators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->declarators_.clear(); +} + +void VariableDeclaration::SetValueDeclarators(VariableDeclarator *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->declarators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; +} + +[[nodiscard]] const ArenaVector &VariableDeclaration::Declarators() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->declarators_; +} + +[[nodiscard]] ArenaVector &VariableDeclaration::DeclaratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->declarators_; +} + void VariableDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t index = 0; index < decorators.size(); ++index) { + if (auto *transformedNode = cb(decorators[index]); decorators[index] != transformedNode) { + decorators[index]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), index); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + auto const &annotations = Annotations(); + for (size_t index = 0; index < annotations.size(); ++index) { + if (auto *transformedNode = cb(annotations[index]); annotations[index] != transformedNode) { + annotations[index]->SetTransformedNode(transformationName, transformedNode); + SetValueAnnotations(transformedNode->AsAnnotationUsage(), index); } } - for (auto *&it : VectorIterationGuard(declarators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsVariableDeclarator(); + auto const &declarators = Declarators(); + for (size_t index = 0; index < declarators.size(); ++index) { + if (auto *transformedNode = cb(declarators[index]); declarators[index] != transformedNode) { + declarators[index]->SetTransformedNode(transformationName, transformedNode); + SetValueDeclarators(transformedNode->AsVariableDeclarator(), index); } } } void VariableDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } @@ -56,7 +124,7 @@ void VariableDeclaration::Iterate(const NodeTraverser &cb) const cb(it); } - for (auto *it : VectorIterationGuard(declarators_)) { + for (auto *it : VectorIterationGuard(Declarators())) { cb(it); } } @@ -65,7 +133,7 @@ void VariableDeclaration::Dump(ir::AstDumper *dumper) const { const char *kind = nullptr; - switch (kind_) { + switch (Kind()) { case VariableDeclarationKind::CONST: { kind = "const"; break; @@ -84,9 +152,9 @@ void VariableDeclaration::Dump(ir::AstDumper *dumper) const } dumper->Add({{"type", "VariableDeclaration"}, - {"declarations", declarators_}, + {"declarations", Declarators()}, {"kind", kind}, - {"decorators", AstDumper::Optional(decorators_)}, + {"decorators", AstDumper::Optional(Decorators())}, {"annotations", AstDumper::Optional(Annotations())}, {"declare", AstDumper::Optional(IsDeclare())}}); } @@ -101,7 +169,7 @@ void VariableDeclaration::Dump(ir::SrcDumper *dumper) const dumper->Add("declare "); } - switch (kind_) { + switch (Kind()) { case VariableDeclarationKind::CONST: dumper->Add("const "); break; @@ -115,15 +183,16 @@ void VariableDeclaration::Dump(ir::SrcDumper *dumper) const ES2PANDA_UNREACHABLE(); } - for (auto declarator : declarators_) { + for (auto declarator : Declarators()) { declarator->Dump(dumper); - if (declarator != declarators_.back()) { + if (declarator != Declarators().back()) { dumper->Add(", "); } } - if ((parent_ != nullptr) && - (parent_->IsBlockStatement() || parent_->IsBlockExpression() || parent_->IsSwitchCaseStatement())) { + auto const parent = Parent(); + if ((parent != nullptr) && + (parent->IsBlockStatement() || parent->IsBlockExpression() || parent->IsSwitchCaseStatement())) { dumper->Add(";"); } } @@ -145,6 +214,33 @@ VariableDeclaration::VariableDeclaration([[maybe_unused]] Tag const tag, Variabl declarators_.emplace_back(d->Clone(allocator, nullptr)->AsVariableDeclarator()); declarators_.back()->SetParent(this); } + + InitHistory(); +} + +VariableDeclaration::VariableDeclaration([[maybe_unused]] Tag const tag, VariableDeclaration const &other, + ArenaAllocator *const allocator, AstNodeHistory *history) + : JsDocAllowed>( + static_cast> const &>(other)), + kind_(other.kind_), + decorators_(allocator->Adapter()), + declarators_(allocator->Adapter()) +{ + for (auto const &d : other.decorators_) { + decorators_.emplace_back(d->Clone(allocator, nullptr)); + decorators_.back()->SetParent(this); + } + + for (auto const &d : other.declarators_) { + declarators_.emplace_back(d->Clone(allocator, nullptr)->AsVariableDeclarator()); + declarators_.back()->SetParent(this); + } + + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } VariableDeclaration *VariableDeclaration::Clone(ArenaAllocator *const allocator, AstNode *const parent) @@ -153,7 +249,7 @@ VariableDeclaration *VariableDeclaration::Clone(ArenaAllocator *const allocator, if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(Range()); return clone; } diff --git a/ets2panda/ir/statements/variableDeclaration.h b/ets2panda/ir/statements/variableDeclaration.h index 7b3f8a5804..cb3703b27d 100644 --- a/ets2panda/ir/statements/variableDeclaration.h +++ b/ets2panda/ir/statements/variableDeclaration.h @@ -40,28 +40,54 @@ public: decorators_(allocator->Adapter()), declarators_(std::move(declarators)) { + InitHistory(); + } + + explicit VariableDeclaration(VariableDeclarationKind kind, ArenaAllocator *allocator, + ArenaVector &&declarators, AstNodeHistory *history) + : JsDocAllowed>(AstNodeType::VARIABLE_DECLARATION, allocator), + kind_(kind), + decorators_(allocator->Adapter()), + declarators_(std::move(declarators)) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } explicit VariableDeclaration(Tag tag, VariableDeclaration const &other, ArenaAllocator *allocator); + explicit VariableDeclaration(Tag const tag, VariableDeclaration const &other, ArenaAllocator *const allocator, + AstNodeHistory *history); + const ArenaVector &Declarators() const { - return declarators_; + return GetHistoryNodeAs()->declarators_; } + [[nodiscard]] const ArenaVector &Declarators(); + + [[nodiscard]] ArenaVector &DeclaratorsForUpdate(); + VariableDeclarationKind Kind() const { - return kind_; + return GetHistoryNodeAs()->kind_; } const ArenaVector &Decorators() const { - return decorators_; + return GetHistoryNodeAs()->decorators_; } + [[nodiscard]] const ArenaVector &Decorators(); + + [[nodiscard]] ArenaVector &DecoratorsForUpdate(); + VariableDeclarator *GetDeclaratorByName(util::StringView name) const { - for (VariableDeclarator *declarator : declarators_) { + for (VariableDeclarator *declarator : Declarators()) { if (declarator->Id()->AsIdentifier()->Name().Compare(name) == 0) { return declarator; } @@ -69,14 +95,10 @@ public: return nullptr; } - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); - } - void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -105,6 +127,13 @@ public: private: friend class SizeOfNodeTest; + void SetValueDecorators(Decorator *source, size_t index); + void SetValueDeclarators(VariableDeclarator *source, size_t index); + void EmplaceDecorators(Decorator *source); + void ClearDecorators(); + void EmplaceDeclarators(VariableDeclarator *source); + void ClearDeclarators(); + VariableDeclarationKind kind_; ArenaVector decorators_; ArenaVector declarators_; diff --git a/ets2panda/ir/ts/tsAnyKeyword.cpp b/ets2panda/ir/ts/tsAnyKeyword.cpp index 99f5e085a2..f8cde5748f 100644 --- a/ets2panda/ir/ts/tsAnyKeyword.cpp +++ b/ets2panda/ir/ts/tsAnyKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSAnyKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSAnyKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index 8a1e1abd2c..8ab2361fb9 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -27,12 +27,8 @@ void TSArrayType::TransformChildren(const NodeTransformer &cb, std::string_view elementType_->SetTransformedNode(transformationName, transformedNode); elementType_ = static_cast(transformedNode); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSArrayType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsBigintKeyword.cpp b/ets2panda/ir/ts/tsBigintKeyword.cpp index 7b42542a7d..0e6a288d94 100644 --- a/ets2panda/ir/ts/tsBigintKeyword.cpp +++ b/ets2panda/ir/ts/tsBigintKeyword.cpp @@ -26,12 +26,7 @@ namespace ark::es2panda::ir { void TSBigintKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSBigintKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsBooleanKeyword.cpp b/ets2panda/ir/ts/tsBooleanKeyword.cpp index 4d5b6f018a..bae3ac4ae1 100644 --- a/ets2panda/ir/ts/tsBooleanKeyword.cpp +++ b/ets2panda/ir/ts/tsBooleanKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSBooleanKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSBooleanKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsConditionalType.cpp b/ets2panda/ir/ts/tsConditionalType.cpp index 6a70708b5c..6a166ea3f0 100644 --- a/ets2panda/ir/ts/tsConditionalType.cpp +++ b/ets2panda/ir/ts/tsConditionalType.cpp @@ -43,12 +43,8 @@ void TSConditionalType::TransformChildren(const NodeTransformer &cb, std::string falseType_->SetTransformedNode(transformationName, transformedNode); falseType_ = transformedNode->AsExpression(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSConditionalType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsConstructorType.cpp b/ets2panda/ir/ts/tsConstructorType.cpp index 681161a310..327034616d 100644 --- a/ets2panda/ir/ts/tsConstructorType.cpp +++ b/ets2panda/ir/ts/tsConstructorType.cpp @@ -26,12 +26,7 @@ namespace ark::es2panda::ir { void TSConstructorType::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { signature_.TransformChildren(cb, transformationName); - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSConstructorType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsEnumDeclaration.cpp b/ets2panda/ir/ts/tsEnumDeclaration.cpp index 42603eda1e..c3d9c28f02 100644 --- a/ets2panda/ir/ts/tsEnumDeclaration.cpp +++ b/ets2panda/ir/ts/tsEnumDeclaration.cpp @@ -25,37 +25,57 @@ #include "utils/arena_containers.h" namespace ark::es2panda::ir { + +void TSEnumDeclaration::SetInternalName(util::StringView internalName) +{ + this->GetOrCreateHistoryNodeAs()->internalName_ = internalName; +} + +void TSEnumDeclaration::SetBoxedClass(ClassDefinition *boxedClass) +{ + this->GetOrCreateHistoryNodeAs()->boxedClass_ = boxedClass; +} + +void TSEnumDeclaration::SetKey(Identifier *key) +{ + this->GetOrCreateHistoryNodeAs()->key_ = key; +} + void TSEnumDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - if (auto *transformedNode = cb(key_); key_ != transformedNode) { - key_->SetTransformedNode(transformationName, transformedNode); - key_ = transformedNode->AsIdentifier(); + auto const key = Key(); + if (auto *transformedNode = cb(key); key != transformedNode) { + key->SetTransformedNode(transformationName, transformedNode); + SetKey(transformedNode->AsIdentifier()); } - for (auto *&it : VectorIterationGuard(members_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode; + auto const &members = Members(); + for (size_t ix = 0; ix < members.size(); ix++) { + if (auto *transformedNode = cb(members[ix]); members[ix] != transformedNode) { + members[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueMembers(transformedNode->AsDecorator(), ix); } } } void TSEnumDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } - cb(key_); + auto const key = GetHistoryNode()->AsTSEnumDeclaration()->key_; + cb(key); - for (auto *it : VectorIterationGuard(members_)) { + for (auto *it : VectorIterationGuard(Members())) { cb(it); } } @@ -63,10 +83,10 @@ void TSEnumDeclaration::Iterate(const NodeTraverser &cb) const void TSEnumDeclaration::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "TSEnumDeclaration"}, - {"decorators", AstDumper::Optional(decorators_)}, - {"id", key_}, - {"members", members_}, - {"const", isConst_}, + {"decorators", AstDumper::Optional(Decorators())}, + {"id", Key()}, + {"members", Members()}, + {"const", IsConst()}, {"declare", IsDeclare()}}); } @@ -105,14 +125,15 @@ void TSEnumDeclaration::Dump(ir::SrcDumper *dumper) const dumper->Add("declare "); } dumper->Add("enum "); - key_->Dump(dumper); + Key()->Dump(dumper); dumper->Add(" {"); - if (!members_.empty()) { + auto const members = Members(); + if (!members.empty()) { dumper->IncrIndent(); dumper->Endl(); - for (auto member : members_) { + for (auto member : members) { member->Dump(dumper); - if (member != members_.back()) { + if (member != members.back()) { dumper->Add(","); dumper->Endl(); } @@ -188,4 +209,56 @@ void TSEnumDeclaration::CopyTo(AstNode *other) const TypedStatement::CopyTo(other); } +void TSEnumDeclaration::EmplaceDecorators(Decorator *source) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(source); +} + +void TSEnumDeclaration::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void TSEnumDeclaration::SetValueDecorators(Decorator *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; +} + +[[nodiscard]] ArenaVector &TSEnumDeclaration::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + +void TSEnumDeclaration::EmplaceMembers(AstNode *source) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->members_.emplace_back(source); +} + +void TSEnumDeclaration::ClearMembers() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->members_.clear(); +} + +void TSEnumDeclaration::SetValueMembers(AstNode *source, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->members_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; +} + +[[nodiscard]] ArenaVector &TSEnumDeclaration::MembersForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->members_; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ts/tsEnumDeclaration.h b/ets2panda/ir/ts/tsEnumDeclaration.h index ffb58b6153..87bb7c13fd 100644 --- a/ets2panda/ir/ts/tsEnumDeclaration.h +++ b/ets2panda/ir/ts/tsEnumDeclaration.h @@ -52,6 +52,28 @@ public: if (flags.isDeclare) { AddModifier(ModifierFlags::DECLARE); } + InitHistory(); + } + + explicit TSEnumDeclaration(ArenaAllocator *allocator, Identifier *key, ArenaVector &&members, + ConstructorFlags &&flags, AstNodeHistory *history) + : TypedStatement(AstNodeType::TS_ENUM_DECLARATION), + decorators_(allocator->Adapter()), + key_(key), + members_(std::move(members)), + isConst_(flags.isConst) + { + if (flags.isStatic) { + AddModifier(ModifierFlags::STATIC); + } + if (flags.isDeclare) { + AddModifier(ModifierFlags::DECLARE); + } + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } [[nodiscard]] bool IsScopeBearer() const noexcept override @@ -61,73 +83,63 @@ public: [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } void SetScope(varbinder::LocalScope *scope) { - ES2PANDA_ASSERT(scope_ == nullptr); - scope_ = scope; + ES2PANDA_ASSERT(Scope() == nullptr); + GetOrCreateHistoryNode()->AsTSEnumDeclaration()->scope_ = scope; } void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } const Identifier *Key() const { - return key_; + return GetHistoryNodeAs()->key_; } Identifier *Key() { - return key_; + return GetHistoryNodeAs()->key_; } const ArenaVector &Members() const { - return members_; + return GetHistoryNodeAs()->members_; } const util::StringView &InternalName() const { - return internalName_; + return GetHistoryNodeAs()->internalName_; } - void SetInternalName(util::StringView internalName) - { - internalName_ = internalName; - } + void SetInternalName(util::StringView internalName); ir::ClassDefinition *BoxedClass() const { - return boxedClass_; + return GetHistoryNodeAs()->boxedClass_; } - void SetBoxedClass(ir::ClassDefinition *const wrapperClass) - { - boxedClass_ = wrapperClass; - } + void SetBoxedClass(ir::ClassDefinition *boxedClass); bool IsConst() const { - return isConst_; + return GetHistoryNodeAs()->isConst_; } const ArenaVector &Decorators() const { - return decorators_; - } - - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); + return GetHistoryNodeAs()->decorators_; } void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = GetOrCreateHistoryNodeAs(); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -154,9 +166,21 @@ public: TSEnumDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; + void EmplaceDecorators(Decorator *source); + void ClearDecorators(); + void SetValueDecorators(Decorator *source, size_t index); + [[nodiscard]] ArenaVector &DecoratorsForUpdate(); + + void EmplaceMembers(AstNode *source); + void ClearMembers(); + void SetValueMembers(AstNode *source, size_t index); + [[nodiscard]] ArenaVector &MembersForUpdate(); + private: bool RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const; friend class SizeOfNodeTest; + void SetKey(Identifier *key); + varbinder::LocalScope *scope_ {nullptr}; ArenaVector decorators_; Identifier *key_; diff --git a/ets2panda/ir/ts/tsFunctionType.cpp b/ets2panda/ir/ts/tsFunctionType.cpp index ed1698e0a2..89e4751aeb 100644 --- a/ets2panda/ir/ts/tsFunctionType.cpp +++ b/ets2panda/ir/ts/tsFunctionType.cpp @@ -27,12 +27,7 @@ namespace ark::es2panda::ir { void TSFunctionType::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) { signature_.TransformChildren(cb, transformationName); - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSFunctionType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsImportType.cpp b/ets2panda/ir/ts/tsImportType.cpp index 7854c7d3c8..a0f981b892 100644 --- a/ets2panda/ir/ts/tsImportType.cpp +++ b/ets2panda/ir/ts/tsImportType.cpp @@ -44,12 +44,8 @@ void TSImportType::TransformChildren(const NodeTransformer &cb, std::string_view qualifier_ = transformedNode->AsExpression(); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSImportType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsIndexedAccessType.cpp b/ets2panda/ir/ts/tsIndexedAccessType.cpp index f2d897be6e..e1e110231a 100644 --- a/ets2panda/ir/ts/tsIndexedAccessType.cpp +++ b/ets2panda/ir/ts/tsIndexedAccessType.cpp @@ -34,12 +34,8 @@ void TSIndexedAccessType::TransformChildren(const NodeTransformer &cb, std::stri indexType_->SetTransformedNode(transformationName, transformedNode); indexType_ = static_cast(transformedNode); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSIndexedAccessType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsInferType.cpp b/ets2panda/ir/ts/tsInferType.cpp index 5db886b2e4..dd9d1746dc 100644 --- a/ets2panda/ir/ts/tsInferType.cpp +++ b/ets2panda/ir/ts/tsInferType.cpp @@ -29,12 +29,8 @@ void TSInferType::TransformChildren(const NodeTransformer &cb, std::string_view typeParam_->SetTransformedNode(transformationName, transformedNode); typeParam_ = transformedNode->AsTSTypeParameter(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSInferType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsInterfaceDeclaration.cpp b/ets2panda/ir/ts/tsInterfaceDeclaration.cpp index bea508e388..4455a8b776 100644 --- a/ets2panda/ir/ts/tsInterfaceDeclaration.cpp +++ b/ets2panda/ir/ts/tsInterfaceDeclaration.cpp @@ -34,50 +34,139 @@ #include "util/language.h" namespace ark::es2panda::ir { + +void TSInterfaceDeclaration::SetInternalName(util::StringView internalName) +{ + this->GetOrCreateHistoryNodeAs()->internalName_ = internalName; +} + +void TSInterfaceDeclaration::SetAnonClass(ClassDeclaration *anonClass) +{ + this->GetOrCreateHistoryNodeAs()->anonClass_ = anonClass; +} + +void TSInterfaceDeclaration::SetId(Identifier *id) +{ + this->GetOrCreateHistoryNodeAs()->id_ = id; +} + +void TSInterfaceDeclaration::SetTypeParams(TSTypeParameterDeclaration *typeParams) +{ + this->GetOrCreateHistoryNodeAs()->typeParams_ = typeParams; +} + +void TSInterfaceDeclaration::SetBody(TSInterfaceBody *body) +{ + this->GetOrCreateHistoryNodeAs()->body_ = body; +} + +void TSInterfaceDeclaration::EmplaceExtends(TSInterfaceHeritage *extends) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->extends_.emplace_back(extends); +} + +void TSInterfaceDeclaration::ClearExtends() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->extends_.clear(); +} + +void TSInterfaceDeclaration::SetValueExtends(TSInterfaceHeritage *extends, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->extends_; + arenaVector[index] = extends; +} + +[[nodiscard]] const ArenaVector &TSInterfaceDeclaration::Extends() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->extends_; +} + +[[nodiscard]] ArenaVector &TSInterfaceDeclaration::ExtendsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->extends_; +} + +void TSInterfaceDeclaration::EmplaceDecorators(Decorator *decorators) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(decorators); +} + +void TSInterfaceDeclaration::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void TSInterfaceDeclaration::SetValueDecorators(Decorator *decorators, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = decorators; +} + +[[nodiscard]] const ArenaVector &TSInterfaceDeclaration::Decorators() +{ + auto newNode = this->GetHistoryNodeAs(); + return newNode->decorators_; +} + +[[nodiscard]] ArenaVector &TSInterfaceDeclaration::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + void TSInterfaceDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - for (auto *&it : Annotations()) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); - if (auto *transformedNode = cb(id_); id_ != transformedNode) { - id_->SetTransformedNode(transformationName, transformedNode); - id_ = transformedNode->AsIdentifier(); + auto const id = Id(); + if (auto *transformedNode = cb(id); id != transformedNode) { + id->SetTransformedNode(transformationName, transformedNode); + SetId(transformedNode->AsIdentifier()); } - if (typeParams_ != nullptr) { - if (auto *transformedNode = cb(typeParams_); typeParams_ != transformedNode) { - typeParams_->SetTransformedNode(transformationName, transformedNode); - typeParams_ = transformedNode->AsTSTypeParameterDeclaration(); + auto const typeParams = TypeParams(); + if (typeParams != nullptr) { + if (auto *transformedNode = cb(typeParams); typeParams != transformedNode) { + typeParams->SetTransformedNode(transformationName, transformedNode); + SetTypeParams(transformedNode->AsTSTypeParameterDeclaration()); } } - for (auto *&it : VectorIterationGuard(extends_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsTSInterfaceHeritage(); + auto const &extends = Extends(); + for (size_t ix = 0; ix < extends.size(); ix++) { + if (auto *transformedNode = cb(extends[ix]); extends[ix] != transformedNode) { + extends[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueExtends(transformedNode->AsTSInterfaceHeritage(), ix); } } - if (auto *transformedNode = cb(body_); body_ != transformedNode) { - body_->SetTransformedNode(transformationName, transformedNode); - body_ = transformedNode->AsTSInterfaceBody(); + auto const &body = Body(); + if (auto *transformedNode = cb(body); body != transformedNode) { + body->SetTransformedNode(transformationName, transformedNode); + SetBody(transformedNode->AsTSInterfaceBody()); } } void TSInterfaceDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } @@ -85,28 +174,31 @@ void TSInterfaceDeclaration::Iterate(const NodeTraverser &cb) const cb(it); } - cb(id_); + auto const id = GetHistoryNode()->AsTSInterfaceDeclaration()->id_; + cb(id); - if (typeParams_ != nullptr) { - cb(typeParams_); + auto const typeParams = GetHistoryNode()->AsTSInterfaceDeclaration()->typeParams_; + if (typeParams != nullptr) { + cb(typeParams); } - for (auto *it : VectorIterationGuard(extends_)) { + for (auto *it : VectorIterationGuard(Extends())) { cb(it); } - cb(body_); + auto const body = GetHistoryNode()->AsTSInterfaceDeclaration()->body_; + cb(body); } void TSInterfaceDeclaration::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "TSInterfaceDeclaration"}, - {"decorators", AstDumper::Optional(decorators_)}, + {"decorators", AstDumper::Optional(Decorators())}, {"annotations", AstDumper::Optional(Annotations())}, - {"body", body_}, - {"id", id_}, - {"extends", extends_}, - {"typeParameters", AstDumper::Optional(typeParams_)}}); + {"body", Body()}, + {"id", Id()}, + {"extends", Extends()}, + {"typeParameters", AstDumper::Optional(TypeParams())}}); } bool TSInterfaceDeclaration::RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const @@ -149,28 +241,32 @@ void TSInterfaceDeclaration::Dump(ir::SrcDumper *dumper) const dumper->Add("declare "); } dumper->Add("interface "); - id_->Dump(dumper); + Id()->Dump(dumper); - if (typeParams_ != nullptr) { + auto const typeParams = TypeParams(); + if (typeParams != nullptr) { dumper->Add("<"); - typeParams_->Dump(dumper); + typeParams->Dump(dumper); dumper->Add(">"); } - if (!extends_.empty()) { + + auto const extends = Extends(); + if (!extends.empty()) { dumper->Add(" extends "); - for (auto ext : extends_) { + for (auto ext : extends) { ext->Dump(dumper); - if (ext != extends_.back()) { + if (ext != extends.back()) { dumper->Add(", "); } } } + auto body = Body(); dumper->Add(" {"); - if (body_ != nullptr) { + if (body != nullptr) { dumper->IncrIndent(); dumper->Endl(); - body_->Dump(dumper); + body->Dump(dumper); dumper->DecrIndent(); dumper->Endl(); } diff --git a/ets2panda/ir/ts/tsInterfaceDeclaration.h b/ets2panda/ir/ts/tsInterfaceDeclaration.h index fb338b4c96..64e6a30e70 100644 --- a/ets2panda/ir/ts/tsInterfaceDeclaration.h +++ b/ets2panda/ir/ts/tsInterfaceDeclaration.h @@ -58,6 +58,29 @@ public: if (isStatic_) { AddModifier(ir::ModifierFlags::STATIC); } + InitHistory(); + } + + explicit TSInterfaceDeclaration(ArenaAllocator *allocator, ArenaVector &&extends, + ConstructorData &&data, AstNodeHistory *history) + : JsDocAllowed>(AstNodeType::TS_INTERFACE_DECLARATION, allocator), + decorators_(allocator->Adapter()), + id_(data.id), + typeParams_(data.typeParams), + body_(data.body), + extends_(std::move(extends)), + isStatic_(data.isStatic), + isExternal_(data.isExternal), + lang_(data.lang) + { + if (isStatic_) { + AddModifier(ir::ModifierFlags::STATIC); + } + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } [[nodiscard]] bool IsScopeBearer() const noexcept override @@ -67,93 +90,84 @@ public: [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } void SetScope(varbinder::LocalScope *scope) { - ES2PANDA_ASSERT(scope_ == nullptr); - scope_ = scope; + ES2PANDA_ASSERT(Scope() == nullptr); + GetOrCreateHistoryNode()->AsTSInterfaceDeclaration()->scope_ = scope; } void ClearScope() noexcept override { - scope_ = nullptr; + GetOrCreateHistoryNode()->AsTSInterfaceDeclaration()->scope_ = nullptr; } TSInterfaceBody *Body() { - return body_; + return GetHistoryNodeAs()->body_; } const TSInterfaceBody *Body() const { - return body_; + return GetHistoryNodeAs()->body_; } Identifier *Id() { - return id_; + return GetHistoryNodeAs()->id_; } const Identifier *Id() const { - return id_; + return GetHistoryNodeAs()->id_; } const util::StringView &InternalName() const { - return internalName_; + return GetHistoryNodeAs()->internalName_; } - void SetInternalName(util::StringView internalName) - { - internalName_ = internalName; - } + void SetInternalName(util::StringView internalName); bool IsStatic() const { - return isStatic_; + return GetHistoryNodeAs()->isStatic_; } bool IsFromExternal() const { - return isExternal_; + return GetHistoryNodeAs()->isExternal_; } const TSTypeParameterDeclaration *TypeParams() const { - return typeParams_; + return GetHistoryNodeAs()->typeParams_; } TSTypeParameterDeclaration *TypeParams() { - return typeParams_; + return GetHistoryNodeAs()->typeParams_; } - ArenaVector &Extends() - { - return extends_; - } + [[nodiscard]] const ArenaVector &Extends(); + [[nodiscard]] ArenaVector &ExtendsForUpdate(); const ArenaVector &Extends() const { - return extends_; + return GetHistoryNodeAs()->extends_; } const ArenaVector &Decorators() const { - return decorators_; - } - - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); + return GetHistoryNodeAs()->decorators_; } void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -165,23 +179,20 @@ public: es2panda::Language Language() const { - return lang_; + return GetHistoryNodeAs()->lang_; } ClassDeclaration *GetAnonClass() noexcept { - return anonClass_; + return GetHistoryNodeAs()->anonClass_; } ClassDeclaration *GetAnonClass() const noexcept { - return anonClass_; + return GetHistoryNodeAs()->anonClass_; } - void SetAnonClass(ClassDeclaration *anonClass) noexcept - { - anonClass_ = anonClass; - } + void SetAnonClass(ClassDeclaration *anonClass); void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; @@ -200,9 +211,23 @@ public: TSInterfaceDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; + void EmplaceExtends(TSInterfaceHeritage *extends); + void ClearExtends(); + void SetValueExtends(TSInterfaceHeritage *extends, size_t index); + + void EmplaceDecorators(Decorator *decorators); + void ClearDecorators(); + void SetValueDecorators(Decorator *decorators, size_t index); + [[nodiscard]] const ArenaVector &Decorators(); + [[nodiscard]] ArenaVector &DecoratorsForUpdate(); + private: bool RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const; friend class SizeOfNodeTest; + void SetId(Identifier *id); + void SetTypeParams(TSTypeParameterDeclaration *typeParams); + void SetBody(TSInterfaceBody *body); + ArenaVector decorators_; varbinder::LocalScope *scope_ {nullptr}; Identifier *id_; diff --git a/ets2panda/ir/ts/tsIntersectionType.cpp b/ets2panda/ir/ts/tsIntersectionType.cpp index 75cf7834dc..6dc630a18a 100644 --- a/ets2panda/ir/ts/tsIntersectionType.cpp +++ b/ets2panda/ir/ts/tsIntersectionType.cpp @@ -31,12 +31,8 @@ void TSIntersectionType::TransformChildren(const NodeTransformer &cb, std::strin it = transformedNode->AsExpression(); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSIntersectionType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsLiteralType.cpp b/ets2panda/ir/ts/tsLiteralType.cpp index 25a998cc17..a679912bf4 100644 --- a/ets2panda/ir/ts/tsLiteralType.cpp +++ b/ets2panda/ir/ts/tsLiteralType.cpp @@ -28,12 +28,8 @@ void TSLiteralType::TransformChildren(const NodeTransformer &cb, std::string_vie literal_->SetTransformedNode(transformationName, transformedNode); literal_ = transformedNode->AsExpression(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSLiteralType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsMappedType.cpp b/ets2panda/ir/ts/tsMappedType.cpp index fef66f0e8c..61da853b75 100644 --- a/ets2panda/ir/ts/tsMappedType.cpp +++ b/ets2panda/ir/ts/tsMappedType.cpp @@ -37,12 +37,8 @@ void TSMappedType::TransformChildren(const NodeTransformer &cb, std::string_view typeAnnotation_ = static_cast(transformedNode); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSMappedType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsNamedTupleMember.cpp b/ets2panda/ir/ts/tsNamedTupleMember.cpp index d07fb3d982..742f9e6cd4 100644 --- a/ets2panda/ir/ts/tsNamedTupleMember.cpp +++ b/ets2panda/ir/ts/tsNamedTupleMember.cpp @@ -34,12 +34,8 @@ void TSNamedTupleMember::TransformChildren(const NodeTransformer &cb, std::strin elementType_->SetTransformedNode(transformationName, transformedNode); elementType_ = static_cast(transformedNode); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSNamedTupleMember::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsNeverKeyword.cpp b/ets2panda/ir/ts/tsNeverKeyword.cpp index 9b1386dcad..a48751933c 100644 --- a/ets2panda/ir/ts/tsNeverKeyword.cpp +++ b/ets2panda/ir/ts/tsNeverKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSNeverKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSNeverKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsNullKeyword.cpp b/ets2panda/ir/ts/tsNullKeyword.cpp index d7050a9ff3..6e089e142a 100644 --- a/ets2panda/ir/ts/tsNullKeyword.cpp +++ b/ets2panda/ir/ts/tsNullKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSNullKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSNullKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsNumberKeyword.cpp b/ets2panda/ir/ts/tsNumberKeyword.cpp index 9c9125def9..afcee6e7b5 100644 --- a/ets2panda/ir/ts/tsNumberKeyword.cpp +++ b/ets2panda/ir/ts/tsNumberKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSNumberKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSNumberKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsObjectKeyword.cpp b/ets2panda/ir/ts/tsObjectKeyword.cpp index fd807caf03..3b4ea39d6e 100644 --- a/ets2panda/ir/ts/tsObjectKeyword.cpp +++ b/ets2panda/ir/ts/tsObjectKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSObjectKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSObjectKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsParenthesizedType.cpp b/ets2panda/ir/ts/tsParenthesizedType.cpp index 4ee640455b..4608efb394 100644 --- a/ets2panda/ir/ts/tsParenthesizedType.cpp +++ b/ets2panda/ir/ts/tsParenthesizedType.cpp @@ -28,12 +28,8 @@ void TSParenthesizedType::TransformChildren(const NodeTransformer &cb, std::stri type_->SetTransformedNode(transformationName, transformedNode); type_ = static_cast(transformedNode); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSParenthesizedType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsStringKeyword.cpp b/ets2panda/ir/ts/tsStringKeyword.cpp index 825b446bc4..be62a34004 100644 --- a/ets2panda/ir/ts/tsStringKeyword.cpp +++ b/ets2panda/ir/ts/tsStringKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSStringKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSStringKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsThisType.cpp b/ets2panda/ir/ts/tsThisType.cpp index da5e36ad8c..9af97be93c 100644 --- a/ets2panda/ir/ts/tsThisType.cpp +++ b/ets2panda/ir/ts/tsThisType.cpp @@ -24,12 +24,7 @@ namespace ark::es2panda::ir { void TSThisType::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSThisType::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTupleType.cpp b/ets2panda/ir/ts/tsTupleType.cpp index cb69e8542c..d98cbd1622 100644 --- a/ets2panda/ir/ts/tsTupleType.cpp +++ b/ets2panda/ir/ts/tsTupleType.cpp @@ -35,12 +35,8 @@ void TSTupleType::TransformChildren(const NodeTransformer &cb, std::string_view it = static_cast(transformedNode); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTupleType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp b/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp index 26bcca0adb..75532d6015 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.cpp @@ -27,31 +27,46 @@ #include "ir/ts/tsTypeParameterDeclaration.h" namespace ark::es2panda::ir { + +void TSTypeAliasDeclaration::SetTypeParameters(TSTypeParameterDeclaration *typeParams) +{ + this->GetOrCreateHistoryNodeAs()->typeParams_ = typeParams; +} + +void TSTypeAliasDeclaration::SetId(Identifier *id) +{ + this->GetOrCreateHistoryNodeAs()->id_ = id; +} + void TSTypeAliasDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(decorators_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsDecorator(); + auto const &decorators = Decorators(); + for (size_t ix = 0; ix < decorators.size(); ix++) { + if (auto *transformedNode = cb(decorators[ix]); decorators[ix] != transformedNode) { + decorators[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueDecorators(transformedNode->AsDecorator(), ix); } } - for (auto *&it : Annotations()) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + auto const &annotations = Annotations(); + for (size_t ix = 0; ix < annotations.size(); ix++) { + if (auto *transformedNode = cb(annotations[ix]); annotations[ix] != transformedNode) { + annotations[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueAnnotations(transformedNode->AsAnnotationUsage(), ix); } } - if (auto *transformedNode = cb(id_); id_ != transformedNode) { - id_->SetTransformedNode(transformationName, transformedNode); - id_ = transformedNode->AsIdentifier(); + auto const id = Id(); + if (auto *transformedNode = cb(id); id != transformedNode) { + id->SetTransformedNode(transformationName, transformedNode); + SetId(transformedNode->AsIdentifier()); } - if (typeParams_ != nullptr) { - if (auto *transformedNode = cb(typeParams_); typeParams_ != transformedNode) { - typeParams_->SetTransformedNode(transformationName, transformedNode); - typeParams_ = transformedNode->AsTSTypeParameterDeclaration(); + auto const typeParams = TypeParams(); + if (typeParams != nullptr) { + if (auto *transformedNode = cb(typeParams); typeParams != transformedNode) { + typeParams->SetTransformedNode(transformationName, transformedNode); + SetTypeParameters(transformedNode->AsTSTypeParameterDeclaration()); } } @@ -65,7 +80,7 @@ void TSTypeAliasDeclaration::TransformChildren(const NodeTransformer &cb, std::s void TSTypeAliasDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(decorators_)) { + for (auto *it : VectorIterationGuard(Decorators())) { cb(it); } @@ -73,10 +88,12 @@ void TSTypeAliasDeclaration::Iterate(const NodeTraverser &cb) const cb(it); } - cb(id_); + auto const id = GetHistoryNode()->AsTSTypeAliasDeclaration()->id_; + cb(id); - if (typeParams_ != nullptr) { - cb(typeParams_); + auto typeParams = GetHistoryNode()->AsTSTypeAliasDeclaration()->typeParams_; + if (typeParams != nullptr) { + cb(typeParams); } if (TypeAnnotation() != nullptr) { @@ -87,11 +104,11 @@ void TSTypeAliasDeclaration::Iterate(const NodeTraverser &cb) const void TSTypeAliasDeclaration::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "TSTypeAliasDeclaration"}, - {"decorators", AstDumper::Optional(decorators_)}, + {"decorators", AstDumper::Optional(Decorators())}, {"annotations", AstDumper::Optional(Annotations())}, - {"id", id_}, + {"id", Id()}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, - {"typeParameters", AstDumper::Optional(typeParams_)}}); + {"typeParameters", AstDumper::Optional(TypeParams())}}); } bool TSTypeAliasDeclaration::RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const @@ -126,14 +143,15 @@ void TSTypeAliasDeclaration::Dump(ir::SrcDumper *dumper) const dumper->Add("export "); } dumper->Add("type "); - id_->Dump(dumper); - if (typeParams_ != nullptr) { + Id()->Dump(dumper); + auto const typeParams = TypeParams(); + if (typeParams != nullptr) { dumper->Add("<"); - typeParams_->Dump(dumper); + typeParams->Dump(dumper); dumper->Add(">"); } dumper->Add(" = "); - if (id_->IsAnnotatedExpression()) { + if (Id()->IsAnnotatedExpression()) { auto type = TypeAnnotation(); ES2PANDA_ASSERT(type); type->Dump(dumper); @@ -180,4 +198,82 @@ void TSTypeAliasDeclaration::CopyTo(AstNode *other) const JsDocAllowed::CopyTo(other); } +void TSTypeAliasDeclaration::EmplaceDecorators(Decorator *decorators) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.emplace_back(decorators); +} + +void TSTypeAliasDeclaration::ClearDecorators() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->decorators_.clear(); +} + +void TSTypeAliasDeclaration::SetValueDecorators(Decorator *decorators, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->decorators_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = decorators; +} + +[[nodiscard]] ArenaVector &TSTypeAliasDeclaration::DecoratorsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->decorators_; +} + +void TSTypeAliasDeclaration::EmplaceTypeParamterTypes(checker::Type *typeParamTypes) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->typeParamTypes_.emplace_back(typeParamTypes); +} + +void TSTypeAliasDeclaration::ClearTypeParamterTypes() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->typeParamTypes_.clear(); +} + +void TSTypeAliasDeclaration::SetValueTypeParamterTypes(checker::Type *typeParamTypes, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->typeParamTypes_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = typeParamTypes; +} + +[[nodiscard]] ArenaVector &TSTypeAliasDeclaration::TypeParamterTypesForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->typeParamTypes_; +} + +void TSTypeAliasDeclaration::EmplaceAnnotations(AnnotationUsage *annotations) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->annotations_.emplace_back(annotations); +} + +void TSTypeAliasDeclaration::ClearAnnotations() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + newNode->annotations_.clear(); +} + +void TSTypeAliasDeclaration::SetValueAnnotations(AnnotationUsage *annotations, size_t index) +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + auto &arenaVector = newNode->annotations_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = annotations; +} + +[[nodiscard]] ArenaVector &TSTypeAliasDeclaration::AnnotationsForUpdate() +{ + auto newNode = this->GetOrCreateHistoryNodeAs(); + return newNode->annotations_; +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ts/tsTypeAliasDeclaration.h b/ets2panda/ir/ts/tsTypeAliasDeclaration.h index 4d44e90021..fb9b8c160d 100644 --- a/ets2panda/ir/ts/tsTypeAliasDeclaration.h +++ b/ets2panda/ir/ts/tsTypeAliasDeclaration.h @@ -40,6 +40,7 @@ public: typeParams_(typeParams), typeParamTypes_(allocator->Adapter()) { + InitHistory(); } explicit TSTypeAliasDeclaration(ArenaAllocator *allocator, Identifier *id) @@ -50,41 +51,35 @@ public: typeParams_(nullptr), typeParamTypes_(allocator->Adapter()) { + InitHistory(); } Identifier *Id() { - return id_; + return GetHistoryNodeAs()->id_; } const Identifier *Id() const { - return id_; + return GetHistoryNodeAs()->id_; } TSTypeParameterDeclaration *TypeParams() const { - return typeParams_; + return GetHistoryNodeAs()->typeParams_; } const ArenaVector &Decorators() const { - return decorators_; + return GetHistoryNodeAs()->decorators_; } - const ArenaVector *DecoratorsPtr() const override - { - return &Decorators(); - } - - void SetTypeParameters(ir::TSTypeParameterDeclaration *typeParams) - { - typeParams_ = typeParams; - } + void SetTypeParameters(ir::TSTypeParameterDeclaration *typeParams); void AddDecorators([[maybe_unused]] ArenaVector &&decorators) override { - decorators_ = std::move(decorators); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->decorators_ = std::move(decorators); } bool CanHaveDecorator([[maybe_unused]] bool inTs) const override @@ -94,28 +89,25 @@ public: void SetTypeParameterTypes(ArenaVector &&typeParamTypes) { - typeParamTypes_ = std::move(typeParamTypes); + auto newNode = reinterpret_cast(GetOrCreateHistoryNode()); + newNode->typeParamTypes_ = std::move(typeParamTypes); } ArenaVector const &TypeParameterTypes() const { - return typeParamTypes_; - } - - [[nodiscard]] ArenaVector &Annotations() noexcept - { - return annotations_; + return GetHistoryNodeAs()->typeParamTypes_; } [[nodiscard]] const ArenaVector &Annotations() const noexcept { - return annotations_; + return GetHistoryNodeAs()->annotations_; } void SetAnnotations(ArenaVector &&annotations) { - annotations_ = std::move(annotations); - for (AnnotationUsage *anno : annotations_) { + auto newNode = reinterpret_cast(GetOrCreateHistoryNode()); + newNode->annotations_ = std::move(annotations); + for (AnnotationUsage *anno : newNode->annotations_) { anno->SetParent(this); } } @@ -137,15 +129,32 @@ public: void CleanUp() override { AstNode::CleanUp(); - typeParamTypes_.clear(); + ClearTypeParamterTypes(); } TSTypeAliasDeclaration *Construct(ArenaAllocator *allocator) override; void CopyTo(AstNode *other) const override; + void EmplaceAnnotations(AnnotationUsage *annotations); + void ClearAnnotations(); + void SetValueAnnotations(AnnotationUsage *annotations, size_t index); + [[nodiscard]] ArenaVector &AnnotationsForUpdate(); + + void EmplaceTypeParamterTypes(checker::Type *typeParamTypes); + void ClearTypeParamterTypes(); + void SetValueTypeParamterTypes(checker::Type *typeParamTypes, size_t index); + [[nodiscard]] ArenaVector &TypeParamterTypesForUpdate(); + + void EmplaceDecorators(Decorator *decorators); + void ClearDecorators(); + void SetValueDecorators(Decorator *decorators, size_t index); + [[nodiscard]] ArenaVector &DecoratorsForUpdate(); + private: bool RegisterUnexportedForDeclGen(ir::SrcDumper *dumper) const; friend class SizeOfNodeTest; + + void SetId(Identifier *id); ArenaVector decorators_; ArenaVector annotations_; Identifier *id_; diff --git a/ets2panda/ir/ts/tsTypeLiteral.cpp b/ets2panda/ir/ts/tsTypeLiteral.cpp index 418d5aa34d..d13f7662cd 100644 --- a/ets2panda/ir/ts/tsTypeLiteral.cpp +++ b/ets2panda/ir/ts/tsTypeLiteral.cpp @@ -34,12 +34,8 @@ void TSTypeLiteral::TransformChildren(const NodeTransformer &cb, std::string_vie it = transformedNode; } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTypeLiteral::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTypeOperator.cpp b/ets2panda/ir/ts/tsTypeOperator.cpp index 7e66c02843..2fa2ad26ad 100644 --- a/ets2panda/ir/ts/tsTypeOperator.cpp +++ b/ets2panda/ir/ts/tsTypeOperator.cpp @@ -28,12 +28,8 @@ void TSTypeOperator::TransformChildren(const NodeTransformer &cb, std::string_vi type_->SetTransformedNode(transformationName, transformedNode); type_ = static_cast(transformedNode); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTypeOperator::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTypeParameter.cpp b/ets2panda/ir/ts/tsTypeParameter.cpp index 88d4b08855..e4a489d111 100644 --- a/ets2panda/ir/ts/tsTypeParameter.cpp +++ b/ets2panda/ir/ts/tsTypeParameter.cpp @@ -25,44 +25,68 @@ #include "utils/arena_containers.h" namespace ark::es2panda::ir { + +void TSTypeParameter::SetConstraint(TypeNode *constraint) +{ + this->GetOrCreateHistoryNodeAs()->constraint_ = constraint; +} + +void TSTypeParameter::SetDefaultType(TypeNode *defaultType) +{ + this->GetOrCreateHistoryNodeAs()->defaultType_ = defaultType; +} + +void TSTypeParameter::SetName(Identifier *name) +{ + this->GetOrCreateHistoryNodeAs()->name_ = name; +} + void TSTypeParameter::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - if (auto *transformedNode = cb(name_); name_ != transformedNode) { - name_->SetTransformedNode(transformationName, transformedNode); - name_ = transformedNode->AsIdentifier(); + auto const name = Name(); + if (auto *transformedNode = cb(name); name != transformedNode) { + name->SetTransformedNode(transformationName, transformedNode); + SetName(transformedNode->AsIdentifier()); } - if (constraint_ != nullptr) { - if (auto *transformedNode = cb(constraint_); constraint_ != transformedNode) { - constraint_->SetTransformedNode(transformationName, transformedNode); - constraint_ = static_cast(transformedNode); + auto const constraint = Constraint(); + if (constraint != nullptr) { + if (auto *transformedNode = cb(constraint); constraint != transformedNode) { + constraint->SetTransformedNode(transformationName, transformedNode); + SetConstraint(static_cast(transformedNode)); } } - if (defaultType_ != nullptr) { - if (auto *transformedNode = cb(defaultType_); defaultType_ != transformedNode) { - defaultType_->SetTransformedNode(transformationName, transformedNode); - defaultType_ = static_cast(transformedNode); + auto const defaultType = DefaultType(); + if (defaultType != nullptr) { + if (auto *transformedNode = cb(defaultType); defaultType != transformedNode) { + defaultType->SetTransformedNode(transformationName, transformedNode); + SetDefaultType(static_cast(transformedNode)); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); + + auto const annotations = Annotations(); + for (size_t ix = 0; ix < annotations.size(); ix++) { + if (auto *transformedNode = cb(annotations[ix]); annotations[ix] != transformedNode) { + annotations[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueAnnotations(transformedNode->AsAnnotationUsage(), ix); } } } void TSTypeParameter::Iterate(const NodeTraverser &cb) const { - cb(name_); + auto const name = GetHistoryNodeAs()->name_; + cb(name); - if (constraint_ != nullptr) { - cb(constraint_); + auto const constraint = GetHistoryNodeAs()->constraint_; + if (constraint != nullptr) { + cb(constraint); } - if (defaultType_ != nullptr) { - cb(defaultType_); + auto const defaultType = GetHistoryNodeAs()->defaultType_; + if (defaultType != nullptr) { + cb(defaultType); } for (auto *it : VectorIterationGuard(Annotations())) { cb(it); @@ -72,9 +96,9 @@ void TSTypeParameter::Iterate(const NodeTraverser &cb) const void TSTypeParameter::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "TSTypeParameter"}, - {"name", name_}, - {"constraint", AstDumper::Optional(constraint_)}, - {"default", AstDumper::Optional(defaultType_)}, + {"name", Name()}, + {"constraint", AstDumper::Optional(Constraint())}, + {"default", AstDumper::Optional(DefaultType())}, {"in", AstDumper::Optional(IsIn())}, {"out", AstDumper::Optional(IsOut())}, {"annotations", AstDumper::Optional(Annotations())}}); @@ -92,15 +116,15 @@ void TSTypeParameter::Dump(ir::SrcDumper *dumper) const dumper->Add("out "); } - name_->Dump(dumper); + Name()->Dump(dumper); - if (defaultType_ != nullptr) { + if (DefaultType() != nullptr) { dumper->Add(" = "); - defaultType_->Dump(dumper); + DefaultType()->Dump(dumper); } - if (constraint_ != nullptr) { + if (Constraint() != nullptr) { dumper->Add(" extends "); - constraint_->Dump(dumper); + Constraint()->Dump(dumper); } } diff --git a/ets2panda/ir/ts/tsTypeParameter.h b/ets2panda/ir/ts/tsTypeParameter.h index fff183fc3c..97c92bf6da 100644 --- a/ets2panda/ir/ts/tsTypeParameter.h +++ b/ets2panda/ir/ts/tsTypeParameter.h @@ -31,6 +31,7 @@ public: constraint_(constraint), defaultType_(defaultType) { + InitHistory(); } explicit TSTypeParameter(Identifier *name, TypeNode *constraint, TypeNode *defaultType, ModifierFlags flags, @@ -41,42 +42,67 @@ public: defaultType_(defaultType) { ES2PANDA_ASSERT(flags == ModifierFlags::NONE || flags == ModifierFlags::IN || flags == ModifierFlags::OUT); + InitHistory(); + } + + // CC-OFFNXT(G.FUN.01-CPP) solid logic + explicit TSTypeParameter(Identifier *name, TypeNode *constraint, TypeNode *defaultType, ModifierFlags flags, + ArenaAllocator *const allocator, AstNodeHistory *history) + : AnnotationAllowed(AstNodeType::TS_TYPE_PARAMETER, flags, allocator), + name_(name), + constraint_(constraint), + defaultType_(defaultType) + { + ES2PANDA_ASSERT(flags == ModifierFlags::NONE || flags == ModifierFlags::IN || flags == ModifierFlags::OUT); + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } + } + + explicit TSTypeParameter(Identifier *name, TypeNode *constraint, TypeNode *defaultType, + ArenaAllocator *const allocator, AstNodeHistory *history) + : AnnotationAllowed(AstNodeType::TS_TYPE_PARAMETER, allocator), + name_(name), + constraint_(constraint), + defaultType_(defaultType) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } const Identifier *Name() const { - return name_; + return GetHistoryNodeAs()->name_; } Identifier *Name() { - return name_; + return GetHistoryNodeAs()->name_; } TypeNode *Constraint() { - return constraint_; + return GetHistoryNodeAs()->constraint_; } const TypeNode *Constraint() const { - return constraint_; + return GetHistoryNodeAs()->constraint_; } - void SetConstraint(TypeNode *constraint) - { - constraint_ = constraint; - } + void SetConstraint(TypeNode *constraint); TypeNode *DefaultType() const { - return defaultType_; + return GetHistoryNodeAs()->defaultType_; } - void SetDefaultType(TypeNode *defaultType) - { - defaultType_ = defaultType; - } + void SetDefaultType(TypeNode *defaultType); void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; void Iterate(const NodeTraverser &cb) const override; @@ -97,6 +123,8 @@ public: private: friend class SizeOfNodeTest; + void SetName(Identifier *name); + Identifier *name_; TypeNode *constraint_; TypeNode *defaultType_; diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp index a236ed060c..1ae682e17f 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp @@ -23,33 +23,45 @@ #include "ir/ts/tsTypeParameter.h" namespace ark::es2panda::ir { + +void TSTypeParameterDeclaration::SetScope(varbinder::LocalScope *source) +{ + this->GetOrCreateHistoryNodeAs()->scope_ = source; +} + +void TSTypeParameterDeclaration::SetRequiredParams(size_t source) +{ + this->GetOrCreateHistoryNodeAs()->requiredParams_ = source; +} + void TSTypeParameterDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view transformationName) { - for (auto *&it : VectorIterationGuard(params_)) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsTSTypeParameter(); + auto const params = Params(); + for (size_t ix = 0; ix < params.size(); ix++) { + if (auto *transformedNode = cb(params[ix]); params[ix] != transformedNode) { + params[ix]->SetTransformedNode(transformationName, transformedNode); + SetValueParams(transformedNode->AsTSTypeParameter(), ix); } } } void TSTypeParameterDeclaration::Iterate(const NodeTraverser &cb) const { - for (auto *it : VectorIterationGuard(params_)) { + for (auto *it : VectorIterationGuard(Params())) { cb(it); } } void TSTypeParameterDeclaration::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", "TSTypeParameterDeclaration"}, {"params", params_}}); + dumper->Add({{"type", "TSTypeParameterDeclaration"}, {"params", Params()}}); } void TSTypeParameterDeclaration::Dump(ir::SrcDumper *dumper) const { - for (auto param : params_) { + for (auto param : Params()) { param->Dump(dumper); - if (param != params_.back()) { + if (param != Params().back()) { dumper->Add(", "); } } diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.h b/ets2panda/ir/ts/tsTypeParameterDeclaration.h index 9fef5c44ff..a72497e5ce 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.h +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.h @@ -29,6 +29,20 @@ public: params_(std::move(params)), requiredParams_(requiredParams) { + InitHistory(); + } + + explicit TSTypeParameterDeclaration(ArenaVector &¶ms, size_t requiredParams, + AstNodeHistory *history) + : Expression(AstNodeType::TS_TYPE_PARAMETER_DECLARATION), + params_(std::move(params)), + requiredParams_(requiredParams) + { + if (history != nullptr) { + history_ = history; + } else { + InitHistory(); + } } [[nodiscard]] bool IsScopeBearer() const noexcept override @@ -38,35 +52,41 @@ public: [[nodiscard]] varbinder::LocalScope *Scope() const noexcept override { - return scope_; + return GetHistoryNodeAs()->scope_; } - void SetScope(varbinder::LocalScope *scope) - { - scope_ = scope; - } + void SetScope(varbinder::LocalScope *source); void ClearScope() noexcept override { - scope_ = nullptr; + SetScope(nullptr); } const ArenaVector &Params() const { - return params_; + return GetHistoryNodeAs()->params_; } void AddParam(TSTypeParameter *param) { - if (requiredParams_ == params_.size() && param->DefaultType() == nullptr) { - requiredParams_++; + if (RequiredParams() == Params().size() && param->DefaultType() == nullptr) { + SetRequiredParams(RequiredParams() + 1); } - params_.push_back(param); + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + newNode->params_.emplace_back(param); + } + + void SetValueParams(TSTypeParameter *source, size_t index) + { + auto newNode = reinterpret_cast(this->GetOrCreateHistoryNode()); + auto &arenaVector = newNode->params_; + ES2PANDA_ASSERT(arenaVector.size() > index); + arenaVector[index] = source; } size_t RequiredParams() const { - return requiredParams_; + return GetHistoryNodeAs()->requiredParams_; } void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; @@ -88,6 +108,9 @@ public: private: friend class SizeOfNodeTest; + + void SetRequiredParams(size_t source); + ArenaVector params_; varbinder::LocalScope *scope_ {nullptr}; size_t requiredParams_; diff --git a/ets2panda/ir/ts/tsTypePredicate.cpp b/ets2panda/ir/ts/tsTypePredicate.cpp index a1b253d850..0ab2158429 100644 --- a/ets2panda/ir/ts/tsTypePredicate.cpp +++ b/ets2panda/ir/ts/tsTypePredicate.cpp @@ -37,12 +37,8 @@ void TSTypePredicate::TransformChildren(const NodeTransformer &cb, std::string_v typeAnnotation_ = static_cast(transformedNode); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTypePredicate::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTypeQuery.cpp b/ets2panda/ir/ts/tsTypeQuery.cpp index 70fe7b63fc..5fa24495e8 100644 --- a/ets2panda/ir/ts/tsTypeQuery.cpp +++ b/ets2panda/ir/ts/tsTypeQuery.cpp @@ -29,12 +29,8 @@ void TSTypeQuery::TransformChildren(const NodeTransformer &cb, std::string_view exprName_->SetTransformedNode(transformationName, transformedNode); exprName_ = transformedNode->AsExpression(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTypeQuery::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsTypeReference.cpp b/ets2panda/ir/ts/tsTypeReference.cpp index 459789b718..57b8f7d2ae 100644 --- a/ets2panda/ir/ts/tsTypeReference.cpp +++ b/ets2panda/ir/ts/tsTypeReference.cpp @@ -44,12 +44,8 @@ void TSTypeReference::TransformChildren(const NodeTransformer &cb, std::string_v typeName_->SetTransformedNode(transformationName, transformedNode); typeName_ = transformedNode->AsExpression(); } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSTypeReference::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsUndefinedKeyword.cpp b/ets2panda/ir/ts/tsUndefinedKeyword.cpp index 4070aaf0b2..5053cebca0 100644 --- a/ets2panda/ir/ts/tsUndefinedKeyword.cpp +++ b/ets2panda/ir/ts/tsUndefinedKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSUndefinedKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSUndefinedKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsUnionType.cpp b/ets2panda/ir/ts/tsUnionType.cpp index a25ccceccb..aca8a8aa89 100644 --- a/ets2panda/ir/ts/tsUnionType.cpp +++ b/ets2panda/ir/ts/tsUnionType.cpp @@ -30,12 +30,8 @@ void TSUnionType::TransformChildren(const NodeTransformer &cb, std::string_view it = static_cast(transformedNode); } } - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + + TransformAnnotations(cb, transformationName); } void TSUnionType::Iterate(const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsUnknownKeyword.cpp b/ets2panda/ir/ts/tsUnknownKeyword.cpp index f1daafebdc..dd0bc5e848 100644 --- a/ets2panda/ir/ts/tsUnknownKeyword.cpp +++ b/ets2panda/ir/ts/tsUnknownKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSUnknownKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSUnknownKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/ts/tsVoidKeyword.cpp b/ets2panda/ir/ts/tsVoidKeyword.cpp index d5a4341f2c..ff09cc56d8 100644 --- a/ets2panda/ir/ts/tsVoidKeyword.cpp +++ b/ets2panda/ir/ts/tsVoidKeyword.cpp @@ -25,12 +25,7 @@ namespace ark::es2panda::ir { void TSVoidKeyword::TransformChildren([[maybe_unused]] const NodeTransformer &cb, [[maybe_unused]] std::string_view const transformationName) { - for (auto *&it : VectorIterationGuard(Annotations())) { - if (auto *transformedNode = cb(it); it != transformedNode) { - it->SetTransformedNode(transformationName, transformedNode); - it = transformedNode->AsAnnotationUsage(); - } - } + TransformAnnotations(cb, transformationName); } void TSVoidKeyword::Iterate([[maybe_unused]] const NodeTraverser &cb) const diff --git a/ets2panda/ir/typed.h b/ets2panda/ir/typed.h index 0c3f32f3ee..cec0ce52c3 100644 --- a/ets2panda/ir/typed.h +++ b/ets2panda/ir/typed.h @@ -38,17 +38,21 @@ public: [[nodiscard]] checker::Type const *TsType() const { - return tsType_; + return AstNode::GetHistoryNodeAs>()->tsType_; } [[nodiscard]] checker::Type *TsType() { - return tsType_; + return AstNode::GetHistoryNodeAs>()->tsType_; } checker::Type *SetTsType(checker::Type *tsType) noexcept { - return (tsType_ = tsType); + auto nowNode = AstNode::GetHistoryNodeAs>(); + if (nowNode->tsType_ != tsType) { + AstNode::GetOrCreateHistoryNodeAs>()->tsType_ = tsType; + } + return tsType; } bool IsTyped() const override diff --git a/ets2panda/lexer/token/sourceLocation.h b/ets2panda/lexer/token/sourceLocation.h index a150a8cfb0..b6557e4d63 100644 --- a/ets2panda/lexer/token/sourceLocation.h +++ b/ets2panda/lexer/token/sourceLocation.h @@ -52,6 +52,11 @@ public: const parser::Program *Program() const; + bool operator!=(const SourcePosition &other) const + { + return index != other.index || line != other.line || program_ != other.program_; + } + private: const parser::Program *program_ {}; }; @@ -68,6 +73,11 @@ public: SourcePosition start {}; SourcePosition end {}; // NOLINTEND(misc-non-private-member-variables-in-classes) + + bool operator!=(const SourceRange &other) const + { + return start != other.start || end != other.end; + } }; class SourceLocation { diff --git a/ets2panda/lsp/src/rename.cpp b/ets2panda/lsp/src/rename.cpp index 10f812d813..e836fb4858 100644 --- a/ets2panda/lsp/src/rename.cpp +++ b/ets2panda/lsp/src/rename.cpp @@ -31,7 +31,7 @@ constexpr size_t QUOTE_START_OFFSET = 1; RenameInfoType GetRenameInfo(es2panda_Context *context, size_t pos) { auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx)->checker->AsETSChecker(); + auto checker = reinterpret_cast(ctx)->GetChecker()->AsETSChecker(); auto program = reinterpret_cast(ctx)->parserProgram; auto node = GetAdjustedLocation(GetTouchingPropertyName(context, pos), true, ctx->allocator); if (node.has_value() && NodeIsEligibleForRename(node.value())) { diff --git a/ets2panda/parser/ETSFormattedParser.cpp b/ets2panda/parser/ETSFormattedParser.cpp index 93fac4b3e5..d0b01fdad5 100644 --- a/ets2panda/parser/ETSFormattedParser.cpp +++ b/ets2panda/parser/ETSFormattedParser.cpp @@ -374,7 +374,7 @@ ArenaVector ETSParser::CreateFormattedStatements(std::string_vi ir::AstNode *ETSParser::CreateFormattedClassFieldDefinition(std::string_view sourceCode, std::vector &insertingNodes) { - static ArenaVector const DUMMY_ARRAY {Allocator()->Adapter()}; + thread_local static ArenaVector const DUMMY_ARRAY {Allocator()->Adapter()}; insertingNodes_.swap(insertingNodes); auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE); @@ -390,7 +390,7 @@ ir::AstNode *ETSParser::CreateFormattedClassFieldDefinition(std::string_view sou ir::AstNode *ETSParser::CreateFormattedClassMethodDefinition(std::string_view sourceCode, std::vector &insertingNodes) { - static ArenaVector const DUMMY_ARRAY {Allocator()->Adapter()}; + thread_local static ArenaVector const DUMMY_ARRAY {Allocator()->Adapter()}; insertingNodes_.swap(insertingNodes); auto *const property = CreateClassElement(sourceCode, DUMMY_ARRAY, ir::ClassDefinitionModifiers::NONE); diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 6a1ca88c8b..d5b3151150 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -133,7 +133,7 @@ void ETSParser::ParseProgram(ScriptKind kind) if ((GetContext().Status() & parser::ParserStatus::DEPENDENCY_ANALYZER_MODE) == 0) { script = ParseETSGlobalScript(startLoc, statements); } else { - script = ParseImportsOnly(startLoc, statements); + script = ParseImportsAndReExportOnly(startLoc, statements); } if ((GetContext().Status() & ParserStatus::IN_PACKAGE) != 0) { @@ -167,7 +167,8 @@ ir::ETSModule *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, A return etsModule; } -ir::ETSModule *ETSParser::ParseImportsOnly(lexer::SourcePosition startLoc, ArenaVector &statements) +ir::ETSModule *ETSParser::ParseImportsAndReExportOnly(lexer::SourcePosition startLoc, + ArenaVector &statements) { ETSNolintParser etsnolintParser(this); etsnolintParser.CollectETSNolints(); @@ -224,11 +225,20 @@ ArenaVector ETSParser::ParseDefaultSources(std::stri std::vector programs; auto *ctx = GetProgram()->VarBinder()->GetContext(); - if (ctx->compilingState != public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { - programs = ParseSources(); - AddExternalSource(programs); + if (ctx->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { + return statements; } + if (!Context()->compiledByCapi) { + AddExternalSource(ParseSources()); + } else { + if (Context()->globalContext != nullptr && Context()->globalContext->stdLibAstCache != nullptr) { + globalProgram_->MergeExternalSource(Context()->globalContext->stdLibAstCache); + importPathManager_->ClearParseList(); + } else { + AddExternalSource(ParseSources()); + } + } return statements; } @@ -279,6 +289,25 @@ static bool SearchImportedExternalSources(ETSParser *parser, const std::string_v return false; } +bool ETSParser::TryMergeFromCache(size_t idx, ArenaVector &parseList) +{ + if (Context()->globalContext == nullptr) { + return false; + } + + auto &importData = parseList[idx].importData; + auto src = importData.HasSpecifiedDeclPath() ? importData.declPath : importData.resolvedSource; + const auto &absPath = std::string {util::Path {src, Allocator()}.GetAbsolutePath()}; + auto cacheExtProgs = Context()->globalContext->cachedExternalPrograms; + if (cacheExtProgs.find(absPath) != cacheExtProgs.end() && cacheExtProgs[absPath] != nullptr) { + if (globalProgram_->MergeExternalSource(cacheExtProgs[absPath])) { + importPathManager_->MarkAsParsed(parseList[idx].importData.resolvedSource); + return true; + } + } + return false; +} + // NOTE (mmartin): Need a more optimal solution here // This is needed, as during a parsing of a file, programs can be re-added to the parseList, which needs to be // re-parsed. This won't change the size of the list, so with only the 'for loop', there can be unparsed files @@ -300,6 +329,11 @@ std::vector ETSParser::SearchForNotParsed(ArenaVectorMarkAsParsed(data.resolvedSource); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 6c905bafe6..6ca2d6d6c8 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -203,11 +203,13 @@ private: ArenaVector ParseImportDeclarations(); ir::Statement *ParseImportDeclarationHelper(lexer::SourcePosition startLoc, ArenaVector &specifiers, ir::ImportKinds importKind); + bool TryMergeFromCache(size_t idx, ArenaVector &parseList); std::vector SearchForNotParsed(ArenaVector &parseList, ArenaVector &directImportsFromMainSource); parser::Program *ParseSource(const SourceFile &sourceFile); ir::ETSModule *ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements); - ir::ETSModule *ParseImportsOnly(lexer::SourcePosition startLoc, ArenaVector &statements); + ir::ETSModule *ParseImportsAndReExportOnly(lexer::SourcePosition startLoc, + ArenaVector &statements); ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; void *ApplyAnnotationsToClassElement(ir::AstNode *property, ArenaVector &&annotations, lexer::SourcePosition pos); diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index c1dc7c92e0..ec767160ae 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -821,7 +821,6 @@ ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::Modi return nullptr; } method->AddModifier(ir::ModifierFlags::PUBLIC); - method->SetRange({Lexer()->GetToken().Start(), method->Id()->End()}); if (methodKind == ir::MethodDefinitionKind::GET) { method->Id()->SetAccessor(); method->Function()->AddFlag(ir::ScriptFunctionFlags::GETTER); diff --git a/ets2panda/parser/ETSparserNamespaces.cpp b/ets2panda/parser/ETSparserNamespaces.cpp index ea4a8feb4b..5024059997 100644 --- a/ets2panda/parser/ETSparserNamespaces.cpp +++ b/ets2panda/parser/ETSparserNamespaces.cpp @@ -82,7 +82,7 @@ ir::ETSModule *ETSParser::ParseNamespaceImp(ir::ModifierFlags flags) if ((flags & ir::ModifierFlags::DECLARE) != 0) { child->AddModifier(ir::ModifierFlags::DECLARE); } - parent->Statements().emplace_back(child); + parent->AddStatement(child); parent = child; } ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); diff --git a/ets2panda/parser/ETSparserTypes.cpp b/ets2panda/parser/ETSparserTypes.cpp index c88b813839..1ee35142fd 100644 --- a/ets2panda/parser/ETSparserTypes.cpp +++ b/ets2panda/parser/ETSparserTypes.cpp @@ -390,7 +390,7 @@ std::pair ETSParser::GetTypeAnnotationFromParentheses(Type return std::make_pair(typeAnnotation, true); } -static bool IsSimpleReturnThis(lexer::Token const &tokenAfterThis) +bool IsSimpleReturnThis(lexer::Token const &tokenAfterThis) { return (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_ARROW) || (tokenAfterThis.Type() == lexer::TokenType::PUNCTUATOR_COMMA) || diff --git a/ets2panda/parser/parserImpl.h b/ets2panda/parser/parserImpl.h index d64de90591..c71ad06628 100644 --- a/ets2panda/parser/parserImpl.h +++ b/ets2panda/parser/parserImpl.h @@ -37,6 +37,10 @@ class Options; class SourcePositionHelper; } // namespace ark::es2panda::util +namespace ark::es2panda::public_lib { +struct Context; +} // namespace ark::es2panda::public_lib + namespace ark::es2panda::parser { using ENUMBITOPS_OPERATORS; @@ -101,6 +105,16 @@ public: lexer::SourcePosition GetPositionForDiagnostic() const; + void SetContext(public_lib::Context *ctx) + { + ctx_ = ctx; + } + + public_lib::Context *Context() + { + return ctx_; + } + protected: virtual void ParseProgram(ScriptKind kind); static ExpressionParseFlags CarryExpressionParserFlag(ExpressionParseFlags origin, ExpressionParseFlags carry); @@ -569,6 +583,7 @@ private: lexer::Lexer *lexer_ {}; const util::Options *options_; util::DiagnosticEngine &diagnosticEngine_; + public_lib::Context *ctx_ {nullptr}; }; } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/program/program.cpp b/ets2panda/parser/program/program.cpp index 3d6ecb19e6..572ce976dc 100644 --- a/ets2panda/parser/program/program.cpp +++ b/ets2panda/parser/program/program.cpp @@ -25,18 +25,52 @@ #include "ir/base/classDefinition.h" #include "ir/statements/blockStatement.h" +#include + namespace ark::es2panda::parser { Program::Program(ArenaAllocator *allocator, varbinder::VarBinder *varbinder) : allocator_(allocator), - varbinder_(varbinder), externalSources_(allocator_->Adapter()), directExternalSources_(allocator_->Adapter()), extension_(varbinder->Extension()), etsnolintCollection_(allocator_->Adapter()), cfg_(allocator_->New(allocator_)), - functionScopes_(allocator_->Adapter()) + functionScopes_(allocator_->Adapter()), + varbinders_(allocator_->Adapter()), + checkers_(allocator_->Adapter()) +{ + PushVarBinder(varbinder); +} + +void Program::PushVarBinder(varbinder::VarBinder *varbinder) +{ + varbinders_.insert({compiler::GetPhaseManager()->GetCurrentMajor(), varbinder}); +} + +const varbinder::VarBinder *Program::VarBinder() const +{ + return varbinders_.at(compiler::GetPhaseManager()->GetCurrentMajor()); +} + +varbinder::VarBinder *Program::VarBinder() +{ + return varbinders_.at(compiler::GetPhaseManager()->GetCurrentMajor()); +} + +checker::Checker *Program::Checker() +{ + return checkers_.at(compiler::GetPhaseManager()->GetCurrentMajor()); +} + +void Program::PushChecker(checker::Checker *checker) +{ + checkers_.push_back(checker); +} + +const checker::Checker *Program::Checker() const { + return checkers_.at(compiler::GetPhaseManager()->GetCurrentMajor()); } std::string Program::Dump() const @@ -53,16 +87,16 @@ void Program::DumpSilent() const varbinder::ClassScope *Program::GlobalClassScope() { - ES2PANDA_ASSERT(globalClass_ != nullptr); - ES2PANDA_ASSERT(globalClass_->Scope() != nullptr); - return globalClass_->Scope()->AsClassScope(); + ES2PANDA_ASSERT(GlobalClass() != nullptr); + ES2PANDA_ASSERT(GlobalClass()->Scope() != nullptr); + return GlobalClass()->Scope()->AsClassScope(); } const varbinder::ClassScope *Program::GlobalClassScope() const { - ES2PANDA_ASSERT(globalClass_ != nullptr); - ES2PANDA_ASSERT(globalClass_->Scope() != nullptr); - return globalClass_->Scope()->AsClassScope(); + ES2PANDA_ASSERT(GlobalClass() != nullptr); + ES2PANDA_ASSERT(GlobalClass()->Scope() != nullptr); + return GlobalClass()->Scope()->AsClassScope(); } varbinder::GlobalScope *Program::GlobalScope() @@ -157,9 +191,40 @@ compiler::CFG *Program::GetCFG() return cfg_; } +ir::ClassDefinition *Program::GlobalClass() +{ + return ast_->AsETSModule()->GlobalClass(); +} + +const ir::ClassDefinition *Program::GlobalClass() const +{ + return ast_->AsETSModule()->GlobalClass(); +} + +void Program::SetGlobalClass(ir::ClassDefinition *globalClass) +{ + ast_->AsETSModule()->SetGlobalClass(globalClass); +} + const compiler::CFG *Program::GetCFG() const { return cfg_; } +bool Program::MergeExternalSource(const ExternalSource *externalSource) +{ + // prevent using cache for cycle import + for (const auto &[moduleName, _] : *externalSource) { + if (ModuleName() == moduleName) { + return false; + } + } + + for (const auto &[moduleName, extProgs] : *externalSource) { + externalSources_.emplace(moduleName, extProgs); + } + + return true; +} + } // namespace ark::es2panda::parser diff --git a/ets2panda/parser/program/program.h b/ets2panda/parser/program/program.h index d3e0ac67a6..c29543942c 100644 --- a/ets2panda/parser/program/program.h +++ b/ets2panda/parser/program/program.h @@ -27,6 +27,7 @@ #include "util/enumbitops.h" #include +#include namespace ark::es2panda::ir { class BlockStatement; @@ -41,6 +42,10 @@ namespace ark::es2panda::compiler { class CFG; } // namespace ark::es2panda::compiler +namespace ark::es2panda::checker { +class Checker; +} // namespace ark::es2panda::checker + namespace ark::es2panda::parser { enum class ScriptKind { SCRIPT, MODULE, STDLIB }; enum EntityType { CLASS_PROPERTY = 0, METHOD_DEFINITION = 1, CLASS_DEFINITION = 2, TS_INTERFACE_DECLARATION = 3 }; @@ -98,20 +103,16 @@ public: return allocator_; } - const varbinder::VarBinder *VarBinder() const - { - return varbinder_; - } + void PushVarBinder(varbinder::VarBinder *varbinder); - varbinder::VarBinder *VarBinder() - { - return varbinder_; - } + const varbinder::VarBinder *VarBinder() const; - void SetVarBinder(varbinder::VarBinder *varbinder) - { - varbinder_ = varbinder; - } + varbinder::VarBinder *VarBinder(); + + checker::Checker *Checker(); + const checker::Checker *Checker() const; + + void PushChecker(checker::Checker *checker); ScriptExtension Extension() const { @@ -190,20 +191,11 @@ public: MaybeTransformToDeclarationModule(); } - ir::ClassDefinition *GlobalClass() - { - return globalClass_; - } + ir::ClassDefinition *GlobalClass(); - const ir::ClassDefinition *GlobalClass() const - { - return globalClass_; - } + const ir::ClassDefinition *GlobalClass() const; - void SetGlobalClass(ir::ClassDefinition *globalClass) - { - globalClass_ = globalClass; - } + void SetGlobalClass(ir::ClassDefinition *globalClass); ExternalSource &ExternalSources() { @@ -289,6 +281,16 @@ public: void SetASTChecked(); bool IsASTChecked(); + void MarkASTAsLowered() + { + isASTlowered_ = true; + } + + bool IsASTLowered() const + { + return isASTlowered_; + } + bool IsStdLib() const { // NOTE (hurton): temporary solution, needs rework when std sources are renamed @@ -315,6 +317,8 @@ public: return declGenExportNodes_; } + bool MergeExternalSource(const ExternalSource *externalSource); + void AddDeclGenExportNode(const std::string &declGenExportStr, ir::AstNode *node) { declGenExportNodes_.emplace_back(declGenExportStr, node); @@ -367,10 +371,9 @@ public: private: void MaybeTransformToDeclarationModule(); +private: ArenaAllocator *allocator_ {}; - varbinder::VarBinder *varbinder_ {nullptr}; ir::BlockStatement *ast_ {}; - ir::ClassDefinition *globalClass_ {}; util::StringView sourceCode_ {}; util::Path sourceFile_ {}; util::StringView sourceFileFolder_ {}; @@ -382,12 +385,16 @@ private: ScriptExtension extension_ {}; ETSNolintsCollectionMap etsnolintCollection_; util::ModuleInfo moduleInfo_; + bool isASTlowered_ {}; lexer::SourcePosition packageStartPosition_ {}; compiler::CFG *cfg_; std::vector> declGenExportNodes_; ArenaVector functionScopes_; std::unordered_map> fileDependencies_; +private: + ArenaMap varbinders_; + ArenaVector checkers_; #ifndef NDEBUG uint32_t poisonValue_ {POISON_VALUE}; #endif diff --git a/ets2panda/public/cppToCTypes.yaml b/ets2panda/public/cppToCTypes.yaml index 37cbb764e9..10e1650666 100644 --- a/ets2panda/public/cppToCTypes.yaml +++ b/ets2panda/public/cppToCTypes.yaml @@ -1942,7 +1942,7 @@ change_types: max_ptr_depth: 1 new_args: cast: - expression: auto |es2panda_arg.type.ptr_depth||arg_name|E2p = reinterpret_cast(context)->checker; + expression: auto |es2panda_arg.type.ptr_depth||arg_name|E2p = reinterpret_cast(context)->GetChecker(); call_cast: start: >- (reinterpret_cast(context)->checker)-> @@ -1997,7 +1997,7 @@ change_types: new_args: cast: expression: >- - auto *|arg_name|E2p = reinterpret_cast(context)->checker->AsETSChecker(); + auto *|arg_name|E2p = reinterpret_cast(context)->GetChecker()->AsETSChecker(); call_cast: start: >- (reinterpret_cast(context)->checker->AsETSChecker())-> diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 68c404993f..8df91d24af 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -243,10 +243,24 @@ __attribute__((unused)) char const *ArenaStrdup(ArenaAllocator *allocator, char return res; } -extern "C" es2panda_Config *CreateConfig(int args, char const *const *argv) +extern "C" void MemInitialize() { + if (mem::MemConfig::IsInitialized()) { + return; + } mem::MemConfig::Initialize(0, 0, COMPILER_SIZE, 0, 0, 0); PoolManager::Initialize(PoolType::MMAP); +} + +extern "C" void MemFinalize() +{ + PoolManager::Finalize(); + mem::MemConfig::Finalize(); +} + +extern "C" es2panda_Config *CreateConfig(int args, char const *const *argv) +{ + MemInitialize(); auto diagnosticEngine = new util::DiagnosticEngine(); auto *options = new util::Options(argv[0], *diagnosticEngine); if (!options->Parse(Span(argv, args))) { @@ -264,9 +278,6 @@ extern "C" es2panda_Config *CreateConfig(int args, char const *const *argv) extern "C" void DestroyConfig(es2panda_Config *config) { - PoolManager::Finalize(); - mem::MemConfig::Finalize(); - auto *cfg = reinterpret_cast(config); if (cfg == nullptr) { return; @@ -294,15 +305,81 @@ static void CompileJob(public_lib::Context *context, varbinder::FunctionScope *s funcEmitter.Generate(); } +static void GenerateStdLibCache(es2panda_Config *config, GlobalContext *globalContext, bool LspUsage); + +extern "C" __attribute__((unused)) es2panda_GlobalContext *CreateGlobalContext(es2panda_Config *config, + const char **externalFileList, + size_t fileNum, bool LspUsage) +{ + auto *globalContext = new GlobalContext; + for (size_t i = 0; i < fileNum; i++) { + auto fileName = externalFileList[i]; + auto globalAllocator = new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + globalContext->cachedExternalPrograms.emplace(fileName, nullptr); + globalContext->externalProgramAllocators.emplace(fileName, globalAllocator); + } + + GenerateStdLibCache(config, globalContext, LspUsage); + + return reinterpret_cast(globalContext); +} + +extern "C" __attribute__((unused)) void RemoveFileCache(es2panda_GlobalContext *globalContext, const char *fileName) +{ + auto globalCtx = reinterpret_cast(globalContext); + ES2PANDA_ASSERT(globalCtx->cachedExternalPrograms.count(fileName) == 1); + globalCtx->cachedExternalPrograms.erase(fileName); + delete globalCtx->externalProgramAllocators[fileName]; + globalCtx->externalProgramAllocators.erase(fileName); +} + +extern "C" __attribute__((unused)) void AddFileCache(es2panda_GlobalContext *globalContext, const char *fileName) +{ + auto globalCtx = reinterpret_cast(globalContext); + ES2PANDA_ASSERT(globalCtx->cachedExternalPrograms.count(fileName) == 0); + auto globalAllocator = new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + globalCtx->cachedExternalPrograms.emplace(fileName, nullptr); + globalCtx->externalProgramAllocators.emplace(fileName, globalAllocator); +} + +extern "C" __attribute__((unused)) void InvalidateFileCache(es2panda_GlobalContext *globalContext, const char *fileName) +{ + RemoveFileCache(globalContext, fileName); + AddFileCache(globalContext, fileName); +} + +static void InitializeContext(Context *res) +{ + res->phaseManager = new compiler::PhaseManager(res, ScriptExtension::ETS, res->allocator); + res->queue = new compiler::CompileQueue(res->config->options->GetThread()); + + auto *varbinder = res->allocator->New(res->allocator); + res->parserProgram = res->allocator->New(res->allocator, varbinder); + res->parser = new parser::ETSParser(res->parserProgram, *res->config->options, *res->diagnosticEngine, + parser::ParserStatus::NO_OPTS); + res->parser->SetContext(res); + + res->PushChecker(res->allocator->New(res->allocator, *res->diagnosticEngine, res->allocator)); + res->isolatedDeclgenChecker = new checker::IsolatedDeclgenChecker(*res->diagnosticEngine, *(res->parserProgram)); + res->PushAnalyzer(res->allocator->New(res->GetChecker())); + res->GetChecker()->SetAnalyzer(res->GetAnalyzer()); + + varbinder->SetProgram(res->parserProgram); + varbinder->SetContext(res); + res->codeGenCb = CompileJob; + res->emitter = new compiler::ETSEmitter(res); + res->program = nullptr; + res->state = ES2PANDA_STATE_NEW; +} + __attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config *config, std::string &&source, - const char *fileName) + const char *fileName, + es2panda_GlobalContext *globalContext, bool isExternal, + bool genStdLib) { auto *cfg = reinterpret_cast(config); auto *res = new Context; - res->input = std::move(source); - res->sourceFileName = fileName; - res->config = cfg; - + res->compiledByCapi = true; if (cfg == nullptr) { res->errorMessage = "Config is nullptr."; res->state = ES2PANDA_STATE_ERROR; @@ -312,61 +389,88 @@ __attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config * if (cfg->options->GetExtension() != ScriptExtension::ETS) { res->errorMessage = "Invalid extension. Plugin API supports only ETS."; res->state = ES2PANDA_STATE_ERROR; + res->diagnosticEngine = cfg->diagnosticEngine; return reinterpret_cast(res); } - res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->IsModule()); - res->allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); - res->queue = new compiler::CompileQueue(cfg->options->GetThread()); - - auto *varbinder = res->allocator->New(res->allocator); - res->parserProgram = new parser::Program(res->allocator, varbinder); + res->config = cfg; + res->isExternal = isExternal; + res->globalContext = reinterpret_cast(globalContext); res->diagnosticEngine = cfg->diagnosticEngine; - res->parser = - new parser::ETSParser(res->parserProgram, *cfg->options, *cfg->diagnosticEngine, parser::ParserStatus::NO_OPTS); - res->checker = new checker::ETSChecker(*res->diagnosticEngine); - res->isolatedDeclgenChecker = new checker::IsolatedDeclgenChecker(*res->diagnosticEngine, *(res->parserProgram)); - res->analyzer = new checker::ETSAnalyzer(res->checker); - res->checker->SetAnalyzer(res->analyzer); - varbinder->SetProgram(res->parserProgram); + res->input = std::move(source); + res->sourceFileName = fileName; + res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->IsModule()); + if (isExternal) { + ir::EnableContextHistory(); + ES2PANDA_ASSERT(res->globalContext != nullptr); + if (genStdLib) { + ES2PANDA_ASSERT(res->globalContext->stdLibAllocator != nullptr); + res->allocator = res->globalContext->stdLibAllocator; + } else { + ES2PANDA_ASSERT(res->globalContext->externalProgramAllocators.count(fileName) != 0); + res->allocator = + reinterpret_cast(res->globalContext->externalProgramAllocators[fileName]); + } + } else { + ir::DisableContextHistory(); + res->allocator = new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + } - varbinder->SetContext(res); - res->codeGenCb = CompileJob; - res->phaseManager = new compiler::PhaseManager(ScriptExtension::ETS, res->allocator); - res->emitter = new compiler::ETSEmitter(res); - res->program = nullptr; - res->state = ES2PANDA_STATE_NEW; + InitializeContext(res); return reinterpret_cast(res); } -extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromFile(es2panda_Config *config, - char const *sourceFileName) +__attribute__((unused)) static std::stringstream ReadFile(char const *sourceFileName, Context *&res) { std::ifstream inputStream; inputStream.open(sourceFileName); if (inputStream.fail()) { - auto *res = new Context; + res = new Context; res->errorMessage = "Failed to open file: "; res->errorMessage.append(sourceFileName); - return reinterpret_cast(res); } std::stringstream ss; ss << inputStream.rdbuf(); if (inputStream.fail()) { - auto *res = new Context; + res = new Context; res->errorMessage = "Failed to read file: "; res->errorMessage.append(sourceFileName); + } + return ss; +} + +extern "C" __attribute__((unused)) es2panda_Context *CreateCacheContextFromFile(es2panda_Config *config, + char const *sourceFileName, + es2panda_GlobalContext *globalContext, + bool isExternal) +{ + Context *res = nullptr; + auto ss = ReadFile(sourceFileName, res); + if (res != nullptr) { + return reinterpret_cast(res); + } + return CreateContext(config, ss.str(), sourceFileName, globalContext, isExternal, false); +} + +extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromFile(es2panda_Config *config, + char const *sourceFileName) +{ + Context *res = nullptr; + auto ss = ReadFile(sourceFileName, res); + if (res != nullptr) { return reinterpret_cast(res); + ; } - return CreateContext(config, ss.str(), sourceFileName); + + return CreateContext(config, ss.str(), sourceFileName, nullptr, false, false); } extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2panda_Config *config, const char *source, char const *fileName) { // NOTE: gogabr. avoid copying source. - return CreateContext(config, std::string(source), fileName); + return CreateContext(config, std::string(source), fileName, nullptr, false, false); } __attribute__((unused)) static Context *Parse(Context *ctx) @@ -377,10 +481,28 @@ __attribute__((unused)) static Context *Parse(Context *ctx) return ctx; } - ctx->phaseManager->Restart(); - ctx->parser->ParseScript(*ctx->sourceFile, - ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); - ctx->state = ES2PANDA_STATE_PARSED; + ctx->phaseManager->Reset(); + if (ctx->isExternal && ctx->allocator != ctx->globalContext->stdLibAllocator) { + auto allocator = ctx->allocator; + auto ident = allocator->New(compiler::Signatures::ETS_GLOBAL, allocator); + ArenaVector stmts(allocator->Adapter()); + auto etsModule = allocator->New(allocator, std::move(stmts), ident, ir::ModuleFlag::ETSSCRIPT, + ctx->parserProgram); + ctx->parserProgram->SetAst(etsModule); + util::ImportPathManager::ImportMetadata importData {util::ImportFlags::NONE}; + importData.resolvedSource = ctx->sourceFileName; + importData.lang = Language::Id::ETS; + importData.declPath = util::ImportPathManager::DUMMY_PATH; + importData.ohmUrl = util::ImportPathManager::DUMMY_PATH; + ctx->parser->AsETSParser()->GetImportPathManager()->AddToParseList(importData); + ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources(true)); + } else { + ctx->parser->ParseScript(*ctx->sourceFile, + ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); + } + ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_PARSED : ES2PANDA_STATE_ERROR; + ctx->diagnosticEngine->FlushDiagnostic(); + ctx->phaseManager->SetCurrentPhaseIdToAfterParse(); return ctx; } @@ -411,6 +533,7 @@ __attribute__((unused)) static Context *Check(Context *ctx) } if (ctx->state == ES2PANDA_STATE_ERROR) { + ctx->diagnosticEngine->FlushDiagnostic(); return ctx; } @@ -421,10 +544,32 @@ __attribute__((unused)) static Context *Check(Context *ctx) } phase->Apply(ctx, ctx->parserProgram); } + ctx->phaseManager->SetCurrentPhaseIdToAfterCheck(); ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_CHECKED : ES2PANDA_STATE_ERROR; return ctx; } +__attribute__((unused)) static void SaveCache(Context *ctx) +{ + if (ctx->allocator == ctx->globalContext->stdLibAllocator) { + return; + } + ES2PANDA_ASSERT(ctx->globalContext != nullptr && + ctx->globalContext->cachedExternalPrograms.count(ctx->sourceFileName) != 0); + ctx->globalContext->cachedExternalPrograms[ctx->sourceFileName] = &(ctx->parserProgram->ExternalSources()); + + // cycle dependencies + for (auto &[_, extPrograms] : ctx->parserProgram->ExternalSources()) { + for (auto extProgram : extPrograms) { + auto absPath = std::string {extProgram->AbsoluteName()}; + auto &cacheMap = ctx->globalContext->cachedExternalPrograms; + if (cacheMap.count(absPath) == 1 && cacheMap[absPath] == nullptr) { + cacheMap[absPath] = &(ctx->parserProgram->ExternalSources()); + } + } + } +} + __attribute__((unused)) static Context *Lower(Context *ctx) { if (ctx->state < ES2PANDA_STATE_CHECKED) { @@ -432,6 +577,7 @@ __attribute__((unused)) static Context *Lower(Context *ctx) } if (ctx->state == ES2PANDA_STATE_ERROR) { + ctx->diagnosticEngine->FlushDiagnostic(); return ctx; } @@ -440,6 +586,18 @@ __attribute__((unused)) static Context *Lower(Context *ctx) phase->Apply(ctx, ctx->parserProgram); } ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_LOWERED : ES2PANDA_STATE_ERROR; + + for (auto &[_, extPrograms] : ctx->parserProgram->ExternalSources()) { + for (auto &extProgram : extPrograms) { + if (!extProgram->IsASTLowered()) { + extProgram->MarkASTAsLowered(); + } + } + } + if (ctx->isExternal) { + SaveCache(ctx); + } + return ctx; } @@ -527,6 +685,10 @@ extern "C" __attribute__((unused)) es2panda_Context *ProceedToState(es2panda_Con ctx->state = ES2PANDA_STATE_ERROR; break; } + + if (ctx->state == ES2PANDA_STATE_ERROR) { + ctx->diagnosticEngine->FlushDiagnostic(); + } return reinterpret_cast(ctx); } @@ -535,17 +697,27 @@ extern "C" __attribute__((unused)) void DestroyContext(es2panda_Context *context auto *ctx = reinterpret_cast(context); delete ctx->program; delete ctx->emitter; - delete ctx->analyzer; - delete ctx->checker; delete ctx->parser; - delete ctx->parserProgram; delete ctx->queue; - delete ctx->allocator; delete ctx->sourceFile; delete ctx->phaseManager; + if (!ctx->isExternal) { + delete ctx->allocator; + } delete ctx; } +extern "C" __attribute__((unused)) void DestroyGlobalContext(es2panda_GlobalContext *globalContext) +{ + auto *globalCtx = reinterpret_cast(globalContext); + for (auto [_, alloctor] : globalCtx->externalProgramAllocators) { + delete alloctor; + } + + delete globalCtx->stdLibAllocator; + delete globalCtx; +} + extern "C" __attribute__((unused)) es2panda_ContextState ContextState(es2panda_Context *context) { auto *s = reinterpret_cast(context); @@ -837,7 +1009,7 @@ extern "C" void AstNodeRecheck(es2panda_Context *ctx, es2panda_AstNode *node) auto E2pNode = reinterpret_cast(node); auto context = reinterpret_cast(ctx); auto varbinder = context->parserProgram->VarBinder()->AsETSBinder(); - auto checker = context->checker->AsETSChecker(); + auto checker = context->GetChecker()->AsETSChecker(); auto phaseManager = context->phaseManager; if (E2pNode->IsScriptFunction() || E2pNode->FindChild([](ir::AstNode *n) { return n->IsScriptFunction(); }) != nullptr) { @@ -1000,7 +1172,7 @@ extern "C" __attribute__((unused)) int GenerateTsDeclarationsFromContext(es2pand const char *outputEts, bool exportAll) { auto *ctxImpl = reinterpret_cast(ctx); - auto *checker = reinterpret_cast(ctxImpl->checker); + auto *checker = reinterpret_cast(ctxImpl->GetChecker()); ark::es2panda::declgen_ets2ts::DeclgenOptions declgenOptions; declgenOptions.exportAll = exportAll; @@ -1032,7 +1204,8 @@ extern "C" void InsertETSImportDeclarationAndParse(es2panda_Context *context, es auto *importDeclE2p = reinterpret_cast(importDeclaration); importDeclE2p->AddAstNodeFlags(ir::AstNodeFlags::NOCLEANUP); - parserProgram->Ast()->Statements().insert(parserProgram->Ast()->Statements().begin(), importDeclE2p); + auto &stmt = parserProgram->Ast()->StatementsForUpdates(); + stmt.insert(stmt.begin(), importDeclE2p); importDeclE2p->SetParent(parserProgram->Ast()); ctx->parser->AsETSParser()->AddExternalSource(ctx->parser->AsETSParser()->ParseSources()); @@ -1042,16 +1215,40 @@ extern "C" void InsertETSImportDeclarationAndParse(es2panda_Context *context, es } } +__attribute__((unused)) static void GenerateStdLibCache(es2panda_Config *config, GlobalContext *globalContext, + bool LspUsage) +{ + auto cfg = reinterpret_cast(config); + globalContext->stdLibAllocator = new ThreadSafeArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + auto ctx = CreateContext(config, std::move(""), cfg->options->SourceFileName().c_str(), + reinterpret_cast(globalContext), true, true); + ProceedToState(ctx, es2panda_ContextState::ES2PANDA_STATE_CHECKED); + if (!LspUsage) { + AstNodeRecheck(ctx, + reinterpret_cast(reinterpret_cast(ctx)->parserProgram->Ast())); + AstNodeRecheck(ctx, + reinterpret_cast(reinterpret_cast(ctx)->parserProgram->Ast())); + } + ProceedToState(ctx, es2panda_ContextState::ES2PANDA_STATE_LOWERED); + globalContext->stdLibAstCache = &(reinterpret_cast(ctx)->parserProgram->ExternalSources()); + DestroyContext(ctx); +} + es2panda_Impl g_impl = { ES2PANDA_LIB_VERSION, + MemInitialize, + MemFinalize, CreateConfig, DestroyConfig, ConfigGetOptions, CreateContextFromFile, + CreateCacheContextFromFile, CreateContextFromString, ProceedToState, DestroyContext, + CreateGlobalContext, + DestroyGlobalContext, ContextState, ContextErrorMessage, ContextProgram, @@ -1101,6 +1298,9 @@ es2panda_Impl g_impl = { GenerateTsDeclarationsFromContext, InsertETSImportDeclarationAndParse, GenerateStaticDeclarationsFromContext, + InvalidateFileCache, + RemoveFileCache, + AddFileCache, #include "generated/es2panda_lib/es2panda_lib_list.inc" diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index b331f56829..cf927443b4 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -43,6 +43,7 @@ extern "C" { typedef struct es2panda_Config es2panda_Config; typedef struct es2panda_Context es2panda_Context; +typedef struct es2panda_GlobalContext es2panda_GlobalContext; typedef struct es2panda_variantDoubleCharArrayBool { int index; @@ -175,15 +176,24 @@ typedef enum es2panda_ContextState es2panda_ContextState; struct CAPI_EXPORT es2panda_Impl { int version; + void (*MemInitialize)(); + void (*MemFinalize)(); + es2panda_Config *(*CreateConfig)(int argc, char const *const *argv); void (*DestroyConfig)(es2panda_Config *config); const es2panda_Options *(*ConfigGetOptions)(es2panda_Config *config); es2panda_Context *(*CreateContextFromFile)(es2panda_Config *config, char const *source_file_name); + es2panda_Context *(*CreateCacheContextFromFile)(es2panda_Config *config, char const *source_file_name, + es2panda_GlobalContext *globalContext, bool isExternal); es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name); es2panda_Context *(*ProceedToState)(es2panda_Context *context, es2panda_ContextState state); // context is consumed void (*DestroyContext)(es2panda_Context *context); + es2panda_GlobalContext *(*CreateGlobalContext)(es2panda_Config *config, const char **externalFileList, + size_t fileNum, bool LspUsage); + void (*DestroyGlobalContext)(es2panda_GlobalContext *globalContext); + es2panda_ContextState (*ContextState)(es2panda_Context *context); char const *(*ContextErrorMessage)(es2panda_Context *context); @@ -257,6 +267,9 @@ struct CAPI_EXPORT es2panda_Impl { es2panda_AstNode *importDeclaration); int (*GenerateStaticDeclarationsFromContext)(es2panda_Context *context, const char *outputPath); + void (*InvalidateFileCache)(es2panda_GlobalContext *globalContext, const char *fileName); + void (*RemoveFileCache)(es2panda_GlobalContext *globalContext, const char *fileName); + void (*AddFileCache)(es2panda_GlobalContext *globalContext, const char *fileName); // CC-OFFNXT(G.INC.08) project code style #include "generated/es2panda_lib/es2panda_lib_decl.inc" }; diff --git a/ets2panda/public/public.cpp b/ets2panda/public/public.cpp new file mode 100644 index 0000000000..3b3754328b --- /dev/null +++ b/ets2panda/public/public.cpp @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "public/public.h" +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::public_lib { + +checker::Checker *Context::GetChecker() const +{ + return checkers_[compiler::GetPhaseManager()->GetCurrentMajor()]; +} + +checker::SemanticAnalyzer *Context::GetAnalyzer() const +{ + return analyzers_[compiler::GetPhaseManager()->GetCurrentMajor()]; +} + +} // namespace ark::es2panda::public_lib diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index fdb18d9ca6..46ddf91b4c 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -34,6 +34,8 @@ class Options; namespace ark::es2panda::compiler { class PhaseManager; +void SetPhaseManager(PhaseManager *phaseManager); +PhaseManager *GetPhaseManager(); } // namespace ark::es2panda::compiler namespace ark::es2panda::public_lib { @@ -52,14 +54,14 @@ struct ConfigImpl { }; using ExternalSources = std::unordered_map>; - +using ExternalSource = ArenaUnorderedMap>; using ComputedAbstracts = ArenaUnorderedMap, ArenaUnorderedSet>>; class TransitionMemory { public: - explicit TransitionMemory(ArenaAllocator *allocator) + explicit TransitionMemory(ThreadSafeArenaAllocator *allocator) : permanentAllocator_(allocator), compiledPrograms_(allocator->Adapter()) { compiledPrograms_ = {}; @@ -70,7 +72,7 @@ public: ~TransitionMemory() = default; - ArenaAllocator *PermanentAllocator() const + ThreadSafeArenaAllocator *PermanentAllocator() const { return permanentAllocator_.get(); } @@ -136,13 +138,20 @@ public: } private: - std::unique_ptr permanentAllocator_; + std::unique_ptr permanentAllocator_; ArenaVector compiledPrograms_; varbinder::VarBinder *varbinder_ {nullptr}; checker::GlobalTypesHolder *globalTypes_ {nullptr}; ComputedAbstracts *cachedComputedAbstracts_ {nullptr}; }; +struct GlobalContext { + std::unordered_map externalProgramAllocators; + std::unordered_map cachedExternalPrograms; + ThreadSafeArenaAllocator *stdLibAllocator = nullptr; + ExternalSource *stdLibAstCache = nullptr; +}; + struct Context { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) using CodeGenCb = @@ -160,11 +169,41 @@ struct Context { return util::NodeAllocator::ForceSetParent(Allocator(), std::forward(args)...); } + checker::Checker *GetChecker() const; + + void PushChecker(checker::Checker *checker) + { + parserProgram->PushChecker(checker); + checkers_.push_back(checker); + } + + void DestoryCheckers() + { + for (auto item : checkers_) { + delete item; + } + } + + checker::SemanticAnalyzer *GetAnalyzer() const; + + void PushAnalyzer(checker::SemanticAnalyzer *analyzer) + { + return analyzers_.push_back(analyzer); + } + + void DestoryAnalyzers() + { + for (auto item : analyzers_) { + delete item; + } + } + ConfigImpl *config = nullptr; + GlobalContext *globalContext = nullptr; std::string sourceFileName; std::string input; SourceFile const *sourceFile = nullptr; - ArenaAllocator *allocator = nullptr; + ThreadSafeArenaAllocator *allocator = nullptr; compiler::CompileQueue *queue = nullptr; std::vector const *plugins = nullptr; std::vector contextLiterals; @@ -173,10 +212,7 @@ struct Context { parser::Program *parserProgram = nullptr; parser::ParserImpl *parser = nullptr; - checker::Checker *checker = nullptr; - checker::IsolatedDeclgenChecker *isolatedDeclgenChecker = nullptr; - checker::SemanticAnalyzer *analyzer = nullptr; compiler::Emitter *emitter = nullptr; pandasm::Program *program = nullptr; util::DiagnosticEngine *diagnosticEngine = nullptr; @@ -188,8 +224,16 @@ struct Context { CompilingState compilingState {CompilingState::NONE_COMPILING}; ExternalSources externalSources; TransitionMemory *transitionMemory {nullptr}; + bool isExternal = false; + bool compiledByCapi = false; + checker::IsolatedDeclgenChecker *isolatedDeclgenChecker {nullptr}; // NOLINTEND(misc-non-private-member-variables-in-classes) + +private: + std::vector checkers_; + std::vector analyzers_; }; + } // namespace ark::es2panda::public_lib #endif diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_for_array_type01.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_for_array_type01.ets index 170649f36e..c2bf21da69 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_for_array_type01.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_for_array_type01.ets @@ -22,5 +22,5 @@ let array: @Anno @Anno Int[][] let deepArray: @Anno @Anno Number[][][][][] -/* @@? 21:19 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno' has already been applied to this element. */ -/* @@? 22:23 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno' has already been applied to this element. */ \ No newline at end of file +/* @@? 21:29 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno' has already been applied to this element. */ +/* @@? 22:42 Error TypeError: Duplicate annotations are not allowed. The annotation 'Anno' has already been applied to this element. */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/re_export/re_export_4.ets b/ets2panda/test/ast/parser/ets/re_export/re_export_4.ets index 32c944833a..399324e4b7 100644 --- a/ets2panda/test/ast/parser/ets/re_export/re_export_4.ets +++ b/ets2panda/test/ast/parser/ets/re_export/re_export_4.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -export {foo} from "./export" -export /* @@ label */{foo} from "./export_2" +export /* @@ label */{foo} from "./export" +export {foo} from "./export_2" /* @@@ label Error TypeError: Ambiguous export 'foo' */ diff --git a/ets2panda/test/parser/ets/getterOverride-expected.txt b/ets2panda/test/parser/ets/getterOverride-expected.txt index e223479634..64aef4f75f 100644 --- a/ets2panda/test/parser/ets/getterOverride-expected.txt +++ b/ets2panda/test/parser/ets/getterOverride-expected.txt @@ -132,13 +132,13 @@ "decorators": [], "loc": { "start": { - "line": 19, - "column": 1, + "line": 18, + "column": 15, "program": "getterOverride.ets" }, "end": { "line": 18, - "column": 15, + "column": 26, "program": "getterOverride.ets" } } diff --git a/ets2panda/test/parser/ets/re_export/import_10-expected.txt b/ets2panda/test/parser/ets/re_export/import_10-expected.txt index 186322d784..2152202423 100644 --- a/ets2panda/test/parser/ets/re_export/import_10-expected.txt +++ b/ets2panda/test/parser/ets/re_export/import_10-expected.txt @@ -374,4 +374,4 @@ } } } -TypeError: Ambiguous export 'foo' [re_export_4.ets:17:8] +TypeError: Ambiguous export 'foo' [re_export_4.ets:16:8] diff --git a/ets2panda/test/parser/ets/re_export/re_export_4-expected.txt b/ets2panda/test/parser/ets/re_export/re_export_4-expected.txt index 74a1b2496b..23266085b0 100644 --- a/ets2panda/test/parser/ets/re_export/re_export_4-expected.txt +++ b/ets2panda/test/parser/ets/re_export/re_export_4-expected.txt @@ -471,4 +471,4 @@ } } } -TypeError: Ambiguous export 'foo' [re_export_4.ets:17:8] +TypeError: Ambiguous export 'foo' [re_export_4.ets:16:8] diff --git a/ets2panda/test/runtime/ets/class_implements_interface_export.ets b/ets2panda/test/runtime/ets/class_implements_interface_export.ets new file mode 100644 index 0000000000..585718a5fa --- /dev/null +++ b/ets2panda/test/runtime/ets/class_implements_interface_export.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class A{} + +interface I { + a: boolean +} + +class B implements I { + a = false +} + diff --git a/ets2panda/test/runtime/ets/class_implements_interface_import.ets b/ets2panda/test/runtime/ets/class_implements_interface_import.ets new file mode 100644 index 0000000000..e779066f3c --- /dev/null +++ b/ets2panda/test/runtime/ets/class_implements_interface_import.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { A } from "./class_implements_interface_export" \ No newline at end of file diff --git a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt index 3888be099f..2e165ab582 100644 --- a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt +++ b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt @@ -102,3 +102,7 @@ ast/compiler/ets/lambda_infer_type/lambda_param_type_cannot_be_determined.ets # Issue: #24605 incorrect column ast/parser/ets/named_types_2.ets + +# +ast/parser/ets/partialGenericInterface.ets +ast/parser/ets/partialGenericInterface_n.ets \ No newline at end of file diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index 42b02135c1..218f408204 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -188,6 +188,8 @@ runtime/ets/exportDefault_1.ets runtime/ets/exportDefault_2.ets runtime/ets/declareExport.ets runtime/ets/implicit_stringliteral_init.ets +runtime/ets/mypackage/implicit_package_import_1.ets +runtime/ets/class_implements_interface_import.ets # #21051 should be log warnings, but there aren't ast/compiler/ets/not_initialized_variable/import_types.ets diff --git a/ets2panda/test/unit/lowerings/node_history.cpp b/ets2panda/test/unit/lowerings/node_history.cpp index c3b982aa63..8a8e6911a8 100644 --- a/ets2panda/test/unit/lowerings/node_history.cpp +++ b/ets2panda/test/unit/lowerings/node_history.cpp @@ -34,6 +34,7 @@ public: allocator_ = std::make_unique(SpaceType::SPACE_TYPE_COMPILER); phaseManager_ = std::make_unique(ScriptExtension::ETS, Allocator()); compiler::SetPhaseManager(phaseManager_.get()); + ir::EnableContextHistory(); } NO_COPY_SEMANTIC(NodeHistoryTest); @@ -54,12 +55,13 @@ private: std::unique_ptr phaseManager_; }; -constexpr int32_t PHASE_ID_0 = 0; -constexpr int32_t PHASE_ID_1 = 1; -constexpr int32_t PHASE_ID_2 = 2; -constexpr int32_t PHASE_ID_3 = 3; -constexpr int32_t PHASE_ID_4 = 4; -constexpr int32_t PHASE_ID_5 = 5; +constexpr compiler::PhaseId PARSER_PHASE_ID = {0, compiler::PARSER_PHASE_ID}; +constexpr compiler::PhaseId PHASE_ID_0 = {0, 0}; +constexpr compiler::PhaseId PHASE_ID_1 = {0, 1}; +constexpr compiler::PhaseId PHASE_ID_2 = {0, 2}; +constexpr compiler::PhaseId PHASE_ID_3 = {0, 3}; +constexpr compiler::PhaseId PHASE_ID_4 = {0, 4}; +constexpr compiler::PhaseId PHASE_ID_5 = {0, 5}; constexpr int32_t INDEX_0 = 0; constexpr int32_t INDEX_1 = 1; @@ -149,26 +151,26 @@ TEST_F(NodeHistoryTest, DoubleLinkedList) TEST_F(NodeHistoryTest, HistoryAt) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier = Allocator()->New(Allocator())->AsIdentifier(); auto history = Allocator()->New(identifier, PhaseManager()->CurrentPhaseId(), Allocator()); - ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->At(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->At(PHASE_ID_0), identifier); ASSERT_EQ(history->At(PHASE_ID_1), nullptr); } TEST_F(NodeHistoryTest, HistoryGet) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier = Allocator()->New(Allocator())->AsIdentifier(); auto history = Allocator()->New(identifier, PhaseManager()->CurrentPhaseId(), Allocator()); - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->Get(PHASE_ID_0), identifier); ASSERT_EQ(history->Get(PHASE_ID_1), identifier); ASSERT_EQ(history->Get(PHASE_ID_2), identifier); @@ -178,25 +180,25 @@ TEST_F(NodeHistoryTest, HistoryGet) // CC-OFFNXT(huge_method, G.FUN.01-CPP, G.FUD.05) solid logic TEST_F(NodeHistoryTest, HistorySet) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier0 = Allocator()->New(Allocator())->AsIdentifier(); auto history = Allocator()->New(identifier0, PhaseManager()->CurrentPhaseId(), Allocator()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); auto identifier1 = Allocator()->New(Allocator())->AsIdentifier(); history->Set(identifier1, PhaseManager()->CurrentPhaseId()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); auto identifier2 = Allocator()->New(Allocator())->AsIdentifier(); history->Set(identifier2, PhaseManager()->CurrentPhaseId()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_3); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_3.minor); history->Set(nullptr, PhaseManager()->CurrentPhaseId()); // Search forward - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->Get(PHASE_ID_0), identifier0); ASSERT_EQ(history->Get(PHASE_ID_1), identifier1); ASSERT_EQ(history->Get(PHASE_ID_2), identifier2); @@ -211,7 +213,7 @@ TEST_F(NodeHistoryTest, HistorySet) ASSERT_EQ(history->Get(PHASE_ID_2), identifier2); ASSERT_EQ(history->Get(PHASE_ID_1), identifier1); ASSERT_EQ(history->Get(PHASE_ID_0), identifier0); - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); // Search random ASSERT_EQ(history->Get(PHASE_ID_1), identifier1); @@ -219,11 +221,11 @@ TEST_F(NodeHistoryTest, HistorySet) ASSERT_EQ(history->Get(PHASE_ID_2), identifier2); ASSERT_EQ(history->Get(PHASE_ID_4), nullptr); ASSERT_EQ(history->Get(PHASE_ID_0), identifier0); - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->Get(PHASE_ID_3), nullptr); // Search precise - ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->At(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->At(PHASE_ID_0), identifier0); ASSERT_EQ(history->At(PHASE_ID_1), identifier1); ASSERT_EQ(history->At(PHASE_ID_2), identifier2); @@ -234,47 +236,54 @@ TEST_F(NodeHistoryTest, HistorySet) TEST_F(NodeHistoryTest, HistoryReplace) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier0Orig = Allocator()->New(Allocator())->AsIdentifier(); auto history = Allocator()->New(identifier0Orig, PhaseManager()->CurrentPhaseId(), Allocator()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); auto identifier1Orig = Allocator()->New(Allocator())->AsIdentifier(); history->Set(identifier1Orig, PhaseManager()->CurrentPhaseId()); - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->Get(PHASE_ID_0), identifier0Orig); ASSERT_EQ(history->Get(PHASE_ID_1), identifier1Orig); ASSERT_EQ(history->Get(PHASE_ID_2), identifier1Orig); ASSERT_EQ(history->Get(PHASE_ID_3), identifier1Orig); - ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->At(PARSER_PHASE_ID), nullptr); ASSERT_EQ(history->At(PHASE_ID_0), identifier0Orig); ASSERT_EQ(history->At(PHASE_ID_1), identifier1Orig); ASSERT_EQ(history->At(PHASE_ID_2), nullptr); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier0New = Allocator()->New(Allocator())->AsIdentifier(); history->Set(identifier0New, PhaseManager()->CurrentPhaseId()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); auto identifier1New = Allocator()->New(Allocator())->AsIdentifier(); history->Set(identifier1New, PhaseManager()->CurrentPhaseId()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); history->Set(nullptr, PhaseManager()->CurrentPhaseId()); - ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr); - ASSERT_EQ(history->Get(PHASE_ID_0), identifier0New); - ASSERT_EQ(history->Get(PHASE_ID_1), identifier1New); - ASSERT_EQ(history->Get(PHASE_ID_2), nullptr); - ASSERT_EQ(history->Get(PHASE_ID_3), nullptr); + ASSERT_EQ(history->Get(PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->Get(PHASE_ID_0), identifier0Orig); + ASSERT_EQ(history->Get(PHASE_ID_1), identifier1Orig); + ASSERT_EQ(history->Get(PHASE_ID_2), identifier1Orig); + ASSERT_EQ(history->Get(PHASE_ID_3), identifier1Orig); + ASSERT_EQ(history->Get({1, PHASE_ID_0.minor}), identifier0New); + ASSERT_EQ(history->Get({1, PHASE_ID_1.minor}), identifier1New); + ASSERT_EQ(history->Get({1, PHASE_ID_2.minor}), nullptr); + ASSERT_EQ(history->Get({1, PHASE_ID_3.minor}), nullptr); - ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr); - ASSERT_EQ(history->At(PHASE_ID_0), identifier0New); - ASSERT_EQ(history->At(PHASE_ID_1), identifier1New); + ASSERT_EQ(history->At(PARSER_PHASE_ID), nullptr); + ASSERT_EQ(history->At(PHASE_ID_0), identifier0Orig); + ASSERT_EQ(history->At(PHASE_ID_1), identifier1Orig); + ASSERT_EQ(history->At(PHASE_ID_2), nullptr); + ASSERT_EQ(history->At({1, PHASE_ID_0.minor}), identifier0New); + ASSERT_EQ(history->At({1, PHASE_ID_1.minor}), identifier1New); ASSERT_EQ(history->At(PHASE_ID_2), nullptr); } @@ -288,9 +297,9 @@ ir::ClassDefinition *NewClassDefinition(ArenaAllocator *allocator) } /// NOTE(mivanov): To be enabled after #24153/#24424 implemented -TEST_F(NodeHistoryTest, DISABLED_UpdateField) +TEST_F(NodeHistoryTest, UpdateField) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); auto definition = NewClassDefinition(Allocator()); ASSERT_FALSE(definition->IsAbstract()); @@ -299,35 +308,35 @@ TEST_F(NodeHistoryTest, DISABLED_UpdateField) definition->AddModifier(ir::ModifierFlags::FINAL); ASSERT_TRUE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); definition->AddModifier(ir::ModifierFlags::ABSTRACT); ASSERT_TRUE(definition->IsAbstract()); definition->ClearModifier(ir::ModifierFlags::FINAL); ASSERT_FALSE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); definition->ClearModifier(ir::ModifierFlags::ABSTRACT); ASSERT_FALSE(definition->IsAbstract()); definition->AddModifier(ir::ModifierFlags::FINAL); ASSERT_TRUE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); definition->ClearModifier(ir::ModifierFlags::FINAL); ASSERT_FALSE(definition->IsFinal()); - PhaseManager()->Restart(); + PhaseManager()->Reset(); ASSERT_FALSE(definition->IsAbstract()); ASSERT_TRUE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); ASSERT_TRUE(definition->IsAbstract()); ASSERT_FALSE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); ASSERT_FALSE(definition->IsAbstract()); ASSERT_TRUE(definition->IsFinal()); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); ASSERT_FALSE(definition->IsAbstract()); ASSERT_FALSE(definition->IsFinal()); } @@ -335,36 +344,36 @@ TEST_F(NodeHistoryTest, DISABLED_UpdateField) /// NOTE(mivanov): To be enabled after #24153/#24424 implemented TEST_F(NodeHistoryTest, DISABLED_UpdateChild) { - ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID); + ASSERT_EQ(PhaseManager()->CurrentPhaseId(), PARSER_PHASE_ID); auto declaration = Allocator()->New(NewClassDefinition(Allocator()), Allocator())->AsClassDeclaration(); ASSERT_EQ(declaration->Definition()->Ident(), nullptr); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); auto identifier0 = Allocator()->New(Allocator())->AsIdentifier(); declaration->Definition()->SetIdent(identifier0); ASSERT_EQ(declaration->Definition()->Ident(), identifier0); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); auto identifier1 = Allocator()->New(Allocator())->AsIdentifier(); declaration->Definition()->SetIdent(identifier1); ASSERT_EQ(declaration->Definition()->Ident(), identifier1); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); declaration->Definition()->SetIdent(nullptr); ASSERT_EQ(declaration->Definition()->Ident(), nullptr); - PhaseManager()->Restart(); + PhaseManager()->Reset(); ASSERT_EQ(declaration->Definition()->Ident(), nullptr); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_0); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_0.minor); ASSERT_EQ(declaration->Definition()->Ident(), identifier0); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_1); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_1.minor); ASSERT_EQ(declaration->Definition()->Ident(), identifier1); - PhaseManager()->SetCurrentPhaseId(PHASE_ID_2); + PhaseManager()->SetCurrentPhaseId(PHASE_ID_2.minor); ASSERT_EQ(declaration->Definition()->Ident(), nullptr); } } // namespace ark::es2panda diff --git a/ets2panda/test/unit/lowerings/scopes_initialization.cpp b/ets2panda/test/unit/lowerings/scopes_initialization.cpp index 472da09d93..1c82aeed87 100644 --- a/ets2panda/test/unit/lowerings/scopes_initialization.cpp +++ b/ets2panda/test/unit/lowerings/scopes_initialization.cpp @@ -30,11 +30,12 @@ public: ~ScopesInitPhaseTest() override = default; ScopesInitPhaseTest() - : allocator_(std::make_unique(SpaceType::SPACE_TYPE_COMPILER)), nodeGen_(allocator_.get()) + : allocator_(std::make_unique(SpaceType::SPACE_TYPE_COMPILER, nullptr, true)), + nodeGen_(allocator_.get()) { } - ArenaAllocator *Allocator() + ark::ThreadSafeArenaAllocator *Allocator() { return allocator_.get(); } @@ -48,7 +49,7 @@ public: NO_MOVE_SEMANTIC(ScopesInitPhaseTest); private: - std::unique_ptr allocator_; + std::unique_ptr allocator_; gtests::NodeGenerator nodeGen_; }; diff --git a/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp b/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp index 536122486f..cfbac8e419 100644 --- a/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp +++ b/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp @@ -37,7 +37,7 @@ TEST_F(LSPAPITests, GetTypeOfSymbolAtLocation1) "float;\nlet g: double;\nlet h: char;\nlet i: boolean;"); ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto checker = reinterpret_cast(ctx)->checker->AsETSChecker(); + auto checker = reinterpret_cast(ctx)->GetChecker()->AsETSChecker(); auto astNode = GetAstFromContext(ctx); auto targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "a"; }); @@ -97,7 +97,7 @@ TEST_F(LSPAPITests, GetTypeOfSymbolAtLocation2) "undefined;\nlet tuple: [number, number] = [1, 2];\nlet union: int | null;"); ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); - auto checker = reinterpret_cast(ctx)->checker->AsETSChecker(); + auto checker = reinterpret_cast(ctx)->GetChecker()->AsETSChecker(); auto astNode = GetAstFromContext(ctx); auto targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "j"; }); diff --git a/ets2panda/test/unit/lsp/isolated_declaration.cpp b/ets2panda/test/unit/lsp/isolated_declaration.cpp index d230e67a2e..5a0f1c776b 100644 --- a/ets2panda/test/unit/lsp/isolated_declaration.cpp +++ b/ets2panda/test/unit/lsp/isolated_declaration.cpp @@ -52,7 +52,7 @@ export function foo(n: number) { Initializer initializer = Initializer(); auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED); auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx->checker); + auto checker = reinterpret_cast(ctx->GetChecker()); auto ast = ctx->parserProgram->Ast(); auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) { return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo"; @@ -91,7 +91,7 @@ export function foo(n: number) { Initializer initializer = Initializer(); auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED); auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx->checker); + auto checker = reinterpret_cast(ctx->GetChecker()); auto ast = ctx->parserProgram->Ast(); auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) { return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo"; @@ -131,7 +131,7 @@ export const foo = () => { Initializer initializer = Initializer(); auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED); auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx->checker); + auto checker = reinterpret_cast(ctx->GetChecker()); auto ast = ctx->parserProgram->Ast(); auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) { return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo"; @@ -172,7 +172,7 @@ export class A { Initializer initializer = Initializer(); auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED); auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx->checker); + auto checker = reinterpret_cast(ctx->GetChecker()); auto ast = ctx->parserProgram->Ast(); auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) { return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo"; @@ -213,7 +213,7 @@ export class A { Initializer initializer = Initializer(); auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED); auto ctx = reinterpret_cast(context); - auto checker = reinterpret_cast(ctx->checker); + auto checker = reinterpret_cast(ctx->GetChecker()); auto ast = ctx->parserProgram->Ast(); auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) { return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo"; diff --git a/ets2panda/test/unit/lsp/lsp_rename_test.cpp b/ets2panda/test/unit/lsp/lsp_rename_test.cpp index ea1af27659..39ad9d3887 100644 --- a/ets2panda/test/unit/lsp/lsp_rename_test.cpp +++ b/ets2panda/test/unit/lsp/lsp_rename_test.cpp @@ -441,7 +441,7 @@ TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoForNode1) ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); auto ast = GetAstFromContext(ctx); - auto checker = reinterpret_cast(ctx)->checker->AsETSChecker(); + auto checker = reinterpret_cast(ctx)->GetChecker()->AsETSChecker(); auto program = reinterpret_cast(ctx)->parserProgram; auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) { diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp index aa95c12304..b700c046a9 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp @@ -39,6 +39,7 @@ int main(int argc, char **argv) std::cout << "LOAD SUCCESS" << std::endl; const char **args = const_cast(&(argv[1])); + impl->MemInitialize(); auto config = impl->CreateConfig(argc - 1, args); auto context = impl->CreateContextFromFile(config, argv[argc - 1]); if (context == nullptr) { @@ -67,6 +68,7 @@ int main(int argc, char **argv) CheckForErrors("BIN", context); impl->DestroyConfig(config); + impl->MemFinalize(); return 0; } diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_import.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_import.cpp index 2efc5c36d5..d795325136 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_import.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_import.cpp @@ -133,7 +133,7 @@ bool Find(es2panda_AstNode *ast) { if (g_impl->IsETSImportDeclaration(ast)) { size_t len = 0; - auto specifiers = g_impl->ImportDeclarationSpecifiers(g_ctx, ast, &len); + auto specifiers = g_impl->ImportDeclarationSpecifiersConst(g_ctx, ast, &len); auto source = g_impl->ImportDeclarationSource(g_ctx, ast); auto importDeclaration = g_impl->UpdateETSImportDeclaration(g_ctx, ast, source, specifiers, len, IMPORT_KINDS_ALL); diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_find_import_declaration.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_find_import_declaration.cpp index 3cbc8d25db..7d7f575528 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_find_import_declaration.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_find_import_declaration.cpp @@ -35,7 +35,7 @@ void CheckForImportDeclaration(es2panda_AstNode *node, void *arg) return; } size_t n = 0; - auto specifiers = impl->ImportDeclarationSpecifiers(context, node, &n); + auto specifiers = impl->ImportDeclarationSpecifiersConst(context, node, &n); for (size_t i = 0; i < n; i++) { if (!impl->IsImportSpecifier(specifiers[i])) { std::cout << impl->IsImportSpecifier(specifiers[i]) << std::endl; diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp index 35f7374b7b..7e88eff580 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp @@ -343,7 +343,7 @@ TEST_F(PluginConversionRuleUnitTest, PairReturnValue) es2panda_Type *classInstance, [[maybe_unused]] es2panda_Type *sourceType/*return_args:*/, es2panda_Type **returnTypeSecond) { - auto *checkerE2p = reinterpret_cast(context)->checker->AsETSChecker(); + auto *checkerE2p = reinterpret_cast(context)->GetChecker()->AsETSChecker(); auto *sourceTypeE2p = reinterpret_cast(sourceType); auto *ctx = reinterpret_cast(context); [[maybe_unused]] auto *ctxAllocator = ctx->allocator; diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp index d6f9e1b282..eee97381aa 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp @@ -60,7 +60,7 @@ TEST_F(PluginConversionRuleUnitTest, CheckerTypeRelationConstructor) std::string targetCAPI {R"( extern "C" es2panda_TypeRelation *CreateTypeRelation([[maybe_unused]] es2panda_Context *context) { - auto *checkerE2p = reinterpret_cast(context)->checker; + auto *checkerE2p = reinterpret_cast(context)->GetChecker(); auto *ctx = reinterpret_cast(context); auto *ctxAllocator = ctx->allocator; return reinterpret_cast(ctxAllocator->New(checkerE2p)); diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iv.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iv.cpp index 8eb1282e8c..1b4c7be1d7 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iv.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iv.cpp @@ -62,7 +62,7 @@ TEST_F(PluginConversionRuleUnitTest, CheckerContextPtrReturnValue) extern "C" es2panda_CheckerContext *CreateCheckerContext([[maybe_unused]] es2panda_Context *context, [[maybe_unused]] Es2pandaCheckerStatus newStatus) { - auto *checkerE2p = reinterpret_cast(context)->checker; + auto *checkerE2p = reinterpret_cast(context)->GetChecker(); auto newStatusE2p = E2pToIrCheckerStatus(newStatus); auto *ctx = reinterpret_cast(context); auto *ctxAllocator = ctx->allocator; @@ -97,7 +97,7 @@ TEST_F(PluginConversionRuleUnitTest, CheckerContextPtrConstructor) extern "C" es2panda_CheckerContext *CreateCheckerContext([[maybe_unused]] es2panda_Context *context, [[maybe_unused]] Es2pandaCheckerStatus newStatus) { - auto *checkerE2p = reinterpret_cast(context)->checker; + auto *checkerE2p = reinterpret_cast(context)->GetChecker(); auto newStatusE2p = E2pToIrCheckerStatus(newStatus); auto *ctx = reinterpret_cast(context); auto *ctxAllocator = ctx->allocator; @@ -352,12 +352,11 @@ TEST_F(PluginConversionRuleUnitTest, PropertyProcessorInputParameter) extern "C" void ETSObjectTypeUpdateTypeProperties([[maybe_unused]] es2panda_Context *context, es2panda_Type *classInstance, [[maybe_unused]] PropertyProcessor func/*return_args:*/) { - auto *checkerE2p = reinterpret_cast(context)->checker->AsETSChecker(); std::function funcE2p = [func](varbinder::LocalVariable *propertyProcessorLambdaVariable, checker::Type *propertyProcessorLambdaType) { return reinterpret_cast(func(reinterpret_cast (propertyProcessorLambdaVariable), reinterpret_cast(propertyProcessorLambdaType)));}; - ((reinterpret_cast< checker::ETSObjectType *>(classInstance))->UpdateTypeProperties(checkerE2p, funcE2p)); + ((reinterpret_cast< checker::ETSObjectType *>(classInstance))->UpdateTypeProperties(funcE2p)); })"}; std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); diff --git a/ets2panda/test/unit/public/ast_verifier_check_abstract_call_test.cpp b/ets2panda/test/unit/public/ast_verifier_check_abstract_call_test.cpp index 4564a46588..7814d7f261 100644 --- a/ets2panda/test/unit/public/ast_verifier_check_abstract_call_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_check_abstract_call_test.cpp @@ -33,7 +33,7 @@ namespace { TEST_F(ASTVerifierTest, LabelsHaveReferences) { ark::es2panda::util::DiagnosticEngine de; - ark::es2panda::checker::ETSChecker checker(de); + ark::es2panda::checker::ETSChecker checker {Allocator(), de}; char const *text = R"( abstract class A { diff --git a/ets2panda/test/unit/public/ast_verifier_check_const_properties_test.cpp b/ets2panda/test/unit/public/ast_verifier_check_const_properties_test.cpp index 51b3a9e2cf..2652cdfe6f 100644 --- a/ets2panda/test/unit/public/ast_verifier_check_const_properties_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_check_const_properties_test.cpp @@ -26,7 +26,7 @@ namespace { TEST_F(ASTVerifierTest, CheckConstProperties) { ark::es2panda::util::DiagnosticEngine de {}; - ark::es2panda::checker::ETSChecker checker {de}; + ark::es2panda::checker::ETSChecker checker {Allocator(), de}; char const *text = R"( class Test diff --git a/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp b/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp index 288cafaf20..dbdd1b433c 100644 --- a/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp @@ -163,7 +163,7 @@ TEST_F(ASTVerifierTest, StructInStruct) } )"; - CONTEXT(ES2PANDA_STATE_PARSED, text) + CONTEXT(ES2PANDA_STATE_PARSED, ES2PANDA_STATE_ERROR, text) { ASSERT_TRUE(GetImpl()->IsAnyError(GetContext())); } diff --git a/ets2panda/test/unit/public/ast_verifier_getter_setter_neg_test.cpp b/ets2panda/test/unit/public/ast_verifier_getter_setter_neg_test.cpp index b8d0e49604..651b6ab840 100644 --- a/ets2panda/test/unit/public/ast_verifier_getter_setter_neg_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_getter_setter_neg_test.cpp @@ -29,7 +29,7 @@ namespace { TEST_F(ASTVerifierTest, ValidateGetterReturnTypeAnnotation) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -87,7 +87,7 @@ TEST_F(ASTVerifierTest, ValidateGetterHasReturnStatement) auto *const method = child->AsMethodDefinition(); if (method->IsGetter() && method->Value()->IsFunctionExpression()) { auto *const function = method->Value()->AsFunctionExpression()->Function(); - auto &returns = function->ReturnStatements(); + auto &returns = function->ReturnStatementsForUpdate(); returns.clear(); } } @@ -104,7 +104,7 @@ TEST_F(ASTVerifierTest, ValidateGetterHasReturnStatement) TEST_F(ASTVerifierTest, ValidateGetterVoidReturnStatement) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -142,7 +142,7 @@ TEST_F(ASTVerifierTest, ValidateGetterVoidReturnStatement) TEST_F(ASTVerifierTest, ValidateGetterArguments) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -166,7 +166,7 @@ TEST_F(ASTVerifierTest, ValidateGetterArguments) auto *const method = child->AsMethodDefinition(); if (method->IsGetter() && method->Value()->IsFunctionExpression()) { auto *const function = method->Value()->AsFunctionExpression()->Function(); - auto ¶ms = function->Params(); + auto ¶ms = function->ParamsForUpdate(); ASSERT_EQ(params.size(), 0); params.push_back(param); } @@ -184,7 +184,7 @@ TEST_F(ASTVerifierTest, ValidateGetterArguments) TEST_F(ASTVerifierTest, ValidateSetterReturnType) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -225,7 +225,7 @@ TEST_F(ASTVerifierTest, ValidateSetterReturnType) TEST_F(ASTVerifierTest, ValidateSetterArguments) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -245,7 +245,7 @@ TEST_F(ASTVerifierTest, ValidateSetterArguments) auto *const method = child->AsMethodDefinition(); if (method->IsSetter() && method->Value()->IsFunctionExpression()) { auto *const function = method->Value()->AsFunctionExpression()->Function(); - auto ¶ms = function->Params(); + auto ¶ms = function->ParamsForUpdate(); ASSERT_EQ(params.size(), 1); params.clear(); } diff --git a/ets2panda/test/unit/public/ast_verifier_getter_setter_test.cpp b/ets2panda/test/unit/public/ast_verifier_getter_setter_test.cpp index 7ee4731ed7..542d91ddf7 100644 --- a/ets2panda/test/unit/public/ast_verifier_getter_setter_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_getter_setter_test.cpp @@ -27,7 +27,7 @@ namespace { TEST_F(ASTVerifierTest, ValidateCorrectGetterSetter) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -52,7 +52,7 @@ TEST_F(ASTVerifierTest, ValidateCorrectGetterSetter) TEST_F(ASTVerifierTest, ValidateAbstractGettersSetters) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( @@ -72,7 +72,7 @@ TEST_F(ASTVerifierTest, ValidateAbstractGettersSetters) TEST_F(ASTVerifierTest, ValidateAmbientGettersSetters) { DiagnosticEngine de {}; - ETSChecker checker {de}; + ETSChecker checker {Allocator(), de}; char const *text = R"( diff --git a/ets2panda/test/unit/public/ast_verifier_short_test.cpp b/ets2panda/test/unit/public/ast_verifier_short_test.cpp index c5cf75fa2b..4a20d2a054 100644 --- a/ets2panda/test/unit/public/ast_verifier_short_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_short_test.cpp @@ -119,7 +119,7 @@ TEST_F(ASTVerifierTest, ScopeNodeTest) TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect1) { DiagnosticEngine de {}; - ETSChecker etschecker {de}; + ETSChecker etschecker {Allocator(), de}; auto left = NumberLiteral(Number {1}); auto right = NumberLiteral(Number {6}); @@ -134,7 +134,7 @@ TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect1) TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect2) { DiagnosticEngine de {}; - ETSChecker etschecker {de}; + ETSChecker etschecker {Allocator(), de}; constexpr uint32_t LEFT1_PARAM = 1; constexpr uint32_t LEFT2_PARAM = 12; @@ -156,7 +156,7 @@ TEST_F(ASTVerifierTest, ArithmeticExpressionCorrect2) TEST_F(ASTVerifierTest, ArithmeticExpressionNegative1) { DiagnosticEngine de {}; - ETSChecker etschecker {de}; + ETSChecker etschecker {Allocator(), de}; const StringView leftParam("1"); constexpr uint32_t RIGHT_PARAM = 1; @@ -174,7 +174,7 @@ TEST_F(ASTVerifierTest, ArithmeticExpressionNegative1) TEST_F(ASTVerifierTest, ArithmeticExpressionNegative2) { DiagnosticEngine de {}; - ETSChecker etschecker {de}; + ETSChecker etschecker {Allocator(), de}; auto left = BooleanLiteral(true); auto right = NumberLiteral(Number {1}); @@ -190,7 +190,7 @@ TEST_F(ASTVerifierTest, ArithmeticExpressionNegative2) TEST_F(ASTVerifierTest, PrimitiveType) { DiagnosticEngine de {}; - ETSChecker etschecker {de}; + ETSChecker etschecker {Allocator(), de}; auto ast = BooleanLiteral(true); ast.SetTsType(etschecker.CreateETSBooleanType(true)); @@ -204,7 +204,7 @@ TEST_F(ASTVerifierTest, PrimitiveType) TEST_F(ASTVerifierTest, SequenceExpressionType) { auto de = DiagnosticEngine(); - auto checker = ETSChecker(de); + auto checker = ETSChecker(Allocator(), de); const auto literalsCount = 3; std::array literals {NumberLiteral {Number {1}}, NumberLiteral {Number {2}}, NumberLiteral {Number {3}}}; diff --git a/ets2panda/test/unit/sizeof_node_test.cpp b/ets2panda/test/unit/sizeof_node_test.cpp index 428a6010b7..3d964e211d 100644 --- a/ets2panda/test/unit/sizeof_node_test.cpp +++ b/ets2panda/test/unit/sizeof_node_test.cpp @@ -69,6 +69,7 @@ size_t SizeOfNodeTest::SizeOf() sizeof(node->flags_) + sizeof(node->astNodeFlags_) + sizeof(node->boxingUnboxingFlags_) + + sizeof(node->history_) + sizeof(node->variable_) + sizeof(node->originalNode_) + sizeof(node->transformedNode_); @@ -588,7 +589,8 @@ size_t SizeOfNodeTest::SizeOf() return SizeOf>>() + sizeof(node->ident_) + Align(sizeof(node->flag_)) + - sizeof(node->program_); + sizeof(node->program_)+ + sizeof(node->globalClass_); // clang-format on } diff --git a/ets2panda/test/unit/union_normalisation_test.h b/ets2panda/test/unit/union_normalisation_test.h index 0a7312aa66..36b345f6c3 100644 --- a/ets2panda/test/unit/union_normalisation_test.h +++ b/ets2panda/test/unit/union_normalisation_test.h @@ -16,6 +16,7 @@ #ifndef PANDA_UNION_NORMALISATION_TEST_H #define PANDA_UNION_NORMALISATION_TEST_H +#include "ir/astNode.h" #include "util/options.h" namespace ark::es2panda::gtests { @@ -23,10 +24,11 @@ namespace ark::es2panda::gtests { class UnionNormalizationTest : public testing::Test { public: UnionNormalizationTest() - : allocator_(std::make_unique(SpaceType::SPACE_TYPE_COMPILER)), + : allocator_(std::make_unique(SpaceType::SPACE_TYPE_COMPILER, nullptr, true)), publicContext_ {std::make_unique()}, + phaseManager_ {ScriptExtension::ETS, Allocator()}, program_ {parser::Program::NewProgram(Allocator())}, - checker_ {diagnosticEngine_} + checker_ {Allocator(), diagnosticEngine_} { } @@ -38,7 +40,7 @@ public: PoolManager::Initialize(); } - ArenaAllocator *Allocator() + ark::ThreadSafeArenaAllocator *Allocator() { return allocator_.get(); } @@ -103,7 +105,7 @@ public: varbinder->SetContext(publicContext_.get()); auto emitter = Emitter(publicContext_.get()); - auto phaseManager = compiler::PhaseManager(unit.ext, allocator_.get()); + auto phaseManager = new compiler::PhaseManager(publicContext_.get(), unit.ext, allocator_.get()); auto config = public_lib::ConfigImpl {}; publicContext_->config = &config; @@ -111,12 +113,14 @@ public: publicContext_->sourceFile = &unit.input; publicContext_->allocator = allocator_.get(); publicContext_->parser = &parser; - publicContext_->checker = checker; - publicContext_->analyzer = publicContext_->checker->GetAnalyzer(); - publicContext_->emitter = &emitter; + parser.SetContext(publicContext_.get()); publicContext_->parserProgram = program; + publicContext_->PushChecker(checker); + publicContext_->PushAnalyzer(publicContext_->GetChecker()->GetAnalyzer()); + publicContext_->emitter = &emitter; publicContext_->diagnosticEngine = &diagnosticEngine_; - publicContext_->phaseManager = &phaseManager; + publicContext_->phaseManager = phaseManager; + publicContext_->GetChecker()->Initialize(varbinder); parser.ParseScript(unit.input, unit.options.GetCompilationMode() == CompilationMode::GEN_STD_LIB); while (auto phase = publicContext_->phaseManager->NextPhase()) { if (!phase->Apply(publicContext_.get(), program)) { @@ -158,8 +162,9 @@ protected: static constexpr uint8_t IDX2 = 2; private: - std::unique_ptr allocator_; + std::unique_ptr allocator_; std::unique_ptr publicContext_; + ark::es2panda::compiler::PhaseManager phaseManager_; parser::Program program_; util::DiagnosticEngine diagnosticEngine_; checker::ETSChecker checker_; diff --git a/ets2panda/test/utils/ast_verifier_test.cpp b/ets2panda/test/utils/ast_verifier_test.cpp index 96fc2c38f9..2175041ca7 100644 --- a/ets2panda/test/utils/ast_verifier_test.cpp +++ b/ets2panda/test/utils/ast_verifier_test.cpp @@ -15,21 +15,25 @@ #include "ast_verifier_test.h" +#include + namespace test::utils { AstVerifierTest::AstVerifierTest() { impl_ = es2panda_GetImpl(ES2PANDA_LIB_VERSION); + impl_->MemInitialize(); auto es2pandaPath = test::utils::PandaExecutablePathGetter::Get()[0]; std::array argv = {es2pandaPath}; cfg_ = impl_->CreateConfig(argv.size(), argv.data()); - allocator_ = new ark::ArenaAllocator(ark::SpaceType::SPACE_TYPE_COMPILER); + allocator_ = new ark::ThreadSafeArenaAllocator(ark::SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + phaseManager_ = new ark::es2panda::compiler::PhaseManager(nullptr, ark::es2panda::ScriptExtension::ETS, allocator_); } AstVerifierTest::~AstVerifierTest() { ASSERT(ctx_ == nullptr); - delete allocator_; + impl_->MemFinalize(); impl_->DestroyConfig(cfg_); } diff --git a/ets2panda/test/utils/ast_verifier_test.h b/ets2panda/test/utils/ast_verifier_test.h index 68ccb22ecb..0d4d9fd955 100644 --- a/ets2panda/test/utils/ast_verifier_test.h +++ b/ets2panda/test/utils/ast_verifier_test.h @@ -18,6 +18,7 @@ #include "ast_verifier/ASTVerifier.h" #include "panda_executable_path_getter.h" +#include "compiler/lowering/phase.h" #include @@ -44,14 +45,14 @@ public: NO_MOVE_SEMANTIC(AstVerifierTest); ~AstVerifierTest() override; - ark::ArenaAllocator *Allocator() const + ark::ThreadSafeArenaAllocator *Allocator() const { return allocator_; } auto *GetChecker() { - return reinterpret_cast(ctx_)->checker->AsETSChecker(); + return reinterpret_cast(ctx_)->GetChecker()->AsETSChecker(); } auto *GetAst() @@ -205,7 +206,8 @@ private: es2panda_Impl const *impl_ {}; es2panda_Config *cfg_ {}; es2panda_Context *ctx_ {}; - ark::ArenaAllocator *allocator_ {}; + ark::ThreadSafeArenaAllocator *allocator_ {}; + ark::es2panda::compiler::PhaseManager *phaseManager_; friend class ::LSPAPITests; }; diff --git a/ets2panda/test/utils/checker_test.h b/ets2panda/test/utils/checker_test.h index cd41db0d66..79259abbad 100644 --- a/ets2panda/test/utils/checker_test.h +++ b/ets2panda/test/utils/checker_test.h @@ -22,6 +22,7 @@ #include "compiler/core/regSpiller.h" #include "compiler/core/ETSemitter.h" #include "checker/ETSAnalyzer.h" +#include "ir/astNode.h" #include "util/options.h" #include "util/diagnosticEngine.h" #include @@ -38,11 +39,13 @@ namespace test::utils { class CheckerTest : public testing::Test { public: CheckerTest() - : allocator_(std::make_unique(ark::SpaceType::SPACE_TYPE_COMPILER)), + : allocator_( + std::make_unique(ark::SpaceType::SPACE_TYPE_COMPILER, nullptr, true)), publicContext_ {std::make_unique()}, + phaseManager_ {ark::es2panda::ScriptExtension::ETS, Allocator()}, program_ {parser_alias::Program::NewProgram(allocator_.get())}, es2pandaPath_ {PandaExecutablePathGetter::Get()[0]}, - checker_(diagnosticEngine_) + checker_(allocator_.get(), diagnosticEngine_) { } ~CheckerTest() override = default; @@ -57,7 +60,7 @@ public: return &checker_; } - ark::ArenaAllocator *Allocator() + ark::ThreadSafeArenaAllocator *Allocator() { return allocator_.get(); } @@ -110,7 +113,7 @@ public: varbinder->SetContext(publicContext_.get()); auto emitter = Emitter(publicContext_.get()); - auto phaseManager = compiler_alias::PhaseManager(unit.ext, allocator_.get()); + auto phaseManager = compiler_alias::PhaseManager(publicContext_.get(), unit.ext, allocator_.get()); auto config = plib_alias::ConfigImpl {}; publicContext_->config = &config; @@ -118,12 +121,14 @@ public: publicContext_->sourceFile = &unit.input; publicContext_->allocator = allocator_.get(); publicContext_->parser = &parser; - publicContext_->checker = checker; - publicContext_->analyzer = publicContext_->checker->GetAnalyzer(); - publicContext_->emitter = &emitter; + parser.SetContext(publicContext_.get()); publicContext_->parserProgram = program; + publicContext_->PushChecker(checker); + publicContext_->PushAnalyzer(publicContext_->GetChecker()->GetAnalyzer()); + publicContext_->emitter = &emitter; publicContext_->diagnosticEngine = &diagnosticEngine_; publicContext_->phaseManager = &phaseManager; + publicContext_->GetChecker()->Initialize(varbinder); parser.ParseScript(unit.input, unit.options.GetCompilationMode() == ark::es2panda::CompilationMode::GEN_STD_LIB); while (auto phase = publicContext_->phaseManager->NextPhase()) { @@ -136,8 +141,9 @@ public: NO_MOVE_SEMANTIC(CheckerTest); private: - std::unique_ptr allocator_; + std::unique_ptr allocator_; std::unique_ptr publicContext_; + ark::es2panda::compiler::PhaseManager phaseManager_; parser_alias::Program program_; std::string es2pandaPath_; util_alias::DiagnosticEngine diagnosticEngine_; diff --git a/ets2panda/test/utils/scope_init_test.h b/ets2panda/test/utils/scope_init_test.h index ce8df944ba..2529a908f5 100644 --- a/ets2panda/test/utils/scope_init_test.h +++ b/ets2panda/test/utils/scope_init_test.h @@ -21,6 +21,7 @@ #include "ir/statements/variableDeclarator.h" #include "ir/statements/variableDeclaration.h" #include "mem/pool_manager.h" +#include "compiler/lowering/phase.h" #include @@ -30,7 +31,14 @@ namespace test::utils { class ScopeInitTest : public testing::Test { public: - ScopeInitTest() : allocator_(std::make_unique(ark::SpaceType::SPACE_TYPE_COMPILER)) {} + ScopeInitTest() + : allocator_( + std::make_unique(ark::SpaceType::SPACE_TYPE_COMPILER, nullptr, true)) + { + phaseManager_ = std::make_unique(ark::es2panda::ScriptExtension::ETS, + allocator_.get()); + ark::es2panda::compiler::SetPhaseManager(phaseManager_.get()); + } /* * Shortcut to convert single elemnt block expression body to it's name @@ -44,13 +52,14 @@ public: ark::PoolManager::Initialize(); } - ark::ArenaAllocator *Allocator() + ark::ThreadSafeArenaAllocator *Allocator() { return allocator_.get(); } private: - std::unique_ptr allocator_; + std::unique_ptr allocator_; + std::unique_ptr phaseManager_; }; } // namespace test::utils diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 131ca76cf8..9660f1f160 100644 --- a/ets2panda/util/diagnosticEngine.cpp +++ b/ets2panda/util/diagnosticEngine.cpp @@ -52,8 +52,8 @@ DiagnosticStorage DiagnosticEngine::GetAllDiagnostic() DiagnosticStorage merged; merged.reserve(totalSize); for (auto &vec : diagnostics_) { - for (auto &&diag : vec) { - merged.emplace_back(std::move(diag)); + for (auto &diag : vec) { + merged.emplace_back(diag); } } return merged; @@ -61,6 +61,9 @@ DiagnosticStorage DiagnosticEngine::GetAllDiagnostic() void DiagnosticEngine::FlushDiagnostic() { + if (isFlushed_) { + return; + } auto log = GetAllDiagnostic(); std::sort(log.begin(), log.end(), [](const auto &lhs, const auto &rhs) { return *lhs < *rhs; }); auto last = @@ -68,6 +71,7 @@ void DiagnosticEngine::FlushDiagnostic() for (auto it = log.begin(); it != last; it++) { printer_->Print(**it); } + isFlushed_ = true; } #ifndef FUZZING_EXIT_ON_FAILED_ASSERT static void SigSegvHandler([[maybe_unused]] int sig) diff --git a/ets2panda/util/diagnosticEngine.h b/ets2panda/util/diagnosticEngine.h index 0562a1cb45..a013fc7a71 100644 --- a/ets2panda/util/diagnosticEngine.h +++ b/ets2panda/util/diagnosticEngine.h @@ -46,7 +46,7 @@ public: void Print(const DiagnosticBase &diagnostic) const override; }; -using DiagnosticStorage = std::vector>; +using DiagnosticStorage = std::vector>; class DiagnosticEngine { public: @@ -79,6 +79,13 @@ public: LogDiagnostic(std::forward(args)...); } + void ClearDiagnostics() + { + for (auto &it : diagnostics_) { + it.clear(); + } + } + // NOTE(schernykh): should be removed void Log([[maybe_unused]] const ThrowableDiagnostic &error) { @@ -165,6 +172,7 @@ private: std::array(DiagnosticType::COUNT)> diagnostics_; std::unique_ptr printer_; bool wError_ {false}; + bool isFlushed_ {false}; }; } // namespace ark::es2panda::util diff --git a/ets2panda/util/enumbitops.h b/ets2panda/util/enumbitops.h index 46a95feeb1..b22f3325b1 100644 --- a/ets2panda/util/enumbitops.h +++ b/ets2panda/util/enumbitops.h @@ -27,7 +27,9 @@ enumbitops::operator^, \ enumbitops::operator|=, \ enumbitops::operator&=, \ - enumbitops::operator^= + enumbitops::operator^=, \ + enumbitops::All, \ + enumbitops::Any // clang-format on namespace enumbitops { @@ -98,6 +100,20 @@ inline constexpr T &operator^=(T &a, T b) return a = a ^ b; } +template ::value, bool> = true> +inline constexpr bool All(T flags, T test) +{ + using Utype = std::underlying_type_t; + return (flags & test) == static_cast(test); +} + +template ::value, bool> = true> +inline constexpr bool Any(T flags, T test) +{ + using Utype = std::underlying_type_t; + return (flags & test) != static_cast(0); +} + } // namespace enumbitops #endif diff --git a/ets2panda/util/es2pandaMacros.h b/ets2panda/util/es2pandaMacros.h index cc0990c7b5..6764fadf6a 100644 --- a/ets2panda/util/es2pandaMacros.h +++ b/ets2panda/util/es2pandaMacros.h @@ -18,6 +18,7 @@ #include "macros.h" #include "lexer/token/sourceLocation.h" + namespace ark::es2panda::parser { class Program; } // namespace ark::es2panda::parser diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index 21095663b0..9e011a2159 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -130,6 +130,11 @@ public: return parseList_; } + void ClearParseList() + { + parseList_.clear(); + } + util::StringView FormModuleName(const util::Path &path, const lexer::SourcePosition &srcPos); ImportMetadata GatherImportMetadata(parser::Program *program, ImportFlags importFlags, ir::StringLiteral *importPath); @@ -161,7 +166,8 @@ private: std::string TryMatchDynamicPath(std::string_view fixedPath) const; StringView GetRealPath(StringView path) const; - void AddToParseList(const ImportMetadata importMetadata); +public: + void AddToParseList(ImportMetadata importMetadata); #ifdef USE_UNIX_SYSCALL void UnixWalkThroughDirectoryAndAddToParseList(ImportMetadata importMetadata); #endif diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0f9ae6db10..3c1b368ce7 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -77,7 +77,7 @@ bool ETSBinder::HandleDynamicVariables(ir::Identifier *ident, Variable *variable bool ETSBinder::LookupInDebugInfoPlugin(ir::Identifier *ident) { - auto *checker = GetContext()->checker->AsETSChecker(); + auto *checker = GetContext()->GetChecker()->AsETSChecker(); auto *debugInfoPlugin = checker->GetDebugInfoPlugin(); if (UNLIKELY(debugInfoPlugin)) { auto *var = debugInfoPlugin->FindClass(ident); @@ -98,7 +98,7 @@ static void CreateDummyVariable(ETSBinder *varBinder, ir::Identifier *ident) varBinder->NewVarDecl(ident->Start(), compiler::GenName(varBinder->Allocator()).View()); var->SetScope(varBinder->GetScope()); ident->SetVariable(var); - ident->SetTsType(var->SetTsType(varBinder->GetContext()->checker->AsETSChecker()->GlobalTypeError())); + ident->SetTsType(var->SetTsType(varBinder->GetContext()->GetChecker()->AsETSChecker()->GlobalTypeError())); decl->BindNode(ident); } @@ -520,7 +520,7 @@ void ETSBinder::BuildClassDefinitionImpl(ir::ClassDefinition *classDef) } } else { ES2PANDA_ASSERT(GetContext()->diagnosticEngine->IsAnyError()); - auto *checker = GetContext()->checker->AsETSChecker(); + auto *checker = GetContext()->GetChecker()->AsETSChecker(); prop->SetTsType(checker->GlobalTypeError()); prop->Id()->SetTsType(checker->GlobalTypeError()); } @@ -647,11 +647,13 @@ void AddOverloadFlag(ArenaAllocator *allocator, bool isStdLib, varbinder::Variab if (!currentNode->HasOverload(method)) { currentNode->AddOverload(method); - method->Function()->Id()->SetVariable(variable); - method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); - method->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD); - util::UString newInternalName(method->Function()->Scope()->Name(), allocator); - method->Function()->Scope()->BindInternalName(newInternalName.View()); + if (method->Function()->Scope()->InternalName() == "") { + method->Function()->Id()->SetVariable(variable); + method->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); + method->Function()->AddFlag(ir::ScriptFunctionFlags::EXTERNAL_OVERLOAD); + util::UString newInternalName(method->Function()->Scope()->Name(), allocator); + method->Function()->Scope()->BindInternalName(newInternalName.View()); + } } } @@ -664,6 +666,9 @@ void ETSBinder::ImportAllForeignBindings(ir::AstNode *const specifier, bool const isStdLib = util::Helpers::IsStdLib(Program()); for (const auto [bindingName, var] : globalBindings) { + if (!var->Declaration()->Node()->IsValidInCurrentPhase()) { + continue; + } if (util::Helpers::IsGlobalVar(var)) { const auto *const classDef = var->Declaration()->Node()->AsClassDeclaration()->Definition(); ImportGlobalProperties(classDef); @@ -973,7 +978,10 @@ static Variable *FindInStatic(parser::Program *program) static Variable *FindInInstance(parser::Program *program) { - auto predicateFunc = [](const auto &item) { return item.second->Declaration()->Node()->IsDefaultExported(); }; + auto predicateFunc = [](const auto &item) { + return item.second->Declaration()->Node()->IsValidInCurrentPhase() && + item.second->Declaration()->Node()->IsDefaultExported(); + }; const auto &instanceMethodBindings = program->GlobalClassScope()->InstanceMethodScope()->Bindings(); auto result = std::find_if(instanceMethodBindings.begin(), instanceMethodBindings.end(), predicateFunc); if (result == instanceMethodBindings.end()) { @@ -1117,7 +1125,7 @@ bool ETSBinder::BuildInternalName(ir::ScriptFunction *scriptFunc) bool compilable = scriptFunc->Body() != nullptr && !isExternal; if (!compilable) { - recordTable_->Signatures().push_back(funcScope); + recordTable_->EmplaceSignatures(funcScope, scriptFunc); } return compilable; @@ -1140,7 +1148,7 @@ bool ETSBinder::BuildInternalNameWithCustomRecordTable(ir::ScriptFunction *const const bool compilable = scriptFunc->Body() != nullptr && !isExternal; if (!compilable) { - recordTable->Signatures().push_back(funcScope); + recordTable->EmplaceSignatures(funcScope, scriptFunc); } return compilable; @@ -1195,10 +1203,7 @@ void ETSBinder::BuildProgram() for (auto &[_, extPrograms] : Program()->ExternalSources()) { (void)_; for (auto *extProg : extPrograms) { - if (!extProg->GetFlag(parser::ProgramFlags::AST_IDENTIFIER_ANALYZED)) { - BuildExternalProgram(extProg); - extProg->SetFlag(parser::ProgramFlags::AST_IDENTIFIER_ANALYZED); - } + BuildExternalProgram(extProg); } } @@ -1208,7 +1213,7 @@ void ETSBinder::BuildProgram() ValidateReexports(); - auto &stmts = Program()->Ast()->Statements(); + auto &stmts = Program()->Ast()->StatementsForUpdates(); const auto etsGlobal = std::find_if(stmts.begin(), stmts.end(), [](const ir::Statement *stmt) { return stmt->IsClassDeclaration() && stmt->AsClassDeclaration()->Definition()->IsGlobal(); }); @@ -1234,13 +1239,19 @@ void ETSBinder::BuildExternalProgram(parser::Program *extProgram) auto flags = Program()->VarBinder()->IsGenStdLib() ? RecordTableFlags::NONE : RecordTableFlags::EXTERNAL; auto *extRecordTable = Allocator()->New(Allocator(), extProgram, flags); + extRecordTable->SetClassDefinition(extProgram->GlobalClass()); + externalRecordTable_.insert({extProgram, extRecordTable}); ResetTopScope(extProgram->GlobalScope()); recordTable_ = extRecordTable; SetProgram(extProgram); - BuildProgram(); + if (!extProgram->IsASTLowered()) { + BuildProgram(); + } else { + extRecordTable->Merge(extProgram->VarBinder()->AsETSBinder()->GetExternalRecordTable().at(extProgram)); + } SetProgram(savedProgram); recordTable_ = savedRecordTable; @@ -1332,7 +1343,7 @@ void ETSBinder::ValidateReexportDeclaration(ir::ETSReExportDeclaration *decl) const auto *const import = decl->GetETSImportDeclarations(); const auto &specifiers = import->Specifiers(); - for (auto specifier : specifiers) { + for (auto const specifier : specifiers) { // Example: export {foo} from "./A" if (specifier->IsImportSpecifier()) { auto importSpecifier = specifier->AsImportSpecifier(); diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index 6d24b0f3c7..140596eccd 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -209,10 +209,15 @@ public: void AddReExportImport(ir::ETSReExportDeclaration *reExport) noexcept { - reExportImports_.push_back(reExport); + reExportImports_.insert(reExport); } - [[nodiscard]] const ArenaVector &ReExportImports() const noexcept + [[nodiscard]] const ArenaUnorderedSet &ReExportImports() const noexcept + { + return reExportImports_; + } + + [[nodiscard]] ArenaUnorderedSet &ReExportImports() noexcept { return reExportImports_; } @@ -273,6 +278,18 @@ public: globalRecordTable_.CleanUp(); } + void CopyTo(VarBinder *target) override + { + auto targetImpl = reinterpret_cast(target); + + targetImpl->defaultImports_ = defaultImports_; + InitImplicitThisParam(); + targetImpl->selectiveExportAliasMultimap_ = selectiveExportAliasMultimap_; + ; + + VarBinder::CopyTo(target); + } + private: void BuildClassDefinitionImpl(ir::ClassDefinition *classDef); void InitImplicitThisParam(); @@ -293,14 +310,14 @@ private: RecordTable globalRecordTable_; RecordTable *recordTable_; ArenaMap externalRecordTable_; - ArenaVector defaultImports_; + ArenaVector defaultImports_; // 1 ArenaVector dynamicImports_; - ArenaVector reExportImports_; + ArenaUnorderedSet reExportImports_; ArenaSet reexportedNames_; DynamicImportVariables dynamicImportVars_; - ir::Identifier *thisParam_ {}; + ir::Identifier *thisParam_ {}; // 2 ir::AstNode *defaultExport_ {}; - ModulesToExportedNamesWithAliases selectiveExportAliasMultimap_; + ModulesToExportedNamesWithAliases selectiveExportAliasMultimap_; // 3 friend class RecordTableContext; }; @@ -310,7 +327,8 @@ public: RecordTableContext(ETSBinder *varBinder, parser::Program *extProgram) : varBinder_(varBinder), savedRecordTable_(varBinder->recordTable_) { - if (extProgram != nullptr) { + if (extProgram != nullptr && + varBinder->externalRecordTable_.find(extProgram) != varBinder->externalRecordTable_.end()) { varBinder->recordTable_ = varBinder->externalRecordTable_[extProgram]; } } diff --git a/ets2panda/varbinder/recordTable.h b/ets2panda/varbinder/recordTable.h index 1b3c9bd10c..437a2ffb79 100644 --- a/ets2panda/varbinder/recordTable.h +++ b/ets2panda/varbinder/recordTable.h @@ -21,6 +21,8 @@ #include "util/ustring.h" #include "util/enumbitops.h" +#include + namespace ark::es2panda::parser { class Program; } // namespace ark::es2panda::parser @@ -72,6 +74,25 @@ public: ~RecordTable() = default; + void Merge(RecordTable *other) + { + for (auto classDef : other->classDefinitions_) { + classDefinitions_.insert(classDef); + } + + for (auto interfaceDecl : other->InterfaceDeclarations()) { + interfaceDeclarations_.insert(interfaceDecl); + } + + for (auto annoDecl : other->AnnotationDeclarations()) { + annotationDeclarations_.insert(annoDecl); + } + + for (auto sig : other->signatures_) { + signatures_.insert(sig); + } + } + bool IsExternal() const { return (flags_ & RecordTableFlags::EXTERNAL) != 0; @@ -107,16 +128,22 @@ public: return annotationDeclarations_; } - ArenaVector &Signatures() + ArenaSet &Signatures() { return signatures_; } - const ArenaVector &Signatures() const + const ArenaSet &Signatures() const { return signatures_; } + void EmplaceSignatures(varbinder::FunctionScope *signature, ir::ScriptFunction *func) + { + func->AddFlag(ir::ScriptFunctionFlags::IN_RECORD); + signatures_.insert(signature); + } + void SetClassDefinition(ir::ClassDefinition *classDefinition) { record_ = classDefinition; @@ -208,7 +235,7 @@ private: ArenaSet classDefinitions_; ArenaSet interfaceDeclarations_; ArenaSet annotationDeclarations_; - ArenaVector signatures_; + ArenaSet signatures_; RecordHolder record_ {nullptr}; parser::Program *program_ {}; BoundContext *boundCtx_ {}; diff --git a/ets2panda/varbinder/varbinder.cpp b/ets2panda/varbinder/varbinder.cpp index 0504029b7b..83750a6424 100644 --- a/ets2panda/varbinder/varbinder.cpp +++ b/ets2panda/varbinder/varbinder.cpp @@ -470,6 +470,19 @@ void VarBinder::VisitScriptFunction(ir::ScriptFunction *func) } if (!BuildInternalName(func)) { + if (func->Body() == nullptr) { + return; + } + auto stmt = func->Body()->AsBlockStatement()->Statements(); + auto scopeCtx = LexicalScope::Enter(this, funcScope); + std::function doNode = [&](ir::AstNode *node) { + if (node->IsTSInterfaceDeclaration() || node->IsClassDeclaration() || node->IsTSEnumDeclaration() || + node->IsAnnotationDeclaration()) { + ResolveReference(node); + } + node->Iterate([&](ir::AstNode *child) { doNode(child); }); + }; + doNode(func->Body()); return; } diff --git a/ets2panda/varbinder/varbinder.h b/ets2panda/varbinder/varbinder.h index 7005e55370..ff674f639b 100644 --- a/ets2panda/varbinder/varbinder.h +++ b/ets2panda/varbinder/varbinder.h @@ -285,6 +285,15 @@ protected: functionScopes_.clear(); } + virtual void CopyTo(VarBinder *target) + { + target->program_ = program_; + target->allocator_ = allocator_; + target->context_ = context_; + target->bindingOptions_ = bindingOptions_; + target->genStdLib_ = genStdLib_; + } + private: parser::Program *program_ {}; ArenaAllocator *allocator_ {}; diff --git a/ets2panda/varbinder/variable.h b/ets2panda/varbinder/variable.h index ba937f6b01..be95eb82d3 100644 --- a/ets2panda/varbinder/variable.h +++ b/ets2panda/varbinder/variable.h @@ -152,7 +152,7 @@ private: class LocalVariable : public Variable { public: explicit LocalVariable(Decl *decl, VariableFlags flags); - explicit LocalVariable(VariableFlags flags); + explicit LocalVariable(const VariableFlags flags); VariableType Type() const override { -- Gitee From fbfc083f2cc84305627a2602e35c47e8da5464c3 Mon Sep 17 00:00:00 2001 From: xudan16 Date: Fri, 30 May 2025 16:57:37 +0800 Subject: [PATCH 015/747] homecheck add s2d object literal rule Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBQ5W Signed-off-by: xudan16 --- ets2panda/linter/homecheck/ruleSet.json | 5 +- .../InteropS2DObjectLiteralsCheck.ts | 347 ++++++++++++++++++ .../src/utils/common/CheckerIndex.ts | 2 + 3 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 ets2panda/linter/homecheck/src/checker/migration/InteropS2DObjectLiteralsCheck.ts diff --git a/ets2panda/linter/homecheck/ruleSet.json b/ets2panda/linter/homecheck/ruleSet.json index adfc2898b5..517d135327 100644 --- a/ets2panda/linter/homecheck/ruleSet.json +++ b/ets2panda/linter/homecheck/ruleSet.json @@ -208,6 +208,7 @@ "@migration/interop-dynamic-object-literals": 1, "@migration/interop-assign": 1, "@migration/interop-boxed-type-check": 1, - "@migration/interop-js-modify-property": 1 + "@migration/interop-js-modify-property": 1, + "@migration/arkts-interop-s2d-object-literal": 1 } -} +} \ No newline at end of file diff --git a/ets2panda/linter/homecheck/src/checker/migration/InteropS2DObjectLiteralsCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/InteropS2DObjectLiteralsCheck.ts new file mode 100644 index 0000000000..79c14788bd --- /dev/null +++ b/ets2panda/linter/homecheck/src/checker/migration/InteropS2DObjectLiteralsCheck.ts @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ArkMethod, + ArkAssignStmt, + Stmt, + Scene, + Value, + ArkInstanceFieldRef, + ClassType, + ArkInvokeStmt, + AbstractInvokeExpr, + ArkField, + ArkReturnStmt, +} from 'arkanalyzer/lib'; +import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; +import { BaseChecker, BaseMetaData } from '../BaseChecker'; +import { Rule, Defects, MatcherCallback, MatcherTypes, MethodMatcher } from '../../Index'; +import { IssueReport } from '../../model/Defects'; +import { ArkClass, ClassCategory } from 'arkanalyzer/lib/core/model/ArkClass'; +import { Language } from 'arkanalyzer/lib/core/model/ArkFile'; +import { getLanguageStr, getLineAndColumn } from './Utils'; + +const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'InteropS2DObjectLiteralCheck'); +const gMetaData: BaseMetaData = { + severity: 1, + ruleDocPath: '', + description: '', +}; + +const s2dRuleId: string = 'arkts-interop-s2d-object-literal'; + +type IssueData = { + stmt: Stmt; + value: Value; +}; + +export class InteropS2DObjectLiteralCheck implements BaseChecker { + private scene: Scene; + readonly metaData: BaseMetaData = gMetaData; + public rule: Rule; + public defects: Defects[] = []; + public issues: IssueReport[] = []; + + private methodMatcher: MethodMatcher = { + matcherType: MatcherTypes.METHOD, + }; + + public registerMatchers(): MatcherCallback[] { + const methodMatcher: MatcherCallback = { + matcher: this.methodMatcher, + callback: this.check, + }; + return [methodMatcher]; + } + + public check = (arkMethod: ArkMethod): void => { + this.scene = arkMethod.getDeclaringArkFile().getScene(); + + if (arkMethod.getLanguage() !== Language.ARKTS1_1) { + return; + } + // 检测的sink点为赋值语句,且左值的类型注解明确为1.2的class或者包含1.2的class的更复杂数据结构 + const stmts = arkMethod.getBody()?.getCfg().getStmts() ?? []; + // 检查所有语句 + // 1. 对于赋值语句,检查左边是否为arkts1.2的class类型或某个field为arkts1.2的class类型,右边对象或对应属性是否用arkts1.1的object litral赋值 + // 2. 对于函数调用,可能为invoke语句或赋值语句的右值为invoke表达式,检查入参是否存在如上的情况 + for (const stmt of stmts) { + if (stmt instanceof ArkAssignStmt) { + this.checkAssignWithObjectLiteral(stmt, arkMethod); + if (stmt.getRightOp() instanceof AbstractInvokeExpr) { + this.checkInvokeWithObjectLiteral(stmt, arkMethod); + } + } else if (stmt instanceof ArkInvokeStmt) { + this.checkInvokeWithObjectLiteral(stmt, arkMethod); + } + } + // 检查函数的返回值,若函数签名中返回类型声明是否为arkts1.2的class类型或某个field为arkts1.2的class类型,且实际返回对象或对应属性是否为arkts1.1的object litral + this.checkReturnWithObjectLiteral(arkMethod); + }; + + private getClassWithType(checkType: ClassType): ArkClass | null { + return this.scene.getClass(checkType.getClassSignature()); + } + + private isClassFromEtsStatic(clazz: ArkClass): boolean { + return clazz.getLanguage() === Language.ARKTS1_2 && clazz.getCategory() !== ClassCategory.OBJECT; + } + + private isObjectLiteralFromEtsDynamic(clazz: ArkClass): boolean { + return clazz.getLanguage() === Language.ARKTS1_1 && clazz.getCategory() === ClassCategory.OBJECT; + } + + private checkAssignWithObjectLiteral(stmt: ArkAssignStmt, target: ArkMethod): void { + const leftOpType = stmt.getLeftOp().getType(); + if (!(leftOpType instanceof ClassType)) { + return; + } + const leftTypeClass = this.getClassWithType(leftOpType); + if (leftTypeClass === null) { + logger.debug(`Failed to find class of type ${leftOpType.toString()}`); + return; + } + if (this.isClassFromEtsStatic(leftTypeClass)) { + const rightOpType = stmt.getRightOp().getType(); + if (!(rightOpType instanceof ClassType)) { + return; + } + const rightTypeClass = this.getClassWithType(rightOpType); + if (rightTypeClass === null) { + logger.debug(`Failed to find class of type ${rightOpType.toString()}`); + return; + } + if (this.isObjectLiteralFromEtsDynamic(rightTypeClass)) { + this.addIssueReport(stmt, stmt.getRightOp()); + return; + } + } + let results: IssueData[] = []; + this.checkAllClassFieldWithValue(stmt, stmt.getRightOp(), leftTypeClass, results); + for (const result of results) { + this.addIssueReport(result.stmt, result.value); + } + } + + private checkInvokeWithObjectLiteral(stmt: ArkInvokeStmt | ArkAssignStmt, target: ArkMethod): void { + let invokeExpr: AbstractInvokeExpr; + if (stmt instanceof ArkInvokeStmt) { + invokeExpr = stmt.getInvokeExpr(); + } else { + const rightOp = stmt.getRightOp(); + if (!(rightOp instanceof AbstractInvokeExpr)) { + return; + } + invokeExpr = rightOp; + } + const method = this.scene.getMethod(invokeExpr.getMethodSignature()); + if (method === null) { + logger.debug(`Failed to find method in invoke expr, method: ${invokeExpr.getMethodSignature().toString()}`); + return; + } + for (const [index, param] of method.getParameters().entries()) { + const paramType = param.getType(); + if (!(paramType instanceof ClassType)) { + continue; + } + const paramTypeClass = this.getClassWithType(paramType); + if (paramTypeClass === null) { + logger.debug(`Failed to find class of method param type ${paramType.toString()}, method: ${method.getSignature().toString()}`); + continue; + } + if (index >= invokeExpr.getArgs().length) { + logger.debug(`Failed to find param with index ${index} of method: ${method.getSignature().toString()}`); + continue; + } + const arg = invokeExpr.getArg(index); + if (this.isClassFromEtsStatic(paramTypeClass)) { + const argType = arg.getType(); + if (!(argType instanceof ClassType)) { + continue; + } + const argTypeClass = this.getClassWithType(argType); + if (argTypeClass === null) { + logger.debug(`Failed to find class of invoke arg type ${argType.toString()}, method: ${method.getSignature().toString()}`); + continue; + } + if (this.isObjectLiteralFromEtsDynamic(argTypeClass)) { + this.addIssueReport(stmt, arg); + return; + } + } + let results: IssueData[] = []; + this.checkAllClassFieldWithValue(stmt, arg, paramTypeClass, results); + for (const result of results) { + this.addIssueReport(result.stmt, result.value); + } + } + } + + private checkReturnWithObjectLiteral(target: ArkMethod): void { + // 构造函数的返回值一定是当前class本身,其各field和method已在其他地方进行检查,这里无需检查构造函数的返回值 + if (target.getName() === 'constructor') { + return; + } + const returnType = target.getReturnType(); + if (!(returnType instanceof ClassType)) { + return; + } + const returnTypeClass = this.getClassWithType(returnType); + if (returnTypeClass === null) { + logger.debug(`Failed to find method of return type ${returnType.toString()}, method ${target.getSignature().toString()}`); + return; + } + const returnStmts = target.getReturnStmt(); + if (this.isClassFromEtsStatic(returnTypeClass)) { + for (const returnStmt of returnStmts) { + if (!(returnStmt instanceof ArkReturnStmt)) { + continue; + } + const valueType = returnStmt.getOp().getType(); + if (!(valueType instanceof ClassType)) { + continue; + } + const valueTypeClass = this.getClassWithType(valueType); + if (valueTypeClass === null) { + logger.debug(`Failed to find method of return value type ${valueType.toString()}, method ${target.getSignature().toString()}`); + continue; + } + if (this.isObjectLiteralFromEtsDynamic(valueTypeClass)) { + this.addIssueReport(returnStmt, returnStmt.getOp()); + } + } + return; + } + + for (const returnStmt of returnStmts) { + if (!(returnStmt instanceof ArkReturnStmt)) { + continue; + } + let results: IssueData[] = []; + this.checkAllClassFieldWithValue(returnStmt, returnStmt.getOp(), returnTypeClass, results); + if (results.length > 0) { + this.addIssueReport(returnStmt, returnStmt.getOp()); + } + } + } + + private checkAllClassFieldWithValue(sinkStmt: Stmt, val: Value, needCheckClass: ArkClass, result: IssueData[], checkedTypes?: Set): void { + let visited: Set = checkedTypes ?? new Set(); + if (visited.has(needCheckClass.getSignature().toString())) { + return; + } + visited.add(needCheckClass.getSignature().toString()); + for (const field of needCheckClass.getFields()) { + const fieldType = field.getType(); + if (!(fieldType instanceof ClassType)) { + continue; + } + const fieldTypeClass = this.getClassWithType(fieldType); + if (fieldTypeClass === null) { + logger.debug( + `Failed to find class of type ${fieldType.toString()} of field: ${field.getName()}, class ${needCheckClass.getSignature().toString()}}` + ); + continue; + } + const fieldInitializers = this.getFieldInitializersWithValue(field, val); + const fieldAssignStmt = this.getFieldAssignStmtInInitializers(field, fieldInitializers); + if (fieldAssignStmt === null) { + continue; + } + if (this.isClassFromEtsStatic(fieldTypeClass)) { + const rightOpType = fieldAssignStmt.getRightOp().getType(); + if (!(rightOpType instanceof ClassType)) { + continue; + } + const rightOpTypeClass = this.getClassWithType(rightOpType); + if (rightOpTypeClass === null) { + logger.debug( + `Failed to find class of type ${rightOpType.toString()} of field initializer, field: ${field.getName()}, class ${needCheckClass.getSignature().toString()}}` + ); + continue; + } + if (this.isObjectLiteralFromEtsDynamic(rightOpTypeClass)) { + result.push({ stmt: sinkStmt, value: val }); + continue; + } + continue; + } + this.checkAllClassFieldWithValue(fieldAssignStmt, fieldAssignStmt.getRightOp(), fieldTypeClass, result, visited); + } + } + + private getFieldAssignStmtInInitializers(field: ArkField, fieldInitializers: Stmt[]): ArkAssignStmt | null { + for (const stmt of fieldInitializers) { + if (!(stmt instanceof ArkAssignStmt)) { + continue; + } + const leftOp = stmt.getLeftOp(); + if (!(leftOp instanceof ArkInstanceFieldRef)) { + continue; + } + if (leftOp.getFieldName() === field.getName()) { + return stmt; + } + } + return null; + } + + // 对于object literal(主要是多层嵌套场景),根据需要查找的field的名字,获取其对应的内部嵌套class的初始化语句 + private getFieldInitializersWithValue(leftField: ArkField, val: Value): Stmt[] { + const res: Stmt[] = []; + const rightOpType = val.getType(); + if (!(rightOpType instanceof ClassType)) { + return res; + } + const rightOpTypeClass = this.getClassWithType(rightOpType); + if (rightOpTypeClass === null) { + logger.debug(`Failed to find class of type ${rightOpType.toString()} of field: ${leftField.getSignature().toString()}`); + return res; + } + for (const field of rightOpTypeClass.getFields()) { + if (field.getName() === leftField.getName()) { + return field.getInitializer(); + } + } + return res; + } + + private addIssueReport(stmt: Stmt, operand: Value): void { + const severity = this.metaData.severity; + let warnInfo = getLineAndColumn(stmt, operand); + let targetLan1 = getLanguageStr(Language.ARKTS1_1); + let targetLan2 = getLanguageStr(Language.ARKTS1_2); + + const problem = 'Interop'; + const desc = `In ${targetLan1}, it is not allowed to create object literal of type from ${targetLan2} (${s2dRuleId})`; + + let defects = new Defects( + warnInfo.line, + warnInfo.startCol, + warnInfo.endCol, + problem, + desc, + severity, + this.rule.ruleId, + warnInfo.filePath, + this.metaData.ruleDocPath, + true, + false, + false + ); + this.issues.push(new IssueReport(defects, undefined)); + } +} diff --git a/ets2panda/linter/homecheck/src/utils/common/CheckerIndex.ts b/ets2panda/linter/homecheck/src/utils/common/CheckerIndex.ts index b022e5bd12..99fbd03f1d 100644 --- a/ets2panda/linter/homecheck/src/utils/common/CheckerIndex.ts +++ b/ets2panda/linter/homecheck/src/utils/common/CheckerIndex.ts @@ -27,6 +27,7 @@ import { InteropObjectLiteralCheck } from '../../checker/migration/InteropDynami import { InteropAssignCheck } from '../../checker/migration/InteropAssignCheck'; import { InteropJSModifyPropertyCheck } from '../../checker/migration/InteropJSModifyPropertyCheck'; import { NoTSLikeAsCheck } from '../../checker/migration/NoTSLikeAsCheck'; +import { InteropS2DObjectLiteralCheck } from '../../checker/migration/InteropS2DObjectLiteralsCheck'; const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'CheckerIndex'); @@ -38,6 +39,7 @@ export const fileRules = { '@migration/arkui-custombuilder-passing': CustomBuilderCheck, '@migration/no-method-overriding-field-check': NoMethodOverridingFieldCheck, '@migration/interop-boxed-type-check': InteropBoxedTypeCheck, + '@migration/arkts-interop-s2d-object-literal': InteropS2DObjectLiteralCheck, }; export const projectRules = { -- Gitee From 5c7ded0f7119f4da42de1f53a05ab8075ab2f0fb Mon Sep 17 00:00:00 2001 From: Gabor Aron Takacs Date: Thu, 29 May 2025 15:55:46 +0200 Subject: [PATCH 016/747] Add diagnostics for export assignment Fixes #24666 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBIUN Change-Id: I8a543f2f20a02950f139b395a50890e9c33bd91d Signed-off-by: Gabor Aron Takacs --- ets2panda/parser/ETSparserClasses.cpp | 2 ++ .../test/ast/parser/ets/export_assignment.ets | 21 +++++++++++++++++++ ets2panda/util/diagnostic/syntax.yaml | 6 +++++- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/ast/parser/ets/export_assignment.ets diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index c1dc7c92e0..df82cbec20 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -1338,6 +1338,8 @@ std::pair ETSParser::ParseMemberModifi Lexer()->Rewind(savedPos); } memberModifiers |= ir::ModifierFlags::EXPORT; + } else if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + LogError(diagnostic::ERROR_ARKTS_NO_EXPORT_ASSIGNMENT); } else { memberModifiers |= ir::ModifierFlags::EXPORT; } diff --git a/ets2panda/test/ast/parser/ets/export_assignment.ets b/ets2panda/test/ast/parser/ets/export_assignment.ets new file mode 100644 index 0000000000..7dc0bbfcc8 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/export_assignment.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export /* @@ label1 */= /* @@ label2 */Point + +/* @@@ label1 Error SyntaxError: 'export = ...' syntax is not supported, use regular import/export instead! */ +/* @@@ label1 Error SyntaxError: Unexpected token '='. */ +/* @@@ label2 Error SyntaxError: Unexpected token 'Point'. */ +/* @@@ label2 Error TypeError: Unresolved reference Point */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index d18a5f9766..bb3bcb5a83 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1234,4 +1234,8 @@ syntax: - name: OPTIONAL_VARIABLE id: 306 - message: "Optional variable is deprecated and no longer supported." \ No newline at end of file + message: "Optional variable is deprecated and no longer supported." + +- name: ERROR_ARKTS_NO_EXPORT_ASSIGNMENT + id: 307 + message: "'export = ...' syntax is not supported, use regular import/export instead!" -- Gitee From 255dfdc5d79b229e3dac4c3cb3dd5cf333ba8318 Mon Sep 17 00:00:00 2001 From: sniperc96 Date: Wed, 28 May 2025 17:37:52 +0800 Subject: [PATCH 017/747] add rule:PropNeedCallMethodForOneWayBinding Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICC0PH Signed-off-by: sniperc96 --- ets2panda/linter/src/lib/CookBookMsg.ts | 2 + ets2panda/linter/src/lib/FaultAttrs.ts | 1 + ets2panda/linter/src/lib/FaultDesc.ts | 1 + ets2panda/linter/src/lib/Problems.ts | 1 + ets2panda/linter/src/lib/TypeScriptLinter.ts | 73 +++ .../src/lib/utils/consts/ArkTS2Rules.ts | 1 + ...s => prop_decorators_and_interfaces_1.ets} | 0 ...decorators_and_interfaces_1.ets.args.json} | 0 ...corators_and_interfaces_1.ets.arkts2.json} | 0 ...prop_decorators_and_interfaces_1.ets.json} | 0 ...s => prop_decorators_and_interfaces_2.ets} | 0 ...decorators_and_interfaces_2.ets.args.json} | 0 ...corators_and_interfaces_2.ets.arkts2.json} | 0 ...prop_decorators_and_interfaces_2.ets.json} | 0 ...s => prop_decorators_and_interfaces_3.ets} | 0 ...decorators_and_interfaces_3.ets.args.json} | 0 ...corators_and_interfaces_3.ets.arkts2.json} | 0 ...prop_decorators_and_interfaces_3.ets.json} | 0 .../main/prop_decorators_and_interfaces_4.ets | 108 +++++ ..._decorators_and_interfaces_4.ets.args.json | 19 + ...ecorators_and_interfaces_4.ets.arkts2.json | 458 ++++++++++++++++++ .../prop_decorators_and_interfaces_4.ets.json | 17 + 22 files changed, 681 insertions(+) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_1.ets => prop_decorators_and_interfaces_1.ets} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_1.ets.args.json => prop_decorators_and_interfaces_1.ets.args.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_1.ets.arkts2.json => prop_decorators_and_interfaces_1.ets.arkts2.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_1.ets.json => prop_decorators_and_interfaces_1.ets.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_2.ets => prop_decorators_and_interfaces_2.ets} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_2.ets.args.json => prop_decorators_and_interfaces_2.ets.args.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_2.ets.arkts2.json => prop_decorators_and_interfaces_2.ets.arkts2.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_2.ets.json => prop_decorators_and_interfaces_2.ets.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_3.ets => prop_decorators_and_interfaces_3.ets} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_3.ets.args.json => prop_decorators_and_interfaces_3.ets.args.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_3.ets.arkts2.json => prop_decorators_and_interfaces_3.ets.arkts2.json} (100%) rename ets2panda/linter/test/main/{prop_decorator_and_interfaces_3.ets.json => prop_decorators_and_interfaces_3.ets.json} (100%) create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.json diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 62c12d1403..dc43661a29 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -286,6 +286,8 @@ cookBookTag[282] = '"@StorageProp" decorator is not supported (arkui-no-storagep cookBookTag[283] = '"@LocalStorageProp" decorator is not supported (arkui-no-localstorageprop-decorator)'; cookBookTag[284] = '"prop" function is not supported (arkui-no-prop-function)'; cookBookTag[285] = '"setAndProp" function is not supported (arkui-no-setandprop-function)'; +cookBookTag[286] = + 'Parameters decorated with "@Prop" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)'; cookBookTag[300] = 'The function type should be explicit (arkts-no-ts-like-function-call)'; cookBookTag[301] = 'Importing from "oh module" requires specifying full path (arkts-ohmurl-full-path)'; cookBookTag[302] = diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index 2d555b1a2a..975b1351fb 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -199,6 +199,7 @@ faultsAttrs[FaultID.StoragePropDecoratorNotSupported] = new FaultAttributes(282) faultsAttrs[FaultID.LocalStoragePropDecoratorNotSupported] = new FaultAttributes(283); faultsAttrs[FaultID.PropFunctionNotSupported] = new FaultAttributes(284); faultsAttrs[FaultID.SetAndPropFunctionNotSupported] = new FaultAttributes(285); +faultsAttrs[FaultID.PropNeedCallMethodForDeepCopy] = new FaultAttributes(286); faultsAttrs[FaultID.ExplicitFunctionType] = new FaultAttributes(300); faultsAttrs[FaultID.OhmUrlFullPath] = new FaultAttributes(301); faultsAttrs[FaultID.InteropCallObjectParam] = new FaultAttributes(302); diff --git a/ets2panda/linter/src/lib/FaultDesc.ts b/ets2panda/linter/src/lib/FaultDesc.ts index d33c364676..49646a1965 100644 --- a/ets2panda/linter/src/lib/FaultDesc.ts +++ b/ets2panda/linter/src/lib/FaultDesc.ts @@ -251,3 +251,4 @@ faultDesc[FaultID.StoragePropDecoratorNotSupported] = '"@StorageProp" decorator faultDesc[FaultID.LocalStoragePropDecoratorNotSupported] = '"@LocalStorageProp" decorator is not supported'; faultDesc[FaultID.PropFunctionNotSupported] = '"prop" function is not supported'; faultDesc[FaultID.SetAndPropFunctionNotSupported] = '"setAndProp" function is not supported'; +faultDesc[FaultID.PropNeedCallMethodForDeepCopy] = 'Deep copy needs to call the specific method'; diff --git a/ets2panda/linter/src/lib/Problems.ts b/ets2panda/linter/src/lib/Problems.ts index 0620a0c837..e9dd80975f 100644 --- a/ets2panda/linter/src/lib/Problems.ts +++ b/ets2panda/linter/src/lib/Problems.ts @@ -252,6 +252,7 @@ export enum FaultID { LocalStoragePropDecoratorNotSupported, PropFunctionNotSupported, SetAndPropFunctionNotSupported, + PropNeedCallMethodForDeepCopy, // this should always be last enum LAST_ID } diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4caeea6c34..a658817c0e 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -1642,6 +1642,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private handlePropertyAssignment(node: ts.PropertyAssignment): void { this.handleDollarBind(node); + this.handlePropertyAssignmentForProp(node); this.handleQuotedHyphenPropsDeprecated(node); const propName = node.name; @@ -8888,6 +8889,78 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return targetTypes.includes(storageType.getText()); } + private handlePropertyAssignmentForProp(node: ts.PropertyAssignment): void { + if (!this.options.arkts2) { + return; + } + + const callExpr = node.parent.parent; + if (!ts.isCallExpression(callExpr)) { + return; + } + + const structDecl = TsUtils.getDeclaration(this.tsTypeChecker.getSymbolAtLocation(callExpr.expression)); + if (!structDecl || !ts.isStructDeclaration(structDecl) || !structDecl.name) { + return; + } + + const variable = node.name; + if (!ts.isIdentifier(variable)) { + return; + } + + const targetNode = TypeScriptLinter.findVariableChangeNodeInStruct(variable, structDecl); + if (!targetNode) { + return; + } + + const targetDecl = TsUtils.getDeclaration(this.tsTypeChecker.getSymbolAtLocation(targetNode)); + if (!targetDecl || !ts.isPropertyDeclaration(targetDecl)) { + return; + } + + const decorators = ts.getDecorators(targetDecl); + if (!decorators || decorators.length === 0) { + return; + } + + const decorator = decorators[0]; + const decoratorName = TsUtils.getDecoratorName(decorator); + if (decoratorName === PropDecoratorName.Prop) { + this.incrementCounters(node, FaultID.PropNeedCallMethodForDeepCopy); + } + } + + private static findVariableChangeNodeInStruct( + variable: ts.Identifier, + structDecl: ts.StructDeclaration + ): ts.MemberName | undefined { + let changeNode: ts.MemberName | undefined; + + function traverse(node: ts.Node): void { + if (changeNode) { + return; + } + + if (ts.isPropertyAccessExpression(node)) { + if ( + node.expression.kind === ts.SyntaxKind.ThisKeyword && + node.name.getText() === variable.getText() && + (ts.findAncestor(node, ts.isPostfixUnaryExpression) || + ts.findAncestor(node, ts.isPrefixUnaryExpression) || + ts.findAncestor(node, ts.isBinaryExpression)) + ) { + changeNode = node.name; + } + } + + ts.forEachChild(node, traverse); + } + + traverse(structDecl); + return changeNode; + } + private getIdentifierForAwaitExpr(awaitExpr: ts.AwaitExpression): IdentifierAndArguments { void this; diff --git a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts index 725c29fdce..2eaef243aa 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts @@ -82,6 +82,7 @@ export const arkts2Rules: number[] = [ 283, 284, 285, + 286, 300, 301, 302, diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.args.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.arkts2.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_1.ets.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.args.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.args.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.args.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.arkts2.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.arkts2.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.arkts2.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_2.ets.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_2.ets.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.args.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.args.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.args.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.arkts2.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.arkts2.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.arkts2.json diff --git a/ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.json similarity index 100% rename from ets2panda/linter/test/main/prop_decorator_and_interfaces_3.ets.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_3.ets.json diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets new file mode 100644 index 0000000000..4f8c44b226 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface ChildComponentOptions { + count: number; +} + +@Component +struct SuperComponent1 { + @State countOptions: ChildComponentOptions = { count: 0 } + + build() { + Column() { + ChildComponent1({ options1: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct SuperComponent2 { + @State countOptions: ChildComponentOptions = { count: 0 } + + build() { + Column() { + ChildComponent2({ options2: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct SuperComponent3 { + @State countOptions: ChildComponentOptions = { count: 0 } + + build() { + Column() { + ChildComponent3({ options3: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct ChildComponent1 { + @Prop options1: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options1.count}`) + Blank() + Button('+').onClick(() => { + this.options1.count++; + }) + Button('-').onClick(() => { + this.options1.count--; + }) + } + } +} + +@Component +struct ChildComponent2 { + @Prop options2: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options2.count}`) + Blank() + Button('change1').onClick(() => { + this.options2.count = 1; + }) + Button('change2').onClick(() => { + this.options2.count = 1; + }) + } + } +} + +@Component +struct ChildComponent3 { + @Prop options3: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options3.count}`) + Blank() + Button('+').onClick(() => { + ++this.options3.count; + }) + Button('-').onClick(() => { + --this.options3.count; + }) + } + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json new file mode 100644 index 0000000000..4acc088d1d --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json @@ -0,0 +1,19 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json new file mode 100644 index 0000000000..552209810c --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json @@ -0,0 +1,458 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 22, + "column": 57, + "endLine": 22, + "endColumn": 58, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 25, + "endLine": 26, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 57, + "endLine": 34, + "endColumn": 58, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 25, + "endLine": 38, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 57, + "endLine": 46, + "endColumn": 58, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 25, + "endLine": 50, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 3, + "endLine": 58, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 3, + "endLine": 76, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 83, + "column": 31, + "endLine": 83, + "endColumn": 32, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 86, + "column": 31, + "endLine": 86, + "endColumn": 32, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 94, + "column": 3, + "endLine": 94, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 2, + "endLine": 20, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 4, + "endLine": 22, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 7, + "endLine": 27, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 4, + "endLine": 34, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 7, + "endLine": 39, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 2, + "endLine": 44, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 4, + "endLine": 46, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 5, + "endLine": 49, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 7, + "endLine": 51, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 2, + "endLine": 56, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 4, + "endLine": 58, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 5, + "endLine": 61, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 7, + "endLine": 62, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 7, + "endLine": 63, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 7, + "endLine": 64, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 7, + "endLine": 67, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 2, + "endLine": 74, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 4, + "endLine": 76, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 5, + "endLine": 79, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 7, + "endLine": 80, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 81, + "column": 7, + "endLine": 81, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 7, + "endLine": 82, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 85, + "column": 7, + "endLine": 85, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 92, + "column": 2, + "endLine": 92, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 94, + "column": 4, + "endLine": 94, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 97, + "column": 5, + "endLine": 97, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 98, + "column": 7, + "endLine": 98, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 99, + "column": 7, + "endLine": 99, + "endColumn": 12, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 100, + "column": 7, + "endLine": 100, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee From 320df9ce3d3d4fa26c01dc8aa43dddbb7326101d Mon Sep 17 00:00:00 2001 From: leo9001 Date: Tue, 27 May 2025 16:41:03 +0800 Subject: [PATCH 018/747] support test cases for class hierarchies Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAWA9 Signed-off-by: leo9001 --- ets2panda/lsp/src/class_hierarchy.cpp | 124 +++++++++++------- .../test/unit/lsp/class_hierarchys_test.cpp | 95 +++++++++++++- 2 files changed, 173 insertions(+), 46 deletions(-) diff --git a/ets2panda/lsp/src/class_hierarchy.cpp b/ets2panda/lsp/src/class_hierarchy.cpp index 7022639d66..368a3ac5a5 100644 --- a/ets2panda/lsp/src/class_hierarchy.cpp +++ b/ets2panda/lsp/src/class_hierarchy.cpp @@ -308,8 +308,8 @@ TypeHierarchiesInfo GetTypeHierarchiesImpl(es2panda_Context *context, size_t pos } /** - * @brief (查找当前类的父类) Retrieves the direct superclass of a given class declaration node - * @param node - AST node representing a class declaration + * @brief (查找当前类的父类) Find immediate superclass of current class node + * @param node - current class node declaration * @return Pointer to the direct superclass node or nullptr if not found */ ir::AstNode *GetClassDirectSuperClass(ir::AstNode *node) @@ -338,9 +338,9 @@ ir::AstNode *GetClassDirectSuperClass(ir::AstNode *node) } /** - * @brief (1. 查找当前类的(所有)父类) Collects all ancestor classes in the inheritance hierarchy + * @brief (1. 查找当前类的(所有)父类) Find all superclasses of the current class node * @param context - Compiler context (unused) - * @param node - Starting class declaration node + * @param node - Current class declaration node * @return Vector of superclass nodes in inheritance order */ std::vector GetClassSuperClasses([[maybe_unused]] es2panda_Context *context, ir::AstNode *node) @@ -361,9 +361,9 @@ std::vector GetClassSuperClasses([[maybe_unused]] es2panda_Contex } /** - * @brief (查找当前类的子类) Finds immediate subclasses of a given class + * @brief (查找当前类的子类) Find immediate subclass of current class node * @param program - Pointer to the program AST - * @param node - Class declaration node to check + * @param node - Current class declaration node * @return Set of direct subclass nodes */ std::unordered_set GetClassDirectSubClasses(ark::es2panda::parser::Program *program, ir::AstNode *node) @@ -394,9 +394,9 @@ std::unordered_set GetClassDirectSubClasses(ark::es2panda::parser } /** - * @brief (2. 查找当前类的(所有)子类) Discovers all subclasses in the inheritance hierarchy using BFS + * @brief (2. 查找当前类的(所有)子类) Find all possible implementing classes of current class node * @param context - Compiler context containing program AST - * @param node - Root class declaration node + * @param node - Current class declaration node * @return Vector of all subclass nodes */ std::vector GetClassSubClasses(es2panda_Context *context, ir::AstNode *node) @@ -432,8 +432,8 @@ std::vector GetClassSubClasses(es2panda_Context *context, ir::Ast } /** - * @brief (查找当前类的父接口) Extracts directly implemented interfaces from class declaration - * @param node - Class declaration node + * @brief (查找当前类的父接口) Find interface of current class node + * @param node - Current class declaration node * @return Set of directly implemented interface nodes */ std::unordered_set GetClassDirectImplementedInterfaces(ir::AstNode *node) @@ -461,8 +461,8 @@ std::unordered_set GetClassDirectImplementedInterfaces(ir::AstNod } /** - * @brief (查找当前接口的父接口) Gets directly extended interfaces from interface declaration - * @param node - Interface declaration node + * @brief (查找当前接口的父接口) Find which interfaces current interface node extends + * @param node - Current declaration node * @return Set of directly extended interface nodes */ std::unordered_set GetInterfaceDirectExtendedInterfaces(ir::AstNode *node) @@ -490,9 +490,9 @@ std::unordered_set GetInterfaceDirectExtendedInterfaces(ir::AstNo } /** - * @brief (3. 查找当前类的(所有)父接口) Aggregates all implemented interfaces including inherited ones + * @brief (3. 查找当前类的(所有)父接口) Find all interfaces extended by current class node * @param context - Compiler context (unused) - * @param node - Starting class declaration node + * @param node - Current class declaration node * @return Vector of implemented interface nodes */ std::vector GetClassImplementedInterfaces([[maybe_unused]] es2panda_Context *context, ir::AstNode *node) @@ -542,9 +542,9 @@ std::vector GetClassImplementedInterfaces([[maybe_unused]] es2pan } /** - * @brief (4. 查找当前接口的(所有)父接口) Collects all ancestor interfaces through extension hierarchy + * @brief (4. 查找当前接口的(所有)父接口) Find all interfaces extended by current interface node * @param context - Compiler context (unused) - * @param node - Starting interface node + * @param node - Current interface node * @return Vector of ancestor interface nodes */ std::vector GetInterfaceSuperInterfaces([[maybe_unused]] es2panda_Context *context, ir::AstNode *node) @@ -558,7 +558,7 @@ std::vector GetInterfaceSuperInterfaces([[maybe_unused]] es2panda if (!visited.insert(currentNode).second) { return; } - auto extends = node->AsTSInterfaceDeclaration()->Extends(); + auto extends = currentNode->AsTSInterfaceDeclaration()->Extends(); for (auto extend : extends) { auto partNode = GetIdentifierFromTSInterfaceHeritage(extend); if (partNode == nullptr) { @@ -590,7 +590,7 @@ std::vector GetImplements(ir::AstNode *node) auto classDefinition = node->AsClassDefinition(); auto implements = classDefinition->Implements(); for (auto implement : implements) { - auto partNode = GetIdentifierFromTSInterfaceHeritage(implement->AsTSInterfaceHeritage()); + auto partNode = GetIdentifierFromTSInterfaceHeritage(implement); if (partNode == nullptr || !partNode->IsIdentifier()) { continue; } @@ -624,7 +624,6 @@ std::vector GetInterfaceOrClasses(es2panda_Context *context, ir:: [&](ir::AstNode *base) { return parentSet.count(base) > 0; }); if (isSubInterface) { result.push_back(child); - GetInterfaceOrClasses(context, child, isInterfaceMode); // 递归处理子接口 } } else { // The current interface gets the subclass @@ -643,29 +642,67 @@ std::vector GetInterfaceOrClasses(es2panda_Context *context, ir:: return result; } +void AddMissingExtends(std::vector &implementingClasses, const std::vector &extends) +{ + std::unordered_set existing(implementingClasses.begin(), implementingClasses.end()); + std::copy_if(extends.begin(), extends.end(), std::back_inserter(implementingClasses), + [&existing](ir::AstNode *node) { return existing.find(node) == existing.end(); }); +} + /** - * @brief (5|6、查找当前接口的(所有)子类或子接口) Finds all subclasses/sub-interfaces of the current interface node - * @param context - Compiler context with AST tree - * @param node - Target interface node to search from - * @return Vector of subclass/sub-interface nodes (includes both direct and nested) + * @brief (通用函数,用于查找接口的子接口或实现类及其子类) Generic function to find sub-interfaces or implementing + * classes and their subclasses of an interface + * @param context - Compiler context containing program AST + * @param node - Current interface node + * @param isInterfaceMode - Flag to determine lookup mode (true for interfaces, false for classes) + * @return Vector of found nodes */ -std::vector GetInterfaceImplementingClasses(es2panda_Context *context, ir::AstNode *node) +std::vector GetRelatedNodes(es2panda_Context *context, ir::AstNode *node, bool isInterfaceMode) { - std::vector implementingClasses; + std::vector result; auto ctx = reinterpret_cast(context); - auto rootNode = ctx->parserProgram->Ast(); - if (rootNode == nullptr) { - return implementingClasses; + if (ctx->parserProgram->Ast() == nullptr) { + return result; } - bool findSubInterfaces = true; - implementingClasses = GetInterfaceOrClasses(context, node, findSubInterfaces); - if (!findSubInterfaces) { - std::vector subInterfaces = GetInterfaceImplementingClasses(context, node); - for (auto subInterface : subInterfaces) { - implementingClasses = GetInterfaceOrClasses(context, subInterface, false); + result = GetInterfaceOrClasses(context, node, isInterfaceMode); + for (size_t i = 0; i < result.size(); ++i) { + auto elem = result[i]; + if (!isInterfaceMode && elem->IsClassDefinition()) { + elem = elem->Parent(); + result[i] = elem; } + std::vector extends; + if (isInterfaceMode) { + extends = GetRelatedNodes(context, elem, isInterfaceMode); + } else { + extends = GetClassSubClasses(context, elem); + } + AddMissingExtends(result, extends); } - return implementingClasses; + return result; +} + +/** + * @brief (5. 查找当前接口的(所有)子接口) Find all interfaces extended by current interface node + * @param context - Compiler context containing program AST + * @param node - Current interface node + * @return Vector of descendant interface nodes + */ +std::vector GetInterfaceSubInterfaces(es2panda_Context *context, ir::AstNode *node) +{ + return GetRelatedNodes(context, node, true); +} + +/** + * @brief (6. 查找当前接口的(所有)子类) Find all interfaces current interface node extends & their corresponding + * implementation classes + * @param context - Compiler context containing program AST + * @param node - Current interface node + * @return Vector of implementing class nodes + */ +std::vector GetInterfaceImplementingClasses(es2panda_Context *context, ir::AstNode *node) +{ + return GetRelatedNodes(context, node, false); } /** @@ -709,19 +746,16 @@ std::vector GetMembers([[maybe_unused]] es2panda_Context *context */ bool IsMethodMatch(ir::AstNode *a, ir::AstNode *b) { - if (!a->IsMethodDefinition() || !b->IsMethodDefinition()) { - return false; - } return GetIdentifierName(a) == GetIdentifierName(b); } /** - * @brief 比较成员匹配情况,记录匹配与未匹配项 - * @param currentMembers 当前类的成员列表 - * @param targetMembers 目标类的成员列表 - * @param matchedContainer 匹配成员的记录容器 - * @param unmatchedContainer 未匹配成员的记录容器 - * @param fileName 文件名,用于记录定位信息 + * @brief Compares member matches and records matched and unmatched items + * @param currentMembers the list of members in the current class + * @param targetMembers the list of members in the target class + * @param matchedContainer the container to record matched members + * @param unmatchedContainer the container to record unmatched members + * @param fileName the file name, used for recording location information */ void CompareMembersCommon(const std::vector ¤tMembers, const std::vector &targetMembers, @@ -814,7 +848,7 @@ std::vector GetClassHierarchiesImpl(es2panda_Context *co ProcessItemsParams {currentMembers, result, GetInterfaceSuperInterfaces, ClassRelationKind::INTERFACE, false, CompareMembersForOverride}); ProcessItems(context, classNode, fileName, - ProcessItemsParams {currentMembers, result, GetInterfaceImplementingClasses, + ProcessItemsParams {currentMembers, result, GetInterfaceSubInterfaces, ClassRelationKind::INTERFACE, true, CompareMembersForOverride}); ProcessItems(context, classNode, fileName, ProcessItemsParams {currentMembers, result, GetInterfaceImplementingClasses, diff --git a/ets2panda/test/unit/lsp/class_hierarchys_test.cpp b/ets2panda/test/unit/lsp/class_hierarchys_test.cpp index e946aed474..5a4647aeb9 100644 --- a/ets2panda/test/unit/lsp/class_hierarchys_test.cpp +++ b/ets2panda/test/unit/lsp/class_hierarchys_test.cpp @@ -32,7 +32,6 @@ using ark::es2panda::lsp::Initializer; class LspClassHierarchiesTests : public LSPAPITests {}; -std::vector fileNames = {"wangz_test.ets"}; std::vector fileContents = { R"( interface Iaa { @@ -120,6 +119,100 @@ TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_001) constexpr size_t expectedInfoCount = 5; constexpr size_t tokenOffset = 600; + std::vector fileNames = {"GetClassHierarchiesImpl_001_file1.ets"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + std::vector sourceFiles; + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents[i]); + } + ASSERT_EQ(fileNames.size(), sourceFiles.size()); + Initializer initializer; + size_t sourceIndex = 0; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + std::vector infos = + ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset); + ASSERT_EQ(expectedInfoCount, infos.size()); +} + +TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_002) +{ + constexpr size_t expectedInfoCount = 5; + constexpr size_t tokenOffset = 1100; + + std::vector fileNames = {"GetClassHierarchiesImpl_002_file1.ets"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + std::vector sourceFiles; + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents[i]); + } + ASSERT_EQ(fileNames.size(), sourceFiles.size()); + Initializer initializer; + size_t sourceIndex = 0; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + std::vector infos = + ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset); + ASSERT_EQ(expectedInfoCount, infos.size()); +} + +TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_003) +{ + constexpr size_t expectedInfoCount = 12; + constexpr size_t tokenOffset = 100; + + std::vector fileNames = {"GetClassHierarchiesImpl_003_file1.ets"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + std::vector sourceFiles; + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents[i]); + } + ASSERT_EQ(fileNames.size(), sourceFiles.size()); + Initializer initializer; + size_t sourceIndex = 0; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + std::vector infos = + ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset); + ASSERT_EQ(expectedInfoCount, infos.size()); +} + +TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_004) +{ + constexpr size_t expectedInfoCount = 7; + constexpr size_t tokenOffset = 130; + + std::vector fileNames = {"GetClassHierarchiesImpl_004_file1.ets"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + std::vector sourceFiles; + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents[i]); + } + ASSERT_EQ(fileNames.size(), sourceFiles.size()); + Initializer initializer; + size_t sourceIndex = 0; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + std::vector infos = + ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset); + ASSERT_EQ(expectedInfoCount, infos.size()); +} + +TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_005) +{ + constexpr size_t expectedInfoCount = 5; + constexpr size_t tokenOffset = 1000; + + std::vector fileNames = {"GetClassHierarchiesImpl_005_file1.ets"}; + auto filePaths = CreateTempFile(fileNames, fileContents); std::vector sourceFiles; for (size_t i = 0; i < filePaths.size(); ++i) { -- Gitee From 0c0a921b131b58940f4521ba56dca76c4d2df96a Mon Sep 17 00:00:00 2001 From: dogasahin Date: Thu, 29 May 2025 13:44:41 +0300 Subject: [PATCH 019/747] [LSP-API] GetNameOrDottedNameSpan Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC9UFH Signed-off-by: dogasahin --- ets2panda/lsp/BUILD.gn | 1 + ets2panda/lsp/CMakeLists.txt | 1 + ets2panda/lsp/include/api.h | 1 + .../include/get_name_or_dotted_name_span.h | 33 ++++ ets2panda/lsp/src/api.cpp | 10 +- .../lsp/src/get_name_or_dotted_name_span.cpp | 145 +++++++++++++++++ ets2panda/test/unit/lsp/CMakeLists.txt | 4 + .../lsp/get_name_or_dotted_name_span_test.cpp | 153 ++++++++++++++++++ 8 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 ets2panda/lsp/include/get_name_or_dotted_name_span.h create mode 100644 ets2panda/lsp/src/get_name_or_dotted_name_span.cpp create mode 100644 ets2panda/test/unit/lsp/get_name_or_dotted_name_span_test.cpp diff --git a/ets2panda/lsp/BUILD.gn b/ets2panda/lsp/BUILD.gn index db6d280f27..c60ab8300f 100644 --- a/ets2panda/lsp/BUILD.gn +++ b/ets2panda/lsp/BUILD.gn @@ -63,6 +63,7 @@ ohos_source_set("libes2panda_lsp_static") { "src/get_adjusted_location.cpp", "src/get_class_property_info.cpp", "src/get_definition_and_bound_span.cpp", + "src/get_name_or_dotted_name_span.cpp", "src/get_safe_delete_info.cpp", "src/inlay_hints.cpp", "src/internal_api.cpp", diff --git a/ets2panda/lsp/CMakeLists.txt b/ets2panda/lsp/CMakeLists.txt index 601ab7f0c9..93b36a5f24 100644 --- a/ets2panda/lsp/CMakeLists.txt +++ b/ets2panda/lsp/CMakeLists.txt @@ -62,6 +62,7 @@ set(ES2PANDA_LSP_SRC ./src/register_code_fix/fix_nan_equality.cpp ./src/register_code_fix/forgetten_this_property_access.cpp ./src/register_code_fix/import_fixes.cpp + ./src/get_name_or_dotted_name_span.cpp ) panda_add_library(${LSP_LIB} SHARED ${ES2PANDA_LSP_SRC}) diff --git a/ets2panda/lsp/include/api.h b/ets2panda/lsp/include/api.h index 099982127c..ce7de8cdae 100644 --- a/ets2panda/lsp/include/api.h +++ b/ets2panda/lsp/include/api.h @@ -557,6 +557,7 @@ typedef struct LSPAPI { CodeFixOptions &codeFixOptions); CombinedCodeActionsInfo (*getCombinedCodeFix)(const char *fileName, const std::string &fixId, CodeFixOptions &codeFixOptions); + TextSpan *(*GetNameOrDottedNameSpan)(es2panda_Context *context, int startPos); } LSPAPI; CAPI_EXPORT LSPAPI const *GetImpl(); // NOLINTEND diff --git a/ets2panda/lsp/include/get_name_or_dotted_name_span.h b/ets2panda/lsp/include/get_name_or_dotted_name_span.h new file mode 100644 index 0000000000..1835282643 --- /dev/null +++ b/ets2panda/lsp/include/get_name_or_dotted_name_span.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GET_NAME_OR_DOTTED_NAME_SPAN_H +#define GET_NAME_OR_DOTTED_NAME_SPAN_H + +#include "api.h" +#include "ir/astNode.h" +#include "es2panda.h" +#include "public/es2panda_lib.h" + +namespace ark::es2panda::lsp { +bool IsRightSideOfPropertyAccess(ir::AstNode *node); +bool IsRightSideOfQualifiedName(ir::AstNode *node); +bool IsNameOfModuleDeclaration(ir::AstNode *node); +ir::AstNode *AscendToRootName(ir::AstNode *node); + +TextSpan *GetNameOrDottedNameSpanImpl(es2panda_Context *context, int startPos); + +} // namespace ark::es2panda::lsp +#endif // GET_NAME_OR_DOTTED_NAME_SPAN_H \ No newline at end of file diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index 9c9b217952..321fe9868b 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -40,6 +40,7 @@ #include "inlay_hints.h" #include "signature_help.h" #include "completions_details.h" +#include "get_name_or_dotted_name_span.h" using ark::es2panda::lsp::details::GetCompletionEntryDetailsImpl; @@ -392,6 +393,12 @@ CombinedCodeActionsInfo GetCombinedCodeFix(const char *fileName, const std::stri return result; } +TextSpan *GetNameOrDottedNameSpan(es2panda_Context *context, int startPos) +{ + auto result = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, startPos); + return result; +} + LSPAPI g_lspImpl = {GetDefinitionAtPosition, GetApplicableRefactors, GetImplementationAtPosition, @@ -429,7 +436,8 @@ LSPAPI g_lspImpl = {GetDefinitionAtPosition, ProvideInlayHints, GetSignatureHelpItems, GetCodeFixesAtPosition, - GetCombinedCodeFix}; + GetCombinedCodeFix, + GetNameOrDottedNameSpan}; } // namespace ark::es2panda::lsp CAPI_EXPORT LSPAPI const *GetImpl() diff --git a/ets2panda/lsp/src/get_name_or_dotted_name_span.cpp b/ets2panda/lsp/src/get_name_or_dotted_name_span.cpp new file mode 100644 index 0000000000..3d942472a4 --- /dev/null +++ b/ets2panda/lsp/src/get_name_or_dotted_name_span.cpp @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "get_name_or_dotted_name_span.h" +#include "get_adjusted_location.h" +#include + +namespace ark::es2panda::lsp { +bool IsRightSideOfPropertyAccess(ir::AstNode *node) +{ + ir::AstNode *parent = node->Parent(); + + if (parent == nullptr) { + return false; + } + + if (parent->Type() == ir::AstNodeType::MEMBER_EXPRESSION) { + auto *memberExpr = static_cast(parent); + return memberExpr->Property() == node; + } + + if (parent->Type() == ir::AstNodeType::CALL_EXPRESSION) { + auto *callExpr = static_cast(parent); + ir::AstNode *callee = callExpr->Callee(); + + if (callee->Type() == ir::AstNodeType::MEMBER_EXPRESSION) { + auto *memberExpr = static_cast(callee); + return memberExpr->Property() == node; + } + } + + return false; +} + +bool IsNameOfModuleDeclaration(ir::AstNode *node) +{ + ir::AstNode *parent = node->Parent(); + if (parent == nullptr || parent->Type() != ir::AstNodeType::TS_MODULE_DECLARATION) { + return false; + } + + auto *moduleDecl = static_cast(parent); + return moduleDecl->Name() == node; +} + +bool IsRightSideOfQualifiedName(ir::AstNode *node) +{ + ir::AstNode *parent = node->Parent(); + if (parent == nullptr || (parent->Type() != ir::AstNodeType::TS_QUALIFIED_NAME && + parent->Type() != ir::AstNodeType::MEMBER_EXPRESSION)) { + return false; + } + + if (parent->Type() == ir::AstNodeType::TS_QUALIFIED_NAME) { + auto *qualifiedName = static_cast(parent); + return qualifiedName->Right() == node; + } + + if (parent->Type() == ir::AstNodeType::MEMBER_EXPRESSION) { + auto *memberExpr = static_cast(parent); + return memberExpr->Property() == node; + } + + return false; +} + +ir::AstNode *AscendToRootName(ir::AstNode *node) +{ + while (node != nullptr) { + if (IsRightSideOfPropertyAccess(node) || IsRightSideOfQualifiedName(node)) { + node = node->Parent(); + continue; + } + + if (!IsNameOfModuleDeclaration(node)) { + break; + } + + ir::AstNode *parentDecl = node->Parent(); + if (parentDecl == nullptr || parentDecl->Parent() == nullptr) { + break; + } + + if (parentDecl->Parent()->Type() != ir::AstNodeType::TS_MODULE_DECLARATION) { + break; + } + + auto *grandParent = static_cast(parentDecl->Parent()); + if (grandParent->Body() != parentDecl) { + break; + } + + node = const_cast(static_cast(grandParent->Name())); + } + + return node; +} + +TextSpan *GetNameOrDottedNameSpanImpl(es2panda_Context *context, int startPos) +{ + ir::AstNode *astNode = ark::es2panda::lsp::GetTouchingPropertyName(context, startPos); + if (astNode == nullptr) { + return nullptr; + } + + switch (astNode->Type()) { + case ir::AstNodeType::TS_QUALIFIED_NAME: + case ir::AstNodeType::STRING_LITERAL: + case ir::AstNodeType::TS_BOOLEAN_KEYWORD: + case ir::AstNodeType::TS_NULL_KEYWORD: + case ir::AstNodeType::SUPER_EXPRESSION: + case ir::AstNodeType::THIS_EXPRESSION: + case ir::AstNodeType::TS_THIS_TYPE: + case ir::AstNodeType::IDENTIFIER: + break; + default: + return nullptr; + } + + auto nodeForStartPos = AscendToRootName(astNode); + if (nodeForStartPos == nullptr) { + return nullptr; + } + size_t start = nodeForStartPos->Start().index; + size_t end = nodeForStartPos->End().index; + if (start >= end) { + return nullptr; + } + + auto span = new TextSpan(start, end - start); + return span; +} +} // namespace ark::es2panda::lsp \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index 6f10ba2d98..60d9b76943 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -210,3 +210,7 @@ ets2panda_add_gtest(lsp_api_test_navigate_to CPP_SOURCES ets2panda_add_gtest(lsp_api_test_code_fix_registration CPP_SOURCES code_fix_registration_test.cpp ) + +ets2panda_add_gtest(lsp_api_test_get_name_or_dotted_name_span CPP_SOURCES + get_name_or_dotted_name_span_test.cpp +) \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_name_or_dotted_name_span_test.cpp b/ets2panda/test/unit/lsp/get_name_or_dotted_name_span_test.cpp new file mode 100644 index 0000000000..26eb5a80b6 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_name_or_dotted_name_span_test.cpp @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "lsp_api_test.h" +#include "lsp/include/internal_api.h" +#include "lsp/include/get_name_or_dotted_name_span.h" + +namespace { +const size_t IDENTIFIER_ONLY_IDX = 24; +const size_t PROPERTY_ACCESS_IDX = 36; +const size_t FULL_DOTTED_EXPR_IDX = 56; +const size_t INVALID_TOKEN_IDX = 31; +const size_t MODULE_DECLARATION_QUALIFIED_NAME_IDX = 72; + +std::string ExtractSpanText(const std::string &source, const TextSpan *span) +{ + if (span == nullptr || span->start + span->length > source.size()) { + return {}; + } + + return source.substr(span->start, span->length); +} + +class GetNameOrDottedNameSpanTests : public LSPAPITests {}; +TEST_F(GetNameOrDottedNameSpanTests, GetNameSpanFromSimpleIdentifier) +{ + std::vector fileNames = {"get_name_span_from_simple_identifier.ets"}; + std::vector fileContents = { + R"( +function myMethod() {} +myMethod(); + )"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + ASSERT_EQ(filePaths.size(), 1); + + ark::es2panda::lsp::Initializer initializer; + auto context = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto content = fileContents[0]; + auto span = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, IDENTIFIER_ONLY_IDX); + ASSERT_NE(span, nullptr); + EXPECT_EQ(ExtractSpanText(content, span), "myMethod"); + initializer.DestroyContext(context); +} + +TEST_F(GetNameOrDottedNameSpanTests, GetNameSpanFromPropertyAccess) +{ + std::vector fileNames = {"get_name_span_from_property_access.ets"}; + std::vector fileContents = { + R"( +class A { +static myMethod() {} +} +A.myMethod(); + )"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + ASSERT_EQ(filePaths.size(), 1); + + ark::es2panda::lsp::Initializer initializer; + auto context = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto content = fileContents[0]; + auto span = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, PROPERTY_ACCESS_IDX); + ASSERT_NE(span, nullptr); + EXPECT_EQ(ExtractSpanText(content, span), "A.myMethod"); + initializer.DestroyContext(context); +} + +TEST_F(GetNameOrDottedNameSpanTests, GetNameSpanFromNestedNamespaceClassCall) +{ + std::vector fileNames = {"get_name_span_from_nested_namespace_class_call.ets"}; + std::vector fileContents = { + R"( +namespace A { +export class B { +static foo() {} +} +} +A.B.foo(); + )"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + ASSERT_EQ(filePaths.size(), 1); + + ark::es2panda::lsp::Initializer initializer; + auto context = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto content = fileContents[0]; + auto span = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, FULL_DOTTED_EXPR_IDX); + ASSERT_NE(span, nullptr); + EXPECT_EQ(ExtractSpanText(content, span), "A.B.foo"); + initializer.DestroyContext(context); +} + +TEST_F(GetNameOrDottedNameSpanTests, GetNameSpanFromInvalidToken) +{ + std::vector fileNames = {"get_name_span_from_invalid_token.ets"}; + std::vector fileContents = { + R"( +let message = "hello"; +console.log(message); + )"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + ASSERT_EQ(filePaths.size(), 1); + + ark::es2panda::lsp::Initializer initializer; + auto context = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto content = fileContents[0]; + auto span = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, INVALID_TOKEN_IDX); + EXPECT_EQ(span, nullptr); + initializer.DestroyContext(context); +} + +TEST_F(GetNameOrDottedNameSpanTests, GetNameSpanFromQualifiedNamespaceFunction) +{ + std::vector fileNames = {"get_name_span_from_qualified_namespace_function.ets"}; + std::vector fileContents = { + R"( +namespace Outer.Inner { + export function greet() {} +} + +Outer.Inner.greet(); + )"}; + + auto filePaths = CreateTempFile(fileNames, fileContents); + ASSERT_EQ(filePaths.size(), 1); + ark::es2panda::lsp::Initializer initializer; + auto context = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto content = fileContents[0]; + auto span = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, MODULE_DECLARATION_QUALIFIED_NAME_IDX); + ASSERT_NE(span, nullptr); + EXPECT_EQ(ExtractSpanText(content, span), "Outer.Inner.greet"); + initializer.DestroyContext(context); +} +} // namespace \ No newline at end of file -- Gitee From 3ffa950a375eb9327defeb60383d36fff723751d Mon Sep 17 00:00:00 2001 From: leo9001 Date: Wed, 28 May 2025 16:34:28 +0800 Subject: [PATCH 020/747] support test cases for getClassPropertyInfo Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB69F Signed-off-by: leo9001 --- ets2panda/lsp/src/get_class_property_info.cpp | 13 +- .../unit/lsp/get_class_property_info_test.cpp | 799 +++++++++++++++++- 2 files changed, 805 insertions(+), 7 deletions(-) diff --git a/ets2panda/lsp/src/get_class_property_info.cpp b/ets2panda/lsp/src/get_class_property_info.cpp index e0228eea95..750d24fd84 100644 --- a/ets2panda/lsp/src/get_class_property_info.cpp +++ b/ets2panda/lsp/src/get_class_property_info.cpp @@ -70,8 +70,17 @@ void CollectClassProperties(const ir::AstNode *classNode, std::vector> modifiersOpt(modifiers); - FieldListProperty propertyInfo("classField", std::move(modifiersOpt), GetIdentifierName(property), - property->Start().index, property->End().index); + std::string name = GetIdentifierName(property); + + constexpr auto K_PROPERTY_PREFIX = ""; + constexpr std::size_t K_PROPERTY_PREFIX_LENGTH = std::char_traits::length(K_PROPERTY_PREFIX); + if (name.size() >= K_PROPERTY_PREFIX_LENGTH && + name.compare(0, K_PROPERTY_PREFIX_LENGTH, K_PROPERTY_PREFIX) == 0) { + name.erase(0, K_PROPERTY_PREFIX_LENGTH); + } + + FieldListProperty propertyInfo("classField", std::move(modifiersOpt), name, property->Start().index, + property->End().index); classInfo.properties.push_back(propertyInfo); } diff --git a/ets2panda/test/unit/lsp/get_class_property_info_test.cpp b/ets2panda/test/unit/lsp/get_class_property_info_test.cpp index b6d8c37e24..039281bfc6 100644 --- a/ets2panda/test/unit/lsp/get_class_property_info_test.cpp +++ b/ets2panda/test/unit/lsp/get_class_property_info_test.cpp @@ -32,7 +32,6 @@ namespace { using ark::es2panda::lsp::Initializer; class LspGetClassPropertyInfoTests : public LSPAPITests {}; -std::vector fileNames = {"GetClassPropertyInfoFile.ets"}; std::vector fileContents = { R"( enum BloodType { @@ -92,7 +91,76 @@ export class Person extends SelectableControlClass implements SelectableControl onUpdate: (() => void) | null = null; } )"}; -std::vector>> expectedResult = { +std::vector fileContents2 = { + R"( +export enum BloodType { + A = 'A', + AB = 'AB' +} + +export class Address { + state: number = 1; + province: string = ''; + city: string = ''; +} + +interface Control { + state: number +} + +export interface SelectableControl extends Control { + select(): void +} +)", + R"( +import { Address, SelectableControl } from "./GetClassPropertyInfo_SelectableControl"; + +export class SelectableControlClass extends Address implements SelectableControl { + select(): void { + throw new Error("Method not implemented."); + } + + private state1: number = 0; + protected readonly hobbies: string[] = []; +} +)", + R"( +import { Address, BloodType, SelectableControl } from "./GetClassPropertyInfo_SelectableControl"; +import { SelectableControlClass } from "./GetClassPropertyInfo_SelectableControlClass"; + +enum Sex { + Male = 'Male' +} + +export class Person extends SelectableControlClass implements SelectableControl { + static MAX_HEIGHT: number = 250; + static BLOOD_TYPES: BloodType = BloodType.AB; + static defaultAddress: Address = { + province: '北京', + city: '北京市', + state: 0 + }; + name: string = ''; + age: number = Person.MAX_HEIGHT; + weight: number = 0; + sex: Sex = Sex.Male; + bloodType: BloodType = BloodType.A; + address: Address = new Address(); + hobbies: string[] = []; + maritalStatus: 'single' | 'married' | 'divorced' = 'single'; + birthday: Date = new Date(); + location: [number, number] = [0, 0]; + avatar: Resource = $r('app.media.startIcon'); + attributes: Map = new Map(); + isEmployed: boolean = false; + private privateIsEmployed: boolean = false; + protected protectedIsEmployed: boolean = false; + protected readonly readonlyIsEmployed: boolean = false; + onUpdate: (() => void) | null = null; +} +)"}; + +std::vector>> expectedResultWangz1 = { {"MAX_HEIGHT", 561, 585, "classField", {"public", "static"}}, {"BLOOD_TYPES", 596, 633, "classField", {"public", "static"}}, {"defaultAddress", 644, 722, "classField", {"public", "static"}}, @@ -114,7 +182,9 @@ std::vector &actualProperties) +void CheckClassPropertiesMatch( + const std::vector &actualProperties, + const std::vector>> &expectedResult) { for (size_t i = 0; i < actualProperties.size(); ++i) { const auto &perp = actualProperties[i]; @@ -144,12 +214,14 @@ void CheckClassPropertiesMatch(const std::vector &actualPrope } } -TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod1) +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethodTest1) { constexpr size_t EXPECTED_CLASS_COUNT = 3; constexpr size_t EXPECTED_CLASS_COUNT_ONE = 1; constexpr size_t EXPECTED_PROP_COUNT = 20; + std::vector fileNames = {"GetClassPropertyInfoMethodFile1.ets"}; + auto filePaths = CreateTempFile(fileNames, fileContents); std::vector sourceFiles; @@ -175,7 +247,724 @@ TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod1) FieldsInfo info = infos2[0]; ASSERT_EQ(EXPECTED_PROP_COUNT, info.properties.size()); ASSERT_EQ("Person", info.name); - CheckClassPropertiesMatch(info.properties); + CheckClassPropertiesMatch(info.properties, expectedResultWangz1); +} + +std::vector>> expectedResultWangz2 = { + {"MAX_HEIGHT", 309, 333, "classField", {"public", "static"}}, + {"BLOOD_TYPES", 344, 381, "classField", {"public", "static"}}, + {"defaultAddress", 392, 483, "classField", {"public", "static"}}, + {"name", 487, 504, "classField", {"public"}}, + {"age", 508, 539, "classField", {"public"}}, + {"weight", 543, 561, "classField", {"public"}}, + {"sex", 565, 584, "classField", {"public"}}, + {"bloodType", 588, 622, "classField", {"public"}}, + {"address", 626, 659, "classField", {"public"}}, + {"hobbies", 662, 684, "classField", {"public"}}, + {"maritalStatus", 688, 747, "classField", {"public"}}, + {"birthday", 751, 779, "classField", {"public"}}, + {"location", 782, 817, "classField", {"public"}}, + {"avatar", 821, 865, "classField", {"public"}}, + {"attributes", 869, 913, "classField", {"public"}}, + {"isEmployed", 916, 943, "classField", {"public"}}, + {"privateIsEmployed", 955, 989, "classField", {"private"}}, + {"protectedIsEmployed", 1003, 1039, "classField", {"protected"}}, + {"readonlyIsEmployed", 1062, 1097, "classField", {"protected", "readonly"}}, + {"onUpdate", 1101, 1137, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethodTest2) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 3; + constexpr size_t EXPECTED_CLASS_COUNT_ONE = 1; + constexpr size_t EXPECTED_PROP_COUNT = 20; + + std::vector fileNames2 = {"GetClassPropertyInfo_SelectableControl.ets", + "GetClassPropertyInfo_SelectableControlClass.ets", + "GetClassPropertyInfo_Person.ets"}; + + auto filePaths = CreateTempFile(fileNames2, fileContents2); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents2[i]); + } + ASSERT_EQ(fileNames2.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 2; + size_t tokenOffset = 300; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + + auto infos2 = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset); + initializer.DestroyContext(context); + ASSERT_EQ(EXPECTED_CLASS_COUNT_ONE, infos2.size()); + + FieldsInfo info = infos2[0]; + ASSERT_EQ(EXPECTED_PROP_COUNT, info.properties.size()); + ASSERT_EQ("Person", info.name); + CheckClassPropertiesMatch(info.properties, expectedResultWangz2); +} + +std::vector fileContents3 = { + R"( +class A { +} +)", + R"( +class B { + p1 + p2 + static p3 + readonly p4 + private p5 +} +)", + R"( +class KKK { + tr:string; + constructor(tr: string) { + this.tr = tr; + } +} + +class NNN extends KKK { +} +)", + R"( +class GGG { + tr:string; + constructor(tr: string) { + this.tr = tr; + } +} + +class HHH extends GGG { + pop:string +} +)", + R"( +abstract class AA { + test: number; +} + +class NN extends AA { + jkk: string; +} +)", + R"( +abstract class AA2 { + test: number; + private kn: string; + das: string; + + constructor(test: number, kn: string) { + this.test = test; + this.kn = kn; + } +} + +class NN2 extends AA2 { + jkk: string; + wwa: number; +} +)", + R"( +class ok { + test?:string; +} +)", + R"( +class TY { + private _a: string = "foo" +} +)", + R"( +class TwY { + static a: string = "foo" +} +)", + R"( +class TwasY { + a: string|number; +} +)", + R"( +abstract class TY { + abstract a: string|number; +} +)", + R"( +class Demo { + private name = 'jack'; + private age = 25; + private doTask = () => 34; +} +)", + R"( +interface AA { + aa: number; + getAA(): number; +} + +class BaseNN { + aa: number; + + constructor(aa: number) { + this.aa = aa; + } + + getAA(): number { + return 1; + } +} + +class MM extends BaseNN implements AA { + aa: number; + getAA(): number { + return super.getAA(); + } +} +)", + R"( +import CommonEventManager from '@ohos.commonEventManager'; + +interface SubscribeInfoType { + events: string[]; +} + +class CommonEventRegister { + subscriber: CommonEventManager.CommonEventSubscriber | null = null; + public subscribeInfo: SubscribeInfoType; +} +)"}; + +std::vector>> expectedResult1 = {}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod1) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 0; + + std::vector fileNames3 = { + "get_class_property_info_test_m1_01.ets", "get_class_property_info_test_m1_02.ets", + "get_class_property_info_test_m1_03.ets", "get_class_property_info_test_m1_04.ets", + "get_class_property_info_test_m1_05.ets", "get_class_property_info_test_m1_06.ets", + "get_class_property_info_test_m1_07.ets", "get_class_property_info_test_m1_08.ets", + "get_class_property_info_test_m1_09.ets", "get_class_property_info_test_m1_10.ets", + "get_class_property_info_test_m1_11.ets", "get_class_property_info_test_m1_12.ets", + "get_class_property_info_test_m1_13.ets", "get_class_property_info_test_m1_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 0; + size_t tokenOffset = 12; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult1); +} + +std::vector>> expectedResult2 = { + {"p1", 13, 15, "classField", {"public"}}, + {"p2", 18, 20, "classField", {"public"}}, + {"p3", 30, 32, "classField", {"public", "static"}}, + {"p4", 44, 46, "classField", {"public", "readonly"}}, + {"p5", 57, 59, "classField", {"private"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod2) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 5; + + std::vector fileNames3 = { + "get_class_property_info_test_m2_01.ets", "get_class_property_info_test_m2_02.ets", + "get_class_property_info_test_m2_03.ets", "get_class_property_info_test_m2_04.ets", + "get_class_property_info_test_m2_05.ets", "get_class_property_info_test_m2_06.ets", + "get_class_property_info_test_m2_07.ets", "get_class_property_info_test_m2_08.ets", + "get_class_property_info_test_m2_09.ets", "get_class_property_info_test_m2_10.ets", + "get_class_property_info_test_m2_11.ets", "get_class_property_info_test_m2_12.ets", + "get_class_property_info_test_m2_13.ets", "get_class_property_info_test_m2_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 1; + size_t tokenOffset = 61; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult2); +} + +std::vector>> expectedResult3 = {}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod3) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 2; + constexpr size_t EXPECTED_PROP_COUNT = 0; + + std::vector fileNames3 = { + "get_class_property_info_test_m3_01.ets", "get_class_property_info_test_m3_02.ets", + "get_class_property_info_test_m3_03.ets", "get_class_property_info_test_m3_04.ets", + "get_class_property_info_test_m3_05.ets", "get_class_property_info_test_m3_06.ets", + "get_class_property_info_test_m3_07.ets", "get_class_property_info_test_m3_08.ets", + "get_class_property_info_test_m3_09.ets", "get_class_property_info_test_m3_10.ets", + "get_class_property_info_test_m3_11.ets", "get_class_property_info_test_m3_12.ets", + "get_class_property_info_test_m3_13.ets", "get_class_property_info_test_m3_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 2; + size_t tokenOffset = 104; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult3); +} + +std::vector>> expectedResult4 = { + {"pop", 107, 119, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod4) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 2; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m4_01.ets", "get_class_property_info_test_m4_02.ets", + "get_class_property_info_test_m4_03.ets", "get_class_property_info_test_m4_04.ets", + "get_class_property_info_test_m4_05.ets", "get_class_property_info_test_m4_06.ets", + "get_class_property_info_test_m4_07.ets", "get_class_property_info_test_m4_08.ets", + "get_class_property_info_test_m4_09.ets", "get_class_property_info_test_m4_10.ets", + "get_class_property_info_test_m4_11.ets", "get_class_property_info_test_m4_12.ets", + "get_class_property_info_test_m4_13.ets", "get_class_property_info_test_m4_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 3; + size_t tokenOffset = 117; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult4); +} + +std::vector>> expectedResult5 = { + {"jkk", 64, 76, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod5) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 2; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m5_01.ets", "get_class_property_info_test_m5_02.ets", + "get_class_property_info_test_m5_03.ets", "get_class_property_info_test_m5_04.ets", + "get_class_property_info_test_m5_05.ets", "get_class_property_info_test_m5_06.ets", + "get_class_property_info_test_m5_07.ets", "get_class_property_info_test_m5_08.ets", + "get_class_property_info_test_m5_09.ets", "get_class_property_info_test_m5_10.ets", + "get_class_property_info_test_m5_11.ets", "get_class_property_info_test_m5_12.ets", + "get_class_property_info_test_m5_13.ets", "get_class_property_info_test_m5_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 4; + size_t tokenOffset = 76; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult5); +} + +std::vector>> expectedResult6 = { + {"jkk", 195, 207, "classField", {"public"}}, {"wwa", 210, 222, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod6) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 2; + constexpr size_t EXPECTED_PROP_COUNT = 2; + + std::vector fileNames3 = { + "get_class_property_info_test_m6_01.ets", "get_class_property_info_test_m6_02.ets", + "get_class_property_info_test_m6_03.ets", "get_class_property_info_test_m6_04.ets", + "get_class_property_info_test_m6_05.ets", "get_class_property_info_test_m6_06.ets", + "get_class_property_info_test_m6_07.ets", "get_class_property_info_test_m6_08.ets", + "get_class_property_info_test_m6_09.ets", "get_class_property_info_test_m6_10.ets", + "get_class_property_info_test_m6_11.ets", "get_class_property_info_test_m6_12.ets", + "get_class_property_info_test_m6_13.ets", "get_class_property_info_test_m6_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 5; + size_t tokenOffset = 222; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult6); +} + +std::vector>> expectedResult7 = { + {"test", 14, 27, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod7) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m7_01.ets", "get_class_property_info_test_m7_02.ets", + "get_class_property_info_test_m7_03.ets", "get_class_property_info_test_m7_04.ets", + "get_class_property_info_test_m7_05.ets", "get_class_property_info_test_m7_06.ets", + "get_class_property_info_test_m7_07.ets", "get_class_property_info_test_m7_08.ets", + "get_class_property_info_test_m7_09.ets", "get_class_property_info_test_m7_10.ets", + "get_class_property_info_test_m7_11.ets", "get_class_property_info_test_m7_12.ets", + "get_class_property_info_test_m7_13.ets", "get_class_property_info_test_m7_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 6; + size_t tokenOffset = 27; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult7); +} + +std::vector>> expectedResult8 = { + {"_a", 22, 40, "classField", {"private"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod8) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m8_01.ets", "get_class_property_info_test_m8_02.ets", + "get_class_property_info_test_m8_03.ets", "get_class_property_info_test_m8_04.ets", + "get_class_property_info_test_m8_05.ets", "get_class_property_info_test_m8_06.ets", + "get_class_property_info_test_m8_07.ets", "get_class_property_info_test_m8_08.ets", + "get_class_property_info_test_m8_09.ets", "get_class_property_info_test_m8_10.ets", + "get_class_property_info_test_m8_11.ets", "get_class_property_info_test_m8_12.ets", + "get_class_property_info_test_m8_13.ets", "get_class_property_info_test_m8_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 7; + size_t tokenOffset = 40; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult8); +} + +std::vector>> expectedResult9 = { + {"a", 22, 39, "classField", {"public", "static"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod9) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m9_01.ets", "get_class_property_info_test_m9_02.ets", + "get_class_property_info_test_m9_03.ets", "get_class_property_info_test_m9_04.ets", + "get_class_property_info_test_m9_05.ets", "get_class_property_info_test_m9_06.ets", + "get_class_property_info_test_m9_07.ets", "get_class_property_info_test_m9_08.ets", + "get_class_property_info_test_m9_09.ets", "get_class_property_info_test_m9_10.ets", + "get_class_property_info_test_m9_11.ets", "get_class_property_info_test_m9_12.ets", + "get_class_property_info_test_m9_13.ets", "get_class_property_info_test_m9_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 8; + size_t tokenOffset = 39; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult9); +} + +std::vector>> expectedResult10 = { + {"a", 17, 34, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod10) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m10_01.ets", "get_class_property_info_test_m10_02.ets", + "get_class_property_info_test_m10_03.ets", "get_class_property_info_test_m10_04.ets", + "get_class_property_info_test_m10_05.ets", "get_class_property_info_test_m10_06.ets", + "get_class_property_info_test_m10_07.ets", "get_class_property_info_test_m10_08.ets", + "get_class_property_info_test_m10_09.ets", "get_class_property_info_test_m10_10.ets", + "get_class_property_info_test_m10_11.ets", "get_class_property_info_test_m10_12.ets", + "get_class_property_info_test_m10_13.ets", "get_class_property_info_test_m10_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 9; + size_t tokenOffset = 35; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult10); +} + +std::vector>> expectedResult11 = { + {"a", 32, 49, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod11) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m11_01.ets", "get_class_property_info_test_m11_02.ets", + "get_class_property_info_test_m11_03.ets", "get_class_property_info_test_m11_04.ets", + "get_class_property_info_test_m11_05.ets", "get_class_property_info_test_m11_06.ets", + "get_class_property_info_test_m11_07.ets", "get_class_property_info_test_m11_08.ets", + "get_class_property_info_test_m11_09.ets", "get_class_property_info_test_m11_10.ets", + "get_class_property_info_test_m11_11.ets", "get_class_property_info_test_m11_12.ets", + "get_class_property_info_test_m11_13.ets", "get_class_property_info_test_m11_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 10; + size_t tokenOffset = 50; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult11); +} + +std::vector>> expectedResult12 = { + {"name", 24, 37, "classField", {"private"}}, + {"age", 49, 57, "classField", {"private"}}, + {"doTask", 69, 86, "classField", {"private"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod12) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 3; + + std::vector fileNames3 = { + "get_class_property_info_test_m12_01.ets", "get_class_property_info_test_m12_02.ets", + "get_class_property_info_test_m12_03.ets", "get_class_property_info_test_m12_04.ets", + "get_class_property_info_test_m12_05.ets", "get_class_property_info_test_m12_06.ets", + "get_class_property_info_test_m12_07.ets", "get_class_property_info_test_m12_08.ets", + "get_class_property_info_test_m12_09.ets", "get_class_property_info_test_m12_10.ets", + "get_class_property_info_test_m12_11.ets", "get_class_property_info_test_m12_12.ets", + "get_class_property_info_test_m12_13.ets", "get_class_property_info_test_m12_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 11; + size_t tokenOffset = 87; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult12); +} + +std::vector>> expectedResult13 = { + {"aa", 216, 227, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod13) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 2; + constexpr size_t EXPECTED_PROP_COUNT = 1; + + std::vector fileNames3 = { + "get_class_property_info_test_m13_01.ets", "get_class_property_info_test_m13_02.ets", + "get_class_property_info_test_m13_03.ets", "get_class_property_info_test_m13_04.ets", + "get_class_property_info_test_m13_05.ets", "get_class_property_info_test_m13_06.ets", + "get_class_property_info_test_m13_07.ets", "get_class_property_info_test_m13_08.ets", + "get_class_property_info_test_m13_09.ets", "get_class_property_info_test_m13_10.ets", + "get_class_property_info_test_m13_11.ets", "get_class_property_info_test_m13_12.ets", + "get_class_property_info_test_m13_13.ets", "get_class_property_info_test_m13_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 12; + size_t tokenOffset = 232; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult13); +} + +std::vector>> expectedResult14 = { + {"subscriber", 144, 210, "classField", {"public"}}, {"subscribeInfo", 221, 254, "classField", {"public"}}}; + +TEST_F(LspGetClassPropertyInfoTests, GetClassPropertyInfoMethod14) +{ + constexpr size_t EXPECTED_CLASS_COUNT = 1; + constexpr size_t EXPECTED_PROP_COUNT = 2; + + std::vector fileNames3 = { + "get_class_property_info_test_m14_01.ets", "get_class_property_info_test_m14_02.ets", + "get_class_property_info_test_m14_03.ets", "get_class_property_info_test_m14_04.ets", + "get_class_property_info_test_m14_05.ets", "get_class_property_info_test_m14_06.ets", + "get_class_property_info_test_m14_07.ets", "get_class_property_info_test_m14_08.ets", + "get_class_property_info_test_m14_09.ets", "get_class_property_info_test_m14_10.ets", + "get_class_property_info_test_m14_11.ets", "get_class_property_info_test_m14_12.ets", + "get_class_property_info_test_m14_13.ets", "get_class_property_info_test_m14_14.ets"}; + + auto filePaths = CreateTempFile(fileNames3, fileContents3); + std::vector sourceFiles; + + for (size_t i = 0; i < filePaths.size(); ++i) { + sourceFiles.emplace_back(filePaths[i], fileContents3[i]); + } + ASSERT_EQ(fileNames3.size(), sourceFiles.size()); + + Initializer initializer; + size_t sourceIndex = 13; + size_t tokenOffset = 256; + auto filePath = std::string {sourceFiles[sourceIndex].filePath}; + auto fileContent = std::string {sourceFiles[sourceIndex].source}; + auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str()); + auto infos = ark::es2panda::lsp::GetClassPropertyInfo(context, tokenOffset, true); + ASSERT_EQ(EXPECTED_CLASS_COUNT, infos.size()); + ASSERT_EQ(EXPECTED_PROP_COUNT, infos[0].properties.size()); + CheckClassPropertiesMatch(infos[0].properties, expectedResult14); } + // NOLINTEND } // namespace \ No newline at end of file -- Gitee From b8bd8a1f337e689178bf2d406daef7cc75625cb1 Mon Sep 17 00:00:00 2001 From: tolgayakar Date: Tue, 3 Jun 2025 12:07:00 +0300 Subject: [PATCH 021/747] Fix no CTE on unions overlap Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICANTK Signed-off-by: tolgayakar --- ets2panda/checker/types/ets/etsUnionType.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index 2bbdf54442..2b20af44a4 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -759,6 +759,12 @@ bool ETSUnionType::IsOverlapWith(TypeRelation *relation, Type *type) if (type->IsETSUnionType() && type->AsETSUnionType()->IsOverlapWith(relation, ct)) { return true; } + if (type->IsETSObjectType() && ct->IsETSObjectType()) { + if (type->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC) && + ct->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC)) { + return true; + } + } if (relation->IsSupertypeOf(ct, type) || relation->IsSupertypeOf(type, ct)) { return true; } -- Gitee From 5b7517c6291dd018b31b976c81390684d946f3cb Mon Sep 17 00:00:00 2001 From: xudan16 Date: Tue, 3 Jun 2025 15:23:02 +0800 Subject: [PATCH 022/747] update exception msg in linter build Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICC5PO Signed-off-by: xudan16 --- ets2panda/linter/build_linter.py | 13 +++++++++++-- ets2panda/linter/package.json | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ets2panda/linter/build_linter.py b/ets2panda/linter/build_linter.py index cfc970134c..bac519dd17 100755 --- a/ets2panda/linter/build_linter.py +++ b/ets2panda/linter/build_linter.py @@ -48,15 +48,24 @@ def run_cmd(cmd, execution_path=None): def run_cmd_with_retry(max_retries, wait_time, cmd, execution_path=None): retry_count = 0 + last_exception = None while retry_count < max_retries: try: run_cmd(cmd, execution_path) break - except Exception: + except Exception as e: + last_exception = e retry_count += 1 time.sleep(wait_time) if retry_count >= max_retries: - raise Exception("Failed to run cmd: " + cmd) + raise Exception( + "Command failed after {r} attempts. Cmd: {c}. Error: {e}" + .format( + r=max_retries, + c=" ".join(cmd), + e=last_exception + ) + ) def is_npm_newer_than_6(options): diff --git a/ets2panda/linter/package.json b/ets2panda/linter/package.json index 9c02abca45..cadf353451 100644 --- a/ets2panda/linter/package.json +++ b/ets2panda/linter/package.json @@ -16,6 +16,7 @@ "compile": "npm run tsc", "postcompile": "node scripts/testRunner/post-compile.mjs", "build": "npm run clean && npm run compile && npm run webpack && npm run pack:linter", + "preinstall": "npm install --production --prefix arkanalyzer && npm install --production --prefix homecheck", "install-ohos-typescript": "node scripts/install-ohos-typescript-and-homecheck.mjs", "pack:linter": "rimraf bundle && mkdir bundle && npm pack --pack-destination bundle", "pretest": " npm run fix", -- Gitee From 7abdae5900e0860066ff2f7712c4f0d2ee7398b5 Mon Sep 17 00:00:00 2001 From: Utku Enes GURSEL Date: Tue, 3 Jun 2025 01:03:56 +0300 Subject: [PATCH 023/747] add autofix for self-addition-deletion rule Issue: ICBZEL Description: Add Autofix for self-addition-deletion rule. Signed-off-by: Utku Enes GURSEL --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 22 +- .../linter/src/lib/autofixes/Autofixer.ts | 232 ++++++++++++++++++ .../linter/src/lib/utils/consts/InteropAPI.ts | 5 + .../interop/increases_decreases_js_obj.ets | 5 + .../increases_decreases_js_obj.ets.args.json | 42 ++-- ...increases_decreases_js_obj.ets.arkts2.json | 42 +++- ...ncreases_decreases_js_obj.ets.autofix.json | 130 +++++++++- ...increases_decreases_js_obj.ets.migrate.ets | 37 ++- ...ncreases_decreases_js_obj.ets.migrate.json | 42 +++- 9 files changed, 522 insertions(+), 35 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4caeea6c34..2f6aecf11b 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8330,14 +8330,22 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private checkAutoIncrementDecrement(unaryExpr: ts.PostfixUnaryExpression | ts.PrefixUnaryExpression): void { - if (ts.isPropertyAccessExpression(unaryExpr.operand)) { - const propertyAccess = unaryExpr.operand; - if (this.useStatic && this.options.arkts2) { - if (this.isFromJSModule(propertyAccess.expression)) { - this.incrementCounters(unaryExpr, FaultID.InteropIncrementDecrement); - } - } + if (!this.useStatic || !this.options.arkts2) { + return; + } + + if (!ts.isPropertyAccessExpression(unaryExpr.operand)) { + return; + } + + const propertyAccess = unaryExpr.operand; + if (!this.tsUtils.isJsImport(propertyAccess.expression)) { + return; } + + const autofix = this.autofixer?.fixUnaryIncrDecr(unaryExpr, propertyAccess); + + this.incrementCounters(unaryExpr, FaultID.InteropIncrementDecrement, autofix); } private handleObjectLiteralforUnionTypeInterop(node: ts.VariableDeclaration): void { diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index dd1918fbf2..24d221667c 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -42,6 +42,7 @@ import { PROVIDE_ALLOW_OVERRIDE_PROPERTY_NAME } from '../utils/consts/ArkuiConstants'; import { ES_VALUE } from '../utils/consts/ESObject'; +import type { IncrementDecrementNodeInfo } from '../utils/consts/InteropAPI'; import { LOAD, GET_PROPERTY_BY_NAME, @@ -88,6 +89,9 @@ const GENERATED_DESTRUCT_ARRAY_TRESHOLD = 1000; const GENERATED_IMPORT_VARIABLE_NAME = 'GeneratedImportVar_'; const GENERATED_IMPORT_VARIABLE_TRESHOLD = 1000; +const GENERATED_TMP_VARIABLE_NAME = 'tmp_'; +const GENERATED_TMP_VARIABLE_TRESHOLD = 1000; + const SPECIAL_LIB_NAME = 'specialAutofixLib'; const OBJECT_LITERAL_CLASS_CONSTRUCTOR_PARAM_NAME = 'init'; @@ -152,6 +156,11 @@ export class Autofixer { GENERATED_IMPORT_VARIABLE_TRESHOLD ); + private readonly tmpVariableNameGenerator = new NameGenerator( + GENERATED_TMP_VARIABLE_NAME, + GENERATED_TMP_VARIABLE_TRESHOLD + ); + private modVarName: string = ''; private readonly lastImportEndMap = new Map(); @@ -3065,6 +3074,229 @@ export class Autofixer { } } + private getVariableName(node: ts.Node): string | undefined { + let variableName: string | undefined; + + switch (node.kind) { + case ts.SyntaxKind.BinaryExpression: { + const binaryExpr = node as ts.BinaryExpression; + if (binaryExpr.operatorToken.kind !== ts.SyntaxKind.EqualsToken) { + return undefined; + } + + variableName = binaryExpr.left.getText(); + break; + } + case ts.SyntaxKind.VariableDeclaration: { + const variableDecl = node as ts.VariableDeclaration; + variableName = variableDecl.name.getText(); + break; + } + case ts.SyntaxKind.ExpressionStatement: { + variableName = TsUtils.generateUniqueName(this.tmpVariableNameGenerator, this.sourceFile); + break; + } + default: { + return undefined; + } + } + + return variableName; + } + + private getNewNodesForIncrDecr(variableName: string, operator: number): IncrementDecrementNodeInfo | undefined { + let update: string | undefined; + let updateNode: ts.BinaryExpression | undefined; + + switch (operator) { + case ts.SyntaxKind.MinusMinusToken: { + const { varAssignText, addOrDecrOperation } = this.createNewIncrDecrNodes( + variableName, + ts.SyntaxKind.MinusToken + ); + update = varAssignText; + updateNode = addOrDecrOperation; + break; + } + case ts.SyntaxKind.PlusPlusToken: { + const { varAssignText, addOrDecrOperation } = this.createNewIncrDecrNodes( + variableName, + ts.SyntaxKind.PlusToken + ); + update = varAssignText; + updateNode = addOrDecrOperation; + break; + } + default: + return undefined; + } + + return { varAssignText: update, addOrDecrOperation: updateNode }; + } + + fixUnaryIncrDecr( + node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, + pan: ts.PropertyAccessExpression + ): Autofix[] | undefined { + const parent = node.parent; + const grandParent = parent.parent; + + const { expression, name } = pan; + const { operator } = node; + const isVariableDeclaration = ts.isVariableDeclaration(node.parent); + + const variableName = this.getVariableName(node.parent); + + if (!variableName) { + return undefined; + } + + const updateNodes = this.getNewNodesForIncrDecr(variableName, operator); + + if (!updateNodes?.varAssignText || !updateNodes.addOrDecrOperation) { + return undefined; + } + + const replacementText = this.getReplacementTextForPrefixAndPostfixUnary( + node, + updateNodes, + expression, + name, + variableName + ); + + if (!replacementText) { + return undefined; + } + + if (isVariableDeclaration) { + const start = grandParent.getStart(); + const end = grandParent.getEnd(); + return [{ replacementText, start, end }]; + } + + const start = parent.getStart(); + const end = parent.getEnd(); + return [{ replacementText, start, end }]; + } + + private getReplacementTextForPrefixAndPostfixUnary( + node: ts.Node, + updateNodes: IncrementDecrementNodeInfo, + expression: ts.LeftHandSideExpression, + name: ts.MemberName, + variableName: string + ): string | undefined { + const { varAssignText, addOrDecrOperation } = updateNodes; + const converted: ts.Node = this.createGetPropertyForIncrDecr(expression.getText(), name.text); + let convertedAssigned = ''; + if (ts.isBinaryExpression(node.parent) && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { + convertedAssigned = this.wrapPropertyAccessInBinaryExpr(variableName, converted); + } else { + convertedAssigned = this.wrapPropertyAccessInVariableDeclaration(variableName, converted); + } + let replacementText = ''; + + switch (node.kind) { + case ts.SyntaxKind.PrefixUnaryExpression: { + const assign = this.createSetProperty( + expression.getText(), + name.text, + ts.factory.createIdentifier(variableName) + ); + replacementText = `${convertedAssigned}\n${varAssignText}\n${assign}\n`; + break; + } + case ts.SyntaxKind.PostfixUnaryExpression: { + const assign = this.createSetProperty(expression.getText(), name.text, addOrDecrOperation as ts.Expression); + replacementText = `${convertedAssigned}\n${assign}\n${varAssignText}\n`; + break; + } + default: { + return undefined; + } + } + + return replacementText; + } + + private wrapPropertyAccessInVariableDeclaration(variableName: string, wrappedNode: ts.Node): string { + const node = ts.factory.createVariableDeclarationList( + [ + ts.factory.createVariableDeclaration( + ts.factory.createIdentifier(variableName), + undefined, + undefined, + wrappedNode as ts.Expression + ) + ], + ts.NodeFlags.Let + ); + + return this.printer.printNode(ts.EmitHint.Unspecified, node, this.sourceFile); + } + + private wrapPropertyAccessInBinaryExpr(variableName: string, wrappedNode: ts.Node): string { + const node = ts.factory.createBinaryExpression( + ts.factory.createIdentifier(variableName), + ts.SyntaxKind.EqualsToken, + wrappedNode as ts.Expression + ); + + return this.printer.printNode(ts.EmitHint.Unspecified, node, this.sourceFile); + } + + private createGetPropertyForIncrDecr(expression: string, name: string): ts.Node { + void this; + return ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(expression), + ts.factory.createIdentifier(GET_PROPERTY_BY_NAME) + ), + undefined, + [ts.factory.createStringLiteral(name)] + ), + ts.factory.createIdentifier(TO_NUMBER) + ), + undefined, + [] + ); + } + + private createNewIncrDecrNodes(variableName: string, token: number): IncrementDecrementNodeInfo { + const update = ts.factory.createBinaryExpression( + ts.factory.createIdentifier(variableName), + ts.factory.createToken(token), + ts.factory.createNumericLiteral('1') + ); + + const node = ts.factory.createBinaryExpression( + ts.factory.createIdentifier(variableName), + ts.factory.createToken(ts.SyntaxKind.EqualsToken), + update + ); + + return { + addOrDecrOperation: update, + varAssignText: this.printer.printNode(ts.EmitHint.Unspecified, node, this.sourceFile) + }; + } + + private createSetProperty(expression: string, field: string, value: ts.Expression): string { + const node = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createIdentifier(expression), + ts.factory.createIdentifier(SET_PROPERTY_BY_NAME) + ), + undefined, + [ts.factory.createIdentifier(field), value] + ); + + return this.printer.printNode(ts.EmitHint.Unspecified, node, this.sourceFile); + } + fixVariableDeclaration(node: ts.VariableDeclaration, isEnum: boolean): Autofix[] | undefined { const initializer = node.initializer; const name = node.name; diff --git a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts index 1a2255324b..ceb9d389fc 100644 --- a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts +++ b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts @@ -81,3 +81,8 @@ export type IdentifierAndArguments = { ident: undefined | ts.Identifier; args: ts.NodeArray | undefined; }; + +export type IncrementDecrementNodeInfo = { + varAssignText: string; + addOrDecrOperation: ts.BinaryExpression; +}; diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets index 826f43035f..9d1ec94c56 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets @@ -18,3 +18,8 @@ a = foo.num++ a = ++foo.num a = foo.num-- a = --foo.num + +foo.num++ +++foo.num +foo.num-- +--foo.num diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.args.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.args.json index 3318ebbbcf..571ee6bb76 100755 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.args.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.args.json @@ -1,21 +1,21 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "mode": { - "arkts2": "", - "autofix": "--arkts-2", - "migrate": "--arkts-2" - } -} +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json index 7be0663596..5733e4a0f9 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.arkts2.json @@ -73,6 +73,46 @@ "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json index 4131e60caa..74a00a0cf4 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.autofix.json @@ -71,6 +71,17 @@ "endLine": 17, "endColumn": 14, "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, a + 1)\na = a + 1\n", + "start": 673, + "end": 686, + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 14 + } + ], "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" @@ -81,6 +92,17 @@ "endLine": 18, "endColumn": 14, "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\na = a + 1\nfoo.setPropertyByName(num, a)\n", + "start": 687, + "end": 700, + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 14 + } + ], "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" @@ -91,6 +113,17 @@ "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, a - 1)\na = a - 1\n", + "start": 701, + "end": 714, + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 14 + } + ], "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" @@ -101,9 +134,104 @@ "endLine": 20, "endColumn": 14, "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\na = a - 1\nfoo.setPropertyByName(num, a)\n", + "start": 715, + "end": 728, + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "let tmp_1 = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, tmp_1 + 1)\ntmp_1 = tmp_1 + 1\n", + "start": 730, + "end": 739, + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "let tmp_2 = foo.getPropertyByName(\"num\").toNumber()\ntmp_2 = tmp_2 + 1\nfoo.setPropertyByName(num, tmp_2)\n", + "start": 740, + "end": 749, + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "let tmp_3 = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, tmp_3 - 1)\ntmp_3 = tmp_3 - 1\n", + "start": 750, + "end": 759, + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 10, + "problem": "InteropIncrementDecrement", + "autofix": [ + { + "replacementText": "let tmp_4 = foo.getPropertyByName(\"num\").toNumber()\ntmp_4 = tmp_4 - 1\nfoo.setPropertyByName(num, tmp_4)\n", + "start": 760, + "end": 769, + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 10 + } + ], "suggest": "", "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets index 58c43c2c1d..f022ce0834 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.ets @@ -16,7 +16,36 @@ let GeneratedImportVar_1 = ESValue.load('./increases_decreases_js_obj_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); let a: number =0.0 -a = foo.num++ -a = ++foo.num -a = foo.num-- -a = --foo.num +a = foo.getPropertyByName("num").toNumber() +foo.setPropertyByName(num, a + 1.0) +a = a + 1.0 + +a = foo.getPropertyByName("num").toNumber() +a = a + 1.0 +foo.setPropertyByName(num, a) + +a = foo.getPropertyByName("num").toNumber() +foo.setPropertyByName(num, a - 1.0) +a = a - 1.0 + +a = foo.getPropertyByName("num").toNumber() +a = a - 1.0 +foo.setPropertyByName(num, a) + + +let tmp_1 = foo.getPropertyByName("num").toNumber() +foo.setPropertyByName(num, tmp_1 + 1.0) +tmp_1 = tmp_1 + 1.0 + +let tmp_2 = foo.getPropertyByName("num").toNumber() +tmp_2 = tmp_2 + 1.0 +foo.setPropertyByName(num, tmp_2) + +let tmp_3 = foo.getPropertyByName("num").toNumber() +foo.setPropertyByName(num, tmp_3 - 1.0) +tmp_3 = tmp_3 - 1.0 + +let tmp_4 = foo.getPropertyByName("num").toNumber() +tmp_4 = tmp_4 - 1.0 +foo.setPropertyByName(num, tmp_4) + diff --git a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json index f2f6070e65..0a10b6a69e 100644 --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.migrate.json @@ -33,6 +33,46 @@ "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" + }, + { + "line": 36, + "column": 5, + "endLine": 36, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 5, + "endLine": 40, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 5, + "endLine": 44, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 5, + "endLine": 48, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" } ] -} \ No newline at end of file +} -- Gitee From 1579da2821245352385eee095f8c56aac3f66b5a Mon Sep 17 00:00:00 2001 From: Utku Enes GURSEL Date: Fri, 30 May 2025 11:13:48 +0300 Subject: [PATCH 024/747] fix ConstructIfaceFromSdk rule check Issue: ICB9IW Description: Instead using ts.Compiler's controller method, checking the type declaration if we are trying to instantiate a interface we raise the error. Signed-off-by: Utku Enes GURSEL --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 2f6aecf11b..be93fbbb4b 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -5042,9 +5042,19 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const type = this.tsTypeChecker.getTypeAtLocation(calleeExpr); - if (type.isClassOrInterface()) { - this.incrementCounters(calleeExpr, FaultID.ConstructorIfaceFromSdk); + if (!type.symbol) { + return; + } + const typeDeclarations = type.symbol.declarations; + if (!typeDeclarations || typeDeclarations.length === 0) { + return; } + + if (!ts.isInterfaceDeclaration(typeDeclarations[0])) { + return; + } + + this.incrementCounters(calleeExpr, FaultID.ConstructorIfaceFromSdk); } private handleNewExpression(node: ts.Node): void { -- Gitee From 9d4c2510ddc5b7854b4f9e381dbe06440bd0fbdc Mon Sep 17 00:00:00 2001 From: cihatfurkaneken Date: Tue, 3 Jun 2025 08:45:33 +0300 Subject: [PATCH 025/747] interop-js2s-js-call-static-func severity change Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBYRM Signed-off-by: cihatfurkaneken --- ets2panda/linter/src/lib/FaultAttrs.ts | 2 +- .../test/interop/interop_import_js_rules.ets.arkts2.json | 4 ++-- .../test/interop/interop_import_js_rules.ets.autofix.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index 2d555b1a2a..89fead1734 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -188,7 +188,7 @@ faultsAttrs[FaultID.MakeObservedIsNotSupported] = new FaultAttributes(262); faultsAttrs[FaultID.ProvideAnnotation] = new FaultAttributes(263); faultsAttrs[FaultID.InteropJsObjectInheritance] = new FaultAttributes(265); faultsAttrs[FaultID.InteropJsObjectTraverseJsInstance] = new FaultAttributes(266); -faultsAttrs[FaultID.InteropJsObjectCallStaticFunc] = new FaultAttributes(267); +faultsAttrs[FaultID.InteropJsObjectCallStaticFunc] = new FaultAttributes(267, ProblemSeverity.WARNING); faultsAttrs[FaultID.InteropJsObjectConditionJudgment] = new FaultAttributes(268); faultsAttrs[FaultID.InteropJsObjectExpandStaticInstance] = new FaultAttributes(269); faultsAttrs[FaultID.InteropJSFunctionInvoke] = new FaultAttributes(270); diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json index dec39fff4b..2fdc4e604e 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.arkts2.json @@ -392,7 +392,7 @@ "problem": "InteropJsObjectCallStaticFunc", "suggest": "", "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" + "severity": "WARNING" }, { "line": 64, @@ -412,7 +412,7 @@ "problem": "InteropJsObjectCallStaticFunc", "suggest": "", "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" + "severity": "WARNING" }, { "line": 65, diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json index c7bff146b9..06785ec219 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json @@ -704,7 +704,7 @@ "problem": "InteropJsObjectCallStaticFunc", "suggest": "", "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" + "severity": "WARNING" }, { "line": 64, @@ -735,7 +735,7 @@ "problem": "InteropJsObjectCallStaticFunc", "suggest": "", "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" + "severity": "WARNING" }, { "line": 65, -- Gitee From 9de5749af324e2f8b3bdf6e84515b26c3b3a52fb Mon Sep 17 00:00:00 2001 From: cihatfurkaneken Date: Tue, 3 Jun 2025 09:51:45 +0300 Subject: [PATCH 026/747] autofix interop js2s compare and binary rules Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBU38 Signed-off-by: cihatfurkaneken --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 8 +- .../linter/src/lib/autofixes/Autofixer.ts | 59 ++ .../test/interop/binary_operation_js_obj.ets | 24 +- .../binary_operation_js_obj.ets.arkts2.json | 202 +++++- .../binary_operation_js_obj.ets.autofix.json | 589 +++++++++++++++++- .../interop/binary_operation_js_obj.ets.json | 13 +- .../binary_operation_js_obj.ets.migrate.ets | 28 +- .../binary_operation_js_obj.ets.migrate.json | 58 +- .../interop/binary_operation_js_obj_js.js | 2 + .../interop_import_js_compare.ets.args.json | 14 +- ...interop_import_js_compare.ets.autofix.json | 582 +++++++++++++++++ .../interop_import_js_compare.ets.migrate.ets | 51 ++ ...interop_import_js_compare.ets.migrate.json | 78 +++ .../interop_import_js_rules.ets.autofix.json | 11 + 14 files changed, 1687 insertions(+), 32 deletions(-) create mode 100644 ets2panda/linter/test/interop/interop_import_js_compare.ets.autofix.json create mode 100644 ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.ets create mode 100644 ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index be93fbbb4b..7bb76d3709 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -2166,7 +2166,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const processExpression = (expr: ts.Expression): void => { const symbol = this.tsUtils.trueSymbolAtLocation(expr); if (this.isJsFileSymbol(symbol) || this.isJsFileExpression(expr)) { - this.incrementCounters(expr, FaultID.InterOpImportJsDataCompare); + const autofix = this.autofixer?.fixInteropOperators(expr); + this.incrementCounters(expr, FaultID.InterOpImportJsDataCompare, autofix); } }; @@ -9137,8 +9138,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const processExpression = (expr: ts.Expression): void => { const symbol = this.tsUtils.trueSymbolAtLocation(expr); - if (this.isJsFileSymbol(symbol)) { - this.incrementCounters(expr, FaultID.BinaryOperations); + if (this.isJsFileSymbol(symbol) || this.isJsFileExpression(expr)) { + const autofix = this.autofixer?.fixInteropOperators(expr); + this.incrementCounters(expr, FaultID.BinaryOperations, autofix); } }; diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 24d221667c..6b69ce45c6 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -4323,6 +4323,65 @@ export class Autofixer { ]; } + fixInteropOperators(expr: ts.Expression): Autofix[] | undefined { + if (ts.isPropertyAccessExpression(expr)) { + return this.fixPropertyAccessToNumber(expr); + } + + if (ts.isIdentifier(expr)) { + const symbol = this.utils.trueSymbolAtLocation(expr); + + if (this.utils.isJsImport(expr)) { + const toNumberCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(expr, ts.factory.createIdentifier(TO_NUMBER)), + undefined, + [] + ); + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, toNumberCall, expr.getSourceFile()); + + return [ + { + start: expr.getStart(), + end: expr.getEnd(), + replacementText + } + ]; + } + + const decl = symbol?.declarations?.find(ts.isVariableDeclaration); + if (decl?.initializer && ts.isPropertyAccessExpression(decl.initializer)) { + return this.fixPropertyAccessToNumber(decl.initializer); + } + } + + return undefined; + } + + private fixPropertyAccessToNumber(expr: ts.PropertyAccessExpression): Autofix[] { + const getPropCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(expr.expression, ts.factory.createIdentifier(GET_PROPERTY_BY_NAME)), + undefined, + [ts.factory.createStringLiteral(expr.name.getText())] + ); + + const toNumberCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(getPropCall, ts.factory.createIdentifier(TO_NUMBER)), + undefined, + [] + ); + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, toNumberCall, expr.getSourceFile()); + + return [ + { + start: expr.getStart(), + end: expr.getEnd(), + replacementText + } + ]; + } + fixInteropArrayElementAccessExpression(express: ts.ElementAccessExpression): Autofix[] | undefined { const statements = ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression(express.expression, ts.factory.createIdentifier(GET_PROPERTY_BY_INDEX)), diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets b/ets2panda/linter/test/interop/binary_operation_js_obj.ets index 44c53b8012..472ad5669d 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {foo} from "./binary_operation_js_obj_js" +import {foo,m,n} from "./binary_operation_js_obj_js" let a = foo.a let b = foo.b a + b @@ -20,4 +20,24 @@ a - b a * b a / b a % b -a ** b \ No newline at end of file +a ** b + +m + n +m % n +m ** n + +let x = 1, y = 2; +x + y; +x - y; +x % y; +x ** y; + +let bar = { a: 1, b: 2 }; + +let x2 = bar.a, y2 = bar.b; +x2 + y2; +x2 - y2; +x2 % y2; +x2 ** y2; + +foo.a + foo.b; \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json index e7eb94f512..88784c2392 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.arkts2.json @@ -18,7 +18,7 @@ "line": 15, "column": 1, "endLine": 15, - "endColumn": 49, + "endColumn": 53, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -173,6 +173,206 @@ "suggest": "", "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 2, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 6, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 2, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 6, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 2, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 6, + "endLine": 27, + "endColumn": 7, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 3, + "endLine": 27, + "endColumn": 5, + "problem": "ExponentOp", + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 5, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 12, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 33, + "column": 3, + "endLine": 33, + "endColumn": 5, + "problem": "ExponentOp", + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 16, + "endLine": 35, + "endColumn": 17, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 23, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 15, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 17, + "endLine": 37, + "endColumn": 27, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 4, + "endLine": 41, + "endColumn": 6, + "problem": "ExponentOp", + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 6, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 9, + "endLine": 43, + "endColumn": 14, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json index b67555d475..02657b3152 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.autofix.json @@ -13,31 +13,31 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ +"result": [ { "line": 15, "column": 1, "endLine": 15, - "endColumn": 49, + "endColumn": 53, "problem": "InterOpImportJs", "autofix": [ { "start": 604, - "end": 652, + "end": 656, "replacementText": "", "line": 15, "column": 1, "endLine": 15, - "endColumn": 49 + "endColumn": 53 }, { - "start": 652, - "end": 652, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "start": 656, + "end": 656, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet m = GeneratedImportVar_1.getPropertyByName('m');\nlet n = GeneratedImportVar_1.getPropertyByName('n');\n", "line": 15, "column": 1, "endLine": 15, - "endColumn": 49 + "endColumn": 53 } ], "suggest": "", @@ -52,8 +52,8 @@ "problem": "InteropObjectProperty", "autofix": [ { - "start": 661, - "end": 666, + "start": 665, + "end": 670, "replacementText": "foo.getPropertyByName(\"a\")", "line": 16, "column": 9, @@ -73,8 +73,8 @@ "problem": "InteropObjectProperty", "autofix": [ { - "start": 675, - "end": 680, + "start": 679, + "end": 684, "replacementText": "foo.getPropertyByName(\"b\")", "line": 17, "column": 9, @@ -92,6 +92,17 @@ "endLine": 18, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -102,6 +113,17 @@ "endLine": 18, "endColumn": 6, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 6 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -112,6 +134,17 @@ "endLine": 19, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -122,6 +155,17 @@ "endLine": 19, "endColumn": 6, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 6 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -132,6 +176,17 @@ "endLine": 20, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -142,6 +197,17 @@ "endLine": 20, "endColumn": 6, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 6 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -152,6 +218,17 @@ "endLine": 21, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -162,6 +239,17 @@ "endLine": 21, "endColumn": 6, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 6 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -172,6 +260,17 @@ "endLine": 22, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -182,6 +281,17 @@ "endLine": 22, "endColumn": 6, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 6 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -192,6 +302,17 @@ "endLine": 23, "endColumn": 2, "problem": "BinaryOperations", + "autofix": [ + { + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 2 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -202,6 +323,17 @@ "endLine": 23, "endColumn": 7, "problem": "BinaryOperations", + "autofix": [ + { + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 23, + "column": 6, + "endLine": 23, + "endColumn": 7 + } + ], "suggest": "", "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", "severity": "ERROR" @@ -215,8 +347,8 @@ "autofix": [ { "replacementText": "Math.pow(a, b)", - "start": 711, - "end": 717, + "start": 715, + "end": 721, "line": 23, "column": 3, "endLine": 23, @@ -226,6 +358,435 @@ "suggest": "", "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", "severity": "ERROR" + }, + { + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 2, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 723, + "end": 724, + "replacementText": "m.toNumber()", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 6, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 727, + "end": 728, + "replacementText": "n.toNumber()", + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 2, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 729, + "end": 730, + "replacementText": "m.toNumber()", + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 6, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 733, + "end": 734, + "replacementText": "n.toNumber()", + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 2, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 735, + "end": 736, + "replacementText": "m.toNumber()", + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 6, + "endLine": 27, + "endColumn": 7, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 740, + "end": 741, + "replacementText": "n.toNumber()", + "line": 27, + "column": 6, + "endLine": 27, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 3, + "endLine": 27, + "endColumn": 5, + "problem": "ExponentOp", + "autofix": [ + { + "replacementText": "Math.pow(m, n)", + "start": 735, + "end": 741, + "line": 27, + "column": 3, + "endLine": 27, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 5, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 747, + "end": 752, + "replacementText": "x: number = 1", + "line": 29, + "column": 5, + "endLine": 29, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 751, + "end": 752, + "replacementText": "1.0", + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 12, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 754, + "end": 759, + "replacementText": "y: number = 2", + "line": 29, + "column": 12, + "endLine": 29, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 758, + "end": 759, + "replacementText": "2.0", + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 33, + "column": 3, + "endLine": 33, + "endColumn": 5, + "problem": "ExponentOp", + "autofix": [ + { + "replacementText": "Math.pow(x, y)", + "start": 782, + "end": 788, + "line": 33, + "column": 3, + "endLine": 33, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12, + "problem": "ObjectLiteralNoContextType", + "autofix": [ + { + "start": 791, + "end": 791, + "replacementText": "interface GeneratedObjectLiteralInterface_1 {\n a: number;\n b: number;\n}\n", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12 + }, + { + "start": 798, + "end": 798, + "replacementText": ": GeneratedObjectLiteralInterface_1", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 16, + "endLine": 35, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 806, + "end": 807, + "replacementText": "1.0", + "line": 35, + "column": 16, + "endLine": 35, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 23, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 812, + "end": 813, + "replacementText": "2.0", + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 23 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 822, + "end": 832, + "replacementText": "x2: number = bar.a", + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 17, + "endLine": 37, + "endColumn": 27, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 834, + "end": 844, + "replacementText": "y2: number = bar.b", + "line": 37, + "column": 17, + "endLine": 37, + "endColumn": 27 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 4, + "endLine": 41, + "endColumn": 6, + "problem": "ExponentOp", + "autofix": [ + { + "replacementText": "Math.pow(x2, y2)", + "start": 873, + "end": 881, + "line": 41, + "column": 4, + "endLine": 41, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "exponent opartions \"**\" and \"**=\" are disabled (arkts-no-exponent-op)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 6, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 884, + "end": 889, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 9, + "endLine": 43, + "endColumn": 14, + "problem": "BinaryOperations", + "autofix": [ + { + "start": 892, + "end": 897, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 43, + "column": 9, + "endLine": 43, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json index ca88f857e9..e28baca176 100755 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json @@ -13,5 +13,16 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets index 83e761ce7f..f29b91c275 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.ets @@ -14,6 +14,8 @@ */ let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); +let m = GeneratedImportVar_1.getPropertyByName('m'); +let n = GeneratedImportVar_1.getPropertyByName('n'); let a = foo.getPropertyByName("a") let b = foo.getPropertyByName("b") @@ -22,4 +24,28 @@ a - b a * b a / b a % b -Math.pow(a, b) \ No newline at end of file +Math.pow(a, b) + +m.toNumber() + n.toNumber() +m.toNumber() % n.toNumber() +Math.pow(m.toNumber(), n.toNumber()) + +let x: number = 1.0, y: number = 2.0; +x + y; +x - y; +x % y; +Math.pow(x, y); + +interface GeneratedObjectLiteralInterface_1 { + a: number; + b: number; +} +let bar: GeneratedObjectLiteralInterface_1 = { a: 1.0, b: 2.0 }; + +let x2: number = bar.a, y2: number = bar.b; +x2 + y2; +x2 - y2; +x2 % y2; +Math.pow(x2, y2); + +foo.getPropertyByName("a").toNumber() + foo.getPropertyByName("b").toNumber(); \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json index bf73aefbeb..817c2a9450 100644 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.migrate.json @@ -34,10 +34,30 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, { "line": 18, "column": 5, "endLine": 18, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, "endColumn": 35, "problem": "AnyType", "suggest": "", @@ -45,9 +65,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 21, "column": 5, - "endLine": 19, + "endLine": 21, "endColumn": 35, "problem": "AnyType", "suggest": "", @@ -55,14 +75,44 @@ "severity": "ERROR" }, { - "line": 25, + "line": 27, + "column": 1, + "endLine": 27, + "endColumn": 15, + "problem": "MathPow", + "suggest": "", + "rule": "function \"Math.pow()\" behavior for ArkTS differs from Typescript version (arkts-math-pow-standard-diff)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 1, + "endLine": 31, + "endColumn": 37, + "problem": "MathPow", + "suggest": "", + "rule": "function \"Math.pow()\" behavior for ArkTS differs from Typescript version (arkts-math-pow-standard-diff)", + "severity": "ERROR" + }, + { + "line": 37, "column": 1, - "endLine": 25, + "endLine": 37, "endColumn": 15, "problem": "MathPow", "suggest": "", "rule": "function \"Math.pow()\" behavior for ArkTS differs from Typescript version (arkts-math-pow-standard-diff)", "severity": "ERROR" + }, + { + "line": 49, + "column": 1, + "endLine": 49, + "endColumn": 17, + "problem": "MathPow", + "suggest": "", + "rule": "function \"Math.pow()\" behavior for ArkTS differs from Typescript version (arkts-math-pow-standard-diff)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/binary_operation_js_obj_js.js b/ets2panda/linter/test/interop/binary_operation_js_obj_js.js index aaf9c1dd4e..c8f9951bda 100755 --- a/ets2panda/linter/test/interop/binary_operation_js_obj_js.js +++ b/ets2panda/linter/test/interop/binary_operation_js_obj_js.js @@ -14,3 +14,5 @@ */ export let foo = {a: 1, b: 2} +export let m = 3 +export let n = 2 \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.args.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.args.json index e2b903f0aa..571ee6bb76 100644 --- a/ets2panda/linter/test/interop/interop_import_js_compare.ets.args.json +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.args.json @@ -1,5 +1,5 @@ { - "copyright": [ + "copyright": [ "Copyright (c) 2025 Huawei Device Co., Ltd.", "Licensed under the Apache License, Version 2.0 (the 'License');", "you may not use this file except in compliance with the License.", @@ -12,8 +12,10 @@ "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", "See the License for the specific language governing permissions and", "limitations under the License." - ], - "mode": { - "arkts2": "" - } - } \ No newline at end of file + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.autofix.json new file mode 100644 index 0000000000..8b8b4fe079 --- /dev/null +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.autofix.json @@ -0,0 +1,582 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 57, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 607, + "end": 663, + "replacementText": "", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 57 + }, + { + "start": 663, + "end": 663, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_compare_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet m = GeneratedImportVar_1.getPropertyByName('m');\nlet n = GeneratedImportVar_1.getPropertyByName('n');\n", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 57 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 9, + "endLine": 18, + "endColumn": 14, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 672, + "end": 677, + "replacementText": "foo.getPropertyByName(\"a\")", + "line": 18, + "column": 9, + "endLine": 18, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 9, + "endLine": 19, + "endColumn": 14, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 686, + "end": 691, + "replacementText": "foo.getPropertyByName(\"b\")", + "line": 19, + "column": 9, + "endLine": 19, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 672, + "end": 677, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 6, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 686, + "end": 691, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 672, + "end": 677, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 6, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 686, + "end": 691, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 672, + "end": 677, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 6, + "endLine": 22, + "endColumn": 7, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 686, + "end": 691, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 22, + "column": 6, + "endLine": 22, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 672, + "end": 677, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 23, + "column": 1, + "endLine": 23, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 6, + "endLine": 23, + "endColumn": 7, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 686, + "end": 691, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 23, + "column": 6, + "endLine": 23, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 5, + "endLine": 24, + "endColumn": 6, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 722, + "end": 723, + "replacementText": "1.0", + "line": 24, + "column": 5, + "endLine": 24, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 2, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 725, + "end": 726, + "replacementText": "m.toNumber()", + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 6, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 729, + "end": 730, + "replacementText": "n.toNumber()", + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 5, + "endLine": 27, + "endColumn": 6, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 735, + "end": 736, + "replacementText": "1.0", + "line": 27, + "column": 5, + "endLine": 27, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 5, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 742, + "end": 747, + "replacementText": "x: number = 1", + "line": 29, + "column": 5, + "endLine": 29, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 10, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 746, + "end": 747, + "replacementText": "1.0", + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 10 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 12, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 749, + "end": 754, + "replacementText": "y: number = 2", + "line": 29, + "column": 12, + "endLine": 29, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 753, + "end": 754, + "replacementText": "2.0", + "line": 29, + "column": 16, + "endLine": 29, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12, + "problem": "ObjectLiteralNoContextType", + "autofix": [ + { + "start": 787, + "end": 787, + "replacementText": "interface GeneratedObjectLiteralInterface_1 {\n a: number;\n b: number;\n}\n", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12 + }, + { + "start": 794, + "end": 794, + "replacementText": ": GeneratedObjectLiteralInterface_1", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 16, + "endLine": 35, + "endColumn": 17, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 802, + "end": 803, + "replacementText": "1.0", + "line": 35, + "column": 16, + "endLine": 35, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 23, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 808, + "end": 809, + "replacementText": "2.0", + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 23 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 818, + "end": 828, + "replacementText": "x2: number = bar.a", + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 17, + "endLine": 37, + "endColumn": 27, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 830, + "end": 840, + "replacementText": "y2: number = bar.b", + "line": 37, + "column": 17, + "endLine": 37, + "endColumn": 27 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 6, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 881, + "end": 886, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", + "line": 43, + "column": 1, + "endLine": 43, + "endColumn": 6 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + }, + { + "line": 43, + "column": 9, + "endLine": 43, + "endColumn": 14, + "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 889, + "end": 894, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", + "line": 43, + "column": 9, + "endLine": 43, + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.ets new file mode 100644 index 0000000000..76633c942c --- /dev/null +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.ets @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +let GeneratedImportVar_1 = ESValue.load('./interop_import_js_compare_js'); +let foo = GeneratedImportVar_1.getPropertyByName('foo'); +let m = GeneratedImportVar_1.getPropertyByName('m'); +let n = GeneratedImportVar_1.getPropertyByName('n'); + +let a = foo.getPropertyByName("a") +let b = foo.getPropertyByName("b") +a > b +a < b +a >= b +a <= b +a = 1.0 + +m.toNumber() > n.toNumber() +m = 1.0 + +let x: number = 1.0, y: number = 2.0; +x > y; +x < y; +x >= y; +x <= y; + +interface GeneratedObjectLiteralInterface_1 { + a: number; + b: number; +} +let bar: GeneratedObjectLiteralInterface_1 = { a: 1.0, b: 2.0 }; + +let x2: number = bar.a, y2: number = bar.b; +x2 > y2; +x2 < y2; +x2 >= y2; +x2 <= y2; + +foo.getPropertyByName("a").toNumber() > foo.getPropertyByName("b").toNumber(); \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.json new file mode 100644 index 0000000000..0ccdec1005 --- /dev/null +++ b/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.json @@ -0,0 +1,78 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 74, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 35, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 5, + "endLine": 23, + "endColumn": 35, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json index 06785ec219..415bd82dc4 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.autofix.json @@ -401,6 +401,17 @@ "endLine": 34, "endColumn": 11, "problem": "InterOpImportJsDataCompare", + "autofix": [ + { + "start": 1118, + "end": 1124, + "replacementText": "ff1.getPropertyByName(\"f1\").toNumber()", + "line": 34, + "column": 5, + "endLine": 34, + "endColumn": 11 + } + ], "suggest": "", "rule": "Importing data directly from the \"JS\" module for comparison is not supported (arkts-interop-js2s-compare-js-data)", "severity": "ERROR" -- Gitee From 1ef191126e67d635a1abc9d505fb5972c0375eab Mon Sep 17 00:00:00 2001 From: beratagaca_9a91 Date: Tue, 3 Jun 2025 11:14:11 +0300 Subject: [PATCH 027/747] unary operation Autofix Description: autofix for unary operation usage Issue: #ICB8I1 Signed-off-by: beratagaca_9a91 --- .../test/interop/unary_operation_js_obj.ets | 20 +++ .../unary_operation_js_obj.ets.args.json | 21 +++ .../unary_operation_js_obj.ets.arkts2.json | 54 +++++++ .../unary_operation_js_obj.ets.autofix.json | 132 ++++++++++++++++++ .../interop/unary_operation_js_obj.ets.json | 3 + .../unary_operation_js_obj.ets.migrate.ets | 22 +++ .../unary_operation_js_obj.ets.migrate.json | 68 +++++++++ .../test/interop/unary_operation_js_obj_js.js | 16 +++ 8 files changed, 336 insertions(+) create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.args.json create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.arkts2.json create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.autofix.json create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.json create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.ets create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.json create mode 100644 ets2panda/linter/test/interop/unary_operation_js_obj_js.js diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets b/ets2panda/linter/test/interop/unary_operation_js_obj.ets new file mode 100644 index 0000000000..a6d66fee06 --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {foo} from "./unary_operation_js_obj_js.js" + ++foo.num; +-foo.num; +!foo.num; +~foo.num; \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.args.json b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.args.json new file mode 100644 index 0000000000..a89d885810 --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.args.json @@ -0,0 +1,21 @@ +{ + "copyright": [ + "Copyright (c) 2024-2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.arkts2.json b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.arkts2.json new file mode 100644 index 0000000000..c935900b7d --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.arkts2.json @@ -0,0 +1,54 @@ +{ + "result": [ + { + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.autofix.json b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.autofix.json new file mode 100644 index 0000000000..f9cba0c863 --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.autofix.json @@ -0,0 +1,132 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 604, + "end": 654, + "replacementText": "", + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51 + }, + { + "start": 654, + "end": 654, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./unary_operation_js_obj_js.js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "autofix": [ + { + "start": 657, + "end": 664, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 9 + } + ], + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "autofix": [ + { + "start": 667, + "end": 674, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "line": 18, + "column": 1, + "endLine": 18, + "endColumn": 9 + } + ], + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "autofix": [ + { + "start": 677, + "end": 684, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 9 + } + ], + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 9, + "problem": "InteropNoHaveNum", + "autofix": [ + { + "start": 687, + "end": 694, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 9 + } + ], + "suggest": "", + "rule": "Interop object does not have property num (arkts-interop-js2s-unary-op)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.json b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.json new file mode 100644 index 0000000000..43cb4a27bc --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.json @@ -0,0 +1,3 @@ +{ + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.ets b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.ets new file mode 100644 index 0000000000..5448d6f5f0 --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +let GeneratedImportVar_1 = ESValue.load('./unary_operation_js_obj_js.js'); +let foo = GeneratedImportVar_1.getPropertyByName('foo'); + + ++foo.getPropertyByName("num").toNumber(); +-foo.getPropertyByName("num").toNumber(); +!foo.getPropertyByName("num").toNumber(); +~foo.getPropertyByName("num").toNumber(); \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.json b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.json new file mode 100644 index 0000000000..4d448e180c --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj.ets.migrate.json @@ -0,0 +1,68 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 15, + "column": 5, + "endLine": 15, + "endColumn": 74, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 16, + "column": 5, + "endLine": 16, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 1, + "endLine": 19, + "endColumn": 41, + "problem": "UnaryArithmNotNumber", + "suggest": "", + "rule": "Unary operators \"+\", \"-\" and \"~\" work only on numbers (arkts-no-polymorphic-unops)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 41, + "problem": "UnaryArithmNotNumber", + "suggest": "", + "rule": "Unary operators \"+\", \"-\" and \"~\" work only on numbers (arkts-no-polymorphic-unops)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 41, + "problem": "UnaryArithmNotNumber", + "suggest": "", + "rule": "Unary operators \"+\", \"-\" and \"~\" work only on numbers (arkts-no-polymorphic-unops)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/unary_operation_js_obj_js.js b/ets2panda/linter/test/interop/unary_operation_js_obj_js.js new file mode 100644 index 0000000000..6787c96784 --- /dev/null +++ b/ets2panda/linter/test/interop/unary_operation_js_obj_js.js @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export let foo = {num: 0}; \ No newline at end of file -- Gitee From fddf62e6b20732d31db6414f5129ae840b870cf8 Mon Sep 17 00:00:00 2001 From: Utku Enes GURSEL Date: Tue, 3 Jun 2025 14:46:03 +0300 Subject: [PATCH 028/747] interop instanceof rule autofix added Description: autofix added for interop instanceof rule Issue: #ICBP8M Signed-off-by: Utku Enes GURSEL --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 10 +- .../linter/src/lib/autofixes/Autofixer.ts | 94 +++-- .../linter/src/lib/utils/consts/InteropAPI.ts | 4 +- .../interop_import_js_index.ets.arkts2.json | 2 +- .../interop_import_js_index.ets.autofix.json | 2 +- .../interop/no_await_js_promise.ets.args.json | 4 +- .../no_await_js_promise.ets.arkts2.json | 14 - .../no_await_js_promise.ets.autofix.json | 278 ++++++++++++++ .../no_await_js_promise.ets.migrate.ets | 70 ++++ .../no_await_js_promise.ets.migrate.json | 188 ++++++++++ .../interop/no_js_instanceof.ets.args.json | 4 +- .../interop/no_js_instanceof.ets.autofix.json | 352 ++++++++++++++++++ .../interop/no_js_instanceof.ets.migrate.ets | 83 +++++ .../interop/no_js_instanceof.ets.migrate.json | 118 ++++++ 14 files changed, 1166 insertions(+), 57 deletions(-) create mode 100644 ets2panda/linter/test/interop/no_await_js_promise.ets.autofix.json create mode 100644 ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.ets create mode 100644 ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.json create mode 100644 ets2panda/linter/test/interop/no_js_instanceof.ets.autofix.json create mode 100644 ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.ets create mode 100644 ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 7bb76d3709..c4cd15426f 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8328,16 +8328,22 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2 || !this.useStatic) { return; } + const left = node.left; const right = node.right; const getNode = (expr: ts.Expression): ts.Node => { return ts.isPropertyAccessExpression(expr) || ts.isCallExpression(expr) ? expr.expression : expr; }; + const leftExpr = getNode(left); const rightExpr = getNode(right); - if (this.tsUtils.isJsImport(leftExpr) || this.tsUtils.isJsImport(rightExpr)) { - this.incrementCounters(node, FaultID.InteropJsInstanceof); + + if (!this.tsUtils.isJsImport(leftExpr) && !this.tsUtils.isJsImport(rightExpr)) { + return; } + + const autofix = this.autofixer?.fixInteropJsInstanceOfExpression(node); + this.incrementCounters(node, FaultID.InteropJsInstanceof, autofix); } private checkAutoIncrementDecrement(unaryExpr: ts.PostfixUnaryExpression | ts.PrefixUnaryExpression): void { diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index 6b69ce45c6..b0e3f2289e 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -57,7 +57,8 @@ import { TO_PROMISE, INVOKE, INVOKE_METHOD, - LENGTH + LENGTH, + IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; @@ -802,9 +803,9 @@ export class Autofixer { propAccessExpr ); // Create statement for the assignment expression, with or without parentheses based on the flag - const statement = needParentheses[index] ? - ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(assignmentExpr)) : - ts.factory.createExpressionStatement(assignmentExpr); + const statement = needParentheses[index] + ? ts.factory.createExpressionStatement(ts.factory.createParenthesizedExpression(assignmentExpr)) + : ts.factory.createExpressionStatement(assignmentExpr); // Append the generated text for the destructuring assignment destructElementText += @@ -1043,7 +1044,7 @@ export class Autofixer { const moduleName = TsUtils.getModuleName(importDeclNode); const newPathParts = [moduleName ?? DEFAULT_MODULE_NAME, SRC_AND_MAIN, ...parts]; const newPath = newPathParts.join(PATH_SEPARATOR); - const newPathString = '\'' + newPath + '\''; + const newPathString = "'" + newPath + "'"; return [{ start: moduleSpecifier.getStart(), end: moduleSpecifier.getEnd(), replacementText: newPathString }]; } @@ -1057,7 +1058,7 @@ export class Autofixer { const newPathParts = [...beforeEts, SRC_AND_MAIN, ...afterEts]; const newPath = newPathParts.join(PATH_SEPARATOR); - const newPathString = '\'' + newPath + '\''; + const newPathString = "'" + newPath + "'"; return [{ start: moduleSpecifier.getStart(), end: moduleSpecifier.getEnd(), replacementText: newPathString }]; } @@ -1356,9 +1357,9 @@ export class Autofixer { fixVarDeclaration(node: ts.VariableDeclarationList): Autofix[] | undefined { const newNode = ts.factory.createVariableDeclarationList(node.declarations, ts.NodeFlags.Let); const text = this.printer.printNode(ts.EmitHint.Unspecified, newNode, node.getSourceFile()); - return this.canAutofixNoVar(node) ? - [{ start: node.getStart(), end: node.getEnd(), replacementText: text }] : - undefined; + return this.canAutofixNoVar(node) + ? [{ start: node.getStart(), end: node.getEnd(), replacementText: text }] + : undefined; } private getFixReturnTypeArrowFunction(funcLikeDecl: ts.FunctionLikeDeclaration, typeNode: ts.TypeNode): string { @@ -1479,15 +1480,14 @@ export class Autofixer { private static getReturnTypePosition(funcLikeDecl: ts.FunctionLikeDeclaration): number { if (funcLikeDecl.body) { - /* * Find position of the first node or token that follows parameters. * After that, iterate over child nodes in reverse order, until found * first closing parenthesis. */ - const postParametersPosition = ts.isArrowFunction(funcLikeDecl) ? - funcLikeDecl.equalsGreaterThanToken.getStart() : - funcLikeDecl.body.getStart(); + const postParametersPosition = ts.isArrowFunction(funcLikeDecl) + ? funcLikeDecl.equalsGreaterThanToken.getStart() + : funcLikeDecl.body.getStart(); const children = funcLikeDecl.getChildren(); for (let i = children.length - 1; i >= 0; i--) { @@ -1512,8 +1512,8 @@ export class Autofixer { ts.isTypeOfExpression(parent) || ts.isVoidExpression(parent) || ts.isAwaitExpression(parent) || - ts.isCallExpression(parent) && node === parent.expression || - ts.isBinaryExpression(parent) && !isAssignmentOperator(parent.operatorToken) + (ts.isCallExpression(parent) && node === parent.expression) || + (ts.isBinaryExpression(parent) && !isAssignmentOperator(parent.operatorToken)) ); } @@ -1849,7 +1849,6 @@ export class Autofixer { objectLiteralType: ts.Type | undefined ): Autofix[] | undefined { if (objectLiteralType) { - /* * Special case for object literal of Record type: fix object's property names * by replacing identifiers with string literals. @@ -1981,7 +1980,6 @@ export class Autofixer { newInterfaceName: string, objectLiteralExpr: ts.ObjectLiteralExpression ): Autofix { - /* * If object literal is initializing a variable or property, * then simply add new 'contextual' type to the declaration. @@ -2236,7 +2234,7 @@ export class Autofixer { } const typeDecl = TsUtils.getDeclaration(objectLiteralType.getSymbol()); - if (!typeDecl || !ts.isClassDeclaration(typeDecl) && !ts.isInterfaceDeclaration(typeDecl) || !typeDecl.name) { + if (!typeDecl || (!ts.isClassDeclaration(typeDecl) && !ts.isInterfaceDeclaration(typeDecl)) || !typeDecl.name) { return undefined; } @@ -3369,7 +3367,7 @@ export class Autofixer { replacement = ts.factory.createCallExpression( ts.factory.createPropertyAccessExpression(callee.expression, ts.factory.createIdentifier(INVOKE_METHOD)), undefined, - [ts.factory.createStringLiteral(callee.name.getText()), ...args || []] + [ts.factory.createStringLiteral(callee.name.getText()), ...(args || [])] ); } else if (ts.isIdentifier(callee)) { // For expressions like foo() or bar(123) => foo.invoke(...) or bar.invoke(...) @@ -3514,11 +3512,11 @@ export class Autofixer { collectExistingNames(parentEnum: ts.EnumDeclaration, tsEnumMember: ts.EnumMember): Set { void this; return new Set( - parentEnum.members. - filter((m) => { + parentEnum.members + .filter((m) => { return m !== tsEnumMember; - }). - map((m) => { + }) + .map((m) => { const nameNode = m.name; if (ts.isStringLiteral(nameNode)) { const fix = this.fixLiteralAsPropertyNamePropertyName(nameNode); @@ -3828,6 +3826,30 @@ export class Autofixer { return [{ start: binaryExpr.getStart(), end: binaryExpr.getEnd(), replacementText }]; } + /** + * Autofix for `foo instanceof Foo` → `foo.isInstanceOf(Foo)`. + * + * @param node The binary `instanceof` expression node. + * @returns A single Autofix replacing the entire `foo instanceof Foo` text. + */ + fixInteropJsInstanceOfExpression(node: ts.BinaryExpression): Autofix[] { + // left-hand and right-hand operands of the `instanceof` + const leftExpr = node.left; + const rightExpr = node.right; + + // build: leftExpr.isInstanceOf(rightExpr) + const callExpr = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(leftExpr, ts.factory.createIdentifier(IS_INSTANCE_OF)), + undefined, + [rightExpr] + ); + + // render back to source text + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, callExpr, node.getSourceFile()); + + return [{ replacementText, start: node.getStart(), end: node.getEnd() }]; + } + createReplacementForJsIndirectImportPropertyAccessExpression(node: ts.PropertyAccessExpression): Autofix[] { // Bypass eslint-check void this; @@ -4123,7 +4145,7 @@ export class Autofixer { const propertyAccessExpr = node.expression as ts.PropertyAccessExpression; const newCallExpr = this.createJSInvokeCallExpression(propertyAccessExpr.expression, INVOKE_METHOD, [ ts.factory.createStringLiteral(propertyAccessExpr.name.text), - ...newArgs || [] + ...(newArgs || []) ]); if (!newCallExpr) { @@ -4132,7 +4154,7 @@ export class Autofixer { return this.printer.printNode(ts.EmitHint.Unspecified, newCallExpr, node.getSourceFile()); } default: { - const callExpr = this.createJSInvokeCallExpression(node.expression, INVOKE, [...newArgs || []]); + const callExpr = this.createJSInvokeCallExpression(node.expression, INVOKE, [...(newArgs || [])]); if (!callExpr) { return undefined; @@ -4150,7 +4172,7 @@ export class Autofixer { return `${base}.${GET_PROPERTY_BY_NAME}('${propName}')`; } else if (ts.isNewExpression(node)) { const newArgs = this.createArgs(node.arguments); - const newCallExpr = this.createJSInvokeCallExpression(node.expression, INSTANTIATE, [...newArgs || []]); + const newCallExpr = this.createJSInvokeCallExpression(node.expression, INSTANTIATE, [...(newArgs || [])]); if (!newCallExpr) { return undefined; @@ -4215,9 +4237,9 @@ export class Autofixer { this.modVarName = newVarName; } const propertyName = originalName || symbolName; - const constructDeclInfo: string[] = isLoad ? - [this.modVarName, ES_VALUE, LOAD] : - [symbolName, this.modVarName, GET_PROPERTY_BY_NAME]; + const constructDeclInfo: string[] = isLoad + ? [this.modVarName, ES_VALUE, LOAD] + : [symbolName, this.modVarName, GET_PROPERTY_BY_NAME]; const newVarDecl = Autofixer.createVariableForInteropImport( constructDeclInfo[0], constructDeclInfo[1], @@ -4602,18 +4624,18 @@ export class Autofixer { } private static createExactObjectInitializer(type: ts.TypeLiteralNode): ts.ObjectLiteralExpression { - const properties = type.members. - filter((member): member is ts.PropertySignature => { + const properties = type.members + .filter((member): member is ts.PropertySignature => { return ts.isPropertySignature(member); - }). - map((member) => { + }) + .map((member) => { const initializer = Autofixer.createInitializerForPropertySignature(member); if (initializer) { return ts.factory.createPropertyAssignment(member.name, initializer); } return null; - }). - filter((property): property is ts.PropertyAssignment => { + }) + .filter((property): property is ts.PropertyAssignment => { return property !== null; }); @@ -4740,7 +4762,7 @@ export class Autofixer { const newCallExpr = this.createJSInvokeCallExpression(accessedProperty, INVOKE_METHOD, [ ts.factory.createStringLiteral(ident.text), - ...newArgs || [] + ...(newArgs || []) ]); if (!newCallExpr) { diff --git a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts index ceb9d389fc..cb8d0468d5 100644 --- a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts +++ b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts @@ -22,6 +22,7 @@ export const LENGTH = 'length'; export const INVOKE = 'invoke'; export const INVOKE_METHOD = 'invokeMethod'; export const TO_PROMISE = 'toPromise'; +export const IS_INSTANCE_OF = 'isInstanceOf'; export const REFLECT_PROPERTIES = [ 'get', @@ -58,7 +59,8 @@ export const OBJECT_PROPERTIES = [ 'isFrozen', 'isSealed' ]; -export const USE_STATIC = '\'use static\''; + +export const USE_STATIC = "'use static'"; export const OBJECT_LITERAL = 'Object'; export const REFLECT_LITERAL = 'Reflect'; export const NONE = 'none'; diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json index 3fc1baeadf..2e7b935be0 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json @@ -105,4 +105,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json index 157682563b..392ce7c30e 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json @@ -191,4 +191,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.args.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.args.json index 66fb88f859..6958168fef 100755 --- a/ets2panda/linter/test/interop/no_await_js_promise.ets.args.json +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.args.json @@ -14,6 +14,8 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" } } diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json index 7201a52ae1..13cd6170a9 100644 --- a/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.arkts2.json @@ -1,18 +1,4 @@ { - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], "result": [ { "line": 16, diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.autofix.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.autofix.json new file mode 100644 index 0000000000..5254337c77 --- /dev/null +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.autofix.json @@ -0,0 +1,278 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 89, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 605, + "end": 693, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 89 + }, + { + "start": 693, + "end": 693, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./no_await_js_promise_export');\nlet p = GeneratedImportVar_1.getPropertyByName('p');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet pFuncCall = GeneratedImportVar_1.getPropertyByName('pFuncCall');\nlet arrowFunc = GeneratedImportVar_1.getPropertyByName('arrowFunc');\nlet pArrowCall = GeneratedImportVar_1.getPropertyByName('pArrowCall');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 89 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 10, + "endLine": 19, + "endColumn": 17, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 742, + "end": 743, + "replacementText": "p.toPromise()", + "line": 19, + "column": 10, + "endLine": 19, + "endColumn": 17 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 10, + "endLine": 23, + "endColumn": 21, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 800, + "end": 805, + "replacementText": "foo.invoke().toPromise()", + "line": 23, + "column": 10, + "endLine": 23, + "endColumn": 21 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 10, + "endLine": 27, + "endColumn": 25, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 860, + "end": 869, + "replacementText": "pFuncCall.toPromise()", + "line": 27, + "column": 10, + "endLine": 27, + "endColumn": 25 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 10, + "endLine": 35, + "endColumn": 26, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 990, + "end": 1000, + "replacementText": "pArrowCall.toPromise()", + "line": 35, + "column": 10, + "endLine": 35, + "endColumn": 26 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 12, + "endLine": 40, + "endColumn": 19, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 1067, + "end": 1068, + "replacementText": "p.toPromise()", + "line": 40, + "column": 12, + "endLine": 40, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 12, + "endLine": 44, + "endColumn": 27, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 1118, + "end": 1127, + "replacementText": "pFuncCall.toPromise()", + "line": 44, + "column": 12, + "endLine": 44, + "endColumn": 27 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 20, + "endLine": 48, + "endColumn": 21, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 3, + "endLine": 51, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 12, + "endLine": 50, + "endColumn": 28, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 1197, + "end": 1207, + "replacementText": "pArrowCall.toPromise()", + "line": 50, + "column": 12, + "endLine": 50, + "endColumn": 28 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 12, + "endLine": 54, + "endColumn": 23, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 1262, + "end": 1267, + "replacementText": "foo.invoke().toPromise()", + "line": 54, + "column": 12, + "endLine": 54, + "endColumn": 23 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 2, + "endLine": 60, + "endColumn": 2, + "problem": "FunctionExpression", + "autofix": [ + { + "start": 1278, + "end": 1338, + "replacementText": "async () => {\n console.log(\"IIFE result:\", await p);\n}", + "line": 58, + "column": 2, + "endLine": 60, + "endColumn": 2 + } + ], + "suggest": "", + "rule": "Use arrow functions instead of function expressions (arkts-no-func-expressions)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 31, + "endLine": 59, + "endColumn": 38, + "problem": "NoAwaitJsPromise", + "autofix": [ + { + "start": 1333, + "end": 1334, + "replacementText": "p.toPromise()", + "line": 59, + "column": 31, + "endLine": 59, + "endColumn": 38 + } + ], + "suggest": "", + "rule": "\"Await\" operator can't be used with interop objects (arkts-interop-js2s-await-js-promise)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.ets b/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.ets new file mode 100644 index 0000000000..a89d3e58d3 --- /dev/null +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.ets @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let GeneratedImportVar_1 = ESValue.load('./no_await_js_promise_export'); +let p = GeneratedImportVar_1.getPropertyByName('p'); +let foo = GeneratedImportVar_1.getPropertyByName('foo'); +let pFuncCall = GeneratedImportVar_1.getPropertyByName('pFuncCall'); +let arrowFunc = GeneratedImportVar_1.getPropertyByName('arrowFunc'); +let pArrowCall = GeneratedImportVar_1.getPropertyByName('pArrowCall'); + + +async function awaitPromise() { + return await p.toPromise(); +} + +async function awaitFunctionCall() { + return await foo.invoke().toPromise(); +} + +async function awaitFuncResult() { + return await pFuncCall.toPromise(); +} + +async function awaitArrowCall() { + return await arrowFunc(); +} + +async function awaitArrowResult() { + return await pArrowCall.toPromise(); +} + +class ExampleClass { + async classMethod() { + return await p.toPromise(); + } + + handler = async () => { + return await pFuncCall.toPromise(); + }; +} + +const exampleObj = { + async objMethod() { + return await pArrowCall.toPromise(); + }, + + arrowHandler: async () => { + return await foo.invoke().toPromise(); + } +}; + +(async () => { + console.log("IIFE result:", await p); +})(); + +(async () => { + console.log("IIFE Arrow result:", await arrowFunc()); +})(); \ No newline at end of file diff --git a/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.json new file mode 100644 index 0000000000..5d4c781348 --- /dev/null +++ b/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.json @@ -0,0 +1,188 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 5, + "endLine": 16, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 68, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 68, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 70, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 16, + "endLine": 24, + "endColumn": 28, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 16, + "endLine": 28, + "endColumn": 33, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 16, + "endLine": 32, + "endColumn": 31, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 16, + "endLine": 36, + "endColumn": 30, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 16, + "endLine": 40, + "endColumn": 32, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 9, + "endLine": 45, + "endColumn": 20, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 13, + "endLine": 51, + "endColumn": 4, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 54, + "column": 20, + "endLine": 54, + "endColumn": 21, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 3, + "endLine": 57, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 55, + "column": 9, + "endLine": 55, + "endColumn": 18, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 17, + "endLine": 61, + "endColumn": 4, + "problem": "LimitedReturnTypeInference", + "suggest": "", + "rule": "Function return type inference is limited (arkts-no-implicit-return-types)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.args.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.args.json index 3ef4496a81..571ee6bb76 100755 --- a/ets2panda/linter/test/interop/no_js_instanceof.ets.args.json +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.args.json @@ -14,6 +14,8 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" } } diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.autofix.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.autofix.json new file mode 100644 index 0000000000..c1c3153c90 --- /dev/null +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.autofix.json @@ -0,0 +1,352 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 88, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 605, + "end": 692, + "replacementText": "", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 88 + }, + { + "start": 692, + "end": 692, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./no_js_instanceof_file.js');\nlet Foo = GeneratedImportVar_1.getPropertyByName('Foo');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet CreatePerson = GeneratedImportVar_1.getPropertyByName('CreatePerson');\nlet a = GeneratedImportVar_1.getPropertyByName('a');\nlet b = GeneratedImportVar_1.getPropertyByName('b');\nlet MyNamespace = GeneratedImportVar_1.getPropertyByName('MyNamespace');\n", + "line": 16, + "column": 1, + "endLine": 16, + "endColumn": 88 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 4, + "endLine": 26, + "endColumn": 22, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "foo.isInstanceOf(Foo)", + "start": 766, + "end": 784, + "line": 26, + "column": 4, + "endLine": 26, + "endColumn": 22 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 4, + "endLine": 30, + "endColumn": 23, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "foo1.isInstanceOf(Foo)", + "start": 799, + "end": 818, + "line": 30, + "column": 4, + "endLine": 30, + "endColumn": 23 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 4, + "endLine": 34, + "endColumn": 23, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "foo.isInstanceOf(Foo1)", + "start": 829, + "end": 848, + "line": 34, + "column": 4, + "endLine": 34, + "endColumn": 23 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 28, + "endLine": 38, + "endColumn": 50, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 883, + "end": 905, + "replacementText": "CreatePerson.invoke(ESValue.wrap('xc'), ESValue.wrap(18))", + "line": 38, + "column": 28, + "endLine": 38, + "endColumn": 50 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 47, + "endLine": 38, + "endColumn": 49, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 902, + "end": 904, + "replacementText": "18.0", + "line": 38, + "column": 47, + "endLine": 38, + "endColumn": 49 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 4, + "endLine": 40, + "endColumn": 34, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "person.isInstanceOf(CreatePerson)", + "start": 910, + "end": 940, + "line": 40, + "column": 4, + "endLine": 40, + "endColumn": 34 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 45, + "column": 8, + "endLine": 45, + "endColumn": 38, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "person.isInstanceOf(CreatePerson)", + "start": 980, + "end": 1010, + "line": 45, + "column": 8, + "endLine": 45, + "endColumn": 38 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 8, + "endLine": 51, + "endColumn": 38, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "person.isInstanceOf(CreatePerson)", + "start": 1059, + "end": 1089, + "line": 51, + "column": 8, + "endLine": 51, + "endColumn": 38 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 12, + "endLine": 58, + "endColumn": 42, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "person.isInstanceOf(CreatePerson)", + "start": 1147, + "end": 1177, + "line": 58, + "column": 12, + "endLine": 58, + "endColumn": 42 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 4, + "endLine": 64, + "endColumn": 22, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "a.isInstanceOf(Array)", + "start": 1204, + "end": 1222, + "line": 64, + "column": 4, + "endLine": 64, + "endColumn": 22 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 4, + "endLine": 68, + "endColumn": 24, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "b().isInstanceOf(Array)", + "start": 1233, + "end": 1253, + "line": 68, + "column": 4, + "endLine": 68, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 4, + "endLine": 68, + "endColumn": 7, + "problem": "CallJSFunction", + "autofix": [ + { + "start": 1233, + "end": 1236, + "replacementText": "b.invoke()", + "line": 68, + "column": 4, + "endLine": 68, + "endColumn": 7 + } + ], + "suggest": "", + "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", + "severity": "ERROR" + }, + { + "line": 72, + "column": 36, + "endLine": 72, + "endColumn": 51, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 5, + "endLine": 74, + "endColumn": 37, + "problem": "InteropJsInstanceof", + "autofix": [ + { + "replacementText": "myDog.isInstanceOf(MyNamespace.Dog)", + "start": 1327, + "end": 1359, + "line": 74, + "column": 5, + "endLine": 74, + "endColumn": 37 + } + ], + "suggest": "", + "rule": "Usage of \"instanceof\" operator is not allowed with interop objects (arkts-interop-js2s-instanceof-js-type)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 22, + "endLine": 74, + "endColumn": 37, + "problem": "InteropJsObjectConditionJudgment", + "autofix": [ + { + "replacementText": "MyNamespace.getPropertyByName('Dog')", + "start": 1344, + "end": 1359, + "line": 74, + "column": 22, + "endLine": 74, + "endColumn": 37 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-condition-judgment)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.ets b/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.ets new file mode 100644 index 0000000000..729ddeb90e --- /dev/null +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.ets @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let GeneratedImportVar_1 = ESValue.load('./no_js_instanceof_file.js'); +let Foo = GeneratedImportVar_1.getPropertyByName('Foo'); +let foo = GeneratedImportVar_1.getPropertyByName('foo'); +let CreatePerson = GeneratedImportVar_1.getPropertyByName('CreatePerson'); +let a = GeneratedImportVar_1.getPropertyByName('a'); +let b = GeneratedImportVar_1.getPropertyByName('b'); +let MyNamespace = GeneratedImportVar_1.getPropertyByName('MyNamespace'); + + +class Foo1 {} + +let foo1 = new Foo1() + +if(foo1 instanceof Foo1) { + +} + +if(foo.isInstanceOf(Foo)) { + +} + +if(foo1.isInstanceOf(Foo)) { + +} + +if(foo.isInstanceOf(Foo1)) { + +} + +let person: CreatePerson = CreatePerson.invoke(ESValue.wrap('xc'), ESValue.wrap(18.0)) + +if(person.isInstanceOf(CreatePerson)) { + +} + +function test1(): void { + if(person.isInstanceOf(CreatePerson)) { + + } +} + +const test2 = (): void => { + if(person.isInstanceOf(CreatePerson)) { + + } +} + +class Test3 { + init(): void { + if(person.isInstanceOf(CreatePerson)) { + + } + } +} + +if(a.isInstanceOf(Array)) { + +} + +if(b().isInstanceOf(Array)) { + +} + +const myDog: MyNamespace.Dog = new MyNamespace.Dog('Buddy'); + +if (myDog.isInstanceOf(MyNamespace.Dog)) { + console.log("This is a Dog!"); +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.json new file mode 100644 index 0000000000..992f388c81 --- /dev/null +++ b/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.json @@ -0,0 +1,118 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 16, + "column": 5, + "endLine": 16, + "endColumn": 70, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 5, + "endLine": 17, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 19, + "column": 5, + "endLine": 19, + "endColumn": 74, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 52, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 19, + "endLine": 71, + "endColumn": 24, + "problem": "ClassAsObjectError", + "suggest": "", + "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", + "severity": "ERROR" + }, + { + "line": 75, + "column": 21, + "endLine": 75, + "endColumn": 26, + "problem": "ClassAsObjectError", + "suggest": "", + "rule": "Classes cannot be used as objects (arkts-no-classes-as-obj)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 36, + "endLine": 79, + "endColumn": 51, + "problem": "DynamicCtorCall", + "suggest": "", + "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", + "severity": "ERROR" + } + ] +} -- Gitee From 868b2e3eb227c78511be3e1662027a5fd7294dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=B6=E7=86=99?= Date: Tue, 27 May 2025 20:33:13 +0800 Subject: [PATCH 029/747] Fix issues with generic lambda expressions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC84ZP Description: See in issue Signed-off-by: 梁家熙 --- ets2panda/checker/ets/typeCheckingHelpers.cpp | 13 +-- .../lowering/scopesInit/scopesInitPhase.cpp | 13 ++- ets2panda/ir/ets/etsFunctionType.cpp | 12 +-- ets2panda/ir/ts/tsTypeParameter.cpp | 18 ++++ ets2panda/ir/ts/tsTypeParameter.h | 1 + .../ir/ts/tsTypeParameterDeclaration.cpp | 15 ++++ ets2panda/ir/ts/tsTypeParameterDeclaration.h | 1 + ets2panda/parser/ETSparser.cpp | 3 + ets2panda/parser/ETSparser.h | 10 ++- ets2panda/parser/ETSparserExpressions.cpp | 9 ++ ets2panda/parser/ETSparserTypes.cpp | 38 ++++++-- ets2panda/parser/TypedParser.cpp | 9 +- ets2panda/parser/TypedParser.h | 2 +- ets2panda/parser/expressionParser.cpp | 9 +- ets2panda/parser/statementParser.cpp | 4 + .../ast/parser/ets/generic_lambda_err1.ets | 28 ++++++ .../ast/parser/ets/generic_lambda_err2.ets | 42 +++++++++ .../ast/parser/ets/generic_lambda_err3.ets | 26 ++++++ .../test/runtime/ets/generic_lambda_1.ets | 58 ++++++++++++ .../test/runtime/ets/generic_lambda_2.ets | 48 ++++++++++ .../test/runtime/ets/generic_lambda_3.ets | 41 +++++++++ .../test/runtime/ets/generic_lambda_4.ets | 45 ++++++++++ .../test/runtime/ets/generic_lambda_5.ets | 41 +++++++++ .../test/runtime/ets/generic_lambda_6.ets | 90 +++++++++++++++++++ .../test/runtime/ets/generic_lambda_7.ets | 32 +++++++ ets2panda/varbinder/ETSBinder.cpp | 2 +- ets2panda/varbinder/scope.cpp | 2 +- ets2panda/varbinder/varbinder.cpp | 1 + 28 files changed, 585 insertions(+), 28 deletions(-) create mode 100644 ets2panda/test/ast/parser/ets/generic_lambda_err1.ets create mode 100644 ets2panda/test/ast/parser/ets/generic_lambda_err2.ets create mode 100644 ets2panda/test/ast/parser/ets/generic_lambda_err3.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_1.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_2.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_3.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_4.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_5.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_6.ets create mode 100644 ets2panda/test/runtime/ets/generic_lambda_7.ets diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 1fa0493279..109c219a84 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -930,6 +930,13 @@ void ETSChecker::CheckFunctionSignatureAnnotations(const ArenaVectorParams()) { + std::ignore = SetUpParameterType(typeParam); + CheckAnnotations(typeParam->Annotations()); + } + } + for (auto *param : params) { if (param->IsETSParameterExpression()) { CheckAnnotations(param->AsETSParameterExpression()->Annotations()); @@ -939,12 +946,6 @@ void ETSChecker::CheckFunctionSignatureAnnotations(const ArenaVectorParams()) { - CheckAnnotations(typeParam->Annotations()); - } - } - if (returnTypeAnnotation != nullptr) { ValidateThisUsage(returnTypeAnnotation); CheckAnnotations(returnTypeAnnotation->Annotations()); diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 49bec80f6e..486ae0daa7 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -699,8 +699,13 @@ void ScopeInitTyped::VisitTSTypeParameter(ir::TSTypeParameter *typeParam) void ScopeInitTyped::VisitTSTypeParameterDeclaration(ir::TSTypeParameterDeclaration *paramDecl) { - BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl); - Iterate(paramDecl); + if (VarBinder()->GetScope()->IsFunctionParamScope() && VarBinder()->GetScope()->Parent()->IsLocalScope()) { + BindScopeNode(VarBinder()->GetScope()->Parent()->AsLocalScope(), paramDecl); + Iterate(paramDecl); + } else { + BindScopeNode(VarBinder()->GetScope()->AsLocalScope(), paramDecl); + Iterate(paramDecl); + } } void ScopeInitTyped::VisitClassDefinition(ir::ClassDefinition *classDef) @@ -1133,7 +1138,9 @@ void InitScopesPhaseETS::VisitETSNewClassInstanceExpression(ir::ETSNewClassInsta void InitScopesPhaseETS::VisitTSTypeParameter(ir::TSTypeParameter *typeParam) { - if (typeParam->Name()->Variable() != nullptr) { + if (typeParam->Name()->Variable() != nullptr && + VarBinder()->GetScope()->FindLocal(typeParam->Name()->Name(), + varbinder::ResolveBindingOptions::ALL_VARIABLES) != nullptr) { return; } auto [decl, var] = diff --git a/ets2panda/ir/ets/etsFunctionType.cpp b/ets2panda/ir/ets/etsFunctionType.cpp index da4e93b20c..0287ab28f8 100644 --- a/ets2panda/ir/ets/etsFunctionType.cpp +++ b/ets2panda/ir/ets/etsFunctionType.cpp @@ -61,7 +61,13 @@ void ETSFunctionType::Dump(ir::SrcDumper *dumper) const for (auto *anno : Annotations()) { anno->Dump(dumper); } - dumper->Add("(("); + dumper->Add("("); + if (TypeParams() != nullptr) { + dumper->Add("<"); + TypeParams()->Dump(dumper); + dumper->Add(">"); + } + dumper->Add("("); for (auto *param : Params()) { param->Dump(dumper); if (param != Params().back()) { @@ -70,10 +76,6 @@ void ETSFunctionType::Dump(ir::SrcDumper *dumper) const } dumper->Add(")"); - if (TypeParams() != nullptr) { - TypeParams()->Dump(dumper); - } - if (ReturnType() != nullptr) { dumper->Add("=> "); ReturnType()->Dump(dumper); diff --git a/ets2panda/ir/ts/tsTypeParameter.cpp b/ets2panda/ir/ts/tsTypeParameter.cpp index 88d4b08855..584964e2d2 100644 --- a/ets2panda/ir/ts/tsTypeParameter.cpp +++ b/ets2panda/ir/ts/tsTypeParameter.cpp @@ -128,6 +128,24 @@ TSTypeParameter *TSTypeParameter::Construct(ArenaAllocator *allocator) return allocator->New(nullptr, nullptr, nullptr, allocator); } +TSTypeParameter *TSTypeParameter::Clone(ArenaAllocator *allocator, AstNode *parent) +{ + auto *clone = allocator->New( + name_->Clone(allocator, this), constraint_ == nullptr ? nullptr : constraint_->Clone(allocator, this), + defaultType_ == nullptr ? nullptr : defaultType_->Clone(allocator, this), allocator); + clone->SetParent(parent); + clone->SetRange(range_); + + if (!Annotations().empty()) { + ArenaVector annotationUsages {allocator->Adapter()}; + for (auto *annotationUsage : Annotations()) { + annotationUsages.push_back(annotationUsage->Clone(allocator, clone)->AsAnnotationUsage()); + } + clone->SetAnnotations(std::move(annotationUsages)); + } + return clone; +} + void TSTypeParameter::CopyTo(AstNode *other) const { auto otherImpl = other->AsTSTypeParameter(); diff --git a/ets2panda/ir/ts/tsTypeParameter.h b/ets2panda/ir/ts/tsTypeParameter.h index fff183fc3c..b52f3d52bb 100644 --- a/ets2panda/ir/ts/tsTypeParameter.h +++ b/ets2panda/ir/ts/tsTypeParameter.h @@ -93,6 +93,7 @@ public: } TSTypeParameter *Construct(ArenaAllocator *allocator) override; + TSTypeParameter *Clone(ArenaAllocator *allocator, AstNode *parent) override; void CopyTo(AstNode *other) const override; private: diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp index a236ed060c..10ae04783f 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp @@ -80,6 +80,21 @@ TSTypeParameterDeclaration *TSTypeParameterDeclaration::Construct(ArenaAllocator return allocator->New(std::move(params), 0); } +TSTypeParameterDeclaration *TSTypeParameterDeclaration::Clone(ArenaAllocator *allocator, AstNode *parent) +{ + ArenaVector params(allocator->Adapter()); + for (auto *param : params_) { + params.push_back(param->Clone(allocator, this)->AsTSTypeParameter()); + } + + auto *const clone = allocator->New(std::move(params), requiredParams_); + if (parent != nullptr) { + clone->SetParent(parent); + } + clone->SetRange(range_); + return clone; +} + void TSTypeParameterDeclaration::CopyTo(AstNode *other) const { auto otherImpl = other->AsTSTypeParameterDeclaration(); diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.h b/ets2panda/ir/ts/tsTypeParameterDeclaration.h index 9fef5c44ff..ff3d2e2dcb 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.h +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.h @@ -77,6 +77,7 @@ public: void Compile(compiler::ETSGen *etsg) const override; checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; + TSTypeParameterDeclaration *Clone(ArenaAllocator *allocator, AstNode *parent) override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 6a1ca88c8b..e58b64c54c 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -1957,6 +1957,9 @@ ir::TSTypeParameter *ETSParser::ParseTypeParameter([[maybe_unused]] TypeAnnotati } auto saveLoc = Lexer()->GetToken().Start(); auto *paramIdent = ExpectIdentifier(false, false, *options); + if (paramIdent == nullptr) { + return nullptr; + } ir::TypeNode *constraint = nullptr; if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_EXTENDS) { diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 6c905bafe6..f44bb3d209 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -254,7 +254,8 @@ private: ir::TypeNode *ParseUnionType(ir::TypeNode *firstType); ir::TypeNode *GetTypeAnnotationOfPrimitiveType(lexer::TokenType tokenType, TypeAnnotationParsingOptions *options); ir::TypeNode *ParseWildcardType(TypeAnnotationParsingOptions *options); - ir::TypeNode *ParseFunctionType(TypeAnnotationParsingOptions *options); + ir::TypeNode *ParseFunctionType(TypeAnnotationParsingOptions *options, + ir::TSTypeParameterDeclaration *typeParamDecl = nullptr); ir::TypeNode *ParseETSTupleType(TypeAnnotationParsingOptions *options); ir::TypeNode *ParseTsArrayType(ir::TypeNode *typeNode, TypeAnnotationParsingOptions *options); bool ParseTriplePeriod(bool spreadTypePresent); @@ -266,9 +267,12 @@ private: bool IsArrowFunctionExpressionStart(); ir::ArrowFunctionExpression *ParseArrowFunctionExpression(); void ReportIfVarDeclaration(VariableParsingFlags flags) override; - ir::TypeNode *ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options); + ir::TypeNode *ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options, + ir::TSTypeParameterDeclaration *typeParamDecl = nullptr); std::pair GetTypeAnnotationFromToken(TypeAnnotationParsingOptions *options); - std::pair GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions *options); + std::pair GetTypeAnnotationFromArrowFunction(TypeAnnotationParsingOptions *options); + std::pair GetTypeAnnotationFromParentheses( + TypeAnnotationParsingOptions *options, ir::TSTypeParameterDeclaration *typeParamDecl = nullptr); ir::TypeNode *ParseLiteralIdent(TypeAnnotationParsingOptions *options); void ParseRightParenthesis(TypeAnnotationParsingOptions *options, ir::TypeNode *&typeAnnotation, lexer::LexerPosition savedPos); diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 7c0bd342e9..70d4452803 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -767,6 +767,15 @@ ir::Expression *ETSParser::ParseExpression(ExpressionParseFlags flags) return ParsePotentialExpressionSequence(yieldExpr, flags); } + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN) { + ir::Expression *expr = ParseGenericArrowFunction(true); + if (expr == nullptr) { + return AllocBrokenExpression(Lexer()->GetToken().Loc()); + } + + return expr; + } + ir::Expression *unaryExpressionNode = ParseUnaryOrPrefixUpdateExpression(flags); if ((flags & ExpressionParseFlags::INSTANCEOF) != 0) { ValidateInstanceOfExpression(unaryExpressionNode); diff --git a/ets2panda/parser/ETSparserTypes.cpp b/ets2panda/parser/ETSparserTypes.cpp index c88b813839..1214cfc390 100644 --- a/ets2panda/parser/ETSparserTypes.cpp +++ b/ets2panda/parser/ETSparserTypes.cpp @@ -185,7 +185,8 @@ ir::TypeNode *ETSParser::ParseWildcardType(TypeAnnotationParsingOptions *options return wildcardType; } -ir::TypeNode *ETSParser::ParseFunctionType(TypeAnnotationParsingOptions *options) +ir::TypeNode *ETSParser::ParseFunctionType(TypeAnnotationParsingOptions *options, + ir::TSTypeParameterDeclaration *typeParamDecl) { auto startLoc = Lexer()->GetToken().Start(); auto params = ParseFunctionParams(); @@ -210,7 +211,8 @@ ir::TypeNode *ETSParser::ParseFunctionType(TypeAnnotationParsingOptions *options ir::ScriptFunctionFlags throwMarker = ParseFunctionThrowMarker(false); auto *funcType = AllocNode( - ir::FunctionSignature(nullptr, std::move(params), returnTypeAnnotation, hasReceiver), throwMarker, Allocator()); + ir::FunctionSignature(typeParamDecl, std::move(params), returnTypeAnnotation, hasReceiver), throwMarker, + Allocator()); funcType->SetRange({startLoc, returnTypeAnnotation->End()}); return funcType; @@ -268,7 +270,8 @@ ir::TypeNode *ETSParser::ParseETSTupleType(TypeAnnotationParsingOptions *const o } // Helper function for ETSParser::GetTypeAnnotationFromToken(...) method -ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options) +ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptions *options, + ir::TSTypeParameterDeclaration *typeParamDecl) { auto savePos = Lexer()->Save(); ExpectToken(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); @@ -298,7 +301,7 @@ ir::TypeNode *ETSParser::ParsePotentialFunctionalType(TypeAnnotationParsingOptio GetContext().Status() |= (ParserStatus::ALLOW_DEFAULT_VALUE | ParserStatus::ALLOW_RECEIVER); // '(' is consumed in `ParseFunctionType` Lexer()->Rewind(savePos); - auto typeAnnotation = ParseFunctionType(options); + auto typeAnnotation = ParseFunctionType(options, typeParamDecl); GetContext().Status() ^= (ParserStatus::ALLOW_DEFAULT_VALUE | ParserStatus::ALLOW_RECEIVER); return typeAnnotation; } @@ -341,6 +344,9 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota case lexer::TokenType::PUNCTUATOR_BACK_TICK: { return std::make_pair(ParseMultilineString(), true); } + case lexer::TokenType::PUNCTUATOR_LESS_THAN: { + return GetTypeAnnotationFromArrowFunction(options); + } case lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS: { return GetTypeAnnotationFromParentheses(options); } @@ -356,11 +362,31 @@ std::pair ETSParser::GetTypeAnnotationFromToken(TypeAnnota } } -std::pair ETSParser::GetTypeAnnotationFromParentheses(TypeAnnotationParsingOptions *options) +std::pair ETSParser::GetTypeAnnotationFromArrowFunction(TypeAnnotationParsingOptions *options) +{ + ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LESS_THAN); + lexer::LexerPosition savedPos = Lexer()->Save(); + + auto typeParamDeclOptions = TypeAnnotationParsingOptions::NO_OPTS; + ir::TSTypeParameterDeclaration *typeParamDecl = ParseTypeParameterDeclaration(&typeParamDeclOptions); + if (typeParamDecl == nullptr) { + Lexer()->Rewind(savedPos); + return {nullptr, true}; + } + + if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + Lexer()->Rewind(savedPos); + return {nullptr, true}; + } + return GetTypeAnnotationFromParentheses(options, typeParamDecl); +} + +std::pair ETSParser::GetTypeAnnotationFromParentheses( + TypeAnnotationParsingOptions *options, ir::TSTypeParameterDeclaration *typeParamDecl) { auto startLoc = Lexer()->GetToken().Start(); - ir::TypeNode *typeAnnotation = ParsePotentialFunctionalType(options); + ir::TypeNode *typeAnnotation = ParsePotentialFunctionalType(options, typeParamDecl); if (typeAnnotation != nullptr) { typeAnnotation->SetStart(startLoc); return std::make_pair(typeAnnotation, true); diff --git a/ets2panda/parser/TypedParser.cpp b/ets2panda/parser/TypedParser.cpp index f826f53499..fa4c1f417a 100644 --- a/ets2panda/parser/TypedParser.cpp +++ b/ets2panda/parser/TypedParser.cpp @@ -221,7 +221,7 @@ ir::Statement *TypedParser::ParseModuleDeclaration([[maybe_unused]] StatementPar return ParseModuleOrNamespaceDeclaration(startLoc); } -ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction() +ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction(bool isThrowError) { ArrowFunctionContext arrowFunctionContext(this, false); @@ -232,6 +232,10 @@ ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction() ir::TSTypeParameterDeclaration *typeParamDecl = ParseTypeParameterDeclaration(&typeParamDeclOptions); if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + if (isThrowError) { + LogError(diagnostic::UNEXPECTED_TOKEN_EXPECTED_PARAM, + {TokenToString(lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS)}); + } return nullptr; } @@ -251,6 +255,9 @@ ir::ArrowFunctionExpression *TypedParser::ParseGenericArrowFunction() } if (Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_ARROW) { + if (isThrowError) { + LogError(diagnostic::UNEXPECTED_TOKEN_EXPECTED_PARAM, {TokenToString(lexer::TokenType::PUNCTUATOR_ARROW)}); + } return nullptr; } diff --git a/ets2panda/parser/TypedParser.h b/ets2panda/parser/TypedParser.h index 8101ab7123..226f8052e6 100644 --- a/ets2panda/parser/TypedParser.h +++ b/ets2panda/parser/TypedParser.h @@ -41,7 +41,7 @@ protected: ArenaVector ParseTypeLiteralOrInterfaceBody(); void CheckObjectTypeForDuplicatedProperties(ir::Expression *key, ArenaVector &members); - ir::ArrowFunctionExpression *ParseGenericArrowFunction(); + ir::ArrowFunctionExpression *ParseGenericArrowFunction(bool isThrowError = false); ir::TSTypeAssertion *ParseTypeAssertion(); ir::TSTypeParameterInstantiation *ParseTypeParameterInstantiation(TypeAnnotationParsingOptions *options); diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 37c03683eb..65d7398c58 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -328,7 +328,10 @@ ir::ArrowFunctionExpression *ParserImpl::ParseArrowFunctionExpressionBody(ArrowF ExpectToken(lexer::TokenType::PUNCTUATOR_RIGHT_BRACE); endLoc = body->End(); } - + if ((GetContext().Status() & ParserStatus::FUNCTION_HAS_RETURN_STATEMENT) != 0) { + arrowFunctionContext->AddFlag(ir::ScriptFunctionFlags::HAS_RETURN); + GetContext().Status() ^= ParserStatus::FUNCTION_HAS_RETURN_STATEMENT; + } // clang-format off funcNode = AllocNode( Allocator(), ir::ScriptFunction::ScriptFunctionData { @@ -572,6 +575,10 @@ ir::Expression *ParserImpl::ParseAssignmentExpressionHelper() ir::Expression *ParserImpl::CreateBinaryAssignmentExpression(ir::Expression *assignmentExpression, ir::Expression *lhsExpression, lexer::TokenType tokenType) { + if (assignmentExpression == nullptr) { + assignmentExpression = AllocBrokenExpression(Lexer()->GetToken().Loc()); + } + auto *binaryAssignmentExpression = AllocNode(lhsExpression, assignmentExpression, tokenType); diff --git a/ets2panda/parser/statementParser.cpp b/ets2panda/parser/statementParser.cpp index ff4089f8bd..86f766bedc 100644 --- a/ets2panda/parser/statementParser.cpp +++ b/ets2panda/parser/statementParser.cpp @@ -711,6 +711,10 @@ ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags) } ir::Expression *exprNode = ParseExpression(ExpressionParseFlags::ACCEPT_COMMA); + if (exprNode == nullptr) { // Error processing. + return AllocBrokenStatement(Lexer()->GetToken().Loc()); + } + context_.Status() = savedStatus; lexer::SourcePosition endPos = exprNode->End(); diff --git a/ets2panda/test/ast/parser/ets/generic_lambda_err1.ets b/ets2panda/test/ast/parser/ets/generic_lambda_err1.ets new file mode 100644 index 0000000000..78a4f357d9 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/generic_lambda_err1.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo = < (): void => {} +} + +/* @@? 17:15 Error SyntaxError: Unexpected token '<<'. */ +/* @@? 17:17 Error SyntaxError: Unexpected token 'T'. */ +/* @@? 17:17 Error TypeError: Unresolved reference T */ +/* @@? 17:17 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@? 17:22 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 17:22 Error SyntaxError: Expected '=>', got 'identification literal'. */ +/* @@? 17:22 Error TypeError: Unresolved reference : */ +/* @@? 17:24 Error SyntaxError: Unexpected token 'void'. */ +/* @@? 17:29 Error SyntaxError: Unexpected token '=>'. */ diff --git a/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets b/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets new file mode 100644 index 0000000000..637801af9a --- /dev/null +++ b/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo1 = (p: T): T => p; + foo1("1", 2) + foo1("1", 2) + + let foo2 = (p: T): T! =>p; + + let foo3 = (p: T): T => p; + + let foo4 = (p: T, q: U): T => p; + foo4(1) + foo4(1) + foo4(1, 1) +} + +/* @@? 18:5 Error TypeError: Expected 1 arguments, got 2. */ +/* @@? 18:5 Error TypeError: No matching call signature for ("1", int) */ +/* @@? 19:5 Error TypeError: Expected 1 type arguments, got 2 . */ +/* @@? 19:5 Error TypeError: No matching call signature for ("1", int) */ +/* @@? 21:32 Error TypeError: Type 'T' is not compatible with the enclosing method's return type 'NonNullable' */ +/* @@? 23:20 Error TypeError: Duplicate type parameter 'T'. */ +/* @@? 26:5 Error TypeError: Expected 2 arguments, got 1. */ +/* @@? 26:5 Error TypeError: No matching call signature for (int) */ +/* @@? 27:5 Error TypeError: Expected 2 arguments, got 1. */ +/* @@? 27:5 Error TypeError: No matching call signature for (int) */ +/* @@? 28:5 Error TypeError: No matching call signature for (int, int) */ +/* @@? 28:26 Error TypeError: Type 'int' is not compatible with type 'String' at index 2 */ diff --git a/ets2panda/test/ast/parser/ets/generic_lambda_err3.ets b/ets2panda/test/ast/parser/ets/generic_lambda_err3.ets new file mode 100644 index 0000000000..533f3f5761 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/generic_lambda_err3.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let foo1 = +let foo2 = () +function main() { + let foo3 = + let foo4 = () +} + +/* @@? 17:1 Error SyntaxError: Unexpected token, expected '('. */ +/* @@? 18:1 Error SyntaxError: Unexpected token, expected '=>'. */ +/* @@? 20:5 Error SyntaxError: Unexpected token, expected '('. */ +/* @@? 21:1 Error SyntaxError: Unexpected token, expected '=>'. */ diff --git a/ets2panda/test/runtime/ets/generic_lambda_1.ets b/ets2panda/test/runtime/ets/generic_lambda_1.ets new file mode 100644 index 0000000000..c91f324d5f --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_1.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo1 = (p: T): T => p; + + // Explicitly deducing generics + assertEQ(foo1(1), 1) + assertEQ(foo1(1.5), 1.5) + assertEQ(foo1(false), false) + assertEQ(foo1("123"), "123") + + let foo1res1: [int, string] = foo1<[int, string]>([123, "123"]) + assertEQ(foo1res1[0] as int, 123) + assertEQ(foo1res1[1] as string, "123") + + let foo1res2: int[] = foo1([1, 2, 3]) + assertEQ(foo1res2[0], 1) + assertEQ(foo1res2[1], 2) + assertEQ(foo1res2[2], 3) + + let foo1res3: [[int, string], int[]] = foo1<[[int, string], int[]]>([foo1res1, foo1res2]) + assertEQ(foo1res3[0][0], 123) + assertEQ(foo1res3[0][1], "123") + assertEQ(foo1res3[1][0], 1) + assertEQ(foo1res3[1][1], 2) + assertEQ(foo1res3[1][2], 3) + + let foo1res4: ()=>void = foo1<()=>void>((): void=>{}) + foo1res4() + + // Implicit derivation of generics + assertEQ(foo1(1), 1) + assertEQ(foo1(1.5), 1.5) + assertEQ(foo1(false), false) + assertEQ(foo1("123"), "123") + + let foo1res5: Array = foo1([123, "123"]) + assertEQ(foo1res5[0] as int, 123) + assertEQ(foo1res5[1] as string, "123") + + let foo1res6: int[] = foo1([1, 2, 3]) + assertEQ(foo1res6[0], 1) + assertEQ(foo1res6[1], 2) + assertEQ(foo1res6[2], 3) +} diff --git a/ets2panda/test/runtime/ets/generic_lambda_2.ets b/ets2panda/test/runtime/ets/generic_lambda_2.ets new file mode 100644 index 0000000000..8eae59c053 --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_2.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo = (p: T, q: U): [T, U] => [p, q] + + // Explicitly deducing generics + let res1 = foo(1.0, "abc") + assertEQ(res1[0], 1.0) + assertEQ(res1[1], "abc") + + let res2 = foo(new Error(), null) + assertTrue(res2[0] instanceof Error) + assertEQ(res2[1], null) + + let res3 = foo<[Double, string], [Error, null]>(res1, res2) + assertEQ(res3[0][0], 1.0) + assertEQ(res3[0][1], "abc") + assertTrue(res3[1][0] instanceof Error) + assertEQ(res3[1][1], null) + + // Implicit derivation of generics + let res4 = foo(1.0, "abc") + assertEQ(res4[0], 1.0) + assertEQ(res4[1], "abc") + + let res5 = foo(new Error(), null) + assertTrue(res5[0] instanceof Error) + assertEQ(res5[1], null) + + let res6 = foo(res1, res2) + assertEQ(res6[0][0], 1.0) + assertEQ(res6[0][1], "abc") + assertTrue(res6[1][0] instanceof Error) + assertEQ(res6[1][1], null) +} diff --git a/ets2panda/test/runtime/ets/generic_lambda_3.ets b/ets2panda/test/runtime/ets/generic_lambda_3.ets new file mode 100644 index 0000000000..78ee055bb2 --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_3.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo = (p: T) : T => { + let t: T = p + return t + } + + // Explicitly deducing generics + let res1 = foo(1) + assertEQ(res1, 1) + + let res2 = foo(1.5) + assertEQ(res2, 1.5) + + let res3 = foo("abc") + assertEQ(res3, "abc") + + // Implicit derivation of generics + let res4 = foo(1) + assertEQ(res4, 1) + + let res5 = foo(1.5) + assertEQ(res5, 1.5) + + let res6 = foo("abc") + assertEQ(res6, "abc") +} diff --git a/ets2panda/test/runtime/ets/generic_lambda_4.ets b/ets2panda/test/runtime/ets/generic_lambda_4.ets new file mode 100644 index 0000000000..21ef60f39f --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_4.ets @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A {} +class B extends A {} + +function main() { + let foo = (p: T, q: U): int => { + if (p !== null && p !== undefined) { + return 0; + } else if (q !== null && q != undefined) { + return 1; + } else { + return 2; + } + } + + // Explicitly deducing generics + assertEQ(foo(new Object(), new Object()), 0) + assertEQ(foo(undefined, new Object()), 1) + assertEQ(foo(undefined, undefined), 2) + assertEQ(foo(new A(), new A()), 0) + assertEQ(foo(new B(), new A()), 0) + assertEQ(foo(new B(), new B()), 0) + + // Implicit derivation of generics + assertEQ(foo(new Object(), new Object()), 0) + assertEQ(foo(undefined, new Object()), 1) + assertEQ(foo(undefined, undefined), 2) + assertEQ(foo(new A(), new A()), 0) + assertEQ(foo(new B(), new A()), 0) + assertEQ(foo(new B(), new B()), 0) +} diff --git a/ets2panda/test/runtime/ets/generic_lambda_5.ets b/ets2panda/test/runtime/ets/generic_lambda_5.ets new file mode 100644 index 0000000000..42ebd796d8 --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_5.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let foo1 = (t: int) => { + return 1; + } + assertEQ(foo1(1), 1) + + let foo2 = (t: int) => { + return t; + } + assertEQ(foo2(1), 1) + assertEQ(foo2(100), 100) + + let foo3 = (t: T) => { + return t; + } + assertEQ(foo3(1), 1) + assertEQ(foo3("123"), "123") + + let foo4 = (t: T, u: U) => { + return t; + } + assertEQ(foo4(1, 1), 1) + assertEQ(foo4(100, 1), 100) + assertEQ(foo4(100, "abc"), 100) + assertEQ(foo4("abc", 100), "abc") +} diff --git a/ets2panda/test/runtime/ets/generic_lambda_6.ets b/ets2panda/test/runtime/ets/generic_lambda_6.ets new file mode 100644 index 0000000000..a9cbee07a9 --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_6.ets @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +// All testcases are set in top level without function +let foo1 = (p: T): T => p; + +// Explicitly deducing generics +assertEQ(foo1(1), 1) +assertEQ(foo1(1.5), 1.5) +assertEQ(foo1(false), false) +assertEQ(foo1("123"), "123") + +let foo1res1: [int, string] = foo1<[int, string]>([123, "123"]) +assertEQ(foo1res1[0] as int, 123) +assertEQ(foo1res1[1] as string, "123") + +let foo1res2: int[] = foo1([1, 2, 3]) +assertEQ(foo1res2[0], 1) +assertEQ(foo1res2[1], 2) +assertEQ(foo1res2[2], 3) + +let foo1res3: [[int, string], int[]] = foo1<[[int, string], int[]]>([foo1res1, foo1res2]) +assertEQ(foo1res3[0][0], 123) +assertEQ(foo1res3[0][1], "123") +assertEQ(foo1res3[1][0], 1) +assertEQ(foo1res3[1][1], 2) +assertEQ(foo1res3[1][2], 3) + +let foo1res4: ()=>void = foo1<()=>void>((): void=>{}) +foo1res4() + +// Implicit derivation of generics +assertEQ(foo1(1), 1) +assertEQ(foo1(1.5), 1.5) +assertEQ(foo1(false), false) +assertEQ(foo1("123"), "123") + +let foo1res5: Array = foo1([123, "123"]) +assertEQ(foo1res5[0] as int, 123) +assertEQ(foo1res5[1] as string, "123") + +let foo1res6: int[] = foo1([1, 2, 3]) +assertEQ(foo1res6[0], 1) +assertEQ(foo1res6[1], 2) +assertEQ(foo1res6[2], 3) + +let foo = (p: T, q: U): [T, U] => [p, q] + +// Explicitly deducing generics +let res1 = foo(1.0, "abc") +assertEQ(res1[0], 1.0) +assertEQ(res1[1], "abc") + +let res2 = foo(new Error(), null) +assertTrue(res2[0] instanceof Error) +assertEQ(res2[1], null) + +let res3 = foo<[Double, string], [Error, null]>(res1, res2) +assertEQ(res3[0][0], 1.0) +assertEQ(res3[0][1], "abc") +assertTrue(res3[1][0] instanceof Error) +assertEQ(res3[1][1], null) + +// Implicit derivation of generics +let res4 = foo(1.0, "abc") +assertEQ(res4[0], 1.0) +assertEQ(res4[1], "abc") + +let res5 = foo(new Error(), null) +assertTrue(res5[0] instanceof Error) +assertEQ(res5[1], null) + +let res6 = foo(res1, res2) +assertEQ(res6[0][0], 1.0) +assertEQ(res6[0][1], "abc") +assertTrue(res6[1][0] instanceof Error) +assertEQ(res6[1][1], null) diff --git a/ets2panda/test/runtime/ets/generic_lambda_7.ets b/ets2panda/test/runtime/ets/generic_lambda_7.ets new file mode 100644 index 0000000000..ab83a032ba --- /dev/null +++ b/ets2panda/test/runtime/ets/generic_lambda_7.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A {} + +function foo(f: (t: T) => T) { + let i1: number = 1.0 + assertEQ(f(i1), i1) + assertEQ(f(i1), i1) + let i2: string = "abc" + assertEQ(f(i2), i2) + assertEQ(f(i2), i2) + let i3: A = new A() + assertEQ(f(i3), i3) + assertEQ(f(i3), i3) +} + +function main() { + foo((t: T): T => t) +} diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0f9ae6db10..a303d2933e 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -150,7 +150,7 @@ void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicName } } - if (LookupInDebugInfoPlugin(ident)) { + if (ident->Variable() != nullptr || LookupInDebugInfoPlugin(ident)) { return; } diff --git a/ets2panda/varbinder/scope.cpp b/ets2panda/varbinder/scope.cpp index ed4d78ebdb..3b6029e614 100644 --- a/ets2panda/varbinder/scope.cpp +++ b/ets2panda/varbinder/scope.cpp @@ -484,7 +484,7 @@ Variable *FunctionParamScope::AddBinding([[maybe_unused]] ArenaAllocator *alloca [[maybe_unused]] Variable *currentVariable, [[maybe_unused]] Decl *newDecl, [[maybe_unused]] ScriptExtension extension) { - ES2PANDA_UNREACHABLE(); + return AddLocal(allocator, currentVariable, newDecl, extension); } Variable *AnnotationParamScope::AddBinding([[maybe_unused]] ArenaAllocator *allocator, diff --git a/ets2panda/varbinder/varbinder.cpp b/ets2panda/varbinder/varbinder.cpp index 0504029b7b..9256d02c86 100644 --- a/ets2panda/varbinder/varbinder.cpp +++ b/ets2panda/varbinder/varbinder.cpp @@ -488,6 +488,7 @@ void VarBinder::VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *f { if (func->TypeParams() != nullptr) { auto typeParamScopeCtx = LexicalScope::Enter(this, func->TypeParams()->Scope()); + ResolveReferences(func->TypeParams()); VisitScriptFunction(func); return; } -- Gitee From ede1ef27b39a147879d70ac5d337a2d5df5b1599 Mon Sep 17 00:00:00 2001 From: Vivien Voros Date: Tue, 3 Jun 2025 18:30:40 +0200 Subject: [PATCH 030/747] Increasing coverage of diagnostic errors - 2 Removing unnecessary, unused code Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCC0N Related Internal Issue: #26188 Change-Id: I839bf2a0948f06ae610934e874c845b08710abc3 Signed-off-by: Vivien Voros --- ets2panda/parser/ETSparser.cpp | 48 +++------------------------ ets2panda/parser/ETSparser.h | 3 +- ets2panda/parser/ETSparserClasses.cpp | 35 ------------------- ets2panda/parser/statementParser.cpp | 2 +- 4 files changed, 6 insertions(+), 82 deletions(-) diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 71fd3ae939..99039876c6 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -756,43 +756,6 @@ ir::TSTypeAliasDeclaration *ETSParser::ParseTypeAliasDeclaration() return typeAliasDecl; } -std::pair ETSParser::CheckDefaultParameters(const ir::ScriptFunction *const function) -{ - bool hasOptionalParameters = false; - bool hasRestParameter = false; - std::size_t requiredParametersNumber = 0U; - - for (auto *const it : function->Params()) { - auto const *const param = it->AsETSParameterExpression(); - - if (param->IsRestParameter()) { - hasRestParameter = true; - continue; - } - - if (hasRestParameter) { - LogError(diagnostic::REST_PARAM_LAST, {}, param->Start()); - } - - if (param->IsOptional()) { - hasOptionalParameters = true; - continue; - } - - if (hasOptionalParameters) { - LogError(diagnostic::REQUIRED_PARAM_AFTER_DEFAULT, {}, param->Start()); - } - - ++requiredParametersNumber; - } - - if (hasOptionalParameters && hasRestParameter) { - LogError(diagnostic::REST_AND_DEFAULT_SAME_TIME, {}, function->Start()); - } - - return std::make_pair(hasOptionalParameters, requiredParametersNumber); -} - std::string ETSParser::PrimitiveTypeToName(ir::PrimitiveType type) const { switch (type) { @@ -1361,7 +1324,8 @@ bool ETSParser::ParseNamedSpecifiesImport(ArenaVector *re auto *imported = ExpectIdentifier(); ir::Identifier *local = nullptr; - if (CheckModuleAsModifier() && Lexer()->TryEatTokenType(lexer::TokenType::KEYW_AS)) { + CheckModuleAsModifier(); + if (Lexer()->TryEatTokenType(lexer::TokenType::KEYW_AS)) { if (Lexer()->TryEatTokenType(lexer::TokenType::KEYW_DEFAULT)) { auto *exportedAnonyConst = AllocNode(imported, imported->Clone(Allocator(), nullptr)); exportedAnonyConst->SetDefault(); @@ -1422,9 +1386,7 @@ void ETSParser::ParseNameSpaceSpecifier(ArenaVector *specifiers, lexer::SourcePosition namespaceStart = Lexer()->GetToken().Start(); Lexer()->NextToken(); // eat `*` character - if (!CheckModuleAsModifier()) { - LogError(diagnostic::UNEXPECTED_TOKEN); - } + CheckModuleAsModifier(); // Note (oeotvos) As a temporary solution we allow the stdlib to use namespace import without an alias, but this // should be handled at some point. @@ -1487,13 +1449,11 @@ ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector * return nullptr; } -bool ETSParser::CheckModuleAsModifier() +void ETSParser::CheckModuleAsModifier() { if ((Lexer()->GetToken().Flags() & lexer::TokenFlags::HAS_ESCAPE) != 0U) { LogError(diagnostic::ESCAPE_SEQUENCES_IN_AS); } - - return true; } ir::AnnotatedExpression *ETSParser::GetAnnotatedExpressionFromParam() diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 6ca2d6d6c8..d1dd448c37 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -260,7 +260,6 @@ private: ir::TypeNode *ParseETSTupleType(TypeAnnotationParsingOptions *options); ir::TypeNode *ParseTsArrayType(ir::TypeNode *typeNode, TypeAnnotationParsingOptions *options); bool ParseTriplePeriod(bool spreadTypePresent); - std::pair CheckDefaultParameters(const ir::ScriptFunction *function); std::string PrimitiveTypeToName(ir::PrimitiveType type) const; std::string GetNameForTypeNode(const ir::TypeNode *typeAnnotation) const; std::string GetNameForETSUnionType(const ir::TypeNode *typeAnnotation) const; @@ -300,7 +299,7 @@ private: ir::AstNode *ParseJsDocInfoInInterfaceBody(); ir::AstNode *ParseAnnotationsInInterfaceBody(); void ParseNameSpaceSpecifier(ArenaVector *specifiers, bool isReExport = false); - bool CheckModuleAsModifier(); + void CheckModuleAsModifier(); bool IsFixedArrayTypeNode(ir::AstNode *node); ir::Expression *ParseFunctionParameterExpression(ir::AnnotatedExpression *paramIdent, bool isOptional); std::pair TypeAnnotationValue(ir::TypeNode *typeAnnotation); diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index ec767160ae..1a6aa6e0f2 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -113,11 +113,6 @@ ir::ModifierFlags ETSParser::ParseClassModifiers() while (IsClassModifier(Lexer()->GetToken().KeywordType())) { ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE; - lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags(); - if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) { - LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS); // Lexer will do it. - } - switch (Lexer()->GetToken().KeywordType()) { case lexer::TokenType::KEYW_STATIC: { currentFlag = ir::ModifierFlags::STATIC; @@ -201,11 +196,6 @@ std::tuple ETSParser::ParseClassMemberAccessModif return {ir::ModifierFlags::NONE, false, false}; } - lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags(); - if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) { - LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS); // Lexer will do it. - } - ir::ModifierFlags accessFlag = ir::ModifierFlags::NONE; const auto token = Lexer()->GetToken(); @@ -266,11 +256,6 @@ ir::ModifierFlags ETSParser::ParseClassFieldModifiers(bool seenStatic) ir::ModifierFlags currentFlag; - lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags(); - if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) { - LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS); // Lexer will do it. - } - switch (Lexer()->GetToken().KeywordType()) { case lexer::TokenType::KEYW_STATIC: { currentFlag = ir::ModifierFlags::STATIC; @@ -403,11 +388,6 @@ ir::ModifierFlags ETSParser::ParseClassMethodModifiers(bool seenStatic) ir::ModifierFlags currentFlag = ir::ModifierFlags::NONE; - lexer::TokenFlags tokenFlags = Lexer()->GetToken().Flags(); - if ((tokenFlags & lexer::TokenFlags::HAS_ESCAPE) != 0) { - LogError(diagnostic::KEYWORD_CONTAINS_ESCAPED_CHARS); // Lexer will do it. - } - currentFlag = ParseClassMethodModifierFlag(); if ((flags & currentFlag) != 0) { LogError(diagnostic::DUPLICATED_MODIFIER); @@ -854,16 +834,6 @@ ir::TSInterfaceDeclaration *ETSParser::ParseInterfaceBody(ir::Identifier *name, lexer::SourcePosition bodyStart = Lexer()->GetToken().Start(); auto members = ParseTypeLiteralOrInterface(); - - for (auto &member : members) { - if (member->Type() == ir::AstNodeType::CLASS_DECLARATION || - member->Type() == ir::AstNodeType::STRUCT_DECLARATION || - member->Type() == ir::AstNodeType::TS_ENUM_DECLARATION || - member->Type() == ir::AstNodeType::TS_INTERFACE_DECLARATION) { - LogError(diagnostic::IMPROPER_NESTING_INTERFACE); - } - } - auto *body = AllocNode(std::move(members)); body->SetRange({bodyStart, Lexer()->GetToken().End()}); @@ -1042,11 +1012,6 @@ ir::AstNode *ETSParser::ParseInterfaceField() ParseInterfaceModifiers(fieldModifiers, optionalField); auto *typeAnnotation = ParseInterfaceTypeAnnotation(name); - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_EQUAL && - Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { - LogError(diagnostic::INITIALIZERS_INTERFACE_PROPS); - Lexer()->NextToken(); // Error processing: eat '='. - } auto *field = AllocNode(name, nullptr, typeAnnotation->Clone(Allocator(), nullptr), fieldModifiers, Allocator(), false); if (optionalField) { diff --git a/ets2panda/parser/statementParser.cpp b/ets2panda/parser/statementParser.cpp index ff4089f8bd..b3d4d898ca 100644 --- a/ets2panda/parser/statementParser.cpp +++ b/ets2panda/parser/statementParser.cpp @@ -297,7 +297,7 @@ ir::Statement *ParserImpl::ParsePotentialExpressionStatement(StatementParsingFla ir::Statement *ParserImpl::ParseStructStatement([[maybe_unused]] StatementParsingFlags flags, ir::ClassDefinitionModifiers modifiers, ir::ModifierFlags modFlags) { - LogError(diagnostic::ILLEGAL_START_EXPRESSION); + LogError(diagnostic::ILLEGAL_START_STRUCT); return ParseStructDeclaration(modifiers, modFlags); } -- Gitee From 0af4d55b182d6da80f747e9d503fa6319121e6a5 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Thu, 29 May 2025 20:53:30 +0800 Subject: [PATCH 031/747] Fix for NosparseArray Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBH3B Test scenarios:new tests update to the linter Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 3 +++ ets2panda/linter/test/main/no_sparse_array.ets | 3 ++- .../linter/test/main/no_sparse_array.ets.arkts2.json | 10 ++++++++++ .../test/main/numeric_semantics2.ets.arkts2.json | 10 ++++++++++ .../test/main/numeric_semantics2.ets.autofix.json | 10 ++++++++++ .../test/main/numeric_semantics2.ets.migrate.json | 10 ++++++++++ .../test/sdkwhite/sdk_type_query.ets.arkts2.json | 10 ++++++++++ 7 files changed, 55 insertions(+), 1 deletion(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4caeea6c34..79a843b992 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -642,6 +642,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { * e.g. there is no element which is untyped object literals */ const arrayLitElements = arrayLitNode.elements; + if (this.options.arkts2 && !arrayLitType && arrayLitElements.length === 0) { + this.incrementCounters(node, FaultID.NosparseArray); + } for (const element of arrayLitElements) { const elementContextType = this.tsTypeChecker.getContextualType(element); if (ts.isObjectLiteralExpression(element)) { diff --git a/ets2panda/linter/test/main/no_sparse_array.ets b/ets2panda/linter/test/main/no_sparse_array.ets index 3298c36c92..a543274d46 100644 --- a/ets2panda/linter/test/main/no_sparse_array.ets +++ b/ets2panda/linter/test/main/no_sparse_array.ets @@ -14,4 +14,5 @@ */ let a = [1, , , 3]; -let b = []; \ No newline at end of file +let b = []; +let c:number[] = []; \ No newline at end of file diff --git a/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json b/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json index 2a8c937e9f..edf83e80e8 100644 --- a/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json @@ -53,6 +53,16 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 17, + "column": 9, + "endLine": 17, + "endColumn": 11, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json b/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json index f7e900af40..6348e6c1b1 100755 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.arkts2.json @@ -204,6 +204,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 44, + "column": 17, + "endLine": 44, + "endColumn": 19, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, { "line": 45, "column": 17, diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json b/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json index 2a6aa3c531..56b02d1556 100644 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.autofix.json @@ -419,6 +419,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 44, + "column": 17, + "endLine": 44, + "endColumn": 19, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, { "line": 45, "column": 17, diff --git a/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json b/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json index 6d6b2576f7..dcabd25e69 100644 --- a/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json +++ b/ets2panda/linter/test/main/numeric_semantics2.ets.migrate.json @@ -74,6 +74,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 46, + "column": 17, + "endLine": 46, + "endColumn": 19, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, { "line": 47, "column": 17, diff --git a/ets2panda/linter/test/sdkwhite/sdk_type_query.ets.arkts2.json b/ets2panda/linter/test/sdkwhite/sdk_type_query.ets.arkts2.json index 67a42975bf..7053b9055f 100755 --- a/ets2panda/linter/test/sdkwhite/sdk_type_query.ets.arkts2.json +++ b/ets2panda/linter/test/sdkwhite/sdk_type_query.ets.arkts2.json @@ -174,6 +174,16 @@ "rule": "\"new\" expression with dynamic constructor type is not supported (arkts-no-dynamic-ctor-call)", "severity": "ERROR" }, + { + "line": 44, + "column": 17, + "endLine": 44, + "endColumn": 19, + "problem": "NosparseArray", + "suggest": "", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", + "severity": "ERROR" + }, { "line": 48, "column": 14, -- Gitee From f3146d957a408975547d0f6fba76230d945fefda Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Tue, 3 Jun 2025 10:36:20 +0800 Subject: [PATCH 032/747] fix issue for arkts-no-structural-typing Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAO2K Test scenarios:new tests update to the linter Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 46 +++++++++++++++++++ .../linter/test/main/structural_identity.ets | 13 +++++- .../main/structural_identity.ets.arkts2.json | 10 ++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4caeea6c34..5e9fe67055 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -5152,6 +5152,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.options.arkts2 && this.tsUtils.needToDeduceStructuralIdentity(targetType, exprType, tsAsExpr.expression, true) ) { + if (this.isExemptedAsExpression(tsAsExpr)) { + return; + } if (!this.tsUtils.isObject(exprType)) { this.incrementCounters(node, FaultID.StructuralIdentity); } @@ -5160,6 +5163,41 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handleNoTuplesArrays(node, targetType, exprType); this.handleObjectLiteralAssignmentToClass(tsAsExpr); } + + private isExemptedAsExpression(node: ts.AsExpression): boolean { + if (!ts.isElementAccessExpression(node.expression)) { + return false; + } + + const sourceType = this.tsTypeChecker.getTypeAtLocation(node.expression); + const targetType = this.tsTypeChecker.getTypeAtLocation(node.type); + const isRecordIndexAccess = (): boolean => { + const exprType = this.tsTypeChecker.getTypeAtLocation(node.expression); + const hasNumberIndex = !!exprType.getNumberIndexType(); + const hasStringIndex = !!exprType.getStringIndexType(); + const hasBooleanIndex = !!exprType.getProperty('true') || !!exprType.getProperty('false'); + + return hasNumberIndex || hasStringIndex || hasBooleanIndex; + }; + + if (isRecordIndexAccess()) { + const targetSymbol = targetType.getSymbol(); + if (targetSymbol && targetSymbol.getName() === 'Array') { + return true; + } + } + const primitiveFlags = ts.TypeFlags.Number | ts.TypeFlags.String | ts.TypeFlags.Boolean; + const objectFlag = ts.TypeFlags.Object; + return ( + sourceType.isUnion() && + sourceType.types.some((t) => { + return t.flags & primitiveFlags; + }) && + sourceType.types.some((t) => { + return t.flags & objectFlag; + }) + ); + } private handleAsExpressionImport(tsAsExpr: ts.AsExpression): void { if (!this.useStatic || !this.options.arkts2) { @@ -5946,6 +5984,14 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } if (this.tsUtils.needToDeduceStructuralIdentity(lhsType, rhsType, rhsExpr, isStrict)) { + if (ts.isNewExpression(rhsExpr) && ts.isIdentifier(rhsExpr.expression) && rhsExpr.expression.text === 'Promise') { + const isReturnStatement = ts.isReturnStatement(rhsExpr.parent); + const enclosingFunction = ts.findAncestor(rhsExpr, ts.isFunctionLike); + const isAsyncFunction = enclosingFunction && (enclosingFunction.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false); + if (isReturnStatement && isAsyncFunction) { + return; + } + } this.incrementCounters(field, FaultID.StructuralIdentity); } } diff --git a/ets2panda/linter/test/main/structural_identity.ets b/ets2panda/linter/test/main/structural_identity.ets index eae4133097..406a7fee8e 100644 --- a/ets2panda/linter/test/main/structural_identity.ets +++ b/ets2panda/linter/test/main/structural_identity.ets @@ -692,4 +692,15 @@ interface goodPerson extends IPerson { sayHello:()=> { return new MyObj2() } - } \ No newline at end of file + } + + async function foo1(): Promise{ + + return new Promise(()=>{ + + }); +} + +function foo2(rule:Record){ + let b:Array = rule['123'] as Array +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json index d621318a9c..89cd070221 100644 --- a/ets2panda/linter/test/main/structural_identity.ets.arkts2.json +++ b/ets2panda/linter/test/main/structural_identity.ets.arkts2.json @@ -1613,6 +1613,16 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 699, + "column": 14, + "endLine": 699, + "endColumn": 21, + "problem": "ConstructorIfaceFromSdk", + "suggest": "", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee From 543a545cf6285b56fee55fdedb0cbb8f9511dbf6 Mon Sep 17 00:00:00 2001 From: chenyiyuan Date: Tue, 20 May 2025 10:40:47 +0800 Subject: [PATCH 033/747] Support bcHars compile Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC9Q59 Signed-off-by: chenyiyuan Change-Id: I080c851fe8c75974874bfba7227acf1f240d8c54 --- .../build_system/src/build/base_mode.ts | 70 ++++++++++++++++--- .../src/build/compile_thread_worker.ts | 27 +++++-- .../build_system/src/build/compile_worker.ts | 34 ++++++--- ets2panda/driver/build_system/src/entry.ts | 5 +- .../driver/build_system/src/error_code.ts | 3 +- .../src/init/process_build_config.ts | 6 +- .../driver/build_system/src/pre_define.ts | 6 -- ets2panda/driver/build_system/src/types.ts | 64 ++++++++++++----- 8 files changed, 163 insertions(+), 52 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index 5d374555e6..d74d252dc9 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -31,7 +31,6 @@ import { import { ABC_SUFFIX, ARKTSCONFIG_JSON_FILE, - BUILD_MODE, DEFAULT_WOKER_NUMS, DECL_ETS_SUFFIX, DEPENDENCY_JSON_FILE, @@ -63,6 +62,8 @@ import { ArkTS, ArkTSGlobal, BuildConfig, + BUILD_MODE, + OHOS_MODULE_TYPE, CompileFileInfo, DependencyFileConfig, DependentModuleConfig, @@ -97,6 +98,7 @@ export abstract class BaseMode { isDebug: boolean; enableDeclgenEts2Ts: boolean; declgenV1OutPath: string | undefined; + declgenV2OutPath: string | undefined; declgenBridgeCodePath: string | undefined; hasMainModule: boolean; abcFiles: Set; @@ -106,6 +108,7 @@ export abstract class BaseMode { dependencyFileMap: DependencyFileConfig | null; isBuildConfigModified: boolean | undefined; hasCleanWorker: boolean; + byteCodeHar: boolean; constructor(buildConfig: BuildConfig) { this.buildConfig = buildConfig; @@ -118,6 +121,7 @@ export abstract class BaseMode { this.sourceRoots = buildConfig.sourceRoots as string[]; this.moduleRootPath = buildConfig.moduleRootPath as string; this.moduleType = buildConfig.moduleType as string; + this.byteCodeHar = buildConfig.byteCodeHar as boolean; this.dependentModuleList = buildConfig.dependentModuleList; this.isDebug = buildConfig.buildMode as string === BUILD_MODE.DEBUG; this.hasMainModule = buildConfig.hasMainModule; @@ -130,6 +134,7 @@ export abstract class BaseMode { this.enableDeclgenEts2Ts = buildConfig.enableDeclgenEts2Ts as boolean; this.declgenV1OutPath = buildConfig.declgenV1OutPath as string | undefined; + this.declgenV2OutPath = buildConfig.declgenV2OutPath as string | undefined; this.declgenBridgeCodePath = buildConfig.declgenBridgeCodePath as string | undefined; this.moduleInfos = new Map(); @@ -174,13 +179,13 @@ export abstract class BaseMode { arktsGlobal.compilerContext = arkts.Context.createFromString(source); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, true); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); let ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, true); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer, true); ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); @@ -240,21 +245,34 @@ export abstract class BaseMode { arktsGlobal.compilerContext = arkts.Context.createFromString(source); PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda proceedToState parsed'); let ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); this.logger.printInfo('plugin parsed finished'); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda proceedToState checked'); + + if (this.hasMainModule && (this.byteCodeHar || this.moduleType === OHOS_MODULE_TYPE.SHARED)) { + let filePathFromModuleRoot: string = path.relative(this.moduleRootPath, fileInfo.filePath); + let declEtsOutputPath: string = changeFileExtension( + path.join(this.declgenV2OutPath as string, this.packageName, filePathFromModuleRoot), + DECL_ETS_SUFFIX + ); + ensurePathExists(declEtsOutputPath); + + // Generate 1.2 declaration files(a temporary solution while binary import not pushed) + arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + } + ast = arkts.EtsScript.fromContext(); PluginDriver.getInstance().getPluginContext().setArkTSAst(ast); PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); this.logger.printInfo('plugin checked finished'); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, arktsGlobal.compilerContext.peer); this.logger.printInfo('es2panda bin generated'); } catch (error) { errorStatus = true; @@ -388,10 +406,13 @@ export abstract class BaseMode { dynamicDepModuleInfos: new Map(), staticDepModuleInfos: new Map(), declgenV1OutPath: module.declgenV1OutPath, + declgenV2OutPath: module.declgenV2OutPath, declgenBridgeCodePath: module.declgenBridgeCodePath, language: module.language, declFilesPath: module.declFilesPath, - dependencies: module.dependencies + dependencies: module.dependencies, + byteCodeHar: module.byteCodeHar, + abcPath: module.abcPath }; this.moduleInfos.set(module.packageName, moduleInfo); }); @@ -411,7 +432,9 @@ export abstract class BaseMode { staticDepModuleInfos: new Map(), compileFileInfos: [], declgenV1OutPath: this.declgenV1OutPath, - declgenBridgeCodePath: this.declgenBridgeCodePath + declgenV2OutPath: this.declgenV2OutPath, + declgenBridgeCodePath: this.declgenBridgeCodePath, + byteCodeHar: this.byteCodeHar }; } @@ -570,10 +593,17 @@ export abstract class BaseMode { return; } this.entryFiles.forEach((file: string) => { + // Skip the declaration files when compiling abc + if (file.endsWith(DECL_ETS_SUFFIX)) { + return; + } for (const [packageName, moduleInfo] of this.moduleInfos) { if (!file.startsWith(moduleInfo.moduleRootPath)) { continue; } + if (moduleInfo.moduleType === OHOS_MODULE_TYPE.HAR && moduleInfo.byteCodeHar) { + return; + } let filePathFromModuleRoot: string = path.relative(moduleInfo.moduleRootPath, file); let filePathInCache: string = path.join(this.cacheDir, moduleInfo.packageName, filePathFromModuleRoot); let abcFilePath: string = path.resolve(changeFileExtension(filePathInCache, ABC_SUFFIX)); @@ -598,6 +628,30 @@ export abstract class BaseMode { ); this.logger.printError(logData); }); + + this.collectAbcFileFromByteCodeHar(); + } + + protected collectAbcFileFromByteCodeHar(): void { + // the abc of the dependent bytecode har needs to be included When compiling hsp/hap + // but it's not required when compiling har + if (this.buildConfig.moduleType !== OHOS_MODULE_TYPE.HAR) { + return; + } + for (const [packageName, moduleInfo] of this.moduleInfos) { + if (!(moduleInfo.moduleType === OHOS_MODULE_TYPE.HAR && moduleInfo.byteCodeHar)) { + continue; + } + if (!moduleInfo.abcPath) { + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_ABC_FILE_MISSING_IN_BCHAR, + `abc file not found in bytecode har ${packageName}. ` + ); + this.logger.printError(logData); + continue; + } + this.abcFiles.add(moduleInfo.abcPath); + } } protected generateModuleInfos(): void { diff --git a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts index c8aaed5662..eef6db8d34 100644 --- a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts @@ -17,15 +17,20 @@ import { parentPort, workerData } from 'worker_threads'; import { CompileFileInfo, JobInfo } from '../types'; import * as fs from 'fs'; import * as path from 'path'; -import { ensurePathExists } from '../utils'; -import { KOALA_WRAPPER_PATH_FROM_SDK } from '../pre_define'; +import { + changeFileExtension, + ensurePathExists +} from '../utils'; +import { + DECL_ETS_SUFFIX, + KOALA_WRAPPER_PATH_FROM_SDK +} from '../pre_define'; import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; import { BuildConfig, + BUILD_MODE, + OHOS_MODULE_TYPE } from '../types'; -import { - BUILD_MODE -} from '../pre_define'; import { LogData, LogDataFactory, @@ -72,6 +77,18 @@ function compileAbc(jobInfo: JobInfo): void { arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, context); + if (config.hasMainModule && (config.byteCodeHar || config.moduleType === OHOS_MODULE_TYPE.SHARED)) { + let filePathFromModuleRoot: string = path.relative(config.moduleRootPath, fileInfo.filePath); + let declEtsOutputPath: string = changeFileExtension( + path.join(config.declgenV2OutPath as string, config.packageName, filePathFromModuleRoot), + DECL_ETS_SUFFIX + ); + ensurePathExists(declEtsOutputPath); + + // Generate 1.2 declaration files(a temporary solution while binary import not pushed) + arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + } + PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, context); diff --git a/ets2panda/driver/build_system/src/build/compile_worker.ts b/ets2panda/driver/build_system/src/build/compile_worker.ts index 38a1fcdb59..fdf1c651a5 100644 --- a/ets2panda/driver/build_system/src/build/compile_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_worker.ts @@ -16,15 +16,20 @@ import { CompileFileInfo, ModuleInfo } from '../types'; import * as fs from 'fs'; import * as path from 'path'; -import { ensurePathExists } from '../utils'; -import { KOALA_WRAPPER_PATH_FROM_SDK } from '../pre_define'; +import { + changeFileExtension, + ensurePathExists +} from '../utils'; +import { + DECL_ETS_SUFFIX, + KOALA_WRAPPER_PATH_FROM_SDK +} from '../pre_define'; import { PluginDriver, PluginHook } from '../plugins/plugins_driver'; import { BuildConfig, + BUILD_MODE, + OHOS_MODULE_TYPE } from '../types'; -import { - BUILD_MODE -} from '../pre_define'; import { LogData, LogDataFactory, @@ -70,13 +75,26 @@ process.on('message', (message: { PluginDriver.getInstance().getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer); + + if (buildConfig.hasMainModule && (buildConfig.byteCodeHar || buildConfig.moduleType === OHOS_MODULE_TYPE.SHARED)) { + let filePathFromModuleRoot: string = path.relative(buildConfig.moduleRootPath, fileInfo.filePath); + let declEtsOutputPath: string = changeFileExtension( + path.join(buildConfig.declgenV2OutPath as string, buildConfig.packageName, filePathFromModuleRoot), + DECL_ETS_SUFFIX + ); + ensurePathExists(declEtsOutputPath); + + // Generate 1.2 declaration files(a temporary solution while binary import not pushed) + arkts.generateStaticDeclarationsFromContext(declEtsOutputPath); + } + PluginDriver.getInstance().runPluginHook(PluginHook.CHECKED); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_BIN_GENERATED, arktsGlobal.compilerContext.peer); } catch (error) { errorStatus = true; if (error instanceof Error) { diff --git a/ets2panda/driver/build_system/src/entry.ts b/ets2panda/driver/build_system/src/entry.ts index f6cd7ef78e..c20fe57e7a 100644 --- a/ets2panda/driver/build_system/src/entry.ts +++ b/ets2panda/driver/build_system/src/entry.ts @@ -18,11 +18,10 @@ import * as path from 'path'; import { processBuildConfig } from './init/process_build_config'; import { BuildMode } from './build/build_mode'; -import { BUILD_TYPE_BUILD } from './pre_define'; import { Logger } from './logger'; import { ArkTSConfigGenerator } from './build/generate_arktsconfig'; import { PluginDriver } from './plugins/plugins_driver'; -import { BuildConfig } from './types'; +import { BuildConfig, BUILD_TYPE } from './types'; import { BuildFrameworkMode } from './build/build_framework_mode'; export async function build(projectConfig: BuildConfig): Promise { @@ -40,7 +39,7 @@ export async function build(projectConfig: BuildConfig): Promise { } else if (projectConfig.enableDeclgenEts2Ts === true) { let buildMode: BuildMode = new BuildMode(buildConfig); await buildMode.generateDeclaration(); - } else if (projectConfig.buildType === BUILD_TYPE_BUILD) { + } else if (projectConfig.buildType === BUILD_TYPE.BUILD) { let buildMode: BuildMode = new BuildMode(buildConfig); await buildMode.run(); } diff --git a/ets2panda/driver/build_system/src/error_code.ts b/ets2panda/driver/build_system/src/error_code.ts index 5a0dc72b4c..ed2562f43a 100644 --- a/ets2panda/driver/build_system/src/error_code.ts +++ b/ets2panda/driver/build_system/src/error_code.ts @@ -34,5 +34,6 @@ export enum ErrorCode { BUILDSYSTEM_DECLGEN_FAIL = '11410013', BUILDSYSTEM_LOAD_HASH_CACHE_FAIL = '11410014', BUILDSYSTEM_Dependency_Analyze_FAIL = '11410015', - BUILDSYSTEM_Dependency_Analyzer_NOT_FOUND_FAIL = '11410016' + BUILDSYSTEM_Dependency_Analyzer_NOT_FOUND_FAIL = '11410016', + BUILDSYSTEM_ABC_FILE_MISSING_IN_BCHAR = '11410017', } diff --git a/ets2panda/driver/build_system/src/init/process_build_config.ts b/ets2panda/driver/build_system/src/init/process_build_config.ts index 596b32486d..2f77380538 100644 --- a/ets2panda/driver/build_system/src/init/process_build_config.ts +++ b/ets2panda/driver/build_system/src/init/process_build_config.ts @@ -23,7 +23,6 @@ import { } from '../utils'; import { PluginDriver } from '../plugins/plugins_driver'; import { - BUILD_MODE, KOALA_WRAPPER_PATH_FROM_SDK, PANDA_SDK_PATH_FROM_SDK, PROJECT_BUILD_CONFIG_FILE @@ -34,7 +33,10 @@ import { Logger } from '../logger'; import { ErrorCode } from '../error_code'; -import { BuildConfig } from '../types'; +import { + BuildConfig, + BUILD_MODE +} from '../types'; export function processBuildConfig(projectConfig: BuildConfig): BuildConfig { let buildConfig: BuildConfig = { diff --git a/ets2panda/driver/build_system/src/pre_define.ts b/ets2panda/driver/build_system/src/pre_define.ts index a51032f4a7..0b42278beb 100644 --- a/ets2panda/driver/build_system/src/pre_define.ts +++ b/ets2panda/driver/build_system/src/pre_define.ts @@ -25,12 +25,6 @@ export const ETS_SUFFIX: string = '.ets'; export const TS_SUFFIX: string = '.ts'; export const ABC_SUFFIX: string = '.abc'; -export const BUILD_TYPE_BUILD: string = 'build'; -export enum BUILD_MODE { - DEBUG = 'Debug', - RELEASE = 'Release' -}; - export enum LANGUAGE_VERSION { ARKTS_1_2 = '1.2', ARKTS_1_1 = '1.1', diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index 91255055f1..0afb84da07 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -13,14 +13,31 @@ * limitations under the License. */ +export enum BUILD_MODE { + DEBUG = 'Debug', + RELEASE = 'Release' +}; + +export enum BUILD_TYPE { + BUILD = 'build', + PREVIEW = 'preview' +} + +export enum OHOS_MODULE_TYPE { + HAP = 'hap', + FEATURE = 'feature', + SHARED = 'shared', + HAR = 'har', +} + // ProjectConfig begins export interface PluginsConfig { [pluginName: string]: string; } export interface BuildBaseConfig { - buildType: 'build' | 'preview' | 'hotreload' | 'coldreload'; - buildMode: 'Debug' | 'Release'; + buildType: BUILD_TYPE; + buildMode: BUILD_MODE; hasMainModule: boolean; arkts: ArkTS; arktsGlobal: ArkTSGlobal; @@ -56,6 +73,7 @@ export interface ArkTS { }; proceedToState: Function; generateTsDeclarationsFromContext: Function; + generateStaticDeclarationsFromContext: Function; destroyConfig: Function; Es2pandaContextState: typeof Es2pandaContextState; MemInitialize: Function; @@ -75,9 +93,10 @@ export enum Es2pandaContextState { export interface ModuleConfig { packageName: string; - moduleType: string; + moduleType: OHOS_MODULE_TYPE; moduleRootPath: string; sourceRoots: string[]; + byteCodeHar: boolean; } export interface PathConfig { @@ -115,6 +134,7 @@ export interface FrameworkConfig { export interface DeclgenConfig { enableDeclgenEts2Ts: boolean; declgenV1OutPath?: string; + declgenV2OutPath?: string; declgenBridgeCodePath?: string; } @@ -132,8 +152,11 @@ export interface DependentModuleConfig { language: string; declFilesPath?: string; dependencies?: string[]; + abcPath?: string; declgenV1OutPath?: string; + declgenV2OutPath?: string; declgenBridgeCodePath?: string; + byteCodeHar: boolean; } export interface BuildConfig extends BuildBaseConfig, DeclgenConfig, LoggerConfig, ModuleConfig, PathConfig, FrameworkConfig { @@ -145,31 +168,34 @@ export interface BuildConfig extends BuildBaseConfig, DeclgenConfig, LoggerConfi // ProjectConfig ends export interface CompileFileInfo { - filePath: string, - dependentFiles: string[], - abcFilePath: string, - arktsConfigFile: string, - packageName: string, + filePath: string; + dependentFiles: string[]; + abcFilePath: string; + arktsConfigFile: string; + packageName: string; }; export interface ModuleInfo { - isMainModule: boolean, - packageName: string, - moduleRootPath: string, - moduleType: string, - sourceRoots: string[], - entryFile: string, - arktsConfigFile: string, - compileFileInfos: CompileFileInfo[], - declgenV1OutPath: string | undefined, - declgenBridgeCodePath: string | undefined, - dependencies?: string[] + isMainModule: boolean; + packageName: string; + moduleRootPath: string; + moduleType: string; + sourceRoots: string[]; + entryFile: string; + arktsConfigFile: string; + compileFileInfos: CompileFileInfo[]; + declgenV1OutPath: string | undefined; + declgenV2OutPath: string | undefined; + declgenBridgeCodePath: string | undefined; + dependencies?: string[]; staticDepModuleInfos: Map; dynamicDepModuleInfos: Map; language?: string; declFilesPath?: string; + abcPath?: string; frameworkMode?: boolean; useEmptyPackage?: boolean; + byteCodeHar: boolean; } export type SetupClusterOptions = { -- Gitee From 6ecb5e9dc0e135adfd5839e296bad4f367ff2daf Mon Sep 17 00:00:00 2001 From: nadolskyanton Date: Fri, 23 May 2025 11:51:56 +0300 Subject: [PATCH 034/747] Refactoring: moved annotations property copying Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC96I2 Description: Created lowering before Checker phase that handles annotations/properties copying Signed-off-by: nadolskyanton --- ets2panda/BUILD.gn | 2 + ets2panda/CMakeLists.txt | 2 + ets2panda/checker/ets/typeCheckingHelpers.cpp | 11 +-- .../lowering/ets/annotationCopyLowering.cpp | 87 +++++++++++++++++++ .../lowering/ets/annotationCopyLowering.h | 31 +++++++ .../ets/annotationCopyPostLowering.cpp | 68 +++++++++++++++ .../lowering/ets/annotationCopyPostLowering.h | 31 +++++++ ets2panda/compiler/lowering/phase.cpp | 4 + ets2panda/docs/lowering-phases.md | 5 ++ .../test/unit/annotations/standard_test.cpp | 64 +++++++------- 10 files changed, 263 insertions(+), 42 deletions(-) create mode 100644 ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp create mode 100644 ets2panda/compiler/lowering/ets/annotationCopyLowering.h create mode 100644 ets2panda/compiler/lowering/ets/annotationCopyPostLowering.cpp create mode 100644 ets2panda/compiler/lowering/ets/annotationCopyPostLowering.h diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 2ef3ae274a..66dc65f081 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -253,6 +253,8 @@ libes2panda_sources = [ "compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp", "compiler/lowering/ets/typeFromLowering.cpp", "compiler/lowering/ets/unionLowering.cpp", + "compiler/lowering/ets/annotationCopyLowering.cpp", + "compiler/lowering/ets/annotationCopyPostLowering.cpp", "compiler/lowering/phase.cpp", "compiler/lowering/plugin_phase.cpp", "compiler/lowering/resolveIdentifiers.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 0857184f54..224e91dd7e 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -320,6 +320,8 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/enumLowering.cpp compiler/lowering/ets/enumPostCheckLowering.cpp compiler/lowering/ets/setJumpTarget.cpp + compiler/lowering/ets/annotationCopyLowering.cpp + compiler/lowering/ets/annotationCopyPostLowering.cpp ir/astDump.cpp ir/srcDump.cpp ir/astNode.cpp diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 1fa0493279..f3f802e4a5 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -1109,10 +1109,7 @@ void ETSChecker::CheckSinglePropertyAnnotation(ir::AnnotationUsage *st, ir::Anno if (annoDecl->Properties().size() > 1) { LogError(diagnostic::ANNOT_MULTIPLE_FIELD, {st->GetBaseName()->Name()}, st->Start()); } - auto singleField = annoDecl->Properties().at(0)->AsClassProperty(); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto clone = singleField->TypeAnnotation()->Clone(ProgramAllocator(), param); - param->SetTypeAnnotation(clone); + ScopeContext scopeCtx(this, st->Scope()); param->Check(this); CheckAnnotationPropertyType(param); @@ -1126,9 +1123,6 @@ void ETSChecker::ProcessRequiredFields(ArenaUnorderedMapLogError(diagnostic::ANNOT_FIELD_NO_VAL, {entry.first}, st->Start()); continue; } - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *clone = entry.second->Clone(checker->ProgramAllocator(), st); - st->AddProperty(clone); } } @@ -1143,9 +1137,6 @@ void ETSChecker::CheckMultiplePropertiesAnnotation(ir::AnnotationUsage *st, util continue; } - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto clone = result->second->TypeAnnotation()->Clone(ProgramAllocator(), param); - param->SetTypeAnnotation(clone); ScopeContext scopeCtx(this, st->Scope()); param->Check(this); CheckAnnotationPropertyType(param); diff --git a/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp b/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp new file mode 100644 index 0000000000..d69ba30f65 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/annotationCopyLowering.cpp @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "annotationCopyLowering.h" + +#include "compiler/lowering/util.h" + +namespace ark::es2panda::compiler { + +std::string_view AnnotationCopyLowering::Name() const +{ + return "AnnotationCopyLowering"; +} + +void CopyAnnotationProperties(public_lib::Context *ctx, ir::AnnotationUsage *st) +{ + if (st->GetBaseName()->Variable() == nullptr || + !st->GetBaseName()->Variable()->Declaration()->Node()->IsAnnotationDeclaration()) { + // Will be handled in Checker + return; + } + + auto *annoDecl = st->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); + + if (annoDecl->Properties().size() < st->Properties().size()) { + // Will be handled in Checker + return; + } + + if (st->Properties().size() == 1 && + st->Properties().front()->AsClassProperty()->Id()->Name() == compiler::Signatures::ANNOTATION_KEY_VALUE) { + auto *param = st->Properties().front()->AsClassProperty(); + auto singleField = annoDecl->Properties().front()->AsClassProperty(); + auto clone = singleField->TypeAnnotation()->Clone(ctx->Allocator(), param); + param->SetTypeAnnotation(clone); + return; + } + + auto findProperty = [&props = annoDecl->Properties()](util::StringView name) { + auto it = std::find_if(props.begin(), props.end(), + [&name](ir::AstNode *node) { return node->AsClassProperty()->Id()->Name() == name; }); + return it == props.end() ? nullptr : (*it)->AsClassProperty(); + }; + + for (auto *it : st->Properties()) { + auto *param = it->AsClassProperty(); + auto *property = findProperty(param->Id()->Name()); + if (property == nullptr) { + // Will be handled in Checker + continue; + } + + auto *clone = property->TypeAnnotation()->Clone(ctx->Allocator(), param); + param->SetTypeAnnotation(clone); + } +} + +bool AnnotationCopyLowering::PerformForModule([[maybe_unused]] public_lib::Context *const ctx, + parser::Program *const program) +{ + program->Ast()->TransformChildrenRecursively( + // CC-OFFNXT(G.FMT.14-CPP) project code style + [ctx](ir::AstNode *ast) { + if (ast->IsAnnotationUsage()) { + CopyAnnotationProperties(ctx, ast->AsAnnotationUsage()); + } + + return ast; + }, + Name()); + + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/annotationCopyLowering.h b/ets2panda/compiler/lowering/ets/annotationCopyLowering.h new file mode 100644 index 0000000000..f290442b2f --- /dev/null +++ b/ets2panda/compiler/lowering/ets/annotationCopyLowering.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::compiler { + +class AnnotationCopyLowering : public PhaseForBodies { +public: + std::string_view Name() const override; + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; +}; + +} // namespace ark::es2panda::compiler + +#endif // ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_LOWERING_H diff --git a/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.cpp b/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.cpp new file mode 100644 index 0000000000..4e101eacaf --- /dev/null +++ b/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.cpp @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "annotationCopyPostLowering.h" + +#include "compiler/lowering/util.h" + +namespace ark::es2panda::compiler { + +std::string_view AnnotationCopyPostLowering::Name() const +{ + return "AnnotationCopyPostLowering"; +} + +void DoCopyAnnotationProperties(public_lib::Context *ctx, ir::AnnotationUsage *st) +{ + if (st->Properties().size() == 1 && + st->Properties().front()->AsClassProperty()->Id()->Name() == compiler::Signatures::ANNOTATION_KEY_VALUE) { + return; + } + + auto *annoDecl = st->GetBaseName()->Variable()->Declaration()->Node()->AsAnnotationDeclaration(); + + auto propertyExist = [&st](util::StringView name) { + return std::any_of(st->Properties().begin(), st->Properties().end(), + [name](ir::AstNode *property) { return property->AsClassProperty()->Id()->Name() == name; }); + }; + + for (auto *it : annoDecl->Properties()) { + auto *field = it->AsClassProperty(); + if (propertyExist(field->Id()->Name())) { + continue; + } + auto *clone = field->Clone(ctx->Allocator(), st); + st->AddProperty(clone); + } +} + +bool AnnotationCopyPostLowering::PerformForModule([[maybe_unused]] public_lib::Context *const ctx, + parser::Program *const program) +{ + program->Ast()->TransformChildrenRecursively( + // CC-OFFNXT(G.FMT.14-CPP) project code style + [ctx](ir::AstNode *ast) { + if (ast->IsAnnotationUsage()) { + DoCopyAnnotationProperties(ctx, ast->AsAnnotationUsage()); + } + + return ast; + }, + Name()); + + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.h b/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.h new file mode 100644 index 0000000000..4af067acb0 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/annotationCopyPostLowering.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_POST_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_POST_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::compiler { + +class AnnotationCopyPostLowering : public PhaseForBodies { +public: + std::string_view Name() const override; + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; +}; + +} // namespace ark::es2panda::compiler + +#endif // ES2PANDA_COMPILER_LOWERING_ANNOTATION_COPY_POST_LOWERING_H diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index a871d1f962..7525670200 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -17,6 +17,8 @@ #include "checker/checker.h" #include "compiler/lowering/checkerPhase.h" #include "compiler/lowering/ets/asyncMethodLowering.h" +#include "compiler/lowering/ets/annotationCopyLowering.h" +#include "compiler/lowering/ets/annotationCopyPostLowering.h" #include "compiler/lowering/ets/ambientLowering.h" #include "compiler/lowering/ets/arrayLiteralLowering.h" #include "compiler/lowering/ets/bigintLowering.h" @@ -116,11 +118,13 @@ std::vector GetETSPhaseList() new CapturedVariables, new SetJumpTargetPhase, new CFGBuilderPhase, + new AnnotationCopyLowering, // please DO NOT change order of these two phases: checkerPhase and pluginsAfterCheck new CheckerPhase, // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them new PluginPhase {g_pluginsAfterCheck, ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}, new ConvertPrimitiveCastMethodCall, + new AnnotationCopyPostLowering, new DynamicImportLowering, new AsyncMethodLowering, new DeclareOverloadLowering, diff --git a/ets2panda/docs/lowering-phases.md b/ets2panda/docs/lowering-phases.md index b328a5bf57..392626e840 100644 --- a/ets2panda/docs/lowering-phases.md +++ b/ets2panda/docs/lowering-phases.md @@ -651,6 +651,11 @@ becomes s.compareTo("test") > 0 ``` +- `AnnotationCopyLowering` and `AnnotationCopyPostLowering` handle copying of annotation properties. These phases ensure that annotation properties are properly copied and processed during the lowering phase. The phases work together to: + 1. Copy annotation properties from annotation declarations to their usages + 2. Process and validate annotation properties + 3. Ensure proper handling of annotation metadata in the generated code + - `PartialExportClassGen` generates declarations for `Partial` where `C` is exported ``` export class C { diff --git a/ets2panda/test/unit/annotations/standard_test.cpp b/ets2panda/test/unit/annotations/standard_test.cpp index fde486b3b6..8cf5681999 100644 --- a/ets2panda/test/unit/annotations/standard_test.cpp +++ b/ets2panda/test/unit/annotations/standard_test.cpp @@ -71,11 +71,11 @@ public: {"authorAge", "35.000000"}, {"testBool", "0"}, {"favorColor", "1"}, - {"color", "MyClass$ClassAuthor$color$12"}, - {"reviewers", "MyClass$ClassAuthor$reviewers$14"}, - {"reviewersAge", "MyClass$ClassAuthor$reviewersAge$15"}, - {"testBools", "MyClass$ClassAuthor$testBools$13"}, - {"mutiArray", "MyClass$ClassAuthor$mutiArray$11"}, + {"color", "MyClass$ClassAuthor$color$8"}, + {"reviewers", "MyClass$ClassAuthor$reviewers$9"}, + {"reviewersAge", "MyClass$ClassAuthor$reviewersAge$10"}, + {"testBools", "MyClass$ClassAuthor$testBools$11"}, + {"mutiArray", "MyClass$ClassAuthor$mutiArray$15"}, }}, }; AnnotationEmitTest::CheckRecordAnnotations(program, recordName, expectedClassAnnotations); @@ -87,13 +87,13 @@ public: const AnnotationMap expectedFuncAnnotations = { {"ClassAuthor", { - {"mutiArray", "MyClass.foo:void;$ClassAuthor$mutiArray$19"}, - {"color", "MyClass.foo:void;$ClassAuthor$color$20"}, - {"testBools", "MyClass.foo:void;$ClassAuthor$testBools$21"}, - {"reviewers", "MyClass.foo:void;$ClassAuthor$reviewers$22"}, + {"mutiArray", "MyClass.foo:void;$ClassAuthor$mutiArray$23"}, + {"color", "MyClass.foo:void;$ClassAuthor$color$16"}, + {"testBools", "MyClass.foo:void;$ClassAuthor$testBools$19"}, + {"reviewers", "MyClass.foo:void;$ClassAuthor$reviewers$17"}, {"favorColor", "1"}, {"testBool", "0"}, - {"reviewersAge", "MyClass.foo:void;$ClassAuthor$reviewersAge$23"}, + {"reviewersAge", "MyClass.foo:void;$ClassAuthor$reviewersAge$18"}, {"authorAge", "35.000000"}, {"authorName", "Jim"}, }}, @@ -116,35 +116,35 @@ public: std::vector {std::string("ETSGLOBAL$ClassAuthor$mutiArray$4"), std::string("ETSGLOBAL$ClassAuthor$mutiArray$5"), std::string("ETSGLOBAL$ClassAuthor$mutiArray$6")}}, - {"MyClass$ClassAuthor$color$12", std::vector {COLOR_OPTION_0, COLOR_OPTION_1}}, - {"MyClass$ClassAuthor$reviewers$14", + {"MyClass$ClassAuthor$color$8", std::vector {COLOR_OPTION_0, COLOR_OPTION_1}}, + {"MyClass$ClassAuthor$reviewers$9", std::vector {std::string("Bob"), std::string("Jim"), std::string("Tom")}}, - {"MyClass$ClassAuthor$reviewersAge$15", std::vector {AGE_18, AGE_21, AGE_32}}, - {"MyClass$ClassAuthor$testBools$13", std::vector {false, true, false}}, - {"MyClass$ClassAuthor$mutiArray$8", std::vector {VALUE_1, VALUE_2, VALUE_3}}, - {"MyClass$ClassAuthor$mutiArray$9", std::vector {VALUE_4, VALUE_5, VALUE_6}}, - {"MyClass$ClassAuthor$mutiArray$10", std::vector {VALUE_7, VALUE_8, VALUE_9}}, - {"MyClass$ClassAuthor$mutiArray$11", - std::vector {std::string("MyClass$ClassAuthor$mutiArray$8"), - std::string("MyClass$ClassAuthor$mutiArray$9"), - std::string("MyClass$ClassAuthor$mutiArray$10")}}, - {"MyClass.foo:void;$ClassAuthor$color$20", + {"MyClass$ClassAuthor$reviewersAge$10", std::vector {AGE_18, AGE_21, AGE_32}}, + {"MyClass$ClassAuthor$testBools$11", std::vector {false, true, false}}, + {"MyClass$ClassAuthor$mutiArray$12", std::vector {VALUE_1, VALUE_2, VALUE_3}}, + {"MyClass$ClassAuthor$mutiArray$13", std::vector {VALUE_4, VALUE_5, VALUE_6}}, + {"MyClass$ClassAuthor$mutiArray$14", std::vector {VALUE_7, VALUE_8, VALUE_9}}, + {"MyClass$ClassAuthor$mutiArray$15", + std::vector {std::string("MyClass$ClassAuthor$mutiArray$12"), + std::string("MyClass$ClassAuthor$mutiArray$13"), + std::string("MyClass$ClassAuthor$mutiArray$14")}}, + {"MyClass.foo:void;$ClassAuthor$color$16", std::vector {COLOR_OPTION_0, COLOR_OPTION_1}}, - {"MyClass.foo:void;$ClassAuthor$reviewers$22", + {"MyClass.foo:void;$ClassAuthor$reviewers$17", std::vector {std::string("Bob"), std::string("Jim"), std::string("Tom")}}, - {"MyClass.foo:void;$ClassAuthor$reviewersAge$23", + {"MyClass.foo:void;$ClassAuthor$reviewersAge$18", std::vector {AGE_18, AGE_21, AGE_32}}, - {"MyClass.foo:void;$ClassAuthor$testBools$21", std::vector {false, true, false}}, - {"MyClass.foo:void;$ClassAuthor$mutiArray$16", + {"MyClass.foo:void;$ClassAuthor$testBools$19", std::vector {false, true, false}}, + {"MyClass.foo:void;$ClassAuthor$mutiArray$20", std::vector {VALUE_1, VALUE_2, VALUE_3}}, - {"MyClass.foo:void;$ClassAuthor$mutiArray$17", + {"MyClass.foo:void;$ClassAuthor$mutiArray$21", std::vector {VALUE_4, VALUE_5, VALUE_6}}, - {"MyClass.foo:void;$ClassAuthor$mutiArray$18", + {"MyClass.foo:void;$ClassAuthor$mutiArray$22", std::vector {VALUE_7, VALUE_8, VALUE_9}}, - {"MyClass.foo:void;$ClassAuthor$mutiArray$19", - std::vector {std::string("MyClass.foo:void;$ClassAuthor$mutiArray$16"), - std::string("MyClass.foo:void;$ClassAuthor$mutiArray$17"), - std::string("MyClass.foo:void;$ClassAuthor$mutiArray$18")}}, + {"MyClass.foo:void;$ClassAuthor$mutiArray$23", + std::vector {std::string("MyClass.foo:void;$ClassAuthor$mutiArray$20"), + std::string("MyClass.foo:void;$ClassAuthor$mutiArray$21"), + std::string("MyClass.foo:void;$ClassAuthor$mutiArray$22")}}, }; AnnotationEmitTest::CheckLiteralArrayTable(program, expectedLiteralArrayTable); -- Gitee From 05b2c6d25c30adac214550c1dfdc0d98792c7864 Mon Sep 17 00:00:00 2001 From: zhangkai366 Date: Tue, 20 May 2025 16:17:13 +0800 Subject: [PATCH 035/747] Fix the bug that performance is not defined Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCL6B Test: grammar&ut Signed-off-by: zhangkai366 Change-Id: I9d68839b48fc0f1549a66df9612fb504e5a263ab --- arkguard/src/utils/PrinterTimeAndMemUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/arkguard/src/utils/PrinterTimeAndMemUtils.ts b/arkguard/src/utils/PrinterTimeAndMemUtils.ts index 3d5b31c78f..b8b714f8f8 100644 --- a/arkguard/src/utils/PrinterTimeAndMemUtils.ts +++ b/arkguard/src/utils/PrinterTimeAndMemUtils.ts @@ -17,6 +17,7 @@ import * as fs from 'fs'; import path from 'path'; import type { IOptions } from '../configs/IOptions'; import type { IPrinterOption } from '../configs/INameObfuscationOption'; +import { performance } from 'perf_hooks'; import { performanceTimeAndMemPrinter } from '../ArkObfuscator'; import { printerTimeAndMemDataConfig } from '../initialization/Initializer'; -- Gitee From bcf4b634066845369db593fa0d1ac81342256092 Mon Sep 17 00:00:00 2001 From: Vivien Voros Date: Wed, 28 May 2025 15:06:06 +0200 Subject: [PATCH 036/747] Increasing coverage of diagnostic errors - 1 Add new tests to increase code coverage Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCBOJ Related Internal Issue: #26188 Change-Id: I07857beeb1680c64f4313d95ec42a7c3e01d7731 Signed-off-by: Vivien Voros --- .../parser/ets/ambient_class_missing_body.ets | 19 ++++++++++++++ .../ets/asteriks_in_selective_binding.ets | 21 ++++++++++++++++ .../parser/ets/declare_ambient_context.ets | 20 +++++++++++++++ ets2panda/test/ast/parser/ets/do_while.ets | 23 +++++++++++++++++ .../ets/export_default_multiple_specifier.ets | 21 ++++++++++++++++ .../ast/parser/ets/getter_not_abstract.ets | 25 +++++++++++++++++++ .../ets/getter_setter_modifier_limited.ets | 21 ++++++++++++++++ .../modules/invalid_namespace_import2.ets | 23 +++++++++++++++++ .../parser/ets/lexical_dec_not_allowed.ets | 20 +++++++++++++++ .../parser/ets/readonly_interface_method.ets | 21 ++++++++++++++++ .../test/ast/parser/ets/rest_no_default.ets | 19 ++++++++++++++ .../test/ast/parser/ets/rest_no_optional.ets | 19 ++++++++++++++ .../parser/ets/type_alias_invalid_name.ets | 18 +++++++++++++ .../test/ast/parser/ts/test_generators.ts | 22 ++++++++++++++++ ..._lexical_dec_not_allowed_async_function.ts | 18 +++++++++++++ .../ts/test_lexical_dec_not_allowed_class.ts | 18 +++++++++++++ .../ast/parser/ts/test_strict_mode_func.ts | 19 ++++++++++++++ 17 files changed, 347 insertions(+) create mode 100644 ets2panda/test/ast/parser/ets/ambient_class_missing_body.ets create mode 100644 ets2panda/test/ast/parser/ets/asteriks_in_selective_binding.ets create mode 100644 ets2panda/test/ast/parser/ets/declare_ambient_context.ets create mode 100644 ets2panda/test/ast/parser/ets/do_while.ets create mode 100644 ets2panda/test/ast/parser/ets/export_default_multiple_specifier.ets create mode 100644 ets2panda/test/ast/parser/ets/getter_not_abstract.ets create mode 100644 ets2panda/test/ast/parser/ets/getter_setter_modifier_limited.ets create mode 100644 ets2panda/test/ast/parser/ets/import_tests/modules/invalid_namespace_import2.ets create mode 100644 ets2panda/test/ast/parser/ets/lexical_dec_not_allowed.ets create mode 100644 ets2panda/test/ast/parser/ets/readonly_interface_method.ets create mode 100644 ets2panda/test/ast/parser/ets/rest_no_default.ets create mode 100644 ets2panda/test/ast/parser/ets/rest_no_optional.ets create mode 100644 ets2panda/test/ast/parser/ets/type_alias_invalid_name.ets create mode 100644 ets2panda/test/ast/parser/ts/test_generators.ts create mode 100644 ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_async_function.ts create mode 100644 ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_class.ts create mode 100644 ets2panda/test/ast/parser/ts/test_strict_mode_func.ts diff --git a/ets2panda/test/ast/parser/ets/ambient_class_missing_body.ets b/ets2panda/test/ast/parser/ets/ambient_class_missing_body.ets new file mode 100644 index 0000000000..1428f6e5ba --- /dev/null +++ b/ets2panda/test/ast/parser/ets/ambient_class_missing_body.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare class B + + +/* @@? 20:1 Error SyntaxError: Ambient class declarations must have a body. */ diff --git a/ets2panda/test/ast/parser/ets/asteriks_in_selective_binding.ets b/ets2panda/test/ast/parser/ets/asteriks_in_selective_binding.ets new file mode 100644 index 0000000000..367d9d3f2b --- /dev/null +++ b/ets2panda/test/ast/parser/ets/asteriks_in_selective_binding.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { * } from './module'; + +/* @@? 16:10 Error SyntaxError: The '*' token is not allowed as a selective binding (between braces). */ +/* @@? 16:10 Error SyntaxError: Unexpected token '*'. */ +/* @@? 16:14 Error TypeError: Unresolved reference from */ +/* @@? 16:19 Error SyntaxError: Unexpected token './module'. */ diff --git a/ets2panda/test/ast/parser/ets/declare_ambient_context.ets b/ets2panda/test/ast/parser/ets/declare_ambient_context.ets new file mode 100644 index 0000000000..f7284c2aee --- /dev/null +++ b/ets2panda/test/ast/parser/ets/declare_ambient_context.ets @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable low or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +declare namespace A{ + declare function foo(): void +} + +/* @@? 17:5 Error SyntaxError: A 'declare' modifier cannot be used in an already ambient context. */ diff --git a/ets2panda/test/ast/parser/ets/do_while.ets b/ets2panda/test/ast/parser/ets/do_while.ets new file mode 100644 index 0000000000..a0256a02dc --- /dev/null +++ b/ets2panda/test/ast/parser/ets/do_while.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +do a + +/* @@? 16:4 Error TypeError: Unresolved reference a */ +/* @@? 24:1 Error SyntaxError: Unexpected token, expected 'while'. */ +/* @@? 24:1 Error SyntaxError: Unexpected token, expected '('. */ +/* @@? 24:1 Error SyntaxError: Unexpected token 'end of stream'. */ +/* @@? 24:1 Error SyntaxError: Missing condition in do while statement */ +/* @@? 24:1 Error SyntaxError: Expected ')', got 'end of stream'. */ diff --git a/ets2panda/test/ast/parser/ets/export_default_multiple_specifier.ets b/ets2panda/test/ast/parser/ets/export_default_multiple_specifier.ets new file mode 100644 index 0000000000..dfd5025564 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/export_default_multiple_specifier.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function myFunc(): void {} +function foo(): void {} + +export default {myFunc as default, foo as default} + +/* @@? 22:1 Error SyntaxError: export default is not allowed to export multiple specifiers. */ diff --git a/ets2panda/test/ast/parser/ets/getter_not_abstract.ets b/ets2panda/test/ast/parser/ets/getter_not_abstract.ets new file mode 100644 index 0000000000..aca30c3be7 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/getter_not_abstract.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface A { + color : string; + get color(): string { + return "red" + } +} + +/* @@? 17:5 Error TypeError: Function color is already declared. */ +/* @@? 18:9 Error TypeError: Variable 'color' has already been declared. */ +/* @@? 18:14 Error SyntaxError: Getter and setter methods must be abstracts in the interface body. */ diff --git a/ets2panda/test/ast/parser/ets/getter_setter_modifier_limited.ets b/ets2panda/test/ast/parser/ets/getter_setter_modifier_limited.ets new file mode 100644 index 0000000000..cb74e1bad8 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/getter_setter_modifier_limited.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Person { + private _age: number = 0; + async get age(): number { return this._age } +} + +/* @@? 18:11 Error SyntaxError: Modifiers of getter and setter are limited to ('abstract', 'static', 'final', 'override', 'native'). */ diff --git a/ets2panda/test/ast/parser/ets/import_tests/modules/invalid_namespace_import2.ets b/ets2panda/test/ast/parser/ets/import_tests/modules/invalid_namespace_import2.ets new file mode 100644 index 0000000000..c61d893c63 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/import_tests/modules/invalid_namespace_import2.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * \u0061s something from "./module" + +/* @@? 16:10 Error SyntaxError: Escape sequences are not allowed in keyword. */ +/* @@? 16:10 Error SyntaxError: Escape sequences are not allowed in 'as' keyword.*/ +/* @@? 16:10 Error SyntaxError: Expected 'as', got 'identification literal'. */ +/* @@? 16:18 Error SyntaxError: Unexpected token, expected 'from'. */ +/* @@? 16:28 Error SyntaxError: Unexpected token, expected string literal. */ +/* @@? 16:33 Error SyntaxError: Unexpected token './module'. */ diff --git a/ets2panda/test/ast/parser/ets/lexical_dec_not_allowed.ets b/ets2panda/test/ast/parser/ets/lexical_dec_not_allowed.ets new file mode 100644 index 0000000000..afbd9e8ed3 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/lexical_dec_not_allowed.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +while(true) function a (){}; + +/* @@? 16:13 Error SyntaxError: Nested functions are not allowed. */ +/* @@? 16:13 Error SyntaxError: Lexical declaration is not allowed in single statement context. */ +/* @@? 16:28 Error SyntaxError: Missing body in while statement */ diff --git a/ets2panda/test/ast/parser/ets/readonly_interface_method.ets b/ets2panda/test/ast/parser/ets/readonly_interface_method.ets new file mode 100644 index 0000000000..418b6c6ef1 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/readonly_interface_method.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +interface A { + readonly(): void {} +} + +/* @@? 17:5 Error SyntaxError: Modifier 'readonly' cannot be applied to an interface method. */ +/* @@? 17:13 Error SyntaxError: Expected 'method name', got '('. */ diff --git a/ets2panda/test/ast/parser/ets/rest_no_default.ets b/ets2panda/test/ast/parser/ets/rest_no_default.ets new file mode 100644 index 0000000000..2964b29db0 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/rest_no_default.ets @@ -0,0 +1,19 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable low or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function sum(...numbers: number = 0): number {} + +/* @@? 16:35 Error SyntaxError: Rest parameter cannot have the default value. */ +/* @@? 16:36 Error SyntaxError: Identifier is needed here. */ diff --git a/ets2panda/test/ast/parser/ets/rest_no_optional.ets b/ets2panda/test/ast/parser/ets/rest_no_optional.ets new file mode 100644 index 0000000000..2fe5e0e584 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/rest_no_optional.ets @@ -0,0 +1,19 @@ + +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable low or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +function sum(...numbers?: number[]): number {} + +/* @@? 17:24 Error SyntaxError: Rest parameter cannot have the default value. */ diff --git a/ets2panda/test/ast/parser/ets/type_alias_invalid_name.ets b/ets2panda/test/ast/parser/ets/type_alias_invalid_name.ets new file mode 100644 index 0000000000..9caf26990c --- /dev/null +++ b/ets2panda/test/ast/parser/ets/type_alias_invalid_name.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type var = number[] + +/* @@? 16:6 Error SyntaxError: Type alias name cannot be 'var'. */ diff --git a/ets2panda/test/ast/parser/ts/test_generators.ts b/ets2panda/test/ast/parser/ts/test_generators.ts new file mode 100644 index 0000000000..06fe8230f5 --- /dev/null +++ b/ets2panda/test/ast/parser/ts/test_generators.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +a: +/* @@ label */function* gen() { + yield 1; +} + +/* @@@ label Error SyntaxError: In strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement. */ +/* @@@ label Error SyntaxError: Generators can only be declared at the top level or inside a block. */ diff --git a/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_async_function.ts b/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_async_function.ts new file mode 100644 index 0000000000..b1817950d8 --- /dev/null +++ b/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_async_function.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +while (true) async /* @@ label */function a() { }; + +/* @@@ label Error SyntaxError: Lexical declaration is not allowed in single statement context. */ diff --git a/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_class.ts b/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_class.ts new file mode 100644 index 0000000000..823d5add6d --- /dev/null +++ b/ets2panda/test/ast/parser/ts/test_lexical_dec_not_allowed_class.ts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +while (true) /* @@ label */class a { }; + +/* @@@ label Error SyntaxError: Lexical declaration is not allowed in single statement context. */ diff --git a/ets2panda/test/ast/parser/ts/test_strict_mode_func.ts b/ets2panda/test/ast/parser/ts/test_strict_mode_func.ts new file mode 100644 index 0000000000..7f8e7cd258 --- /dev/null +++ b/ets2panda/test/ast/parser/ts/test_strict_mode_func.ts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +a: +/* @@ label */function foo() { } + +/* @@@ label Error SyntaxError: In strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement. */ -- Gitee From 43938523b75156aeab2688af2069bc504befa390 Mon Sep 17 00:00:00 2001 From: Torok Gergo Date: Tue, 3 Jun 2025 11:39:54 +0200 Subject: [PATCH 037/747] Fixing async assertion error Reason: Async methods with optional parameter emitted assertion error. Description: Replace SetAnnotations to AddAnnotations so the previous data doest'n get lost Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICC9SZ Signed-off-by: Torok Gergo --- ets2panda/compiler/core/ETSemitter.cpp | 2 +- .../test/runtime/ets/asyncWithDefaultParam.ets | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/runtime/ets/asyncWithDefaultParam.ets diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 3edebf6826..852fc67da7 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -291,7 +291,7 @@ void ETSEmitter::GenAnnotation() if (scriptFunc->IsAsyncFunc()) { std::vector annotations; annotations.push_back(GenAnnotationAsync(scriptFunc)); - func.metadata->SetAnnotations(std::move(annotations)); + func.metadata->AddAnnotations(annotations); } Program()->AddToFunctionTable(std::move(func)); } diff --git a/ets2panda/test/runtime/ets/asyncWithDefaultParam.ets b/ets2panda/test/runtime/ets/asyncWithDefaultParam.ets new file mode 100644 index 0000000000..1082ea3a1a --- /dev/null +++ b/ets2panda/test/runtime/ets/asyncWithDefaultParam.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +async function emitAsync1(args: int | undefined = 1): Promise {} +async function emitAsync2(args?: int): Promise {} -- Gitee From 511d84a3f8171bbed11e074926af08a18ae1350d Mon Sep 17 00:00:00 2001 From: Vsevolod Pukhov Date: Fri, 18 Apr 2025 16:32:56 +0300 Subject: [PATCH 038/747] Static initialization null-safety checks Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICBJ1U Signed-off-by: Vsevolod Pukhov --- ets2panda/compiler/core/ETSCompiler.cpp | 22 +++++---- ets2panda/compiler/core/ETSGen.cpp | 21 ++++++++ ets2panda/compiler/core/ETSGen.h | 9 ++++ .../test/runtime/ets/StaticInitNullChecks.ets | 49 +++++++++++++++++++ 4 files changed, 92 insertions(+), 9 deletions(-) create mode 100644 ets2panda/test/runtime/ets/StaticInitNullChecks.ets diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 86ee12f811..be12b648ee 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -1718,18 +1718,22 @@ void ETSCompiler::Compile(const ir::TSNonNullExpression *expr) const expr->Expr()->Compile(etsg); if (etsg->GetAccumulatorType()->PossiblyETSNullish()) { - auto arg = etsg->AllocReg(); - etsg->StoreAccumulator(expr, arg); - etsg->LoadAccumulator(expr, arg); + if (!etsg->GetAccumulatorType()->PossiblyETSNull()) { + etsg->EmitNullcheck(expr); + etsg->SetAccumulatorType(expr->OriginalType()); + } else { + auto arg = etsg->AllocReg(); + etsg->StoreAccumulator(expr, arg); - auto endLabel = etsg->AllocLabel(); + auto endLabel = etsg->AllocLabel(); - etsg->BranchIfNotNullish(expr, endLabel); - etsg->EmitNullishException(expr); + etsg->BranchIfNotNullish(expr, endLabel); + etsg->EmitNullishException(expr); - etsg->SetLabel(expr, endLabel); - etsg->LoadAccumulator(expr, arg); - etsg->AssumeNonNullish(expr, expr->OriginalType()); + etsg->SetLabel(expr, endLabel); + etsg->LoadAccumulator(expr, arg); + etsg->AssumeNonNullish(expr, expr->OriginalType()); + } } ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->OriginalType())); diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 004427936c..39cd26789b 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -390,11 +390,32 @@ void ETSGen::StoreStaticProperty(const ir::AstNode *const node, const checker::T } } +static bool StaticAccessRequiresReferenceSafetyCheck(const ir::AstNode *const node, const checker::Type *propType) +{ + if (propType->PossiblyETSUndefined()) { + return false; + } + auto parent = node->Parent(); + if (parent->IsMemberExpression()) { + return false; + } + if (parent->IsCallExpression() && parent->AsCallExpression()->Callee() == node) { + return false; + } + if (node->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { + return false; + } + return true; +} + void ETSGen::LoadStaticProperty(const ir::AstNode *const node, const checker::Type *propType, const util::StringView &fullName) { if (propType->IsETSReferenceType()) { Sa().Emit(node, fullName); + if (StaticAccessRequiresReferenceSafetyCheck(node, propType)) { + EmitNullcheck(node); + } } else if (IsWidePrimitiveType(propType)) { Sa().Emit(node, fullName); } else { diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index dcc6d78ab1..211722e558 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -96,6 +96,15 @@ public: void IsInstanceDynamic(const ir::BinaryExpression *node, VReg srcReg, VReg tgtReg); void EmitFailedTypeCastException(const ir::AstNode *node, VReg src, checker::Type const *target); + void EmitNullcheck([[maybe_unused]] const ir::AstNode *node) + { +#ifdef PANDA_WITH_ETS + Sa().Emit(node); +#else + ES2PANDA_UNREACHABLE(); +#endif // PANDA_WITH_ETS + } + void BinaryLogic(const ir::AstNode *node, lexer::TokenType op, VReg lhs); void BinaryArithmLogic(const ir::AstNode *node, lexer::TokenType op, VReg lhs); void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); diff --git a/ets2panda/test/runtime/ets/StaticInitNullChecks.ets b/ets2panda/test/runtime/ets/StaticInitNullChecks.ets new file mode 100644 index 0000000000..3a1c953562 --- /dev/null +++ b/ets2panda/test/runtime/ets/StaticInitNullChecks.ets @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + These tests should be not be affected by compile-time + nullsafety checks. Please adjust the code if compiler has actually + succeeded to figure out there is an unitialized value access. +*/ + +class A { + static x: object = B.getx() + static getx() { return A.x } +} + +class B { + static x: object = A.getx() + static getx() { return B.x } +} + +expectThrow(() => { A.getx() }, (e) => e instanceof NullPointerError) +expectThrow(() => { A.getx() }, (e) => e instanceof LinkerUnresolvedClassError) +expectThrow(() => { B.getx() }, (e) => e instanceof LinkerUnresolvedClassError) + +class C { + static x: string + + static { + cb() + C.x = "a" + } +} + +let cb: () => void +cb = () => { C.x } + +expectThrow(() => { new C() }, (e) => e instanceof NullPointerError) +expectThrow(() => { new C() }, (e) => e instanceof LinkerUnresolvedClassError) -- Gitee From edd34db30bd92d04be60aa3fb5bd12bcc4b764cf Mon Sep 17 00:00:00 2001 From: lihao Date: Thu, 22 May 2025 23:08:37 +0800 Subject: [PATCH 039/747] File-based hybrid compilation 1.2 Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICB371 Signed-off-by: lihao --- .../build_system/src/build/base_mode.ts | 24 ++++++-- .../src/build/compile_thread_worker.ts | 12 ++-- .../build_system/src/build/declgen_worker.ts | 4 +- .../src/build/generate_arktsconfig.ts | 59 +++++++++++++++---- .../driver/build_system/src/error_code.ts | 1 + 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index d74d252dc9..e1d65f97f6 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -338,8 +338,7 @@ export abstract class BaseMode { if (module.isMainModule) { return; } - module.language === LANGUAGE_VERSION.ARKTS_1_2 ? - staticDepModules.set(packageName, module) : dynamicDepModules.set(packageName, module); + this.collectDependencyModules(packageName, module, dynamicDepModules, staticDepModules); }); return [dynamicDepModules, staticDepModules]; } @@ -354,17 +353,32 @@ export abstract class BaseMode { ); this.logger.printErrorAndExit(logData); } else { - depModuleInfo.language === LANGUAGE_VERSION.ARKTS_1_2 ? - staticDepModules.set(packageName, depModuleInfo) : dynamicDepModules.set(packageName, depModuleInfo); + this.collectDependencyModules(packageName, depModuleInfo, dynamicDepModules, staticDepModules); } }); } return [dynamicDepModules, staticDepModules]; } + private collectDependencyModules( + packageName: string, + module: ModuleInfo, + dynamicDepModules: Map, + staticDepModules: Map + ): void { + if (module.language === LANGUAGE_VERSION.ARKTS_1_2) { + staticDepModules.set(packageName, module); + } else if (module.language === LANGUAGE_VERSION.ARKTS_1_1) { + dynamicDepModules.set(packageName, module); + } else if (module.language === LANGUAGE_VERSION.ARKTS_HYBRID) { + staticDepModules.set(packageName, module); + dynamicDepModules.set(packageName, module); + } + } + protected generateArkTSConfigForModules(): void { this.moduleInfos.forEach((moduleInfo: ModuleInfo, moduleRootPath: string) => { - ArkTSConfigGenerator.getInstance(this.buildConfig, this.moduleInfos).writeArkTSConfigFile(moduleInfo); + ArkTSConfigGenerator.getInstance(this.buildConfig, this.moduleInfos).writeArkTSConfigFile(moduleInfo, this.enableDeclgenEts2Ts); }); } diff --git a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts index eef6db8d34..8eb6212e58 100644 --- a/ets2panda/driver/build_system/src/build/compile_thread_worker.ts +++ b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts @@ -64,10 +64,10 @@ function compileAbc(jobInfo: JobInfo): void { } ets2pandaCmd.push(fileInfo.filePath); - let config = arkts.Config.create(ets2pandaCmd).peer; - arktsGlobal.config = config; + let arkConfig = arkts.Config.create(ets2pandaCmd).peer; + arktsGlobal.config = arkConfig; - let context = arkts.Context.createCacheContextFromFile(config, fileInfo.filePath, jobInfo.globalContextPtr, false).peer; + let context = arkts.Context.createCacheContextFromFile(arkConfig, fileInfo.filePath, jobInfo.globalContextPtr, false).peer; PluginDriver.getInstance().getPluginContext().setContextPtr(context); @@ -130,10 +130,10 @@ function compileExternalProgram(jobInfo: JobInfo): void { } ets2pandaCmd.push(fileInfo.filePath); - let config = arkts.Config.create(ets2pandaCmd).peer; - arktsGlobal.config = config; + let arkConfig = arkts.Config.create(ets2pandaCmd).peer; + arktsGlobal.config = arkConfig; - let context = arkts.Context.createCacheContextFromFile(config, fileInfo.filePath, jobInfo.globalContextPtr, true).peer; + let context = arkts.Context.createCacheContextFromFile(arkConfig, fileInfo.filePath, jobInfo.globalContextPtr, true).peer; PluginDriver.getInstance().getPluginContext().setContextPtr(context); diff --git a/ets2panda/driver/build_system/src/build/declgen_worker.ts b/ets2panda/driver/build_system/src/build/declgen_worker.ts index 2d25e9704d..63968d0d15 100644 --- a/ets2panda/driver/build_system/src/build/declgen_worker.ts +++ b/ets2panda/driver/build_system/src/build/declgen_worker.ts @@ -79,13 +79,13 @@ process.on('message', (message: { arktsGlobal.compilerContext = arkts.Context.createFromString(source); pluginDriver.getPluginContext().setArkTSProgram(arktsGlobal.compilerContext.program); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, true); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_PARSED, arktsGlobal.compilerContext.peer, true); let ast = arkts.EtsScript.fromContext(); pluginDriver.getPluginContext().setArkTSAst(ast); pluginDriver.runPluginHook(PluginHook.PARSED); - arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, true); + arkts.proceedToState(arkts.Es2pandaContextState.ES2PANDA_STATE_CHECKED, arktsGlobal.compilerContext.peer, true); ast = arkts.EtsScript.fromContext(); pluginDriver.getPluginContext().setArkTSAst(ast); diff --git a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts index 6cac43bb3e..0c71605418 100644 --- a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts +++ b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts @@ -49,7 +49,7 @@ interface ArkTSConfigObject { baseUrl: string, paths: Record; dependencies: string[] | undefined; - entry: string; + entry?: string; dynamicPaths: Record; useEmptyPackage?: boolean; } @@ -152,17 +152,39 @@ export class ArkTSConfigGenerator { this.generateSystemSdkPathSection(this.pathSection); this.moduleInfos.forEach((moduleInfo: ModuleInfo, packageName: string) => { - if (moduleInfo.language === LANGUAGE_VERSION.ARKTS_1_2) { - this.pathSection[moduleInfo.packageName] = [ - path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]) - ]; - } - + if (moduleInfo.language !== LANGUAGE_VERSION.ARKTS_1_2 && moduleInfo.language !== LANGUAGE_VERSION.ARKTS_HYBRID) { + return; + } + if (!moduleInfo.entryFile) { + return; + } + this.handleEntryFile(moduleInfo); }); - return this.pathSection; } + private handleEntryFile(moduleInfo: ModuleInfo): void { + try { + const stat = fs.statSync(moduleInfo.entryFile); + if (!stat.isFile()) { + return; + } + const entryFilePath = moduleInfo.entryFile; + const firstLine = fs.readFileSync(entryFilePath, 'utf-8').split('\n')[0]; + if (firstLine.includes('use static')) { + this.pathSection[moduleInfo.packageName] = [ + path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]) + ]; + } + } catch (error) { + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_HANDLE_ENTRY_FILE, + `Error handle entry file for module ${moduleInfo.packageName}` + ); + this.logger.printError(logData); + } + } + private getDependenciesSection(moduleInfo: ModuleInfo, dependenciesSection: string[]): void { let depModules: Map = moduleInfo.staticDepModuleInfos; depModules.forEach((depModuleInfo: ModuleInfo) => { @@ -203,7 +225,7 @@ export class ArkTSConfigGenerator { }); } - public writeArkTSConfigFile(moduleInfo: ModuleInfo): void { + public writeArkTSConfigFile(moduleInfo: ModuleInfo, enableDeclgenEts2Ts: boolean): void { if (!moduleInfo.sourceRoots || moduleInfo.sourceRoots.length === 0) { const logData: LogData = LogDataFactory.newInstance( ErrorCode.BUILDSYSTEM_SOURCEROOTS_NOT_SET_FAIL, @@ -214,9 +236,11 @@ export class ArkTSConfigGenerator { let pathSection = this.getPathSection(); let dependenciesSection: string[] = []; this.getDependenciesSection(moduleInfo, dependenciesSection); - let dynamicPathSection: Record = {}; - this.getDynamicPathSection(moduleInfo, dynamicPathSection); + + if (!enableDeclgenEts2Ts) { + this.getDynamicPathSection(moduleInfo, dynamicPathSection); + } let baseUrl: string = path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]); let arktsConfig: ArkTSConfigObject = { @@ -229,6 +253,19 @@ export class ArkTSConfigGenerator { dynamicPaths: dynamicPathSection } }; + + if (moduleInfo.entryFile) { + const entryFilePath = moduleInfo.entryFile; + const stat = fs.statSync(entryFilePath); + if (fs.existsSync(entryFilePath) && stat.isFile()) { + const firstLine = fs.readFileSync(entryFilePath, 'utf-8').split('\n')[0]; + // If the entryFile is not an ArkTS 1.2 implementation, remove the entry property field. + if (!firstLine.includes('use static')) { + delete arktsConfig.compilerOptions.entry; + } + } + } + if (moduleInfo.frameworkMode) { arktsConfig.compilerOptions.useEmptyPackage = moduleInfo.useEmptyPackage; } diff --git a/ets2panda/driver/build_system/src/error_code.ts b/ets2panda/driver/build_system/src/error_code.ts index ed2562f43a..25da0af026 100644 --- a/ets2panda/driver/build_system/src/error_code.ts +++ b/ets2panda/driver/build_system/src/error_code.ts @@ -36,4 +36,5 @@ export enum ErrorCode { BUILDSYSTEM_Dependency_Analyze_FAIL = '11410015', BUILDSYSTEM_Dependency_Analyzer_NOT_FOUND_FAIL = '11410016', BUILDSYSTEM_ABC_FILE_MISSING_IN_BCHAR = '11410017', + BUILDSYSTEM_HANDLE_ENTRY_FILE = '11410018', } -- Gitee From d5ad1cebd15fd7d551d8e60810ccbd10454d9ea7 Mon Sep 17 00:00:00 2001 From: ekkoruse Date: Wed, 4 Jun 2025 20:43:05 +0800 Subject: [PATCH 040/747] fixpartial Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCN0C?from=project-issue Change-Id: I71d2b879265c6c9e50750fcbb13f83609c81faa7 Signed-off-by: ekkoruse --- .../ets/topLevelStmts/topLevelStmts.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp index 3db02c7218..fbd267cee5 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp @@ -48,6 +48,30 @@ static bool CheckProgramSourcesConsistency(parser::Program *program) return success; } +static void AddExportModifierForInterface(ir::AstNode *const ast) +{ + auto body = ast->AsClassDeclaration()->Definition()->BodyForUpdate(); + for (auto it : body) { + if (it->IsTSInterfaceDeclaration()) { + it->AsTSInterfaceDeclaration()->AddModifier(ir::ModifierFlags::EXPORT); + } + } +}; + +static void DeclareNamespaceExportAdjust(parser::Program *program, const std::string_view &name) +{ + program->Ast()->TransformChildrenRecursively( + [](ir::AstNode *const ast) { + if (ast->IsClassDeclaration() && ast->AsClassDeclaration()->Definition()->IsNamespaceTransformed() && + ast->AsClassDeclaration()->Definition()->IsDeclare() && + (ast->IsExported() || ast->IsDefaultExported())) { + AddExportModifierForInterface(ast); + } + return ast; + }, + name); +} + bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *program) { auto imports = ImportExportDecls(program->VarBinder()->AsETSBinder(), ctx->parser->AsETSParser()); @@ -61,6 +85,9 @@ bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *prog if (!extPrograms.front()->IsASTLowered()) { auto moduleDependencies = imports.HandleGlobalStmts(extPrograms); globalClass.SetupGlobalClass(extPrograms, &moduleDependencies); + for (auto extProg : extPrograms) { + DeclareNamespaceExportAdjust(extProg, Name()); + } } } @@ -68,6 +95,8 @@ bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *prog mainModule.emplace_back(program); auto moduleDependencies = imports.HandleGlobalStmts(mainModule); globalClass.SetupGlobalClass(mainModule, &moduleDependencies); + DeclareNamespaceExportAdjust(program, Name()); + return true; } -- Gitee From ffe73c73f7ec227ee8c0488d7860c91a82a09233 Mon Sep 17 00:00:00 2001 From: Gabor Aron Takacs Date: Mon, 2 Jun 2025 18:13:35 +0200 Subject: [PATCH 041/747] Add diagnostics for ambient declarations Fixes #24687 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBZ1F Change-Id: I616e52ad50e43b2d1b5b87772ab64261a46202cc Signed-off-by: Gabor Aron Takacs --- ets2panda/parser/ETSparser.cpp | 5 +++++ .../ast/parser/ets/ambient_declaration.ets | 21 +++++++++++++++++++ ets2panda/util/diagnostic/syntax.yaml | 4 ++++ 3 files changed, 30 insertions(+) create mode 100644 ets2panda/test/ast/parser/ets/ambient_declaration.ets diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 71fd3ae939..0a05f99f26 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -2050,6 +2050,11 @@ void ETSParser::CheckDeclare() Lexer()->NextToken(); // eat 'declare' + if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT && Lexer()->GetToken().Ident().Is("module")) { + LogError(diagnostic::ERROR_ARKTS_NO_AMBIENT_DECLS); + return; + } + switch (Lexer()->GetToken().KeywordType()) { case lexer::TokenType::KEYW_LET: case lexer::TokenType::KEYW_CONST: diff --git a/ets2panda/test/ast/parser/ets/ambient_declaration.ets b/ets2panda/test/ast/parser/ets/ambient_declaration.ets new file mode 100644 index 0000000000..ee8515f116 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/ambient_declaration.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare /* @@ label1 */module /* @@ label2 */"someModule" /* @@ label3 */{} + +/* @@@ label1 Error SyntaxError: Ambient module declaration is not supported! */ +/* @@@ label1 Error TypeError: Unresolved reference module */ +/* @@@ label2 Error SyntaxError: Unexpected token 'someModule'. */ +/* @@@ label3 Error SyntaxError: Unexpected token '{'. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index bb3bcb5a83..c8550ea251 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1239,3 +1239,7 @@ syntax: - name: ERROR_ARKTS_NO_EXPORT_ASSIGNMENT id: 307 message: "'export = ...' syntax is not supported, use regular import/export instead!" + +- name: ERROR_ARKTS_NO_AMBIENT_DECLS + id: 308 + message: "Ambient module declaration is not supported!" -- Gitee From e36efde166b340deab4f6ba00181d0d6790c1eac Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Thu, 5 Jun 2025 10:22:00 +0800 Subject: [PATCH 042/747] fix arkts-interop-js2s-access-js-prop Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCDPB Test scenarios: fix bug Signed-off-by: zhongning --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 37 ++- .../interop_import_typeof_js.ets.arkts2.json | 10 + .../interop_import_typeof_js.ets.autofix.json | 21 ++ .../interop_import_typeof_js.ets.migrate.ets | 2 +- .../interop_import_typeof_js.ets.migrate.json | 2 +- .../interop_not_have_property_arkts2.ets | 6 +- ...p_not_have_property_arkts2.ets.arkts2.json | 90 ++++++-- ..._not_have_property_arkts2.ets.autofix.json | 211 ++++++++++++------ .../interop_not_have_property_arkts2.ets.json | 23 +- ...p_not_have_property_arkts2.ets.migrate.ets | 6 +- ..._not_have_property_arkts2.ets.migrate.json | 22 +- 11 files changed, 332 insertions(+), 98 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e9000385f1..d67e91dd05 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -1412,6 +1412,36 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private isJsRelated(node: ts.Expression): boolean { + if (this.tsUtils.isJsImport(node)) { + return true; + } + + if (ts.isNewExpression(node)) { + return this.tsUtils.isJsImport(node.expression); + } + + if (ts.isIdentifier(node)) { + const symbol = this.tsUtils.trueSymbolAtLocation(node); + if (!symbol) { + return false; + } + + const declarations = symbol.getDeclarations(); + if (!declarations || declarations.length === 0) { + return false; + } + + for (const declaration of declarations) { + if (ts.isVariableDeclaration(declaration) && declaration.initializer) { + return this.isJsRelated(declaration.initializer); + } + } + } + + return false; + } + propertyAccessExpressionForInterop(propertyAccessNode: ts.PropertyAccessExpression): void { if (!this.useStatic || !this.options.arkts2) { return; @@ -1424,10 +1454,11 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } return current; - }; - + } + const firstObjNode = getFirstObjectNode(propertyAccessNode); - if (!this.tsUtils.isJsImport(firstObjNode)) { + const isJsObject = this.isJsRelated(firstObjNode); + if (!isJsObject) { return; } diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json index 0d41c5dd84..a388ad4be8 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json @@ -194,6 +194,16 @@ "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", "severity": "ERROR" }, + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 22, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, { "line": 36, "column": 12, diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json index f9f9b5c814..bf0571a063 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json @@ -397,6 +397,27 @@ "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", "severity": "ERROR" }, + { + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 22, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 1136, + "end": 1147, + "replacementText": "person.getPropertyByName(\"name\")", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 22 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, { "line": 36, "column": 12, diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets index 71c8bd3946..197a8577ce 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.ets @@ -42,7 +42,7 @@ const aClass:ClassA = ClassA.instantiate() ClassA.instantiate().typeOf() //error typeof aClass; let person:Person = Person.instantiate(); -let name =person.name +let name =person.getPropertyByName("name") let name2 =person.invokeMethod("getName") function getPersonInfo(){ typeof person; diff --git a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json index 221ab45494..f709470eef 100644 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.migrate.json @@ -138,7 +138,7 @@ "line": 45, "column": 5, "endLine": 45, - "endColumn": 22, + "endColumn": 43, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets index ad6fbcab7d..e76e5da604 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets @@ -13,10 +13,14 @@ * limitations under the License. */ +'use static' import {foo, person} from "./interop_not_have_property_js" foo.name foo.name = "456" person.age = 23 person.male = [2, 3] -foo.age = 12 \ No newline at end of file +foo.age = 12 + +let a = new foo() +a.age = 12 \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json index cb366b21c4..4b9d5b3863 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.arkts2.json @@ -15,9 +15,19 @@ ], "result": [ { - "line": 16, + "line": 17, "column": 1, - "endLine": 16, + "endLine": 17, + "endColumn": 59, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, "endColumn": 59, "problem": "InterOpImportJs", "suggest": "", @@ -25,9 +35,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 19, "column": 1, - "endLine": 18, + "endLine": 19, "endColumn": 9, "problem": "InteropObjectProperty", "suggest": "", @@ -35,9 +45,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 20, "column": 1, - "endLine": 19, + "endLine": 20, "endColumn": 17, "problem": "InteropObjectProperty", "suggest": "", @@ -45,9 +55,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 21, "column": 1, - "endLine": 20, + "endLine": 21, "endColumn": 16, "problem": "InteropObjectProperty", "suggest": "", @@ -55,9 +65,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 21, "column": 14, - "endLine": 20, + "endLine": 21, "endColumn": 16, "problem": "NumericSemantics", "suggest": "", @@ -65,9 +75,9 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 1, - "endLine": 21, + "endLine": 22, "endColumn": 21, "problem": "InteropObjectProperty", "suggest": "", @@ -75,9 +85,9 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 16, - "endLine": 21, + "endLine": 22, "endColumn": 17, "problem": "NumericSemantics", "suggest": "", @@ -85,9 +95,9 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 19, - "endLine": 21, + "endLine": 22, "endColumn": 20, "problem": "NumericSemantics", "suggest": "", @@ -95,9 +105,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 23, "column": 1, - "endLine": 22, + "endLine": 23, "endColumn": 13, "problem": "InteropObjectProperty", "suggest": "", @@ -105,14 +115,54 @@ "severity": "ERROR" }, { - "line": 22, + "line": 23, "column": 11, - "endLine": 22, + "endLine": 23, "endColumn": 13, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 18, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 9, + "endLine": 25, + "endColumn": 18, + "problem": "InstantiatedJsOjbect", + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 11, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 9, + "endLine": 26, + "endColumn": 11, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json index bc3b0d40f5..1324eb3b62 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.autofix.json @@ -15,28 +15,38 @@ ], "result": [ { - "line": 16, + "line": 17, "column": 1, - "endLine": 16, + "endLine": 17, + "endColumn": 59, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" + }, + { + "line": 17, + "column": 1, + "endLine": 17, "endColumn": 59, "problem": "InterOpImportJs", "autofix": [ { - "start": 605, - "end": 663, + "start": 618, + "end": 676, "replacementText": "", - "line": 16, + "line": 17, "column": 1, - "endLine": 16, + "endLine": 17, "endColumn": 59 }, { - "start": 663, - "end": 663, + "start": 676, + "end": 676, "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_not_have_property_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet person = GeneratedImportVar_1.getPropertyByName('person');\n", - "line": 16, + "line": 17, "column": 1, - "endLine": 16, + "endLine": 17, "endColumn": 59 } ], @@ -45,19 +55,19 @@ "severity": "ERROR" }, { - "line": 18, + "line": 19, "column": 1, - "endLine": 18, + "endLine": 19, "endColumn": 9, "problem": "InteropObjectProperty", "autofix": [ { - "start": 665, - "end": 673, + "start": 678, + "end": 686, "replacementText": "foo.getPropertyByName(\"name\")", - "line": 18, + "line": 19, "column": 1, - "endLine": 18, + "endLine": 19, "endColumn": 9 } ], @@ -66,19 +76,19 @@ "severity": "ERROR" }, { - "line": 19, + "line": 20, "column": 1, - "endLine": 19, + "endLine": 20, "endColumn": 17, "problem": "InteropObjectProperty", "autofix": [ { - "start": 674, - "end": 690, + "start": 687, + "end": 703, "replacementText": "foo.setPropertyByName(\"name\", ESValue.wrap(\"456\"))", - "line": 19, + "line": 20, "column": 1, - "endLine": 19, + "endLine": 20, "endColumn": 17 } ], @@ -87,19 +97,19 @@ "severity": "ERROR" }, { - "line": 20, + "line": 21, "column": 1, - "endLine": 20, + "endLine": 21, "endColumn": 16, "problem": "InteropObjectProperty", "autofix": [ { - "start": 691, - "end": 706, + "start": 704, + "end": 719, "replacementText": "person.setPropertyByName(\"age\", ESValue.wrap(23))", - "line": 20, + "line": 21, "column": 1, - "endLine": 20, + "endLine": 21, "endColumn": 16 } ], @@ -108,19 +118,19 @@ "severity": "ERROR" }, { - "line": 20, + "line": 21, "column": 14, - "endLine": 20, + "endLine": 21, "endColumn": 16, "problem": "NumericSemantics", "autofix": [ { - "start": 704, - "end": 706, + "start": 717, + "end": 719, "replacementText": "23.0", - "line": 20, + "line": 21, "column": 14, - "endLine": 20, + "endLine": 21, "endColumn": 16 } ], @@ -129,19 +139,19 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 1, - "endLine": 21, + "endLine": 22, "endColumn": 21, "problem": "InteropObjectProperty", "autofix": [ { - "start": 707, - "end": 727, + "start": 720, + "end": 740, "replacementText": "person.setPropertyByName(\"male\", ESValue.wrap([2, 3]))", - "line": 21, + "line": 22, "column": 1, - "endLine": 21, + "endLine": 22, "endColumn": 21 } ], @@ -150,19 +160,19 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 16, - "endLine": 21, + "endLine": 22, "endColumn": 17, "problem": "NumericSemantics", "autofix": [ { - "start": 722, - "end": 723, + "start": 735, + "end": 736, "replacementText": "2.0", - "line": 21, + "line": 22, "column": 16, - "endLine": 21, + "endLine": 22, "endColumn": 17 } ], @@ -171,19 +181,19 @@ "severity": "ERROR" }, { - "line": 21, + "line": 22, "column": 19, - "endLine": 21, + "endLine": 22, "endColumn": 20, "problem": "NumericSemantics", "autofix": [ { - "start": 725, - "end": 726, + "start": 738, + "end": 739, "replacementText": "3.0", - "line": 21, + "line": 22, "column": 19, - "endLine": 21, + "endLine": 22, "endColumn": 20 } ], @@ -192,19 +202,19 @@ "severity": "ERROR" }, { - "line": 22, + "line": 23, "column": 1, - "endLine": 22, + "endLine": 23, "endColumn": 13, "problem": "InteropObjectProperty", "autofix": [ { - "start": 728, - "end": 740, + "start": 741, + "end": 753, "replacementText": "foo.setPropertyByName(\"age\", ESValue.wrap(12))", - "line": 22, + "line": 23, "column": 1, - "endLine": 22, + "endLine": 23, "endColumn": 13 } ], @@ -213,25 +223,98 @@ "severity": "ERROR" }, { - "line": 22, + "line": 23, "column": 11, - "endLine": 22, + "endLine": 23, "endColumn": 13, "problem": "NumericSemantics", "autofix": [ { - "start": 738, - "end": 740, + "start": 751, + "end": 753, "replacementText": "12.0", - "line": 22, + "line": 23, "column": 11, - "endLine": 22, + "endLine": 23, "endColumn": 13 } ], "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 18, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 9, + "endLine": 25, + "endColumn": 18, + "problem": "InstantiatedJsOjbect", + "autofix": [ + { + "start": 763, + "end": 772, + "replacementText": "foo.instantiate()", + "line": 25, + "column": 9, + "endLine": 25, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 11, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 773, + "end": 783, + "replacementText": "a.setPropertyByName(\"age\", ESValue.wrap(12))", + "line": 26, + "column": 1, + "endLine": 26, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 9, + "endLine": 26, + "endColumn": 11, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 781, + "end": 783, + "replacementText": "12.0", + "line": 26, + "column": 9, + "endLine": 26, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json index ca88f857e9..aa378b7cdb 100755 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.json @@ -13,5 +13,26 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 17, + "column": 1, + "endLine": 17, + "endColumn": 59, + "problem": "ImportAfterStatement", + "suggest": "", + "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 18, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + } + ] } \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets index cfddb44b00..41e6e710a6 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.ets @@ -13,6 +13,7 @@ * limitations under the License. */ +'use static' let GeneratedImportVar_1 = ESValue.load('./interop_not_have_property_js'); let foo = GeneratedImportVar_1.getPropertyByName('foo'); let person = GeneratedImportVar_1.getPropertyByName('person'); @@ -22,4 +23,7 @@ foo.getPropertyByName("name") foo.setPropertyByName("name", ESValue.wrap("456")) person.setPropertyByName("age", ESValue.wrap(23.0)) person.setPropertyByName("male", ESValue.wrap([2.0, 3.0])) -foo.setPropertyByName("age", ESValue.wrap(12.0)) \ No newline at end of file +foo.setPropertyByName("age", ESValue.wrap(12.0)) + +let a = foo.instantiate() +a.setPropertyByName("age", ESValue.wrap(12.0)) \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json index ae940558e7..5d0bee8059 100644 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets.migrate.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 16, + "line": 17, "column": 5, - "endLine": 16, + "endLine": 17, "endColumn": 74, "problem": "AnyType", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 18, "column": 5, - "endLine": 17, + "endLine": 18, "endColumn": 56, "problem": "AnyType", "suggest": "", @@ -35,14 +35,24 @@ "severity": "ERROR" }, { - "line": 18, + "line": 19, "column": 5, - "endLine": 18, + "endLine": 19, "endColumn": 62, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" + }, + { + "line": 28, + "column": 5, + "endLine": 28, + "endColumn": 26, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee From 71724a536a11e95d169a6fdbe41aa6abd263b532 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Thu, 5 Jun 2025 11:29:22 +0800 Subject: [PATCH 043/747] Fix for JsObjectTraverseJsInstance Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCBGR Test scenarios:new tests add to the linter Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 15 +- .../test/interop/interop_import_js_index.ets | 19 +- .../interop_import_js_index.ets.arkts2.json | 196 ++++++++- .../interop_import_js_index.ets.autofix.json | 405 +++++++++++++++--- .../interop_import_js_index.ets.migrate.ets | 28 +- .../interop_import_js_index.ets.migrate.json | 50 +++ 6 files changed, 635 insertions(+), 78 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e9000385f1..a0f2896c8d 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8041,7 +8041,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2 || !this.useStatic) { return; } - + if (!TypeScriptLinter.isInForLoopBody(elementAccessExpr)) { + return; + } const variableDeclaration = ts.isIdentifier(elementAccessExpr.expression) ? this.tsUtils.findVariableDeclaration(elementAccessExpr.expression) : undefined; @@ -8065,6 +8067,17 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.incrementCounters(elementAccessExpr, FaultID.InteropJsObjectTraverseJsInstance, autofix); } + private static isInForLoopBody(node: ts.Node): boolean { + let current: ts.Node | undefined = node.parent; + while (current) { + if (ts.isForStatement(current) || ts.isForInStatement(current) || ts.isForOfStatement(current)) { + return true; + } + current = current.parent; + } + return false; + } + private handleTaskPoolDeprecatedUsages(node: ts.CallExpression): void { if (!this.options.arkts2 || !this.useStatic) { return; diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets index ba165c68fd..a4ffabe660 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets @@ -12,8 +12,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import { ff3 } from "./interop_import_js_rules_js" import {foo} from "./interop_import_js_index_js" let arr = foo.arr arr[1] -arr[3] = 4 \ No newline at end of file +arr[3] = 4 + +let arr1 = ff3.arr +let len = arr1.length as number +for (let i = 0; i < arr1.length; ++i) { + console.log(arr1[i]+''); //error + let x = arr1[i] //error + arr1[i] = 0 //error + console.log(arr1[i]+''); //error +} + +for (let element of arr1) { //error + if (element == 8) { + console.log("hi"); + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json index 2e7b935be0..7586fcda51 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.arkts2.json @@ -14,6 +14,16 @@ "limitations under the License." ], "result": [ + { + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51, + "problem": "InterOpImportJs", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { "line": 16, "column": 1, @@ -44,16 +54,6 @@ "rule": "Array bound not checked. (arkts-runtime-array-check)", "severity": "ERROR" }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7, - "problem": "InteropJsObjectTraverseJsInstance", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", - "severity": "ERROR" - }, { "line": 18, "column": 1, @@ -78,27 +78,187 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 7, - "problem": "InteropJsObjectTraverseJsInstance", + "endColumn": 11, + "problem": "InterOpImportJsIndex", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", "severity": "ERROR" }, { "line": 19, - "column": 1, + "column": 10, "endLine": 19, "endColumn": 11, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 12, + "endLine": 21, + "endColumn": 19, + "problem": "InteropObjectProperty", + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 10, + "endLine": 23, + "endColumn": 15, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 14, + "endLine": 23, + "endColumn": 15, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, "problem": "InterOpImportJsIndex", "suggest": "", "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", "severity": "ERROR" }, { - "line": 19, - "column": 10, - "endLine": 19, - "endColumn": 11, + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "InterOpImportJsIndex", + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 12, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 16, + "problem": "InterOpImportJsIndex", + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 15, + "endLine": 26, + "endColumn": 16, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "InterOpImportJsIndex", + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 1, + "endLine": 34, + "endColumn": 2, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 19, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json index 392ce7c30e..8e7830812f 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.autofix.json @@ -14,6 +14,36 @@ "limitations under the License." ], "result": [ + { + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51, + "problem": "InterOpImportJs", + "autofix": [ + { + "start": 604, + "end": 654, + "replacementText": "", + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51 + }, + { + "start": 703, + "end": 703, + "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_rules_js');\nlet ff3 = GeneratedImportVar_1.getPropertyByName('ff3');\n", + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", + "severity": "ERROR" + }, { "line": 16, "column": 1, @@ -22,8 +52,8 @@ "problem": "InterOpImportJs", "autofix": [ { - "start": 606, - "end": 654, + "start": 655, + "end": 703, "replacementText": "", "line": 16, "column": 1, @@ -31,9 +61,9 @@ "endColumn": 49 }, { - "start": 654, - "end": 654, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_import_js_index_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", + "start": 703, + "end": 703, + "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_index_js');\nlet foo = GeneratedImportVar_2.getPropertyByName('foo');\n", "line": 16, "column": 1, "endLine": 16, @@ -52,8 +82,8 @@ "problem": "InteropObjectProperty", "autofix": [ { - "start": 665, - "end": 672, + "start": 714, + "end": 721, "replacementText": "foo.getPropertyByName(\"arr\")", "line": 17, "column": 11, @@ -75,27 +105,6 @@ "rule": "Array bound not checked. (arkts-runtime-array-check)", "severity": "ERROR" }, - { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7, - "problem": "InteropJsObjectTraverseJsInstance", - "autofix": [ - { - "replacementText": "arr.getPropertyByIndex(1).toNumber()", - "start": 673, - "end": 679, - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 7 - } - ], - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", - "severity": "ERROR" - }, { "line": 18, "column": 1, @@ -104,8 +113,8 @@ "problem": "InterOpImportJsIndex", "autofix": [ { - "start": 673, - "end": 679, + "start": 722, + "end": 728, "replacementText": "arr.getPropertyByIndex(1)", "line": 18, "column": 1, @@ -131,59 +140,351 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 7, - "problem": "InteropJsObjectTraverseJsInstance", + "endColumn": 11, + "problem": "InterOpImportJsIndex", "autofix": [ { + "start": 729, + "end": 739, "replacementText": "arr.setPropertyByIndex(3, ESValue.wrap(4))", - "start": 680, - "end": 690, "line": 19, "column": 1, "endLine": 19, - "endColumn": 7 + "endColumn": 11 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", "severity": "ERROR" }, { "line": 19, - "column": 1, + "column": 10, "endLine": 19, "endColumn": 11, - "problem": "InterOpImportJsIndex", + "problem": "NumericSemantics", "autofix": [ { - "start": 680, - "end": 690, - "replacementText": "arr.setPropertyByIndex(3, ESValue.wrap(4))", + "start": 738, + "end": 739, + "replacementText": "4.0", "line": 19, - "column": 1, + "column": 10, "endLine": 19, "endColumn": 11 } ], "suggest": "", - "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { - "line": 19, + "line": 21, + "column": 12, + "endLine": 21, + "endColumn": 19, + "problem": "InteropObjectProperty", + "autofix": [ + { + "start": 752, + "end": 759, + "replacementText": "ff3.getPropertyByName(\"arr\")", + "line": 21, + "column": 12, + "endLine": 21, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "severity": "ERROR" + }, + { + "line": 23, "column": 10, - "endLine": 19, - "endColumn": 11, + "endLine": 23, + "endColumn": 15, "problem": "NumericSemantics", "autofix": [ { - "start": 689, - "end": 690, - "replacementText": "4.0", - "line": 19, + "start": 801, + "end": 806, + "replacementText": "i: number = 0", + "line": 23, "column": 10, - "endLine": 19, - "endColumn": 11 + "endLine": 23, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 14, + "endLine": 23, + "endColumn": 15, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 805, + "end": 806, + "replacementText": "0.0", + "line": 23, + "column": 14, + "endLine": 23, + "endColumn": 15 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr1.getPropertyByIndex(i).toNumber()", + "start": 848, + "end": 855, + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 848, + "end": 855, + "replacementText": "arr1.getPropertyByIndex(i)", + "line": 24, + "column": 17, + "endLine": 24, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr1.getPropertyByIndex(i).toNumber()", + "start": 882, + "end": 889, + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 882, + "end": 889, + "replacementText": "arr1.getPropertyByIndex(i)", + "line": 25, + "column": 13, + "endLine": 25, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 12, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr1.setPropertyByIndex(i, ESValue.wrap(0 //error\n))", + "start": 903, + "end": 914, + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 12 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 16, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 903, + "end": 914, + "replacementText": "arr1.setPropertyByIndex(i, ESValue.wrap(0))", + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 16 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 15, + "endLine": 26, + "endColumn": 16, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 913, + "end": 914, + "replacementText": "0.0", + "line": 26, + "column": 15, + "endLine": 26, + "endColumn": 16 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "RuntimeArrayCheck", + "suggest": "", + "rule": "Array bound not checked. (arkts-runtime-array-check)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "InteropJsObjectTraverseJsInstance", + "autofix": [ + { + "replacementText": "arr1.getPropertyByIndex(i).toNumber()", + "start": 940, + "end": 947, + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24, + "problem": "InterOpImportJsIndex", + "autofix": [ + { + "start": 940, + "end": 947, + "replacementText": "arr1.getPropertyByIndex(i)", + "line": 27, + "column": 17, + "endLine": 27, + "endColumn": 24 + } + ], + "suggest": "", + "rule": "Interop objects can't be indexed directly (arkts-interop-js2s-access-js-index)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 1, + "endLine": 34, + "endColumn": 2, + "problem": "InteropJsObjectTraverseJsInstance", + "suggest": "", + "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js2s-traverse-js-instance)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 19, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1019, + "end": 1020, + "replacementText": "8.0", + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 19 } ], "suggest": "", diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets index d521cdc8aa..adc49e209c 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.ets @@ -12,10 +12,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -let GeneratedImportVar_1 = ESValue.load('./interop_import_js_index_js'); -let foo = GeneratedImportVar_1.getPropertyByName('foo'); + +let GeneratedImportVar_2 = ESValue.load('./interop_import_js_index_js'); +let foo = GeneratedImportVar_2.getPropertyByName('foo'); +let GeneratedImportVar_1 = ESValue.load('./interop_import_js_rules_js'); +let ff3 = GeneratedImportVar_1.getPropertyByName('ff3'); let arr = foo.getPropertyByName("arr") -arr.getPropertyByIndex(1.0).toNumber() -arr.setPropertyByIndex(3.0, ESValue.wrap(4.0)) \ No newline at end of file +arr.getPropertyByIndex(1.0) +arr.setPropertyByIndex(3.0, ESValue.wrap(4.0)) + +let arr1 = ff3.getPropertyByName("arr") +let len: number = arr1.length as number +for (let i: number = 0.0; i < arr1.length; ++i) { + console.log(arr1.getPropertyByIndex(i).toNumber()+''); //error + let x = arr1.getPropertyByIndex(i).toNumber() //error + arr1.setPropertyByIndex(i, ESValue.wrap(0.0 //error +)) //error + console.log(arr1.getPropertyByIndex(i).toNumber()+''); //error +} + +for (let element of arr1) { //error + if (element == 8.0) { + console.log("hi"); + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json index d12c3ee91b..526bcedf9d 100644 --- a/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json +++ b/ets2panda/linter/test/interop/interop_import_js_index.ets.migrate.json @@ -34,15 +34,65 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 18, + "column": 5, + "endLine": 18, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, { "line": 19, "column": 5, "endLine": 19, + "endColumn": 56, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 5, + "endLine": 21, "endColumn": 39, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 40, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 9, + "endLine": 29, + "endColumn": 50, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 10, + "endLine": 35, + "endColumn": 17, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee From cfd61ec2068059e9e0048e3cb758b1031d21aaef Mon Sep 17 00:00:00 2001 From: fanglou Date: Wed, 4 Jun 2025 23:50:23 +0800 Subject: [PATCH 044/747] add option to skip interop Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCNOT Signed-off-by: fanglou Change-Id: Iec5c3b903c9f7c676f8f8b20f0a06019547e07f6 --- ets2panda/linter/src/cli/CommandLineParser.ts | 9 +++++---- ets2panda/linter/src/lib/CommandLineOptions.ts | 1 + ets2panda/linter/src/lib/HomeCheck.ts | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ets2panda/linter/src/cli/CommandLineParser.ts b/ets2panda/linter/src/cli/CommandLineParser.ts index d20a18c218..9849eedf17 100644 --- a/ets2panda/linter/src/cli/CommandLineParser.ts +++ b/ets2panda/linter/src/cli/CommandLineParser.ts @@ -152,6 +152,9 @@ function formArkts2Options(cmdOptions: CommandLineOptions, commanderOpts: Option if (commanderOpts.verbose) { cmdOptions.verbose = true; } + if (commanderOpts.enableInterop) { + cmdOptions.scanWholeProjectInHomecheck = true; + } } function formCommandLineOptions(parsedCmd: ParsedCommand): CommandLineOptions { @@ -226,12 +229,10 @@ function createCommand(): Command { option('--migration-max-pass ', 'Maximum number of migration passes'). option('--migration-report', 'Generate migration report'). option('--check-ts-and-js', 'check ts and js files'). - option( - '--only-arkts2-syntax-rules', - 'only syntax rules, excluding rules such as SDK, Arkui, Interop, Concurrent, etc' - ). + option('--only-arkts2-syntax-rules', 'only syntax rules'). option('-o, --output-file-path ', 'path to store all log and result files'). option('--verbose', 'set log level to see debug messages'). + option('--enable-interop', 'scan whole project to report 1.1 import 1.2'). addOption(new Option('--warnings-as-errors', 'treat warnings as errors').hideHelp(true)). addOption(new Option('--no-check-ts-as-source', 'check TS files as third-party libary').hideHelp(true)). addOption(new Option('--no-use-rt-logic', 'run linter with SDK logic').hideHelp(true)). diff --git a/ets2panda/linter/src/lib/CommandLineOptions.ts b/ets2panda/linter/src/lib/CommandLineOptions.ts index cbcc81f622..1bdde46fae 100644 --- a/ets2panda/linter/src/lib/CommandLineOptions.ts +++ b/ets2panda/linter/src/lib/CommandLineOptions.ts @@ -33,4 +33,5 @@ export interface CommandLineOptions { disableStrictDiagnostics?: boolean; outputFilePath?: string; verbose?: boolean; + scanWholeProjectInHomecheck?: boolean; } diff --git a/ets2panda/linter/src/lib/HomeCheck.ts b/ets2panda/linter/src/lib/HomeCheck.ts index a8845c1999..e49ec0338d 100644 --- a/ets2panda/linter/src/lib/HomeCheck.ts +++ b/ets2panda/linter/src/lib/HomeCheck.ts @@ -41,6 +41,10 @@ export function getHomeCheckConfigInfo(cmdOptions: CommandLineOptions): { projectConfigInfo: ProjectConfigInfo; } { let inputFiles = cmdOptions.inputFiles; + let fliesTocheck: string[] = inputFiles; + if (cmdOptions.scanWholeProjectInHomecheck === true) { + fliesTocheck = []; + } inputFiles = inputFiles.filter((input) => { return shouldProcessFile(cmdOptions, input); }); @@ -61,7 +65,7 @@ export function getHomeCheckConfigInfo(cmdOptions: CommandLineOptions): { hmsSdkPath: cmdOptions.sdkExternalApiPath ? cmdOptions.sdkExternalApiPath[0] : '', reportDir: './', languageTags: languageTags, - fileOrFolderToCheck: [], + fileOrFolderToCheck: fliesTocheck, logLevel: cmdOptions.verbose ? 'DEBUG' : 'INFO', arkAnalyzerLogLevel: cmdOptions.verbose ? 'DEBUG' : 'ERROR' }; -- Gitee From 67b7dfbbb7c46fb599d70b26d239f19d490400ed Mon Sep 17 00:00:00 2001 From: lijunru Date: Mon, 26 May 2025 11:00:13 +0800 Subject: [PATCH 045/747] Fix_doesnt_implement_inherited_abstract_member Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICANHJ Signed-off-by: lijunru --- ets2panda/lsp/BUILD.gn | 1 + ets2panda/lsp/CMakeLists.txt | 1 + ...esnt_implement_inherited_abstract_member.h | 40 ++++ ...nt_implement_inherited_abstract_member.cpp | 175 ++++++++++++++++++ ets2panda/test/unit/lsp/CMakeLists.txt | 6 +- .../unit/lsp/code_fix_registration_test.cpp | 2 +- ...plement_inherited_abstract_member_test.cpp | 160 ++++++++++++++++ 7 files changed, 383 insertions(+), 2 deletions(-) create mode 100644 ets2panda/lsp/include/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h create mode 100644 ets2panda/lsp/src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp create mode 100644 ets2panda/test/unit/lsp/fix_class_doesnt_implement_inherited_abstract_member_test.cpp diff --git a/ets2panda/lsp/BUILD.gn b/ets2panda/lsp/BUILD.gn index e8572f6d7c..5cd817c9c5 100644 --- a/ets2panda/lsp/BUILD.gn +++ b/ets2panda/lsp/BUILD.gn @@ -77,6 +77,7 @@ ohos_source_set("libes2panda_lsp_static") { "src/refactors/refactor_types.cpp", "src/references.cpp", "src/register_code_fix/add_missing_declare_property.cpp", + "src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp", "src/register_code_fix/fix_missing_call_parantheses.cpp", "src/register_code_fix/fix_nan_equality.cpp", "src/register_code_fix/forgetten_this_property_access.cpp", diff --git a/ets2panda/lsp/CMakeLists.txt b/ets2panda/lsp/CMakeLists.txt index b3dd0cc578..f9e2e474c8 100644 --- a/ets2panda/lsp/CMakeLists.txt +++ b/ets2panda/lsp/CMakeLists.txt @@ -59,6 +59,7 @@ set(ES2PANDA_LSP_SRC ./src/types.cpp ./src/navigate_to.cpp ./src/code_fix_provider.cpp + ./src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp ./src/register_code_fix/add_missing_declare_property.cpp ./src/register_code_fix/fix_missing_call_parantheses.cpp ./src/register_code_fix/fix_nan_equality.cpp diff --git a/ets2panda/lsp/include/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h b/ets2panda/lsp/include/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h new file mode 100644 index 0000000000..f94586a1a2 --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at* + * + * http://www.apache.org/licenses/LICENSE-2.0* + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIX_CLASS_DOESNT_IMPLEMENT_INHERITED_ABSTRACT_MEMBER_H +#define FIX_CLASS_DOESNT_IMPLEMENT_INHERITED_ABSTRACT_MEMBER_H + +#include "lsp/include/code_fixes/code_fix_types.h" +#include "public/es2panda_lib.h" + +namespace ark::es2panda::lsp { + +class FixClassNotImplementingInheritedMembers : public CodeFixRegistration { +public: + FixClassNotImplementingInheritedMembers(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; + + TextChange MakeTextChange(es2panda_Context *context, size_t offset); + std::string MakeNewText(ir::AstNode *node); + std::string MakeMethodSignature(ir::AstNode *node); + ir::AstNode *GetSuperClassDefinition(ir::AstNode *node); +}; + +} // namespace ark::es2panda::lsp + +#endif // FIX_CLASS_DOESNT_IMPLEMENT_INHERITED_ABSTRACT_MEMBER_H \ No newline at end of file diff --git a/ets2panda/lsp/src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp b/ets2panda/lsp/src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp new file mode 100644 index 0000000000..cd11ddd12e --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.cpp @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at* + * + * http://www.apache.org/licenses/LICENSE-2.0* + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "code_fix_provider.h" +#include "code_fixes/code_fix_types.h" +#include "compiler/lowering/util.h" +#include "internal_api.h" +#include "ir/astNode.h" +#include "ir/base/classDefinition.h" +#include "public/es2panda_lib.h" +#include "register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h" +#include "public/public.h" +#include "types.h" +#include +#include + +namespace ark::es2panda::lsp { + +ir::AstNode *FixClassNotImplementingInheritedMembers::GetSuperClassDefinition(ir::AstNode *node) +{ + if (node == nullptr || !node->IsClassDefinition()) { + return nullptr; + } + auto superClass = node->AsClassDefinition()->Super(); + if (superClass->IsETSTypeReference()) { + auto part = superClass->AsETSTypeReference()->Part(); + if (part->IsETSTypeReferencePart()) { + auto name = part->Name(); + return compiler::DeclarationFromIdentifier(name->AsIdentifier()); + } + } + return nullptr; +} + +std::string FixClassNotImplementingInheritedMembers::MakeMethodSignature(ir::AstNode *node) +{ + if (node == nullptr || !node->IsMethodDefinition()) { + return ""; + } + auto methodName = node->AsMethodDefinition()->Key()->AsIdentifier()->Name(); + return std::string(methodName) + node->AsMethodDefinition()->Function()->Signature()->ToString(); +} + +std::string FixClassNotImplementingInheritedMembers::MakeNewText(ir::AstNode *node) +{ + if (node == nullptr || !node->IsMethodDefinition()) { + return ""; + } + const std::string suffix = " {}"; + const std::string prefix = " "; + auto methodName = node->AsMethodDefinition()->Key()->AsIdentifier()->Name(); + auto newText = std::string(methodName) + node->AsMethodDefinition()->Function()->DumpEtsSrc(); + newText.insert(0, prefix); + newText.insert(newText.size() - 1, suffix); + return newText; +} + +TextChange FixClassNotImplementingInheritedMembers::MakeTextChange(es2panda_Context *context, size_t offset) +{ + TextChange res {{0, 0}, ""}; + if (context == nullptr) { + return res; + } + + auto targetNode = GetTouchingToken(context, offset, false); + if (targetNode == nullptr) { + return res; + } + + while (targetNode->Parent() != nullptr) { + if (targetNode->IsClassDefinition()) { + targetNode = targetNode->AsClassDefinition()->Ident(); + break; + } + targetNode = targetNode->Parent(); + } + if (!targetNode->IsIdentifier()) { + return res; + } + auto targetDecl = compiler::DeclarationFromIdentifier(targetNode->AsIdentifier()); + if (targetDecl == nullptr || !targetDecl->IsClassDefinition()) { + return res; + } + + auto targetClassBodys = targetDecl->AsClassDefinition()->Body(); + res.span.start = targetDecl->AsClassDefinition()->Start().index + 1; + std::unordered_set methodSignature; + for (auto it : targetClassBodys) { + methodSignature.insert(MakeMethodSignature(it)); + } + + auto superClassDecl = GetSuperClassDefinition(targetDecl); + if (superClassDecl == nullptr || !superClassDecl->IsClassDefinition()) { + return res; + } + auto superClassBodys = superClassDecl->AsClassDefinition()->Body(); + for (const auto &method : superClassBodys) { + if (!method->IsAbstract()) { + continue; + } + auto signature = MakeMethodSignature(method); + if (methodSignature.count(signature) == 0) { + res.newText += MakeNewText(method); + } + } + return res; +} + +const int G_FIX_CLASS_NOT_IMPLEMENTING_INHERITED_MEMBERS = 1006; + +FixClassNotImplementingInheritedMembers::FixClassNotImplementingInheritedMembers() +{ + const char *fixClassNotImplementingInheritedMembersId = "FixClassNotImplementingInheritedMembers"; + SetErrorCodes({G_FIX_CLASS_NOT_IMPLEMENTING_INHERITED_MEMBERS}); + SetFixIds({fixClassNotImplementingInheritedMembersId}); +} + +std::vector FixClassNotImplementingInheritedMembers::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + if (context.span.length == 0) { + return returnedActions; + } + std::vector textChanges; + auto ctx = reinterpret_cast(context.context); + const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SEMANTIC); + for (const auto &diagnostic : diagnostics) { + auto index = lexer::LineIndex(ctx->parserProgram->SourceCode()); + auto offset = + index.GetOffset(lexer::SourceLocation(diagnostic->Line(), diagnostic->Offset(), ctx->parserProgram)); + size_t end = context.span.start + context.span.length; + if (offset < context.span.start || offset >= end) { + break; + } + textChanges.push_back(MakeTextChange(context.context, offset)); + } + CodeFixAction codeAction; + codeAction.changes.emplace_back(std::string(ctx->parserProgram->SourceFilePath()), textChanges); + codeAction.fixId = "FixClassNotImplementingInheritedMembers"; + returnedActions.push_back(codeAction); + return returnedActions; +} + +CombinedCodeActions FixClassNotImplementingInheritedMembers::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + CombinedCodeActions combinedCodeActions; + std::vector textChanges; + auto ctx = reinterpret_cast(codeFixAll.context); + const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SEMANTIC); + for (const auto &diagnostic : diagnostics) { + auto index = lexer::LineIndex(ctx->parserProgram->SourceCode()); + auto offset = + index.GetOffset(lexer::SourceLocation(diagnostic->Line(), diagnostic->Offset(), ctx->parserProgram)); + textChanges.push_back(MakeTextChange(codeFixAll.context, offset)); + } + combinedCodeActions.changes.emplace_back(std::string(ctx->parserProgram->SourceFilePath()), textChanges); + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_fixClassNotImplementingInheritedMembers( + "FixClassNotImplementingInheritedMembers"); + +} // namespace ark::es2panda::lsp \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index e50ecc4ac0..739388e5a4 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -211,6 +211,10 @@ ets2panda_add_gtest(lsp_api_test_code_fix_registration CPP_SOURCES code_fix_registration_test.cpp ) +ets2panda_add_gtest(lsp_api_test_fix_abstract_member CPP_SOURCES + fix_class_doesnt_implement_inherited_abstract_member_test.cpp +) + ets2panda_add_gtest(lsp_api_test_get_name_or_dotted_name_span CPP_SOURCES get_name_or_dotted_name_span_test.cpp -) \ No newline at end of file +) diff --git a/ets2panda/test/unit/lsp/code_fix_registration_test.cpp b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp index c493453dba..1918c0c7a5 100644 --- a/ets2panda/test/unit/lsp/code_fix_registration_test.cpp +++ b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp @@ -25,6 +25,6 @@ TEST(RefactorProviderRegistrationTest, RegistersConvertFunctionRefactor) const auto &fixIdToRegistration = provider.GetFixIdToRegistration(); EXPECT_FALSE(errors.empty()); EXPECT_FALSE(fixIdToRegistration.empty()); - EXPECT_EQ(errors.size(), 5); + EXPECT_EQ(errors.size(), 6); } } // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/fix_class_doesnt_implement_inherited_abstract_member_test.cpp b/ets2panda/test/unit/lsp/fix_class_doesnt_implement_inherited_abstract_member_test.cpp new file mode 100644 index 0000000000..be40871cb8 --- /dev/null +++ b/ets2panda/test/unit/lsp/fix_class_doesnt_implement_inherited_abstract_member_test.cpp @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "lsp/include/internal_api.h" +#include "lsp/include/types.h" +#include "lsp/include/register_code_fix/fix_class_doesnt_implement_inherited_abstract_member.h" +#include "lsp_api_test.h" +#include "public/es2panda_lib.h" +#include "lsp/include/code_fixes/code_fix_types.h" + +namespace { + +using ark::es2panda::lsp::Initializer; + +class LspFixAbstractMemberTests : public LSPAPITests { +public: + std::vector MockGetCodeActions(es2panda_Context *context, TextSpan span) + { + std::vector returnedActions; + if (span.length == 0) { + return returnedActions; + } + std::vector textChanges; + auto ctx = reinterpret_cast(context); + const auto &diagnostics = + ctx->diagnosticEngine->GetDiagnosticStorage(ark::es2panda::util::DiagnosticType::SEMANTIC); + ark::es2panda::lsp::FixClassNotImplementingInheritedMembers handle; + for (const auto &diagnostic : diagnostics) { + auto index = ark::es2panda::lexer::LineIndex(ctx->parserProgram->SourceCode()); + auto offset = index.GetOffset( + ark::es2panda::lexer::SourceLocation(diagnostic->Line(), diagnostic->Offset(), ctx->parserProgram)); + size_t end = span.start + span.length; + if (offset < span.start || offset >= end) { + break; + } + textChanges.push_back(handle.MakeTextChange(context, offset)); + } + ark::es2panda::lsp::CodeFixAction codeAction; + codeAction.changes.emplace_back(std::string(ctx->parserProgram->SourceFilePath()), textChanges); + codeAction.fixId = "FixClassNotImplementingInheritedMembers"; + returnedActions.push_back(codeAction); + return returnedActions; + } + + std::vector MockGetAllCodeActions(es2panda_Context *context) + { + std::vector returnedActions; + std::vector textChanges; + auto ctx = reinterpret_cast(context); + const auto &diagnostics = + ctx->diagnosticEngine->GetDiagnosticStorage(ark::es2panda::util::DiagnosticType::SEMANTIC); + ark::es2panda::lsp::FixClassNotImplementingInheritedMembers handle; + for (const auto &diagnostic : diagnostics) { + auto index = ark::es2panda::lexer::LineIndex(ctx->parserProgram->SourceCode()); + auto offset = index.GetOffset( + ark::es2panda::lexer::SourceLocation(diagnostic->Line(), diagnostic->Offset(), ctx->parserProgram)); + textChanges.push_back(handle.MakeTextChange(context, offset)); + } + ark::es2panda::lsp::CodeFixAction codeAction; + codeAction.changes.emplace_back(std::string(ctx->parserProgram->SourceFilePath()), textChanges); + codeAction.fixId = "FixClassNotImplementingInheritedMembers"; + returnedActions.push_back(codeAction); + return returnedActions; + } +}; + +TEST_F(LspFixAbstractMemberTests, getCodeActionsToFixClassNotImplementingInheritedMembers1) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("LspFixAbstractMemberTests_001.ets", ES2PANDA_STATE_CHECKED, R"(abstract class A { + abstract foo(a:number, b:number): number; + abstract foo1(a:number, b:number); +} + +class B extends A { + foo(a: number, b: number): number {} +})"); + const size_t start = 109; + ark::es2panda::lsp::FixClassNotImplementingInheritedMembers handle; + auto result = handle.MakeTextChange(ctx, start); + std::string expectedNewText = " foo1(a: number, b: number) {}\n"; + const size_t expectedStart = 122; + const size_t expectedLength = 0; + ASSERT_EQ(result.newText, expectedNewText); + ASSERT_EQ(result.span.start, expectedStart); + ASSERT_EQ(result.span.length, expectedLength); + initializer.DestroyContext(ctx); +} + +TEST_F(LspFixAbstractMemberTests, getCodeActionsToFixClassNotImplementingInheritedMembers2) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("LspFixAbstractMemberTests_002.ets", ES2PANDA_STATE_CHECKED, R"(abstract class A { + abstract foo(a:number, b:number): number; + abstract foo1(a:number, b:number); +} + +class B extends A { +}; +class C extends A { +})"); + const size_t start = 109; + const size_t length = 20; + auto result = MockGetCodeActions(ctx, {start, length}); + std::string expectedNewText = " foo(a: number, b: number): number {}\n foo1(a: number, b: number) {}\n"; + std::string expectedFileName = "LspFixAbstractMemberTests_002.ets"; + const size_t expectedStart = 122; + const size_t expectedLength = 0; + ASSERT_EQ(result[0].changes[0].fileName, expectedFileName); + ASSERT_EQ(result[0].changes[0].textChanges[0].newText, expectedNewText); + ASSERT_EQ(result[0].changes[0].textChanges[0].span.start, expectedStart); + ASSERT_EQ(result[0].changes[0].textChanges[0].span.length, expectedLength); + initializer.DestroyContext(ctx); +} + +TEST_F(LspFixAbstractMemberTests, getCodeActionsToFixClassNotImplementingInheritedMembers3) +{ + Initializer initializer = Initializer(); + es2panda_Context *ctx = + initializer.CreateContext("LspFixAbstractMemberTests_003.ets", ES2PANDA_STATE_CHECKED, R"(abstract class A { + abstract foo(a:number, b:number): number; + abstract foo1(a:number, b:number); +} + +class B extends A { +}; +class C extends A { +})"); + auto result = MockGetAllCodeActions(ctx); + std::string expectedNewText = " foo(a: number, b: number): number {}\n foo1(a: number, b: number) {}\n"; + std::string expectedFileName = "LspFixAbstractMemberTests_003.ets"; + const size_t expectedStart = 122; + const size_t expectedStart2 = 145; + const size_t expectedLength = 0; + ASSERT_EQ(result[0].changes[0].fileName, expectedFileName); + ASSERT_EQ(result[0].changes[0].textChanges[0].newText, expectedNewText); + ASSERT_EQ(result[0].changes[0].textChanges[0].span.start, expectedStart); + ASSERT_EQ(result[0].changes[0].textChanges[0].span.length, expectedLength); + ASSERT_EQ(result[0].changes[0].fileName, expectedFileName); + ASSERT_EQ(result[0].changes[0].textChanges[1].newText, expectedNewText); + ASSERT_EQ(result[0].changes[0].textChanges[1].span.start, expectedStart2); + ASSERT_EQ(result[0].changes[0].textChanges[1].span.length, expectedLength); + initializer.DestroyContext(ctx); +} +} // namespace \ No newline at end of file -- Gitee From 308a8ffade25befe7b29e949622d409c45d21c6a Mon Sep 17 00:00:00 2001 From: Sizov Nikita Date: Tue, 3 Jun 2025 16:46:00 +0300 Subject: [PATCH 046/747] Add u4 IR node Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICB9UX?from=project-issue Change-Id: Ib2d04fad99d508d72eccf4bfae693922e08f08d4 Signed-off-by: Sizov Nikita --- ets2panda/ir/irnode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/ir/irnode.h b/ets2panda/ir/irnode.h index bf462a5ef8..84f269da1f 100644 --- a/ets2panda/ir/irnode.h +++ b/ets2panda/ir/irnode.h @@ -51,7 +51,7 @@ enum class OperandKind { enum class OperandType { REF, // ref - B32, // u1 u2 i8 u8 i16 u16 i32 u32 b32 f32 + B32, // u1 u2 u4 i8 u8 i16 u16 i32 u32 b32 f32 B64, // i64, f64, b64 ANY, // any NONE -- Gitee From 36c1abc85c2b67264b5e565663085ad3c7e33375 Mon Sep 17 00:00:00 2001 From: zhongning Date: Wed, 4 Jun 2025 18:33:13 +0800 Subject: [PATCH 047/747] Rename arkts-no-debugger-stmt Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCJGE Test scenarios:new tests update to the linter Signed-off-by: zhongning --- ets2panda/linter/src/lib/CookBookMsg.ts | 2 +- ets2panda/linter/src/lib/HomeCheck.ts | 2 +- ets2panda/linter/src/lib/TypeScriptLinter.ts | 4 +- .../linter/src/lib/autofixes/AutofixTitles.ts | 1 - .../linter/src/lib/autofixes/Autofixer.ts | 6 --- .../main/debugger_statememt.ets.args.json | 4 +- .../main/debugger_statememt.ets.arkts2.json | 4 +- .../main/debugger_statememt.ets.autofix.json | 52 ------------------- .../main/debugger_statememt.ets.migrate.ets | 22 -------- .../main/debugger_statememt.ets.migrate.json | 17 ------ 10 files changed, 7 insertions(+), 107 deletions(-) delete mode 100644 ets2panda/linter/test/main/debugger_statememt.ets.autofix.json delete mode 100644 ets2panda/linter/test/main/debugger_statememt.ets.migrate.ets delete mode 100644 ets2panda/linter/test/main/debugger_statememt.ets.migrate.json diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index 62c12d1403..09564fae6b 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -236,7 +236,7 @@ cookBookTag[198] = 'Class TS overloading is not supported(arkts-no-ts-overload)' cookBookTag[199] = 'Sendable containers are not supported (arkts-no-need-stdlib-sendable-containers)'; cookBookTag[202] = 'Literal types are restricted(arkts-limited-literal-types)'; cookBookTag[203] = 'exponent opartions "**" and "**=" are disabled (arkts-no-exponent-op)'; -cookBookTag[206] = '"debugger" is not supported (arkts-no-debugger-stmt)'; +cookBookTag[206] = '"debugger" is not supported (arkts-no-debugger)'; cookBookTag[207] = 'Special arguments object inside functions are not supported (arkts-no-arguments-obj)'; cookBookTag[208] = 'Tagged templates are not supported (arkts-no-tagged-templates)'; cookBookTag[209] = 'The index expression must be of a numeric type (arkts-array-index-expr-type)'; diff --git a/ets2panda/linter/src/lib/HomeCheck.ts b/ets2panda/linter/src/lib/HomeCheck.ts index a8845c1999..2562aca418 100644 --- a/ets2panda/linter/src/lib/HomeCheck.ts +++ b/ets2panda/linter/src/lib/HomeCheck.ts @@ -46,7 +46,7 @@ export function getHomeCheckConfigInfo(cmdOptions: CommandLineOptions): { }); const languageTags = new Map(); inputFiles.forEach((file) => { - languageTags.set(file, 2); + languageTags.set(path.normalize(file), 2); }); const ruleConfigInfo = { ruleSet: ['plugin:@migration/all'], diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 4caeea6c34..17a171330c 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -6107,8 +6107,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2) { return; } - const autofix = this.autofixer?.fixDebuggerStatement(node as ts.DebuggerStatement); - this.incrementCounters(node, FaultID.DebuggerStatement, autofix); + + this.incrementCounters(node, FaultID.DebuggerStatement); } private handleTSOverload(decl: ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration): void { diff --git a/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts b/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts index 8b54a99d03..25eee895a5 100644 --- a/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts +++ b/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts @@ -39,7 +39,6 @@ export const cookBookRefToFixTitle: Map = new Map([ [180, 'Remove the decorator'], [189, 'Add type annotations to numerical variables'], [193, 'Replace with arrow function'], - [206, 'Replace with a special library to call'], [209, 'Transform "number" to "int"'], [251, 'Transform "!!" to "$$()"'], [252, 'Transform "$$" to "$$()"'], diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index dd1918fbf2..4639a77ea6 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -2621,12 +2621,6 @@ export class Autofixer { return { pattern, flag }; } - fixDebuggerStatement(debuggerStmt: ts.DebuggerStatement): Autofix[] { - void this; - const text = SPECIAL_LIB_NAME + '.debugger();'; - return [{ start: debuggerStmt.getStart(), end: debuggerStmt.getEnd(), replacementText: text }]; - } - /* * "unsafe" (result is not common subset) autofixes */ diff --git a/ets2panda/linter/test/main/debugger_statememt.ets.args.json b/ets2panda/linter/test/main/debugger_statememt.ets.args.json index f56752f228..4acc088d1d 100644 --- a/ets2panda/linter/test/main/debugger_statememt.ets.args.json +++ b/ets2panda/linter/test/main/debugger_statememt.ets.args.json @@ -14,8 +14,6 @@ "limitations under the License." ], "mode": { - "arkts2": "", - "autofix": "--arkts-2", - "migrate": "--arkts-2" + "arkts2": "" } } \ No newline at end of file diff --git a/ets2panda/linter/test/main/debugger_statememt.ets.arkts2.json b/ets2panda/linter/test/main/debugger_statememt.ets.arkts2.json index a220a01038..09196c4c33 100644 --- a/ets2panda/linter/test/main/debugger_statememt.ets.arkts2.json +++ b/ets2panda/linter/test/main/debugger_statememt.ets.arkts2.json @@ -21,7 +21,7 @@ "endColumn": 10, "problem": "DebuggerStatement", "suggest": "", - "rule": "\"debugger\" is not supported (arkts-no-debugger-stmt)", + "rule": "\"debugger\" is not supported (arkts-no-debugger)", "severity": "ERROR" }, { @@ -31,7 +31,7 @@ "endColumn": 12, "problem": "DebuggerStatement", "suggest": "", - "rule": "\"debugger\" is not supported (arkts-no-debugger-stmt)", + "rule": "\"debugger\" is not supported (arkts-no-debugger)", "severity": "ERROR" } ] diff --git a/ets2panda/linter/test/main/debugger_statememt.ets.autofix.json b/ets2panda/linter/test/main/debugger_statememt.ets.autofix.json deleted file mode 100644 index 6c9d73e3d1..0000000000 --- a/ets2panda/linter/test/main/debugger_statememt.ets.autofix.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [ - { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 10, - "problem": "DebuggerStatement", - "autofix": [ - { - "start": 605, - "end": 614, - "replacementText": "specialAutofixLib.debugger();" - } - ], - "suggest": "", - "rule": "\"debugger\" is not supported (arkts-no-debugger-stmt)", - "severity": "ERROR" - }, - { - "line": 19, - "column": 3, - "endLine": 19, - "endColumn": 12, - "problem": "DebuggerStatement", - "autofix": [ - { - "start": 633, - "end": 642, - "replacementText": "specialAutofixLib.debugger();" - } - ], - "suggest": "", - "rule": "\"debugger\" is not supported (arkts-no-debugger-stmt)", - "severity": "ERROR" - } - ] -} \ No newline at end of file diff --git a/ets2panda/linter/test/main/debugger_statememt.ets.migrate.ets b/ets2panda/linter/test/main/debugger_statememt.ets.migrate.ets deleted file mode 100644 index 04eeeb8969..0000000000 --- a/ets2panda/linter/test/main/debugger_statememt.ets.migrate.ets +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -specialAutofixLib.debugger(); - -function a() { - specialAutofixLib.debugger(); -} - -console.log('debugger'); \ No newline at end of file diff --git a/ets2panda/linter/test/main/debugger_statememt.ets.migrate.json b/ets2panda/linter/test/main/debugger_statememt.ets.migrate.json deleted file mode 100644 index ca88f857e9..0000000000 --- a/ets2panda/linter/test/main/debugger_statememt.ets.migrate.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "copyright": [ - "Copyright (c) 2025 Huawei Device Co., Ltd.", - "Licensed under the Apache License, Version 2.0 (the 'License');", - "you may not use this file except in compliance with the License.", - "You may obtain a copy of the License at", - "", - "http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an 'AS IS' BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License." - ], - "result": [] -} \ No newline at end of file -- Gitee From 03167a379eac3be6c3ab9dcca4dca6f9d070b4dd Mon Sep 17 00:00:00 2001 From: mozgovoykirill Date: Fri, 16 May 2025 18:08:12 +0300 Subject: [PATCH 048/747] Static library libes2panda-public for windows Issue:#IC8FIB Testing:'ninja all tests' Signed-off-by: mozgovoykirill --- ets2panda/public/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ets2panda/public/CMakeLists.txt b/ets2panda/public/CMakeLists.txt index 12227ac6fe..cb015aa58c 100644 --- a/ets2panda/public/CMakeLists.txt +++ b/ets2panda/public/CMakeLists.txt @@ -629,6 +629,9 @@ set(ES2PANDA_PUBLIC_SOURCES ../util/plugin.cpp ) +if (PANDA_TARGET_WINDOWS) + set(CMAKE_STATIC_LIBRARY_SUFFIX ".lib") +endif() panda_add_library(es2panda-public ${PANDA_DEFAULT_LIB_TYPE} ${ES2PANDA_PUBLIC_SOURCES}) add_dependencies(es2panda-lib gen_api) -- Gitee From c81c113d2a9e3e9889a7a546bb134d5be460b52e Mon Sep 17 00:00:00 2001 From: lihao Date: Thu, 5 Jun 2025 16:52:34 +0800 Subject: [PATCH 049/747] bugfix:file based hybrid compile Issue: [Bug]: bugfix:file based hybrid compile https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCY71 Signed-off-by: lihao --- .../driver/build_system/src/build/generate_arktsconfig.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts index 0c71605418..197b6efdd6 100644 --- a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts +++ b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts @@ -171,7 +171,8 @@ export class ArkTSConfigGenerator { } const entryFilePath = moduleInfo.entryFile; const firstLine = fs.readFileSync(entryFilePath, 'utf-8').split('\n')[0]; - if (firstLine.includes('use static')) { + // If the file is an ArkTS 1.2 implementation, configure the path in pathSection. + if (moduleInfo.language === LANGUAGE_VERSION.ARKTS_1_2 || moduleInfo.language === LANGUAGE_VERSION.ARKTS_HYBRID && firstLine.includes('use static')) { this.pathSection[moduleInfo.packageName] = [ path.resolve(moduleInfo.moduleRootPath, moduleInfo.sourceRoots[0]) ]; @@ -254,7 +255,7 @@ export class ArkTSConfigGenerator { } }; - if (moduleInfo.entryFile) { + if (moduleInfo.entryFile && moduleInfo.language === LANGUAGE_VERSION.ARKTS_HYBRID) { const entryFilePath = moduleInfo.entryFile; const stat = fs.statSync(entryFilePath); if (fs.existsSync(entryFilePath) && stat.isFile()) { -- Gitee From 8e29c9aa69c7d6d544d454b37753819dda8dc410 Mon Sep 17 00:00:00 2001 From: xuhangqi Date: Fri, 30 May 2025 17:30:37 +0800 Subject: [PATCH 050/747] Fix soft link Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBQOQ Signed-off-by: xuhangqi Change-Id: I5e0204e8e0d0f11f90044b5da0c79fa934593862 --- ets2panda/driver/build_system/README.md | 14 ++++ ets2panda/driver/build_system/jest.config.js | 20 ++++++ ets2panda/driver/build_system/package.json | 4 +- .../src/build/generate_arktsconfig.ts | 17 ++--- .../driver/build_system/src/error_code.ts | 1 + ets2panda/driver/build_system/src/utils.ts | 21 ++++++ .../build_system/test/ut/safeRealpath.test.ts | 72 +++++++++++++++++++ 7 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 ets2panda/driver/build_system/jest.config.js create mode 100644 ets2panda/driver/build_system/test/ut/safeRealpath.test.ts diff --git a/ets2panda/driver/build_system/README.md b/ets2panda/driver/build_system/README.md index 55498874a8..d685a1014e 100644 --- a/ets2panda/driver/build_system/README.md +++ b/ets2panda/driver/build_system/README.md @@ -50,3 +50,17 @@ Then run the following command to build npm run mixed_hap:gen_abc # build demo_mix_hap npm run demo_hap:gen_abc # build demo_hap ``` + +### step5 +Run tests (using Jest) +Jest is almost ready to use out of the box. +The test file path has been configured through jest.config.js. +In the build_system/test directory, scan for test files with the suffix .test.ts +Install Jest and its TypeScript support libraries +```bash +npm install --save-dev jest ts-jest @types/jest +``` +To run tests: +```bash +npm run ut_test +``` \ No newline at end of file diff --git a/ets2panda/driver/build_system/jest.config.js b/ets2panda/driver/build_system/jest.config.js new file mode 100644 index 0000000000..a3c4407a95 --- /dev/null +++ b/ets2panda/driver/build_system/jest.config.js @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['/test/**/*.test.ts'], +}; \ No newline at end of file diff --git a/ets2panda/driver/build_system/package.json b/ets2panda/driver/build_system/package.json index 597e3abe96..4aa6431aec 100644 --- a/ets2panda/driver/build_system/package.json +++ b/ets2panda/driver/build_system/package.json @@ -13,7 +13,9 @@ "mixed_hap:gen_abc": "node ./dist/entry.js test/demo_mix_hap/build_config.json", "mixed_hap:run": "npm run mixed_hap:gen_decl && npm run mixed_hap:gen_abc", - "demo_hap:gen_abc": "npm run build && node ./dist/entry.js test/demo_hap/build_config.json" + "demo_hap:gen_abc": "npm run build && node ./dist/entry.js test/demo_hap/build_config.json", + + "ut_test": "jest test/ut" }, "devDependencies": { "typescript": "^5.0.0", diff --git a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts index 0c71605418..340b3d0e57 100644 --- a/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts +++ b/ets2panda/driver/build_system/src/build/generate_arktsconfig.ts @@ -26,7 +26,8 @@ import { } from '../error_code'; import { changeFileExtension, - ensurePathExists + ensurePathExists, + safeRealpath } from '../utils'; import { BuildConfig, @@ -68,17 +69,17 @@ export class ArkTSConfigGenerator { private logger: Logger; private constructor(buildConfig: BuildConfig, moduleInfos: Map) { - let pandaStdlibPath: string = buildConfig.pandaStdlibPath ?? - path.resolve(buildConfig.pandaSdkPath!!, 'lib', 'stdlib'); - this.stdlibStdPath = path.resolve(pandaStdlibPath, 'std'); - this.stdlibEscompatPath = path.resolve(pandaStdlibPath, 'escompat'); - this.systemSdkPath = path.resolve(buildConfig.buildSdkPath, SYSTEM_SDK_PATH_FROM_SDK); + this.logger = Logger.getInstance(); + const realPandaSdkPath = safeRealpath(buildConfig.pandaSdkPath!!, this.logger); + const realBuildSdkPath = safeRealpath(buildConfig.buildSdkPath, this.logger); + const realPandaStdlibPath = buildConfig.pandaStdlibPath ?? path.resolve(realPandaSdkPath, 'lib', 'stdlib'); + this.stdlibStdPath = path.resolve(realPandaStdlibPath, 'std'); + this.stdlibEscompatPath = path.resolve(realPandaStdlibPath, 'escompat'); + this.systemSdkPath = path.resolve(realBuildSdkPath, SYSTEM_SDK_PATH_FROM_SDK); this.externalApiPaths = buildConfig.externalApiPaths; this.moduleInfos = moduleInfos; this.pathSection = {}; - - this.logger = Logger.getInstance(); } public static getInstance(buildConfig?: BuildConfig, moduleInfos?: Map): ArkTSConfigGenerator { diff --git a/ets2panda/driver/build_system/src/error_code.ts b/ets2panda/driver/build_system/src/error_code.ts index 25da0af026..8ec79285a6 100644 --- a/ets2panda/driver/build_system/src/error_code.ts +++ b/ets2panda/driver/build_system/src/error_code.ts @@ -37,4 +37,5 @@ export enum ErrorCode { BUILDSYSTEM_Dependency_Analyzer_NOT_FOUND_FAIL = '11410016', BUILDSYSTEM_ABC_FILE_MISSING_IN_BCHAR = '11410017', BUILDSYSTEM_HANDLE_ENTRY_FILE = '11410018', + BUILDSYSTEM_PATH_RESOLVE_FAIL = '11410019' } diff --git a/ets2panda/driver/build_system/src/utils.ts b/ets2panda/driver/build_system/src/utils.ts index 2e6919a9a9..33ca3c7c53 100644 --- a/ets2panda/driver/build_system/src/utils.ts +++ b/ets2panda/driver/build_system/src/utils.ts @@ -18,6 +18,12 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { DECL_ETS_SUFFIX } from './pre_define'; +import { + Logger, + LogData, + LogDataFactory +} from './logger'; +import { ErrorCode } from './error_code'; const WINDOWS: string = 'Windows_NT'; const LINUX: string = 'Linux'; @@ -82,3 +88,18 @@ export function readFirstLineSync(filePath: string): string | null { return firstLine; } + +export function safeRealpath(path: string, logger: Logger): string { + try { + return fs.realpathSync(path); + } catch(error) { + const msg = error instanceof Error ? error.message : String(error); + const logData: LogData = LogDataFactory.newInstance( + ErrorCode.BUILDSYSTEM_PATH_RESOLVE_FAIL, + `Error resolving path "${path}".`, + msg + ); + logger.printError(logData); + throw logData; + } +} diff --git a/ets2panda/driver/build_system/test/ut/safeRealpath.test.ts b/ets2panda/driver/build_system/test/ut/safeRealpath.test.ts new file mode 100644 index 0000000000..788945ee41 --- /dev/null +++ b/ets2panda/driver/build_system/test/ut/safeRealpath.test.ts @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as path from 'path'; +import * as fs from 'fs'; +import { safeRealpath } from '../../src/utils'; +import { ErrorCode } from '../../src/error_code'; +import { Logger } from '../../src/logger'; + +describe('safeRealpath', () => { + const tempDir = path.join(__dirname, 'tmp'); + const realDir = path.join(tempDir, 'real'); + const linkDir = path.join(tempDir, 'link'); + const nonExistent = path.join(tempDir, 'does-not-exist'); + + const mockLogger = { + printError: jest.fn() + } as unknown as Logger; + + beforeAll(() => { + fs.mkdirSync(tempDir, { recursive: true }); + fs.mkdirSync(realDir, { recursive: true }); + + if (!fs.existsSync(linkDir)) { + fs.symlinkSync(realDir, linkDir, 'dir'); + } + }); + + afterAll(() => { + fs.rmSync(tempDir, { recursive: true, force: true }); + }); + + test('returns real path for existing non-symlink', () => { + const result = safeRealpath(realDir, mockLogger); + expect(result).toBe(fs.realpathSync(realDir)); + }); + + test('returns resolved path for symlink', () => { + const result = safeRealpath(linkDir, mockLogger); + expect(result).toBe(fs.realpathSync(linkDir)); + expect(result).toBe(realDir); + }); + + test('throws error for non-existent path', () => { + try { + safeRealpath(nonExistent, mockLogger); + } catch (e: any) { + expect(e.code).toBe(ErrorCode.BUILDSYSTEM_PATH_RESOLVE_FAIL); + } + }); + + test('throws error for empty path string', () => { + try { + safeRealpath('', mockLogger); + } catch (e: any) { + expect(e.code).toBe(ErrorCode.BUILDSYSTEM_PATH_RESOLVE_FAIL); + } + }); + +}); -- Gitee From 7856b7dd59387eafb318771e834e13194ff17c0f Mon Sep 17 00:00:00 2001 From: nadolskyanton Date: Thu, 5 Jun 2025 15:55:00 +0300 Subject: [PATCH 051/747] SrcDumper: fix improper export dump Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCZ1A Description: Fixed SrcDump for export statement Signed-off-by: nadolskyanton --- .../ir/module/importNamespaceSpecifier.cpp | 4 +- .../srcdumper/srcdumper-ets-ignored.txt | 159 ++---------------- 2 files changed, 20 insertions(+), 143 deletions(-) diff --git a/ets2panda/ir/module/importNamespaceSpecifier.cpp b/ets2panda/ir/module/importNamespaceSpecifier.cpp index 5519952e54..4425928858 100644 --- a/ets2panda/ir/module/importNamespaceSpecifier.cpp +++ b/ets2panda/ir/module/importNamespaceSpecifier.cpp @@ -43,7 +43,9 @@ void ImportNamespaceSpecifier::Dump(ir::AstDumper *dumper) const void ImportNamespaceSpecifier::Dump(ir::SrcDumper *dumper) const { dumper->Add("* "); - dumper->Add("as "); + if (!local_->Name().Empty()) { + dumper->Add("as "); + } local_->Dump(dumper); } diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index 218f408204..41eeda0c92 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -7,160 +7,35 @@ parser/ets/string_template_3.ets parser/ets/string_template_4.ets # FailKind.SRC_DUMPER_FAIL (Issue #20458) -runtime/ets/annotation_tests/AnnotationForDifferentTypes.ets -runtime/ets/annotation_tests/AnnotationForTypesInDifferentCase.ets -ast/compiler/ets/async_import_1.ets -ast/compiler/ets/optionalClassProperty1.ets -ast/compiler/ets/ambient_interface/use_interface.ets -ast/parser/ets/import_tests/enum/import.ets +ast/compiler/ets/namespace_tests/Import_ambient_namespace.ets +ast/compiler/ets/namespace_tests/declare_namespace.ets ast/parser/ets/import_tests/export_and_import_class.ets ast/parser/ets/import_tests/export_and_import_top_level.ets -ast/parser/ets/re_export/import_11.ets -ast/parser/ets/re_export/import_12.ets -ast/parser/ets/re_export/export_5.ets -ast/parser/ets/re_export/export_6.ets -ast/parser/ets/re_export/re_export_11.ets -ast/parser/ets/re_export/re_export_12.ets -ast/parser/ets/re_export/re_export_5.ets -ast/parser/ets/re_export/re_export_7.ets -ast/parser/ets/record_lower_phase_external_main.ets -ast/parser/ets/unresolved_reference_argname_main.ets -compiler/ets/abstractNewClassInstanceExpression.ets -runtime/ets/implicit_package_import_1.ets -runtime/ets/implicit_package_import_2.ets -compiler/ets/implicit_package_import/package_test_1/package_module_1.ets -compiler/ets/implicit_package_import/package_test_1/package_module_2.ets -compiler/ets/implicit_package_import/package_test_2/subpackage_1/package_module_1.ets -compiler/ets/implicit_package_import/package_test_2/subpackage_1/package_module_2.ets -compiler/ets/import_tests/asyncfunc_lambda_main.ets -compiler/ets/import_tests/enum_import.ets -compiler/ets/import_tests/generic_typealias_func_type.ets -compiler/ets/import_tests/import_class_with_getters_setters.ets -compiler/ets/import_tests/infer_imported_function_return_type.ets -compiler/ets/import_tests/re-export_with_alias/import_aliased_re-export.ets -compiler/ets/import_tests/re-export_with_alias/re-export_with_alias.ets -compiler/ets/import_tests/selective_export_tests/import_interface.ets -compiler/ets/import_tests/selective_export_tests/import_selective_exported.ets -compiler/ets/import_tests/selective_export_tests/selective_import_with_alias_1.ets -compiler/ets/import_tests/selective_export_tests/selective_import_with_alias_2.ets -compiler/ets/import_type.ets -runtime/ets/CastPrimitive.ets -runtime/ets/ClassNewInstance.ets -runtime/ets/conditionalExpressionGenericLUB.ets -runtime/ets/dynmicImportUnimplemented.ets -runtime/ets/finallyTryAbruptedByContinue.ets -runtime/ets/funcRefWithRestArguments.ets -runtime/ets/generics_1.ets -runtime/ets/labeledStatement.ets -runtime/ets/newArrayCreationUnionType.ets -runtime/ets/type_param_in_union.ets -ast/parser/ets/re_export/import_18.ets -ast/parser/ets/re_export/import_19.ets -ast/parser/ets/re_export/import_20.ets -ast/parser/ets/re_export/re_export_13.ets -ast/parser/ets/re_export/re_export_14.ets -ast/parser/ets/re_export/re_export_15.ets -ast/parser/ets/re_export/re_export_16.ets +compiler/ets/generic_arrayaslist.ets +compiler/ets/returnTypeGenericArray.ets parser/ets/ambient_indexer_1.ets parser/ets/ambient_indexer_6.ets -parser/ets/conversions.ets -parser/ets/declare_namespace.ets -runtime/ets/namespace_tests/namespace_import_type_test/namespace_export.ets -parser/ets/declare_namespace_2.ets -parser/ets/declare_namespace_3.ets -parser/ets/declare_namespace_4.ets -ast/compiler/ets/namespace_tests/declare_namespace.ets -ast/compiler/ets/namespace_tests/Import_ambient_namespace.ets -parser/ets/import_tests/diamond/test1.ets -parser/ets/import_tests/diamond/test2.ets -parser/ets/import_tests/diamond/test3.ets -parser/ets/import_tests/duplicated/extdef.ets -parser/ets/import_tests/duplicated/extusedef.ets -parser/ets/import_tests/import_alias/import_alias_1.ets -parser/ets/import_tests/import_all_type_alias.ets -parser/ets/import_tests/import_diff_paths.ets -parser/ets/import_tests/import_extension/import_extension.ets -parser/ets/import_tests/import_function_overload.ets -parser/ets/import_tests/import_interface_test.ets -parser/ets/import_tests/import_interface_test_2.ets -parser/ets/import_tests/modules/module1/src/re_export_file.ets -parser/ets/import_tests/modules/module2/src/import_file.ets -parser/ets/import_tests/modules/module2/src/re_export_file_2.ets -parser/ets/import_tests/modules/test_lib2.ets -parser/ets/import_tests/relative_import/Line.ets -parser/ets/import_tests/relative_import/alias1.ets -parser/ets/import_tests/repeat.ets -parser/ets/import_tests/subsequent_relative_imports/folder1/file1.ets -parser/ets/import_tests/subsequent_relative_imports/folder2/file2.ets +parser/ets/array_creation_expression.ets parser/ets/labeledDoWhileStatement.ets parser/ets/labeledForStatement.ets parser/ets/labeledSwitchStatement.ets parser/ets/labeledWhileStatement.ets -parser/ets/lambda_import_alias_1-2.ets -parser/ets/lambda_import_alias_1.ets -parser/ets/promiseCasting.ets -parser/ets/re_export/diamond/B.ets -parser/ets/re_export/diamond/B2.ets -parser/ets/re_export/diamond/C.ets -parser/ets/re_export/diamond/C2.ets -parser/ets/re_export/diamond/D.ets -parser/ets/re_export/diamond/D2.ets -parser/ets/re_export/folder/re_export_6.ets -parser/ets/re_export/folder/re_export_7.ets -parser/ets/re_export/folderIndex/index.ets -parser/ets/re_export/folderIndex2/index.ets -parser/ets/re_export/import.ets -parser/ets/re_export/import_10.ets -parser/ets/re_export/import_11.ets -parser/ets/re_export/import_12.ets -parser/ets/re_export/import_13.ets -parser/ets/re_export/import_14.ets -parser/ets/re_export/import_15.ets -parser/ets/re_export/import_2.ets -parser/ets/re_export/import_3.ets -parser/ets/re_export/import_6.ets -parser/ets/re_export/import_7.ets -parser/ets/re_export/import_8.ets -parser/ets/re_export/import_9.ets -parser/ets/re_export/re_export.ets -parser/ets/re_export/re_export_10.ets -parser/ets/re_export/re_export_11.ets -parser/ets/re_export/re_export_12.ets -parser/ets/re_export/re_export_2.ets -parser/ets/re_export/re_export_3.ets -parser/ets/re_export/re_export_4.ets -parser/ets/re_export/re_export_5.ets -parser/ets/re_export/re_export_7.ets -parser/ets/re_export/re_export_8.ets -parser/ets/re_export/re_export_9.ets -parser/ets/selective_export/import_1.ets -parser/ets/selective_export/import_2.ets -parser/ets/selective_export/import_3.ets -parser/ets/selective_export/import_4.ets -parser/ets/test-type-alias-call8.ets -parser/ets/import_tests/packages/import_package_with_alias/import_package_with_alias.ets -parser/ets/re_export/import_index.ets -parser/ets/re_export/import_index_2.ets -parser/ets/re_export/import_index_3.ets -parser/ets/import_folder.ets -parser/ets/import_tests/import_relative_path.ets -runtime/ets/Multiline_string_escape_char.ets +runtime/ets/ClassNewInstance.ets runtime/ets/Multiline_string.ets +runtime/ets/Multiline_string_escape_char.ets +runtime/ets/finallyTryAbruptedByContinue.ets runtime/ets/generic-set.ets -compiler/ets/generic_arrayaslist.ets -compiler/ets/returnTypeGenericArray.ets -parser/ets/array_creation_expression.ets -runtime/ets/re_export/export/reexport_elements1.ets -runtime/ets/re_export/export/reexport_elements2.ets -runtime/ets/re_export/import.ets -ast/compiler/ets/package_initializer_warning/P3/P3.ets -ast/compiler/ets/package_initializer_warning/main_test.ets -runtime/ets/import_declare_type_alias.ets -ast/compiler/ets/import_type_without_export.ets -ast/compiler/ets/type_binding_01.ets -ast/compiler/ets/type_binding_02.ets +runtime/ets/generics_1.ets +runtime/ets/labeledStatement.ets +runtime/ets/namespace_tests/namespace_import_type_test/namespace_export.ets +runtime/ets/newArrayCreationUnionType.ets + # FailKind.ES2PANDA_FAIL +compiler/ets/abstractNewClassInstanceExpression.ets +runtime/ets/conditionalExpressionGenericLUB.ets +runtime/ets/funcRefWithRestArguments.ets +runtime/ets/type_param_in_union.ets runtime/ets/StringFasta.ets runtime/ets/struct-identifier.ets runtime/ets/struct-init2.ets -- Gitee From 345cb1d8045b684fdc0d6da1cf6fcdc204798519 Mon Sep 17 00:00:00 2001 From: Vsevolod Pukhov Date: Mon, 19 May 2025 16:49:56 +0300 Subject: [PATCH 052/747] Any type * Add Any built-in type and type relations * Make Any a new top boundary type * Refactor TypeKind flag computer * Remove IsConditionalExprType concept * Simplify codegen for narrowings Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICB3H9 Signed-off-by: Vsevolod Pukhov --- ets2panda/BUILD.gn | 1 + ets2panda/CMakeLists.txt | 1 + .../invariants/identifierHasVariable.cpp | 17 ++- ets2panda/checker/ETSAnalyzer.cpp | 15 ++- ets2panda/checker/ETSAnalyzerHelpers.cpp | 3 +- ets2panda/checker/ETSchecker.cpp | 29 ++++- ets2panda/checker/ETSchecker.h | 14 +-- ets2panda/checker/ets/aliveAnalyzer.cpp | 6 +- ets2panda/checker/ets/arithmetic.cpp | 15 +-- ets2panda/checker/ets/helpers.cpp | 2 +- ets2panda/checker/ets/object.cpp | 4 +- ets2panda/checker/ets/typeCheckingHelpers.cpp | 38 +++--- ets2panda/checker/ets/typeConverter.h | 4 +- ets2panda/checker/ets/typeCreation.cpp | 4 +- ets2panda/checker/ets/utilityTypeHandlers.cpp | 8 ++ ets2panda/checker/types/ets/etsAnyType.cpp | 112 +++++++++++++++++ ets2panda/checker/types/ets/etsAnyType.h | 49 ++++++++ .../checker/types/ets/etsFunctionType.cpp | 2 +- ets2panda/checker/types/ets/types.h | 1 + ets2panda/checker/types/globalTypesHolder.cpp | 16 ++- ets2panda/checker/types/globalTypesHolder.h | 10 +- ets2panda/checker/types/type.h | 5 - ets2panda/checker/types/typeFlag.h | 9 +- ets2panda/checker/types/typeMapping.h | 3 +- ets2panda/compiler/base/condition.cpp | 1 - ets2panda/compiler/core/ETSCompiler.cpp | 1 + ets2panda/compiler/core/ETSGen.cpp | 43 +++---- ets2panda/compiler/core/ETSGen.h | 16 +++ .../lowering/ets/arrayLiteralLowering.cpp | 2 +- .../lowering/ets/declareOverloadLowering.cpp | 6 +- .../lowering/ets/enumPostCheckLowering.cpp | 2 +- .../compiler/lowering/ets/lambdaLowering.cpp | 18 ++- ets2panda/compiler/scripts/signatures.yaml | 2 + ets2panda/ir/ets/etsTypeReferencePart.cpp | 114 +++++++++--------- ets2panda/ir/ets/etsTypeReferencePart.h | 2 - ets2panda/lexer/scripts/keywords.yaml | 5 + ets2panda/scripts/arkui.properties | 2 +- .../FunctionalTypeAsArrayElement.ets | 2 +- .../ets/FunctionalTypeAsArrayElement.ets | 2 +- .../annotationDecl_bad_initializer03.ets | 4 +- .../annotationUsage_bad_param04.ets | 2 +- ...ment-on-nullish-type-undefined-invalid.ets | 1 - .../ast/parser/ets/type_from_utility_type.ets | 1 - ets2panda/test/runtime/ets/AnyType.ets | 41 +++++++ ets2panda/test/runtime/ets/Function.ets | 4 +- ets2panda/test/runtime/ets/NoConstraint.ets | 6 +- .../runtime/ets/defaultLocalInitializers.ets | 2 +- .../test/runtime/ets/stringComparision.ets | 2 +- ets2panda/util/diagnostic/semantic.yaml | 8 -- ets2panda/varbinder/ETSBinder.cpp | 7 +- 50 files changed, 453 insertions(+), 211 deletions(-) create mode 100644 ets2panda/checker/types/ets/etsAnyType.cpp create mode 100644 ets2panda/checker/types/ets/etsAnyType.h create mode 100644 ets2panda/test/runtime/ets/AnyType.ets diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 66dc65f081..0982392c38 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -126,6 +126,7 @@ libes2panda_sources = [ "checker/types/ets/intType.cpp", "checker/types/ets/longType.cpp", "checker/types/ets/shortType.cpp", + "checker/types/ets/etsAnyType.cpp", "checker/types/ets/wildcardType.cpp", "checker/types/globalTypesHolder.cpp", "checker/types/signature.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 224e91dd7e..3cef5f00dc 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -584,6 +584,7 @@ set(ES2PANDA_LIB_SRC checker/types/ets/intType.cpp checker/types/ets/longType.cpp checker/types/ets/shortType.cpp + checker/types/ets/etsAnyType.cpp checker/types/ets/etsArrayType.cpp checker/types/ets/etsBooleanType.cpp checker/types/ets/etsDynamicType.cpp diff --git a/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp b/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp index 930ac3249a..4eae5c316c 100644 --- a/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp +++ b/ets2panda/ast_verifier/invariants/identifierHasVariable.cpp @@ -25,8 +25,8 @@ public: ExceptionsMatcher(const IdentifierHasVariable *inv, const ir::Identifier *ast) : inv_(inv), ast_(ast) {} bool Match() { - auto res = IsLengthProp() || IsEmptyName() || IsInObjectExpr() || IsInPackageDecl() || IsUtilityType() || - IsUnionMemberAccess() || IsFixedArrayType(); + auto res = IsLengthProp() || IsEmptyName() || IsInObjectExpr() || IsInPackageDecl() || IsBuiltinType() || + IsUnionMemberAccess(); return res; } @@ -69,16 +69,13 @@ private: return false; } - bool IsUtilityType() + bool IsBuiltinType() { + auto name = ast_->Name(); // NOTE(mmartin): find a better solution to handle utility type resolution - return ast_->Name().Is(Signatures::PARTIAL_TYPE_NAME) || ast_->Name().Is(Signatures::REQUIRED_TYPE_NAME) || - ast_->Name().Is(Signatures::READONLY_TYPE_NAME); - } - - bool IsFixedArrayType() - { - return ast_->Name().Is(Signatures::FIXED_ARRAY_TYPE_NAME); + return name.Is(Signatures::PARTIAL_TYPE_NAME) || name.Is(Signatures::REQUIRED_TYPE_NAME) || + name.Is(Signatures::READONLY_TYPE_NAME) || name.Is(Signatures::FIXED_ARRAY_TYPE_NAME) || + name.Is(compiler::Signatures::ANY_TYPE_NAME); } bool IsUnionMemberAccess() diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index cc87b76f34..f5b0778cde 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -849,6 +849,11 @@ static bool CheckArrayExpressionElements(ETSChecker *checker, ir::ArrayExpressio return allElementsAssignable; } +static bool IsPossibleArrayExpressionType(Type const *type) +{ + return type->IsETSArrayType() || type->IsETSTupleType() || type->IsETSResizableArrayType(); +} + void ETSAnalyzer::GetUnionPreferredType(ir::Expression *expr, Type *originalType) const { if (originalType == nullptr || !originalType->IsETSUnionType()) { @@ -856,7 +861,7 @@ void ETSAnalyzer::GetUnionPreferredType(ir::Expression *expr, Type *originalType } checker::Type *preferredType = nullptr; for (auto &type : originalType->AsETSUnionType()->ConstituentTypes()) { - if (type->IsETSArrayType() || type->IsETSTupleType() || type->IsETSResizableArrayType()) { + if (IsPossibleArrayExpressionType(type)) { if (preferredType != nullptr) { preferredType = nullptr; break; @@ -890,6 +895,10 @@ checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const if (expr->GetPreferredType()->IsETSUnionType()) { GetUnionPreferredType(expr, expr->GetPreferredType()); } + + if (expr->GetPreferredType() != nullptr && !IsPossibleArrayExpressionType(expr->GetPreferredType())) { + expr->SetPreferredType(nullptr); + } } if (!IsArrayExpressionValidInitializerForType(checker, expr->GetPreferredType())) { @@ -1554,7 +1563,7 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const } if (calleeType->IsETSArrowType()) { expr->SetUncheckedType(checker->GuaranteedTypeForUncheckedCast( - checker->GlobalETSNullishObjectType(), checker->MaybeBoxType(expr->Signature()->ReturnType()))); + checker->GlobalETSAnyType(), checker->MaybeBoxType(expr->Signature()->ReturnType()))); } else { expr->SetUncheckedType(checker->GuaranteedTypeForUncheckedCallReturn(expr->Signature())); } @@ -1813,7 +1822,7 @@ checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const } if (!checker->CheckNonNullish(expr->Object())) { auto *invalidType = checker->HasStatus(checker::CheckerStatus::IN_EXTENSION_ACCESSOR_CHECK) - ? checker->GlobalETSNullishType() + ? checker->GlobalETSUnionUndefinedNull() : checker->InvalidateType(expr); return invalidType; } diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index ff4be3487e..bf00645a61 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -516,8 +516,7 @@ void ProcessExclamationMark(ETSChecker *checker, ir::UnaryExpression *expr, chec return; } - if (operandType == nullptr || !operandType->IsConditionalExprType()) { - checker->LogError(diagnostic::ASSERT_NOT_LOGICAL, {}, expr->Argument()->Start()); + if (operandType == nullptr || operandType->IsTypeError()) { expr->SetTsType(checker->GlobalTypeError()); return; } diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 01e68b8bac..3955fcc851 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -423,6 +423,22 @@ bool ETSChecker::IsClassStaticMethod(checker::ETSObjectType *objType, checker::S signature->HasSignatureFlag(checker::SignatureFlags::STATIC); } +[[nodiscard]] TypeFlag ETSChecker::TypeKind(const Type *const type) noexcept +{ + // These types were not present in the ETS_TYPE list. Some of them are omited intentionally, other are just bugs + static constexpr auto TO_CLEAR = TypeFlag::CONSTANT | TypeFlag::GENERIC | TypeFlag::ETS_INT_ENUM | + TypeFlag::ETS_STRING_ENUM | TypeFlag::READONLY | TypeFlag::BIGINT_LITERAL | + TypeFlag::ETS_TYPE_ALIAS | TypeFlag::TYPE_ERROR; + + // Bugs: these types do not appear as a valid TypeKind, as the TypeKind has more then one bit set + [[maybe_unused]] static constexpr auto NOT_A_TYPE_KIND = TypeFlag::ETS_DYNAMIC_FLAG; + + auto res = static_cast(type->TypeFlags() & ~(TO_CLEAR)); + ES2PANDA_ASSERT_POS(res == TypeFlag::NONE || helpers::math::IsPowerOfTwo(res & ~(NOT_A_TYPE_KIND)), + ark::es2panda::GetPositionForDiagnostic()); + return res; +} + template ETSObjectType *ETSChecker::AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const { @@ -524,6 +540,11 @@ Type *ETSChecker::GlobalETSUndefinedType() const return GetGlobalTypesHolder()->GlobalETSUndefinedType(); } +Type *ETSChecker::GlobalETSAnyType() const +{ + return GetGlobalTypesHolder()->GlobalETSAnyType(); +} + Type *ETSChecker::GlobalETSNeverType() const { return GetGlobalTypesHolder()->GlobalETSNeverType(); @@ -549,15 +570,15 @@ ETSObjectType *ETSChecker::GlobalETSObjectType() const return AsETSObjectType(&GlobalTypesHolder::GlobalETSObjectType); } -ETSUnionType *ETSChecker::GlobalETSNullishType() const +ETSUnionType *ETSChecker::GlobalETSUnionUndefinedNull() const { - auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSNullishType)(); + auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSUnionUndefinedNull)(); return ret != nullptr ? ret->AsETSUnionType() : nullptr; } -ETSUnionType *ETSChecker::GlobalETSNullishObjectType() const +ETSUnionType *ETSChecker::GlobalETSUnionUndefinedNullObject() const { - auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSNullishObjectType)(); + auto *ret = (GetGlobalTypesHolder()->*&GlobalTypesHolder::GlobalETSUnionUndefinedNullObject)(); return ret != nullptr ? ret->AsETSUnionType() : nullptr; } diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index bf9cd81c5f..79552cedb2 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -111,15 +111,12 @@ public: NO_COPY_SEMANTIC(ETSChecker); NO_MOVE_SEMANTIC(ETSChecker); - [[nodiscard]] static inline TypeFlag ETSType(const Type *const type) noexcept + [[nodiscard]] static TypeFlag ETSType(const Type *const type) noexcept { - return static_cast(type->TypeFlags() & TypeFlag::ETS_TYPE); + return ETSChecker::TypeKind(type); } - [[nodiscard]] static inline TypeFlag TypeKind(const Type *const type) noexcept - { - return static_cast(type->TypeFlags() & checker::TypeFlag::ETS_TYPE); - } + [[nodiscard]] static TypeFlag TypeKind(const Type *const type) noexcept; Type *GlobalByteType() const; Type *GlobalShortType() const; @@ -132,6 +129,7 @@ public: Type *GlobalVoidType() const; Type *GlobalETSNullType() const; Type *GlobalETSUndefinedType() const; + Type *GlobalETSAnyType() const; Type *GlobalETSNeverType() const; Type *GlobalETSStringLiteralType() const; Type *GlobalETSBigIntType() const; @@ -147,8 +145,8 @@ public: Type *GlobalETSBooleanBuiltinType() const; ETSObjectType *GlobalETSObjectType() const; - ETSUnionType *GlobalETSNullishType() const; - ETSUnionType *GlobalETSNullishObjectType() const; + ETSUnionType *GlobalETSUnionUndefinedNull() const; + ETSUnionType *GlobalETSUnionUndefinedNullObject() const; ETSObjectType *GlobalBuiltinETSResizableArrayType() const; ETSObjectType *GlobalBuiltinETSStringType() const; ETSObjectType *GlobalBuiltinETSBigIntType() const; diff --git a/ets2panda/checker/ets/aliveAnalyzer.cpp b/ets2panda/checker/ets/aliveAnalyzer.cpp index ff2ba27302..5714edf7ca 100644 --- a/ets2panda/checker/ets/aliveAnalyzer.cpp +++ b/ets2panda/checker/ets/aliveAnalyzer.cpp @@ -281,7 +281,7 @@ void AliveAnalyzer::AnalyzeDoLoop(const ir::DoWhileStatement *doWhile) AnalyzeStat(doWhile->Body()); status_ = Or(status_, ResolveContinues(doWhile)); AnalyzeNode(doWhile->Test()); - ES2PANDA_ASSERT(doWhile->Test()->TsType() && doWhile->Test()->TsType()->IsConditionalExprType()); + ES2PANDA_ASSERT(doWhile->Test()->TsType()); const auto exprRes = doWhile->Test()->TsType()->ResolveConditionExpr(); status_ = And(status_, static_cast(!std::get<0>(exprRes) || !std::get<1>(exprRes))); status_ = Or(status_, ResolveBreaks(doWhile)); @@ -291,7 +291,7 @@ void AliveAnalyzer::AnalyzeWhileLoop(const ir::WhileStatement *whileStmt) { SetOldPendingExits(PendingExits()); AnalyzeNode(whileStmt->Test()); - ES2PANDA_ASSERT(whileStmt->Test()->TsType() && whileStmt->Test()->TsType()->IsConditionalExprType()); + ES2PANDA_ASSERT(whileStmt->Test()->TsType()); const auto exprRes = whileStmt->Test()->TsType()->ResolveConditionExpr(); status_ = And(status_, static_cast(!std::get<0>(exprRes) || std::get<1>(exprRes))); AnalyzeStat(whileStmt->Body()); @@ -309,7 +309,7 @@ void AliveAnalyzer::AnalyzeForLoop(const ir::ForUpdateStatement *forStmt) if (forStmt->Test() != nullptr) { AnalyzeNode(forStmt->Test()); - ES2PANDA_ASSERT(forStmt->Test()->TsType() && forStmt->Test()->TsType()->IsConditionalExprType()); + ES2PANDA_ASSERT(forStmt->Test()->TsType()); condType = forStmt->Test()->TsType(); std::tie(resolveType, res) = forStmt->Test()->TsType()->ResolveConditionExpr(); status_ = From(!resolveType || res); diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index b0b3e32efd..61273a7daf 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -556,15 +556,16 @@ checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir:: return CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)}); } +// NOTE: code inside this function follows the broken logic bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, checker::Type *const rightType) { - auto isGlobalObjectType {[](checker::Type *const type) -> bool { - return type->IsETSObjectType() && type->AsETSObjectType()->IsGlobalETSObjectType(); + auto isRelaxedType {[](checker::Type *const type) -> bool { + return (type->IsETSObjectType() && type->AsETSObjectType()->IsGlobalETSObjectType()) || type->IsETSAnyType() || + type->IsETSNullType() || type->IsETSUndefinedType(); }}; - // Equality expression is always allowed for Object, undefined and null - if (isGlobalObjectType(leftType) || isGlobalObjectType(rightType) || leftType->IsETSUndefinedType() || - rightType->IsETSUndefinedType() || leftType->IsETSNullType() || rightType->IsETSNullType()) { + // Equality expression is always allowed for *magic types* + if (isRelaxedType(leftType) || isRelaxedType(rightType)) { return true; } @@ -651,10 +652,10 @@ static Type *CheckOperatorEqualDynamic(ETSChecker *checker, BinaryArithmOperands } if (otherExp->TsType()->IsETSReferenceType()) { // have to prevent casting dyn_exp via ApplyCast without nullish flag - return checker->GlobalETSNullishObjectType(); + return checker->GlobalETSAnyType(); } checker->LogError(diagnostic::BINOP_DYN_UNIMPLEMENTED, {}, ops.expr->Start()); - return checker->GlobalETSNullishObjectType(); + return checker->GlobalETSAnyType(); } static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOperands const &ops) diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 82a6fdb2c2..5ae8c1dd92 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1086,7 +1086,7 @@ std::pair ETSChecker::CheckTestNullishCondition(Type *testedType return {GlobalETSUndefinedType(), RemoveUndefinedType(actualType)}; } - return {GlobalETSNullishType(), GetNonNullishType(actualType)}; + return {GlobalETSUnionUndefinedNull(), GetNonNullishType(actualType)}; } // Auxiliary method to reduce the size of common 'CheckTestSmartCastConditions' function. diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index cbf729d09f..b656a25717 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -376,7 +376,7 @@ void ETSChecker::SetUpTypeParameterConstraint(ir::TSTypeParameter *const param) traverseReferenced(param->Constraint()); paramType->SetConstraintType(param->Constraint()->GetType(this)); } else { - paramType->SetConstraintType(GlobalETSNullishObjectType()); + paramType->SetConstraintType(GlobalETSAnyType()); } if (param->DefaultType() != nullptr) { @@ -401,7 +401,7 @@ ETSTypeParameter *ETSChecker::SetUpParameterType(ir::TSTypeParameter *const para paramType->SetDeclNode(param); paramType->SetVariable(param->Variable()); // NOTE: #15026 recursive type parameter workaround - paramType->SetConstraintType(GlobalETSNullishObjectType()); + paramType->SetConstraintType(GlobalETSAnyType()); var->SetTsType(paramType); return paramType; diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index f5a530a277..7fdd86d463 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -55,8 +55,7 @@ void ETSChecker::CheckTruthinessOfType(ir::Expression *expr) expr->SetTsType(conditionType); - if (conditionType == nullptr || (!conditionType->IsTypeError() && !conditionType->IsConditionalExprType())) { - LogError(diagnostic::NOT_COND_TYPE, {}, expr->Start()); + if (conditionType == nullptr) { return; } @@ -94,6 +93,9 @@ Type *ETSChecker::GetNonNullishType(Type *type) if (type->DefinitelyNotETSNullish()) { return type; } + if (type->IsETSAnyType()) { + return type; + } if (type->IsETSTypeParameter()) { return ProgramAllocator()->New(type->AsETSTypeParameter()); } @@ -116,7 +118,7 @@ Type *ETSChecker::GetNonNullishType(Type *type) Type *ETSChecker::RemoveNullType(Type *const type) { - if (type->DefinitelyNotETSNullish() || type->IsETSUndefinedType()) { + if (type->IsETSAnyType() || type->DefinitelyNotETSNullish() || type->IsETSUndefinedType()) { return type; } @@ -144,7 +146,7 @@ Type *ETSChecker::RemoveNullType(Type *const type) Type *ETSChecker::RemoveUndefinedType(Type *const type) { - if (type->DefinitelyNotETSNullish() || type->IsETSNullType()) { + if (type->IsETSAnyType() || type->DefinitelyNotETSNullish() || type->IsETSNullType()) { return type; } @@ -176,8 +178,12 @@ std::pair ETSChecker::RemoveNullishTypes(Type *type) return {GetGlobalTypesHolder()->GlobalETSNeverType(), type}; } + if (type->IsETSAnyType()) { + return {type, type}; + } + if (type->IsETSTypeParameter()) { - return {GetGlobalTypesHolder()->GlobalETSNullishType(), + return {GetGlobalTypesHolder()->GlobalETSUnionUndefinedNull(), ProgramAllocator()->New(type->AsETSTypeParameter())}; } @@ -251,21 +257,21 @@ static bool MatchConstituentOrConstraint(const Type *type, Pred const &pred) bool Type::PossiblyETSNull() const { return MatchConstituentOrConstraint( - this, [](const Type *t) { return t->IsETSNullType(); }, + this, [](const Type *t) { return t->IsETSAnyType() || t->IsETSNullType(); }, [](const Type *t) { return !t->IsETSNonNullishType(); }); } bool Type::PossiblyETSUndefined() const { return MatchConstituentOrConstraint( - this, [](const Type *t) { return t->IsETSUndefinedType(); }, + this, [](const Type *t) { return t->IsETSAnyType() || t->IsETSUndefinedType(); }, [](const Type *t) { return !t->IsETSNonNullishType(); }); } bool Type::PossiblyETSNullish() const { return MatchConstituentOrConstraint( - this, [](const Type *t) { return t->IsETSNullType() || t->IsETSUndefinedType(); }, + this, [](const Type *t) { return t->IsETSAnyType() || t->IsETSNullType() || t->IsETSUndefinedType(); }, [](const Type *t) { return !t->IsETSNonNullishType(); }); } @@ -287,7 +293,8 @@ bool Type::DefinitelyNotETSNullish() const bool Type::PossiblyETSString() const { return MatchConstituentOrConstraint(this, [](const Type *t) { - return t->IsETSStringType() || (t->IsETSObjectType() && t->AsETSObjectType()->IsGlobalETSObjectType()); + return t->IsETSAnyType() || t->IsETSStringType() || + (t->IsETSObjectType() && t->AsETSObjectType()->IsGlobalETSObjectType()); }); } @@ -308,7 +315,8 @@ bool Type::PossiblyETSValueTyped() const bool Type::PossiblyETSValueTypedExceptNullish() const { return MatchConstituentOrConstraint(this, [](const Type *t) { - return t->IsETSFunctionType() || (t->IsETSObjectType() && IsValueTypedObjectType(t->AsETSObjectType())); + return t->IsETSAnyType() || t->IsETSFunctionType() || + (t->IsETSObjectType() && IsValueTypedObjectType(t->AsETSObjectType())); }); } @@ -328,9 +336,9 @@ bool Type::IsETSMethodType() const static constexpr TypeFlag ETS_SANE_REFERENCE_TYPE = TypeFlag::TYPE_ERROR | TypeFlag::ETS_NULL | TypeFlag::ETS_UNDEFINED | TypeFlag::ETS_OBJECT | TypeFlag::ETS_TYPE_PARAMETER | TypeFlag::WILDCARD | TypeFlag::ETS_NONNULLISH | - TypeFlag::ETS_REQUIRED_TYPE_PARAMETER | TypeFlag::ETS_NEVER | TypeFlag::ETS_UNION | TypeFlag::ETS_ARRAY | - TypeFlag::FUNCTION | TypeFlag::ETS_PARTIAL_TYPE_PARAMETER | TypeFlag::ETS_TUPLE | TypeFlag::ETS_ENUM | - TypeFlag::ETS_READONLY; + TypeFlag::ETS_REQUIRED_TYPE_PARAMETER | TypeFlag::ETS_ANY | TypeFlag::ETS_NEVER | TypeFlag::ETS_UNION | + TypeFlag::ETS_ARRAY | TypeFlag::FUNCTION | TypeFlag::ETS_PARTIAL_TYPE_PARAMETER | TypeFlag::ETS_TUPLE | + TypeFlag::ETS_ENUM | TypeFlag::ETS_READONLY; // Issues if (type->IsETSVoidType()) { // NOTE(vpukhov): #19701 void refactoring @@ -340,7 +348,7 @@ bool Type::IsETSMethodType() const return true; } if (type->IsNeverType()) { // NOTE(vpukhov): #20562 We use ets/never and ts/never simultaneously - return true; + ES2PANDA_UNREACHABLE(); } return type->HasTypeFlag(ETS_SANE_REFERENCE_TYPE); } @@ -1173,7 +1181,7 @@ Type *ETSChecker::MaybeUnboxConditionalInRelation(Type *const objectType) return objectType; } - if ((objectType == nullptr) || !objectType->IsConditionalExprType()) { + if (objectType == nullptr) { return nullptr; } diff --git a/ets2panda/checker/ets/typeConverter.h b/ets2panda/checker/ets/typeConverter.h index 2d0bd3db6c..46635fdc5d 100644 --- a/ets2panda/checker/ets/typeConverter.h +++ b/ets2panda/checker/ets/typeConverter.h @@ -62,7 +62,7 @@ public: template static Type *ConvertConstantType(Type *source, ArenaAllocator *allocator) { - switch (static_cast(source->TypeFlags() & TypeFlag::ETS_TYPE)) { + switch (static_cast(source->TypeFlags() & (TypeFlag::ETS_NUMERIC | TypeFlag::CHAR))) { case TypeFlag::INT: return ConvertConstant(source->AsIntType(), allocator); @@ -95,7 +95,7 @@ public: { ES2PANDA_ASSERT(source->IsETSPrimitiveType() && target->IsETSPrimitiveType() && source->IsConstantType()); - switch (static_cast(target->TypeFlags() & TypeFlag::ETS_TYPE)) { + switch (static_cast(target->TypeFlags() & (TypeFlag::ETS_NUMERIC | TypeFlag::CHAR))) { case TypeFlag::INT: return ConvertConstantType(source, allocator); diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 53b6838523..7ae0ec47b2 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -307,8 +307,8 @@ static ETSObjectType *InitializeGlobalBuiltinObjectType(ETSChecker *checker, Glo auto *objType = setType(GlobalTypeId::ETS_OBJECT_BUILTIN, create())->AsETSObjectType(); auto null = checker->GlobalETSNullType(); auto undef = checker->GlobalETSUndefinedType(); - setType(GlobalTypeId::ETS_NULLISH_OBJECT, checker->CreateETSUnionType({objType, null, undef})); - setType(GlobalTypeId::ETS_NULLISH_TYPE, checker->CreateETSUnionType({null, undef})); + setType(GlobalTypeId::ETS_UNION_UNDEFINED_NULL_OBJECT, checker->CreateETSUnionType({objType, null, undef})); + setType(GlobalTypeId::ETS_UNION_UNDEFINED_NULL, checker->CreateETSUnionType({null, undef})); return objType; } case GlobalTypeId::ETS_STRING_BUILTIN: { diff --git a/ets2panda/checker/ets/utilityTypeHandlers.cpp b/ets2panda/checker/ets/utilityTypeHandlers.cpp index c77f536455..c267defa3c 100644 --- a/ets2panda/checker/ets/utilityTypeHandlers.cpp +++ b/ets2panda/checker/ets/utilityTypeHandlers.cpp @@ -59,6 +59,10 @@ Type *ETSChecker::HandleUtilityTypeParameterNode(const ir::TSTypeParameterInstan return GlobalTypeError(); } + if (baseType->IsETSAnyType()) { + return baseType; + } + if (utilityType == compiler::Signatures::PARTIAL_TYPE_NAME) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return CreatePartialType(baseType); @@ -115,6 +119,10 @@ Type *ETSChecker::CreatePartialType(Type *const typeToBePartial) { ES2PANDA_ASSERT(typeToBePartial->IsETSReferenceType()); + if (typeToBePartial->IsETSAnyType()) { + return typeToBePartial; + } + if (typeToBePartial->IsETSTypeParameter()) { return CreatePartialTypeParameter(typeToBePartial->AsETSTypeParameter()); } diff --git a/ets2panda/checker/types/ets/etsAnyType.cpp b/ets2panda/checker/types/ets/etsAnyType.cpp new file mode 100644 index 0000000000..811705455b --- /dev/null +++ b/ets2panda/checker/types/ets/etsAnyType.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsAnyType.h" + +#include "checker/ETSchecker.h" +#include "checker/ets/conversion.h" +#include "etsTypeParameter.h" + +namespace ark::es2panda::checker { +void ETSAnyType::Identical(TypeRelation *relation, Type *other) +{ + relation->Result(other->IsAnyType()); +} + +void ETSAnyType::AssignmentTarget(TypeRelation *relation, Type *source) +{ + if (!source->IsETSPrimitiveType()) { + relation->Result(true); + return; + } + + if (relation->ApplyBoxing()) { + auto checker = relation->GetChecker()->AsETSChecker(); + relation->GetNode()->AddBoxingUnboxingFlags(checker->GetBoxingFlag(checker->MaybeBoxType(source))); + relation->Result(true); + } +} + +bool ETSAnyType::AssignmentSource(TypeRelation *relation, Type *target) +{ + Identical(relation, target); + return relation->IsTrue(); +} + +void ETSAnyType::Compare([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *other) +{ + ES2PANDA_UNREACHABLE(); +} + +void ETSAnyType::Cast(TypeRelation *relation, Type *target) +{ + if (!relation->InCastingContext()) { + Identical(relation, target); + return; + } + + if (!target->IsETSPrimitiveType()) { + relation->Result(true); + return; + } + + if (relation->ApplyUnboxing()) { + auto *const boxedTarget = relation->GetChecker()->AsETSChecker()->MaybeBoxInRelation(target); + conversion::Unboxing(relation, boxedTarget->AsETSObjectType()); + relation->Result(true); + } +} + +void ETSAnyType::CastTarget(TypeRelation *relation, [[maybe_unused]] Type *source) +{ + AssignmentTarget(relation, source); +} + +void ETSAnyType::IsSubtypeOf(TypeRelation *relation, Type *target) +{ + Identical(relation, target); +} + +void ETSAnyType::IsSupertypeOf(TypeRelation *relation, Type *source) +{ + relation->Result(!source->IsETSPrimitiveType()); +} + +void ETSAnyType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const +{ + ss << compiler::Signatures::ANY_TYPE_NAME; +} + +void ETSAnyType::ToAssemblerType(std::stringstream &ss) const +{ + ss << compiler::Signatures::BUILTIN_OBJECT; +} + +TypeFacts ETSAnyType::GetTypeFacts() const +{ + return TypeFacts::NONE; +} + +void ETSAnyType::ToDebugInfoType(std::stringstream &ss) const +{ + ss << ETSObjectType::NameToDescriptor(compiler::Signatures::BUILTIN_OBJECT); +} + +Type *ETSAnyType::Instantiate(ArenaAllocator *allocator, [[maybe_unused]] TypeRelation *relation, + [[maybe_unused]] GlobalTypesHolder *globalTypes) +{ + return allocator->New(); +} +} // namespace ark::es2panda::checker \ No newline at end of file diff --git a/ets2panda/checker/types/ets/etsAnyType.h b/ets2panda/checker/types/ets/etsAnyType.h new file mode 100644 index 0000000000..3dbca0c808 --- /dev/null +++ b/ets2panda/checker/types/ets/etsAnyType.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_ANY_TYPE_H +#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_ANY_TYPE_H + +#include "checker/types/type.h" +#include "ir/astNode.h" + +namespace ark::es2panda::checker { +class ETSAnyType : public Type { +public: + ETSAnyType() : Type(TypeFlag::ETS_ANY) {} + + void Identical(TypeRelation *relation, Type *other) override; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + bool AssignmentSource(TypeRelation *relation, Type *target) override; + void Compare(TypeRelation *relation, Type *other) override; + void Cast(TypeRelation *relation, Type *target) override; + void CastTarget(TypeRelation *relation, Type *source) override; + void IsSubtypeOf(TypeRelation *relation, Type *target) override; + void IsSupertypeOf(TypeRelation *relation, Type *source) override; + void ToString(std::stringstream &ss, bool precise) const override; + void ToAssemblerType(std::stringstream &ss) const override; + void ToDebugInfoType([[maybe_unused]] std::stringstream &ss) const override; + + TypeFacts GetTypeFacts() const override; + + Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; + + std::tuple ResolveConditionExpr() const override + { + return {IsConstantType(), false}; + } +}; +} // namespace ark::es2panda::checker + +#endif diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index dbb55f46bc..cb1fe63b87 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -76,7 +76,7 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, auto *substitution = checker->NewSubstitution(); auto *elementType = !signature->RestVar()->TsType()->IsETSTupleType() ? checker->GetElementTypeOfArray(signature->RestVar()->TsType()) - : checker->GlobalETSNullishObjectType(); + : checker->GlobalETSAnyType(); substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), checker->MaybeBoxType(elementType)); return functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); } diff --git a/ets2panda/checker/types/ets/types.h b/ets2panda/checker/types/ets/types.h index 89d59b801e..68b9f0079e 100644 --- a/ets2panda/checker/types/ets/types.h +++ b/ets2panda/checker/types/ets/types.h @@ -40,6 +40,7 @@ #include "etsNullishTypes.h" #include "checker/types/signature.h" #include "etsReadonlyType.h" +#include "etsAnyType.h" #include "etsNeverType.h" #endif /* TYPES_H */ diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 784aa977a4..300e9b3fbf 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -48,6 +48,7 @@ #include "checker/types/ets/etsNullishTypes.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/wildcardType.h" +#include "checker/types/ets/etsAnyType.h" #include "checker/types/ets/etsNeverType.h" #include "util/helpers.h" @@ -148,11 +149,13 @@ void GlobalTypesHolder::AddEtsSpecificTypes(ArenaAllocator *allocator) globalTypes_[static_cast(GlobalTypeId::ETS_UNDEFINED)] = allocator->New(); globalTypes_[static_cast(GlobalTypeId::ETS_WILDCARD)] = allocator->New(); globalTypes_[static_cast(GlobalTypeId::TYPE_ERROR)] = allocator->New(); + globalTypes_[static_cast(GlobalTypeId::ETS_ANY)] = allocator->New(); globalTypes_[static_cast(GlobalTypeId::ETS_NEVER)] = allocator->New(); } void GlobalTypesHolder::AddEtsSpecificBuiltinTypes() { + builtinNameMappings_.emplace("Any", GlobalTypeId::ETS_ANY); builtinNameMappings_.emplace("Boolean", GlobalTypeId::ETS_BOOLEAN_BUILTIN); builtinNameMappings_.emplace("Byte", GlobalTypeId::ETS_BYTE_BUILTIN); builtinNameMappings_.emplace("Char", GlobalTypeId::ETS_CHAR_BUILTIN); @@ -403,19 +406,24 @@ Type *GlobalTypesHolder::GlobalETSUndefinedType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_UNDEFINED)); } +Type *GlobalTypesHolder::GlobalETSAnyType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_ANY)); +} + Type *GlobalTypesHolder::GlobalETSNeverType() { return globalTypes_.at(static_cast(GlobalTypeId::ETS_NEVER)); } -Type *GlobalTypesHolder::GlobalETSNullishObjectType() +Type *GlobalTypesHolder::GlobalETSUnionUndefinedNullObject() { - return globalTypes_.at(static_cast(GlobalTypeId::ETS_NULLISH_OBJECT)); + return globalTypes_.at(static_cast(GlobalTypeId::ETS_UNION_UNDEFINED_NULL_OBJECT)); } -Type *GlobalTypesHolder::GlobalETSNullishType() +Type *GlobalTypesHolder::GlobalETSUnionUndefinedNull() { - return globalTypes_.at(static_cast(GlobalTypeId::ETS_NULLISH_TYPE)); + return globalTypes_.at(static_cast(GlobalTypeId::ETS_UNION_UNDEFINED_NULL)); } Type *GlobalTypesHolder::GlobalWildcardType() diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index 2242097f8d..635c8b080e 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -57,9 +57,10 @@ enum class GlobalTypeId : std::size_t { ETS_OBJECT_BUILTIN, ETS_NULL, ETS_UNDEFINED, - ETS_NULLISH_TYPE, + ETS_UNION_UNDEFINED_NULL, + ETS_ANY, ETS_NEVER, - ETS_NULLISH_OBJECT, + ETS_UNION_UNDEFINED_NULL_OBJECT, ETS_WILDCARD, ETS_BOOLEAN_BUILTIN, ETS_BYTE_BUILTIN, @@ -267,9 +268,10 @@ public: Type *GlobalETSObjectType(); Type *GlobalETSNullType(); Type *GlobalETSUndefinedType(); + Type *GlobalETSAnyType(); Type *GlobalETSNeverType(); - Type *GlobalETSNullishType(); - Type *GlobalETSNullishObjectType(); + Type *GlobalETSUnionUndefinedNull(); + Type *GlobalETSUnionUndefinedNullObject(); Type *GlobalWildcardType(); Type *GlobalETSBooleanBuiltinType(); Type *GlobalByteBuiltinType(); diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 1104cada5f..12a433f569 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -189,11 +189,6 @@ public: return reinterpret_cast(this); } - bool IsConditionalExprType() const - { - return HasTypeFlag(TypeFlag::CONDITION_EXPRESSION_TYPE); - } - bool IsConstantType() const { return HasTypeFlag(checker::TypeFlag::CONSTANT); diff --git a/ets2panda/checker/types/typeFlag.h b/ets2panda/checker/types/typeFlag.h index 86e149f3a3..feea58ce12 100644 --- a/ets2panda/checker/types/typeFlag.h +++ b/ets2panda/checker/types/typeFlag.h @@ -48,7 +48,6 @@ enum class TypeFlag : uint64_t { INTERSECTION = 1ULL << 19ULL, // x: a & b INDEX = 1ULL << 20ULL, // keyof x INDEX_ACCESS = 1ULL << 21ULL, // x[a] - CONDITIONAL = 1ULL << 22ULL, // x extends a ? b : c TEMPLATE_LITERAL = 1ULL << 23ULL, // x: `hello ${World}` ANY = 1ULL << 24ULL, // x: any ARRAY = 1ULL << 25ULL, // x: number[] @@ -88,14 +87,11 @@ enum class TypeFlag : uint64_t { ETS_PARTIAL_TYPE_PARAMETER = 1ULL << 59ULL, // ETS Partial type parameter TYPE_ERROR = 1ULL << 60ULL, // type error ETS_TYPE_ALIAS = 1ULL << 61ULL, // ETS Type alias + ETS_ANY = 1ULL << 22ULL, // ETS any, the value was *stolen* from the CONDITIONAL type kind ETS_NEVER = 1ULL << 62ULL, // ETS never ETS_METHOD = 1ULL << 63ULL, // ETS method (or function in module) (possibly overloaded) ETS_DYNAMIC_TYPE = ETS_OBJECT | ETS_DYNAMIC_FLAG, ETS_DYNAMIC_FUNCTION_TYPE = FUNCTION | ETS_DYNAMIC_FLAG, - ETS_TYPE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_VOID | ETS_OBJECT | ETS_ARRAY | - FUNCTION | WILDCARD | ETS_TYPE_PARAMETER | ETS_DYNAMIC_TYPE | ETS_UNION | ETS_NULL | ETS_UNDEFINED | - ETS_NONNULLISH | ETS_READONLY | ETS_REQUIRED_TYPE_PARAMETER | ETS_PARTIAL_TYPE_PARAMETER | ETS_NEVER | - ETS_TUPLE, ETS_INTEGRAL_NUMERIC = BYTE | SHORT | INT | LONG, ETS_FLOATING_POINT = FLOAT | DOUBLE, ETS_NUMERIC = ETS_INTEGRAL_NUMERIC | ETS_FLOATING_POINT, @@ -123,9 +119,6 @@ enum class TypeFlag : uint64_t { VALID_ARITHMETIC_TYPE = ANY | NUMBER_LIKE | BIGINT_LIKE | ENUM, UNIT = LITERAL | UNDEFINED | NULL_TYPE, GETTER_SETTER = GETTER | SETTER, - CONDITION_EXPRESSION_TYPE = ETS_NULL | ETS_UNDEFINED | ETS_OBJECT | ETS_ARRAY | ETS_UNION | CONSTANT | BYTE | CHAR | - SHORT | INT | LONG | FLOAT | DOUBLE | ETS_BOOLEAN | ETS_INT_ENUM | ETS_STRING_ENUM | - FUNCTION | ETS_TUPLE, }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/typeMapping.h b/ets2panda/checker/types/typeMapping.h index 4964190828..a856a49bdb 100644 --- a/ets2panda/checker/types/typeMapping.h +++ b/ets2panda/checker/types/typeMapping.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -53,6 +53,7 @@ _(TypeFlag::ETS_VOID, ETSVoidType) \ _(TypeFlag::ETS_NULL, ETSNullType) \ _(TypeFlag::ETS_UNDEFINED, ETSUndefinedType) \ + _(TypeFlag::ETS_ANY, ETSAnyType) \ _(TypeFlag::ETS_NEVER, ETSNeverType) \ _(TypeFlag::FUNCTION, ETSFunctionType) \ _(TypeFlag::ETS_OBJECT, ETSObjectType) \ diff --git a/ets2panda/compiler/base/condition.cpp b/ets2panda/compiler/base/condition.cpp index c8a7d0de4d..dc0b40e8dc 100644 --- a/ets2panda/compiler/base/condition.cpp +++ b/ets2panda/compiler/base/condition.cpp @@ -235,7 +235,6 @@ void Condition::Compile(ETSGen *etsg, const ir::Expression *expr, Label *falseLa etsg->BranchIfTrue(expr, falseLabel); return; } - ES2PANDA_ASSERT(expr->TsType()->IsConditionalExprType()); expr->Compile(etsg); etsg->ApplyConversion(expr, etsg->Checker()->GlobalETSBooleanType()); etsg->ResolveConditionalResultIfFalse(expr, falseLabel); diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index be12b648ee..0d3494b72f 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -1664,6 +1664,7 @@ void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const case checker::TypeFlag::ETS_NONNULLISH: case checker::TypeFlag::ETS_PARTIAL_TYPE_PARAMETER: case checker::TypeFlag::ETS_UNION: + case checker::TypeFlag::ETS_ANY: case checker::TypeFlag::ETS_NULL: case checker::TypeFlag::ETS_UNDEFINED: { etsg->CastToReftype(expr, targetType, expr->isUncheckedCast_); diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 39cd26789b..e1e8635c3c 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -713,18 +713,6 @@ void ETSGen::ReturnAcc(const ir::AstNode *node) } } -static bool IsAnyReferenceSupertype(checker::Type const *type) -{ - if (!type->IsETSUnionType()) { - return false; - } - auto const &constituent = type->AsETSUnionType()->ConstituentTypes(); - return constituent.size() == 3U && std::all_of(constituent.begin(), constituent.end(), [](checker::Type *t) { - return t->IsETSUndefinedType() || t->IsETSNullType() || - (t->IsETSObjectType() && t->AsETSObjectType()->IsGlobalETSObjectType()); - }); // CC-OFF(G.FMT.02) project code style -} - static bool IsNullUnsafeObjectType(checker::Type const *type) { return type->IsETSObjectType() && type->AsETSObjectType()->IsGlobalETSObjectType(); @@ -762,10 +750,10 @@ void ETSGen::IsInstanceDynamic(const ir::BinaryExpression *const node, const VRe Language lang = rhsType->AsETSDynamicType()->Language(); VReg dynTypeReg = MoveAccToReg(node); LoadAccumulator(node, srcReg); - Sa().Emit(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); + EmitIsInstance(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); BranchIfFalse(node, ifFalse); LoadAccumulator(node, srcReg); - Sa().Emit(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); + EmitCheckCast(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); CallExact(node, Signatures::BUILTIN_JSRUNTIME_INSTANCE_OF_DYNAMIC, srcReg, dynTypeReg); SetLabel(node, ifFalse); } else { @@ -819,7 +807,7 @@ void ETSGen::TestIsInstanceConstituent(const ir::AstNode *const node, std::tuple break; case checker::TypeFlag::ETS_OBJECT: if (!IsNullUnsafeObjectType(target)) { - Sa().Emit(node, ToAssemblerType(target)); + EmitIsInstance(node, ToAssemblerType(target)); BranchIfTrue(node, ifTrue); break; } @@ -831,7 +819,7 @@ void ETSGen::TestIsInstanceConstituent(const ir::AstNode *const node, std::tuple case checker::TypeFlag::ETS_ARRAY: case checker::TypeFlag::ETS_TUPLE: case checker::TypeFlag::FUNCTION: { - Sa().Emit(node, ToAssemblerType(target)); + EmitIsInstance(node, ToAssemblerType(target)); BranchIfTrue(node, ifTrue); break; } @@ -879,7 +867,7 @@ void ETSGen::IsInstance(const ir::AstNode *const node, const VReg srcReg, const target = Checker()->GetApparentType(target); ES2PANDA_ASSERT(target->IsETSReferenceType()); - if (IsAnyReferenceSupertype(target)) { // should be IsSupertypeOf(target, source) + if (target->IsETSAnyType()) { // should be IsSupertypeOf(target, source) LoadAccumulatorBoolean(node, true); return; } @@ -906,7 +894,7 @@ void ETSGen::InternalIsInstance(const ir::AstNode *node, const es2panda::checker { ES2PANDA_ASSERT(target->IsETSObjectType() || target->IsETSArrayType()); if (!IsNullUnsafeObjectType(target)) { - Sa().Emit(node, ToAssemblerType(target)); + EmitIsInstance(node, ToAssemblerType(target)); SetAccumulatorType(Checker()->GlobalETSBooleanType()); } else { LoadAccumulatorBoolean(node, true); @@ -918,7 +906,7 @@ void ETSGen::InternalCheckCast(const ir::AstNode *node, const es2panda::checker: { ES2PANDA_ASSERT(target->IsETSObjectType() || target->IsETSArrayType() || target->IsETSTupleType()); if (!IsNullUnsafeObjectType(target)) { - Sa().Emit(node, ToAssemblerType(target)); + EmitCheckCast(node, ToAssemblerType(target)); } SetAccumulatorType(target); } @@ -972,7 +960,7 @@ void ETSGen::CheckedReferenceNarrowing(const ir::AstNode *node, const checker::T target = Checker()->GetApparentType(target); ES2PANDA_ASSERT(target->IsETSReferenceType()); - if (IsAnyReferenceSupertype(target)) { // should be IsSupertypeOf(target, source) + if (target->IsETSAnyType()) { // should be IsSupertypeOf(target, source) SetAccumulatorType(target); return; } @@ -994,7 +982,7 @@ void ETSGen::CheckedReferenceNarrowing(const ir::AstNode *node, const checker::T SetLabel(node, ifTrue); LoadAccumulator(node, srcReg); // Verifier can't infer type if isinstance met, help him - Sa().Emit(node, ToAssemblerType(target)); + EmitCheckCast(node, ToAssemblerType(target)); SetAccumulatorType(target); } @@ -1755,7 +1743,7 @@ void ETSGen::CastDynamicToObject(const ir::AstNode *node, const checker::Type *t // and this function will need to be refactored in the future. if (targetType->IsETSArrayType() || targetType->IsETSObjectType() || targetType->IsETSTypeParameter() || targetType->IsETSUnionType() || targetType->IsETSFunctionType() || targetType->DefinitelyETSNullish() || - targetType->IsETSTupleType()) { + targetType->IsETSTupleType() || targetType->IsETSAnyType()) { auto lang = GetAccumulatorType()->AsETSDynamicType()->Language(); auto methodName = compiler::Signatures::Dynamic::GetObjectBuiltin(lang); @@ -1770,7 +1758,7 @@ void ETSGen::CastDynamicToObject(const ir::AstNode *node, const checker::Type *t StoreAccumulator(node, typeReg); Ra().Emit(node, methodName, dynObjReg, typeReg); - Sa().Emit(node, assemblerType); // trick verifier + EmitCheckCast(node, assemblerType); // trick verifier SetAccumulatorType(targetType); return; } @@ -1815,6 +1803,7 @@ void ETSGen::CastToDynamic(const ir::AstNode *node, const checker::ETSDynamicTyp case checker::TypeFlag::ETS_NONNULLISH: case checker::TypeFlag::ETS_PARTIAL_TYPE_PARAMETER: case checker::TypeFlag::ETS_UNION: // NOTE(vpukhov): refine dynamic type cast rules + case checker::TypeFlag::ETS_ANY: if (GetAccumulatorType()->IsETSStringType()) { methodName = compiler::Signatures::Dynamic::NewStringBuiltin(type->Language()); break; @@ -2150,7 +2139,7 @@ void ETSGen::ResolveConditionalResultReference(const ir::AstNode *node) compiler::VReg objReg = AllocReg(); StoreAccumulator(node, objReg); - Sa().Emit(node, Checker()->GlobalBuiltinETSStringType()->AssemblerName()); + EmitIsInstance(node, Checker()->GlobalBuiltinETSStringType()->AssemblerName()); BranchIfTrue(node, isString); Sa().Emit(node, 1); Branch(node, end); @@ -2326,10 +2315,9 @@ void ETSGen::BranchIfNotNullish(const ir::AstNode *node, Label *ifNotNullish) void ETSGen::AssumeNonNullish(const ir::AstNode *node, checker::Type const *targetType) { auto const *nullishType = GetAccumulatorType(); - if (nullishType->PossiblyETSNull() && - ToAssemblerType(targetType) != ToAssemblerType(Checker()->GlobalETSObjectType())) { + if (nullishType->PossiblyETSNull()) { // clear 'null' dataflow - Sa().Emit(node, ToAssemblerType(targetType)); + EmitCheckCast(node, ToAssemblerType(targetType)); } SetAccumulatorType(targetType); } @@ -2704,7 +2692,6 @@ void ETSGen::Negate(const ir::AstNode *node) void ETSGen::LogicalNot(const ir::AstNode *node) { - ES2PANDA_ASSERT(GetAccumulatorType()->IsConditionalExprType()); ResolveConditionalResultIfFalse(node); Sa().Emit(node, 1); SetAccumulatorType(Checker()->GlobalETSBooleanType()); diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index 211722e558..bdfe9e92fa 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -486,6 +486,22 @@ private: #endif // PANDA_WITH_ETS } + void EmitCheckCast(const ir::AstNode *node, util::StringView target) + { + if (target != Signatures::BUILTIN_OBJECT) { + Sa().Emit(node, target); + } + } + + void EmitIsInstance(const ir::AstNode *node, util::StringView target) + { + if (target != Signatures::BUILTIN_OBJECT) { + Sa().Emit(node, target); + } else { + LoadAccumulatorBoolean(node, true); + } + } + template void EmitEtsEquals([[maybe_unused]] const ir::AstNode *node, [[maybe_unused]] const VReg lhs, [[maybe_unused]] const VReg rhs) diff --git a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp index bf9fea2cc5..f9dd8d0d64 100644 --- a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp @@ -40,7 +40,7 @@ ArenaVector ArrayLiteralLowering::GenerateDefaultCallToConstruc { std::stringstream ss; std::vector newStmts; - if (!eleType->IsETSUnionType()) { + if (!eleType->IsETSUnionType() && !eleType->IsETSAnyType()) { auto *indexSymbol = Gensym(Allocator()); auto *lengthSymbol = Gensym(Allocator()); auto *typeNode = checker_->AllocNode(eleType, Allocator()); diff --git a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp index c1e53dd59b..4033c033f3 100644 --- a/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/declareOverloadLowering.cpp @@ -30,7 +30,7 @@ void GenerateOverloadHelperParams(public_lib::Context *ctx, uint32_t minArg, siz if (!hasRestVar) { for (size_t idx = 0; idx < maxArg; ++idx) { auto *id = Gensym(allocator); - auto *typeAnnotation = ctx->AllocNode(checker->GlobalETSNullishObjectType(), allocator); + auto *typeAnnotation = ctx->AllocNode(checker->GlobalETSAnyType(), allocator); id->SetTsTypeAnnotation(typeAnnotation); typeAnnotation->SetParent(id); auto *param = ctx->AllocNode(id, false, allocator); @@ -42,7 +42,7 @@ void GenerateOverloadHelperParams(public_lib::Context *ctx, uint32_t minArg, siz auto *restIdent = Gensym(allocator); auto *spread = ctx->AllocNode(ir::AstNodeType::REST_ELEMENT, allocator, restIdent); - auto *arr = checker->CreateETSArrayType(checker->GlobalETSNullishObjectType(), false); + auto *arr = checker->CreateETSArrayType(checker->GlobalETSAnyType(), false); auto *typeAnnotation = ctx->AllocNode(arr, allocator); spread->SetTsTypeAnnotation(typeAnnotation); @@ -68,7 +68,7 @@ void BuildOverloadHelperFunction(public_lib::Context *ctx, ir::MethodDefinition auto params = ArenaVector(allocator->Adapter()); GenerateOverloadHelperParams(ctx, minArg, maxArg, hasRestVar, params); - auto *returnType = returnVoid ? checker->GlobalVoidType() : checker->GlobalETSNullishObjectType(); + auto *returnType = returnVoid ? checker->GlobalVoidType() : checker->GlobalETSAnyType(); auto *returnAnno = ctx->AllocNode(returnType, allocator); ir::ScriptFunctionFlags functionFlag = method->Function()->Flags(); diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index a46a63ea5e..1eb861ff8a 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp @@ -209,7 +209,7 @@ ir::Expression *EnumPostCheckLoweringPhase::HandleEnumTypeCasting(checker::Type // Generate fromValue call; if (type->IsETSEnumType()) { auto exprType = expr->TsType(); - if (exprType->IsETSEnumType() || + if (exprType->IsETSEnumType() || exprType->IsETSAnyType() || (exprType->IsETSObjectType() && exprType->AsETSObjectType()->IsGlobalETSObjectType())) { return expr; } diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index e43a0437b3..d3ad50c52a 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -389,7 +389,7 @@ static ir::MethodDefinition *CreateCallee(public_lib::Context *ctx, ir::ArrowFun auto calleeName = lambda->Function()->IsAsyncFunc() ? (util::UString {checker::ETSChecker::GetAsyncImplName(info->name), allocator}).View() : info->name; - auto *forcedReturnType = lambda->Function()->IsAsyncFunc() ? checker->GlobalETSNullishObjectType() : nullptr; + auto *forcedReturnType = lambda->Function()->IsAsyncFunc() ? checker->GlobalETSAnyType() : nullptr; CalleeMethodInfo cmInfo; cmInfo.calleeName = calleeName; @@ -538,10 +538,9 @@ static ArenaVector CreateRestArgumentsArrayReall << "}"; args = parser->CreateFormattedStatement( statements.str(), restParameterIndex, tmpArray, elementType, elementType, lciInfo->restParameterIdentifier, - lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, - checker->GlobalETSNullishObjectType(), lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, - restParameterIndex, spreadArrIterator, checker->MaybeBoxType(elementType), elementType, restParameterIndex, - restParameterIndex); + lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, checker->GlobalETSAnyType(), + lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, restParameterIndex, spreadArrIterator, + checker->MaybeBoxType(elementType), elementType, restParameterIndex, restParameterIndex); } else { ES2PANDA_ASSERT(restParameterSubstituteType->IsETSResizableArrayType()); auto *typeNode = allocator->New( @@ -559,7 +558,7 @@ static ArenaVector CreateRestArgumentsArrayReall << "}"; args = parser->CreateFormattedStatement( statements.str(), restParameterIndex, lciInfo->restArgumentIdentifier, typeNode, - lciInfo->restParameterIdentifier, spreadArrIterator, checker->GlobalETSNullishObjectType(), + lciInfo->restParameterIdentifier, spreadArrIterator, checker->GlobalETSAnyType(), lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, restParameterIndex, spreadArrIterator, checker->MaybeBoxType(elementType), restParameterIndex, restParameterIndex); } @@ -572,14 +571,13 @@ static void CreateInvokeMethodRestParameter(public_lib::Context *ctx, LambdaClas { auto *allocator = ctx->allocator; auto *checker = ctx->GetChecker()->AsETSChecker(); - auto *anyType = checker->GlobalETSNullishObjectType(); auto *restIdent = Gensym(allocator); lciInfo->restParameterIdentifier = restIdent->Name(); auto *spread = allocator->New(ir::AstNodeType::REST_ELEMENT, allocator, restIdent); auto *arr = lciInfo->lambdaSignature->RestVar()->TsType()->IsETSTupleType() ? lciInfo->lambdaSignature->RestVar()->TsType() - : checker->CreateETSArrayType(anyType); + : checker->CreateETSArrayType(checker->GlobalETSAnyType()); auto *typeAnnotation = allocator->New(arr, allocator); spread->SetTsTypeAnnotation(typeAnnotation); @@ -680,7 +678,7 @@ static ir::BlockStatement *CreateLambdaClassInvokeBody(public_lib::Context *ctx, auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); auto *checker = ctx->GetChecker()->AsETSChecker(); - auto *anyType = checker->GlobalETSNullishObjectType(); + auto *anyType = checker->GlobalETSAnyType(); auto *call = CreateCallForLambdaClassInvoke(ctx, info, lciInfo, wrapToObject); auto bodyStmts = CreateRestArgumentsArrayReallocation(ctx, lciInfo); @@ -708,7 +706,7 @@ static void CreateLambdaClassInvokeMethod(public_lib::Context *ctx, LambdaInfo c { auto *allocator = ctx->allocator; auto *checker = ctx->GetChecker()->AsETSChecker(); - auto *anyType = checker->GlobalETSNullishObjectType(); + auto *anyType = checker->GlobalETSAnyType(); auto params = ArenaVector(allocator->Adapter()); for (size_t idx = 0; idx < lciInfo->arity; ++idx) { diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 496aa8e961..c6bfa42dbc 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -159,6 +159,8 @@ defines: ref: ARRAY - name: '' ref: PROPERTY + - name: 'Any' + ref: ANY_TYPE_NAME - name: 'never' ref: NEVER_TYPE_NAME - name: 'SOURCE' diff --git a/ets2panda/ir/ets/etsTypeReferencePart.cpp b/ets2panda/ir/ets/etsTypeReferencePart.cpp index befb996682..9dbef072a2 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.cpp +++ b/ets2panda/ir/ets/etsTypeReferencePart.cpp @@ -117,91 +117,95 @@ checker::VerifiedType ETSTypeReferencePart::Check(checker::ETSChecker *checker) return {this, checker->GetAnalyzer()->Check(this)}; } -checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *const checker) +static checker::Type *HandleFixedArrayType(checker::ETSChecker *const checker, ETSTypeReferencePart *ref) { - auto const name = Name(); - ES2PANDA_ASSERT(name->IsIdentifier() || name->IsTSQualifiedName()); - - Identifier *ident = GetIdent(); - varbinder::Variable *variable = nullptr; + auto typeParams = ref->TypeParams(); + if (typeParams == nullptr || typeParams->Params().size() != 1) { + checker->LogError(diagnostic::FIXED_ARRAY_PARAM_ERROR, {}, ref->Start()); + return checker->GlobalTypeError(); + } + return checker->CreateETSArrayType(typeParams->Params()[0]->GetType(checker), ref->IsReadonlyType()); +} - if (name->IsIdentifier()) { - variable = ident->Variable(); - } else { - if (name->AsTSQualifiedName()->Left()->Variable() != nullptr && - name->AsTSQualifiedName()->Left()->Variable()->TsType() != nullptr && - name->AsTSQualifiedName()->Left()->Variable()->TsType()->IsETSObjectType()) { - variable = name->AsTSQualifiedName()->Left()->Variable()->TsType()->AsETSObjectType()->GetProperty( - ident->Name(), checker::PropertySearchFlags::SEARCH_DECL); +static checker::Type *HandlePartialType(checker::ETSChecker *const checker, ETSTypeReferencePart *ref) +{ + auto *baseType = checker->HandleUtilityTypeParameterNode(ref->TypeParams(), ref->GetIdent()); + if (baseType != nullptr && baseType->IsETSObjectType() && !baseType->AsETSObjectType()->TypeArguments().empty()) { + // we treat Partial> class as a different copy from A now, + // but not a generic type param for Partial<> + if (ref->TypeParams() != nullptr) { + for (auto &typeRef : ref->TypeParams()->Params()) { + checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), + typeRef->AsETSTypeReference()->Part()->TypeParams(), ref->Start()); + baseType = ctx.Result(); + } } } + return baseType; +} - if (variable != nullptr && variable->Declaration()->IsTypeAliasDecl()) { - return checker->HandleTypeAlias(name, TypeParams(), - variable->Declaration()->AsTypeAliasDecl()->Node()->AsTSTypeAliasDeclaration()); +static checker::Type *CheckPredefinedBuiltinTypes(checker::ETSChecker *const checker, ETSTypeReferencePart *ref) +{ + auto const ident = ref->GetIdent(); + if (ident->Name() == compiler::Signatures::ANY_TYPE_NAME) { + return checker->GlobalETSAnyType(); } - if (ident->Name() == compiler::Signatures::UNDEFINED) { return checker->GlobalETSUndefinedType(); } - if (ident->Name() == compiler::Signatures::NULL_LITERAL) { return checker->GlobalETSNullType(); } - if (ident->Name() == compiler::Signatures::NEVER_TYPE_NAME) { return checker->GlobalETSNeverType(); } if (ident->Name() == compiler::Signatures::READONLY_TYPE_NAME || ident->Name() == compiler::Signatures::REQUIRED_TYPE_NAME) { - return checker->HandleUtilityTypeParameterNode(TypeParams(), ident); + return checker->HandleUtilityTypeParameterNode(ref->TypeParams(), ident); } - if (ident->Name() == compiler::Signatures::PARTIAL_TYPE_NAME) { - return HandlePartialType(checker, ident); + return HandlePartialType(checker, ref); } - if (ident->Name() == compiler::Signatures::FIXED_ARRAY_TYPE_NAME) { - return HandleFixedArrayType(checker); + return HandleFixedArrayType(checker, ref); } - - if (ident->IsErrorPlaceHolder()) { - return checker->GlobalTypeError(); - } - return nullptr; } -checker::Type *ETSTypeReferencePart::HandleFixedArrayType(checker::ETSChecker *const checker) +checker::Type *ETSTypeReferencePart::HandleInternalTypes(checker::ETSChecker *const checker) { - auto const typeParams = TypeParams(); - if (typeParams == nullptr || typeParams->Params().size() != 1) { - checker->LogError(diagnostic::FIXED_ARRAY_PARAM_ERROR, {}, Start()); - return checker->GlobalTypeError(); - } - checker::Type *type = checker->CreateETSArrayType(typeParams->Params()[0]->GetType(checker), IsReadonlyType()); - SetTsType(type); - return type; -} + auto const name = Name(); + ES2PANDA_ASSERT(name->IsIdentifier() || name->IsTSQualifiedName()); -checker::Type *ETSTypeReferencePart::HandlePartialType(checker::ETSChecker *const checker, - const Identifier *const ident) -{ - auto const typeParams = TypeParams(); - auto *baseType = checker->HandleUtilityTypeParameterNode(typeParams, ident); - if (baseType != nullptr && baseType->IsETSObjectType() && !baseType->AsETSObjectType()->TypeArguments().empty()) { - // we treat Partial> class as a different copy from A now, - // but not a generic type param for Partial<> - if (typeParams != nullptr) { - for (auto &typeRef : typeParams->Params()) { - checker::InstantiationContext ctx(checker, baseType->AsETSObjectType(), - typeRef->AsETSTypeReference()->Part()->TypeParams(), Start()); - baseType = ctx.Result(); - } + Identifier *const ident = GetIdent(); + varbinder::Variable *variable = nullptr; + + if (name->IsIdentifier()) { + variable = ident->Variable(); + } else { + if (name->AsTSQualifiedName()->Left()->Variable() != nullptr && + name->AsTSQualifiedName()->Left()->Variable()->TsType() != nullptr && + name->AsTSQualifiedName()->Left()->Variable()->TsType()->IsETSObjectType()) { + variable = name->AsTSQualifiedName()->Left()->Variable()->TsType()->AsETSObjectType()->GetProperty( + ident->Name(), checker::PropertySearchFlags::SEARCH_DECL); } } - return baseType; + + if (variable != nullptr && variable->Declaration()->IsTypeAliasDecl()) { + return checker->HandleTypeAlias(name, TypeParams(), + variable->Declaration()->AsTypeAliasDecl()->Node()->AsTSTypeAliasDeclaration()); + } + + if (auto res = CheckPredefinedBuiltinTypes(checker, this); res != nullptr) { + return res; + } + + if (ident->IsErrorPlaceHolder()) { + return checker->GlobalTypeError(); + } + + return nullptr; } checker::Type *ETSTypeReferencePart::GetType(checker::ETSChecker *checker) diff --git a/ets2panda/ir/ets/etsTypeReferencePart.h b/ets2panda/ir/ets/etsTypeReferencePart.h index 54a2156b99..9fe657e930 100644 --- a/ets2panda/ir/ets/etsTypeReferencePart.h +++ b/ets2panda/ir/ets/etsTypeReferencePart.h @@ -109,9 +109,7 @@ public: void CopyTo(AstNode *other) const override; private: - checker::Type *HandlePartialType(checker::ETSChecker *const checker, const Identifier *const ident); checker::Type *HandleInternalTypes(checker::ETSChecker *checker); - checker::Type *HandleFixedArrayType(checker::ETSChecker *const checker); friend class SizeOfNodeTest; void SetName(ir::Expression *name); diff --git a/ets2panda/lexer/scripts/keywords.yaml b/ets2panda/lexer/scripts/keywords.yaml index a3dc0855ad..3ed7f5ff79 100644 --- a/ets2panda/lexer/scripts/keywords.yaml +++ b/ets2panda/lexer/scripts/keywords.yaml @@ -32,6 +32,11 @@ keywords: keyword_like: [ts] flags: [reserved_type_name] + - name: 'Any' + token: KEYW_BUILTIN_ANY + keyword_like: [ets] + flags: [predefined_type] + - name: 'anyref' token: KEYW_ANYREF keyword_like: [as] diff --git a/ets2panda/scripts/arkui.properties b/ets2panda/scripts/arkui.properties index 0cbcc38439..bcd5168bfd 100644 --- a/ets2panda/scripts/arkui.properties +++ b/ets2panda/scripts/arkui.properties @@ -1,3 +1,3 @@ ARKUI_DEV_REPO=https://gitee.com/rri_opensource/koala_projects.git -ARKUI_DEV_BRANCH=panda_rev_8 +ARKUI_DEV_BRANCH=panda_rev_8_any_2 ARKUI_DEST=koala-sig diff --git a/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets b/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets index e6559e42e9..5a026a6288 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets @@ -19,4 +19,4 @@ function main(){ ] } -/* @@? 17:48 Error TypeError: Expected type for array literal should be an array type, got () => FixedArray */ +/* @@? 17:48 Error TypeError: Type 'Array<() => Int>' cannot be assigned to type '() => FixedArray' */ diff --git a/ets2panda/test/ast/parser/ets/FunctionalTypeAsArrayElement.ets b/ets2panda/test/ast/parser/ets/FunctionalTypeAsArrayElement.ets index 4e6298318b..d31642e769 100644 --- a/ets2panda/test/ast/parser/ets/FunctionalTypeAsArrayElement.ets +++ b/ets2panda/test/ast/parser/ets/FunctionalTypeAsArrayElement.ets @@ -19,4 +19,4 @@ function main(){ ] } -/* @@? 17:38 Error TypeError: Expected type for array literal should be an array type, got () => Array */ +/* @@? 17:38 Error TypeError: Type 'Array<() => Int>' cannot be assigned to type '() => Array' */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer03.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer03.ets index 956e26b9c6..6d9b6522bd 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer03.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer03.ets @@ -14,8 +14,8 @@ */ @interface MyAnno { - testProperty1: string = /* @@ label */[1,2,a] + testProperty1: string = [1,2,/* @@ label */a] } -/* @@@ label Error TypeError: Expected type for array literal should be an array type, got String */ +/* @@@ label Error TypeError: Unresolved reference a */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets index cd104710cf..8dd647720d 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets @@ -21,4 +21,4 @@ @MyAnno({testProperty1: "1", testProperty2: [1, 2, a]}) class B{} -/* @@? 21:45 Error TypeError: Expected type for array literal should be an array type, got double */ +/* @@? 21:52 Error TypeError: Unresolved reference a */ diff --git a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets index e3b52ed7ae..4fd228987d 100644 --- a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets +++ b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets @@ -19,4 +19,3 @@ /* @@@ label Error SyntaxError: Unexpected token '~'. */ /* @@@ label1 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ /* @@@ label2 Error SyntaxError: Unexpected token ';'. */ -/* @@@ label2 Error TypeError: Bad operand type, the type of the operand must be boolean type. */ diff --git a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets index 36718f3d1e..6b220807a6 100644 --- a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets +++ b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets @@ -31,7 +31,6 @@ let recordarrA = Type.from,Array>>(); let recordarrT = Type.from,Array>>(); } - /* @@? 17:20 Error TypeError: No matching call signature */ /* @@? 30:19 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 30:29 Error TypeError: No static $_invoke method and static $_instantiate method in Record. Record() is not allowed. */ /* @@? 30:29 Error TypeError: Type 'Record' has no call signatures. */ diff --git a/ets2panda/test/runtime/ets/AnyType.ets b/ets2panda/test/runtime/ets/AnyType.ets new file mode 100644 index 0000000000..5b84855f12 --- /dev/null +++ b/ets2panda/test/runtime/ets/AnyType.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let a: Any + +a = undefined +a = new Object() +a = null +a = 1 + +a = undefined as Any +a = new Object() as Any +a = null as Any +a = 1 as Any + +function asgn(a: T): Any { return a } + +assertTrue(asgn(null) === null) +assertTrue(asgn(undefined) === undefined) +assertTrue(asgn("a") === "a") +assertTrue(asgn(1) === 1) + +class C {} + +asgn>(new C()) +asgn>(new C()) +asgn>(new C()) +asgn>(new C()) +asgn>(new C()) diff --git a/ets2panda/test/runtime/ets/Function.ets b/ets2panda/test/runtime/ets/Function.ets index 45406aca33..5889ad5f60 100644 --- a/ets2panda/test/runtime/ets/Function.ets +++ b/ets2panda/test/runtime/ets/Function.ets @@ -24,9 +24,7 @@ class B extends A { } } -type __T = object | null | undefined - -function test(f: Function, action: (f: Function) => __T, v: __T) { +function test(f: Function, action: (f: Function) => Any, v: Any) { assertEQ(action(f), v) } diff --git a/ets2panda/test/runtime/ets/NoConstraint.ets b/ets2panda/test/runtime/ets/NoConstraint.ets index 16189c1b13..e0736e7696 100644 --- a/ets2panda/test/runtime/ets/NoConstraint.ets +++ b/ets2panda/test/runtime/ets/NoConstraint.ets @@ -13,13 +13,11 @@ * limitations under the License. */ -type NullishFoo = Object | null | undefined; - -function foo(x: T): NullishFoo { +function foo(x: T): Any { return x; } -function bar(x: T): NullishFoo { +function bar(x: T): Any { return x; } diff --git a/ets2panda/test/runtime/ets/defaultLocalInitializers.ets b/ets2panda/test/runtime/ets/defaultLocalInitializers.ets index 9aa08962a2..96cb2300f1 100644 --- a/ets2panda/test/runtime/ets/defaultLocalInitializers.ets +++ b/ets2panda/test/runtime/ets/defaultLocalInitializers.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -function erase(v: T): object | null | undefined { return v } +function erase(v: T): Any { return v } assertTrue(erase((() => { let r: boolean | undefined; diff --git a/ets2panda/test/runtime/ets/stringComparision.ets b/ets2panda/test/runtime/ets/stringComparision.ets index e1d40eabf1..0af50e17f8 100644 --- a/ets2panda/test/runtime/ets/stringComparision.ets +++ b/ets2panda/test/runtime/ets/stringComparision.ets @@ -14,7 +14,7 @@ */ function foo(p: T, q: U): T|U { - return p!.toString() > q!.toString() ? p : q + return (p! as object).toString() > (q! as object).toString() ? p : q } function main() { diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index e61143986b..7565ace3dd 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -40,10 +40,6 @@ semantic: id: 7 message: Cannot use array creation expression with type parameter. -- name: NOT_COND_TYPE - id: 8 - message: "Condition must be of possible condition type" - - name: VOID_IN_LOGIC id: 9 message: "An expression of type 'void' cannot be tested for truthiness" @@ -124,10 +120,6 @@ semantic: id: 28 message: "Invalid string template expression" -- name: ASSERT_NOT_LOGICAL - id: 29 - message: "Bad operand type, the type of the operand must be boolean type." - - name: ASSERT_MESSAGE_NOT_STRING id: 30 message: "Assert message must be string" diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0cccb97f42..f2983e06ca 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -56,9 +56,10 @@ void ETSBinder::LookupTypeArgumentReferences(ir::ETSTypeReference *typeRef) static bool IsSpecialName(const util::StringView &name) { - return name == compiler::Signatures::UNDEFINED || name == compiler::Signatures::NULL_LITERAL || - name == compiler::Signatures::READONLY_TYPE_NAME || name == compiler::Signatures::PARTIAL_TYPE_NAME || - name == compiler::Signatures::REQUIRED_TYPE_NAME || name == compiler::Signatures::FIXED_ARRAY_TYPE_NAME; + return name == compiler::Signatures::ANY_TYPE_NAME || name == compiler::Signatures::UNDEFINED || + name == compiler::Signatures::NULL_LITERAL || name == compiler::Signatures::READONLY_TYPE_NAME || + name == compiler::Signatures::PARTIAL_TYPE_NAME || name == compiler::Signatures::REQUIRED_TYPE_NAME || + name == compiler::Signatures::FIXED_ARRAY_TYPE_NAME; } bool ETSBinder::HandleDynamicVariables(ir::Identifier *ident, Variable *variable, bool allowDynamicNamespaces) -- Gitee From fff2493aba6ca920e0f5d87ae2c6e450540b54e0 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Tue, 27 May 2025 14:32:21 +0800 Subject: [PATCH 053/747] fix arkts-limited-void-type Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAO2M Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 36 +++++++++++++++++-- .../linter/test/main/limit_void_type.ets | 4 +++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index 34a087faa2..9bc1f5f9e5 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -6137,12 +6137,42 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const signature = this.tsTypeChecker.getResolvedSignature(node); - if (signature) { - const returnType = this.tsTypeChecker.getReturnTypeOfSignature(signature); - if (this.tsTypeChecker.typeToString(returnType) === 'void') { + if (!signature) { + return; + } + + const returnType = this.tsTypeChecker.getReturnTypeOfSignature(signature); + if (this.tsTypeChecker.typeToString(returnType) !== 'void') { + return; + } + + if (ts.isReturnStatement(node.parent)) { + const functionLike = TypeScriptLinter.findContainingFunction(node); + if (functionLike && TypeScriptLinter.isRecursiveCall(node, functionLike)) { this.incrementCounters(node, FaultID.LimitedVoidType); } + return; } + + this.incrementCounters(node, FaultID.LimitedVoidType); + } + + private static findContainingFunction(node: ts.Node): ts.FunctionLikeDeclaration | undefined { + while (node) { + if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) { + return node; + } + node = node.parent; + } + return undefined; + } + + // Helper function to check if a call is recursive + private static isRecursiveCall(callExpr: ts.CallExpression, fn: ts.FunctionLikeDeclaration): boolean { + return ts.isIdentifier(callExpr.expression) && + ts.isFunctionDeclaration(fn) && + !!fn.name && + fn.name.text === callExpr.expression.text; } private handleArrayType(arrayType: ts.Node): void { diff --git a/ets2panda/linter/test/main/limit_void_type.ets b/ets2panda/linter/test/main/limit_void_type.ets index d6ae5d427f..7296884de6 100644 --- a/ets2panda/linter/test/main/limit_void_type.ets +++ b/ets2panda/linter/test/main/limit_void_type.ets @@ -202,4 +202,8 @@ dd = aa === '1' ? foo() : bar(); // Error interface testB{ u:void; // Error fooIf():void; +} + +function foo1():void{ + return foo(); // No Error } \ No newline at end of file -- Gitee From b4f6d17675844b345af96b8c0351ee4f0203b094 Mon Sep 17 00:00:00 2001 From: leo9001 Date: Tue, 27 May 2025 15:28:08 +0800 Subject: [PATCH 054/747] support getClassConstructorInfo new circumstance Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAU0Y Signed-off-by: leo9001 --- ets2panda/lsp/src/generate_constructor.cpp | 170 ++++-- ets2panda/lsp/src/quick_info.cpp | 10 + .../test/unit/lsp/get_constructor_test.cpp | 545 ++++++++++++++++-- 3 files changed, 634 insertions(+), 91 deletions(-) diff --git a/ets2panda/lsp/src/generate_constructor.cpp b/ets2panda/lsp/src/generate_constructor.cpp index 1dbaf7deae..b78c0c223a 100644 --- a/ets2panda/lsp/src/generate_constructor.cpp +++ b/ets2panda/lsp/src/generate_constructor.cpp @@ -23,7 +23,7 @@ namespace ark::es2panda::lsp { -bool HasConstructorNode(ir::AstNode *classNode) +ir::AstNode *GetConstructorNode(const ir::AstNode *classNode) { size_t start = classNode->Start().index; size_t end = classNode->End().index; @@ -34,7 +34,7 @@ bool HasConstructorNode(ir::AstNode *classNode) return node->Start().index >= start && node->End().index <= end && node->IsConstructor(); }); - return constructorNode != nullptr; + return constructorNode; } std::vector GetClassProperties(ir::AstNode *classNode, const std::vector &properties) @@ -47,6 +47,9 @@ std::vector GetClassProperties(ir::AstNode *classNode, const std: if (node->IsStatic() || !node->IsClassProperty()) { continue; } + if (classNode->AsClassDeclaration()->Definition()->IsAbstract() && node->IsAbstract()) { + continue; + } classProperties.emplace_back(node); } } @@ -60,19 +63,25 @@ std::vector GetExtendedClassProperties(ir::AstNode *classNode) if (baseNode == nullptr) { return {}; } - std::vector extendedClassProperties = {}; - auto baseNodeBody = baseNode->AsClassDeclaration()->Definition()->Body(); - for (auto node : baseNodeBody) { - if (!node->IsClassProperty()) { - continue; - } - auto tmp = node->AsClassProperty(); - if (tmp->IsStatic()) { - continue; - } - extendedClassProperties.push_back(node); + auto constructorNode = GetConstructorNode(baseNode); + if (constructorNode == nullptr) { + return {}; + } + + std::vector extendedClassProperties; + auto params = constructorNode->AsMethodDefinition() + ->Value() + ->AsFunctionExpression() + ->Function() + ->AsScriptFunction() + ->Params(); + for (auto param : params) { + auto id = param->AsETSParameterExpression()->Ident(); + auto tmp = compiler::DeclarationFromIdentifier(id); + extendedClassProperties.emplace_back(tmp); } + return extendedClassProperties; } @@ -86,43 +95,31 @@ void RemoveTrailingChar(std::string &str, const std::string &lastChar) } } -void GetParameterListAndFunctionBody(std::string ¶meterList, std::string &functionBody, - const std::vector &nodeList, bool isSuper) +std::string FilterSubstring(const std::string &input, const std::string &toRemove) { - if (nodeList.empty()) { - return; - } + std::string result = input; + size_t pos = 0; - std::vector strList1 = {}; - std::vector strList2 = {}; - for (auto propertyNode : nodeList) { - auto nodeName = GetIdentifierName(propertyNode); - auto typeAnnotation = propertyNode->AsClassProperty()->TypeAnnotation(); - if (typeAnnotation->IsETSTypeReference()) { - auto propertyType = GetNameForTypeReference(typeAnnotation); - auto str = nodeName; - str += ": "; - str += propertyType; - str += ", "; - strList1.push_back(str); - strList2.push_back(nodeName); - } + while ((pos = result.find(toRemove)) != std::string::npos) { + result.erase(pos, toRemove.length()); } - for (const auto &str : strList1) { - parameterList += str; - } + return result; +} +std::string GetFunctionBody(const std::vector &strVec, bool isSuper) +{ + std::string functionBody; if (isSuper) { functionBody += " super("; - for (const auto &str : strList2) { + for (const auto &str : strVec) { functionBody += str; functionBody += ", "; } RemoveTrailingChar(functionBody, ","); functionBody += ");\n"; } else { - for (const auto &str : strList2) { + for (const auto &str : strVec) { functionBody += " this."; functionBody += str; functionBody += " = "; @@ -130,16 +127,107 @@ void GetParameterListAndFunctionBody(std::string ¶meterList, std::string &fu functionBody += ";\n"; } } + + return functionBody; +} + +std::string GetNameForFunctionExpression(const ir::Expression *type) +{ + auto function = type->AsArrowFunctionExpression()->Function(); + if (function == nullptr || !function->IsScriptFunction()) { + return "undefined"; + } + + std::string returnType; + auto statements = function->AsScriptFunction()->Body()->AsBlockStatement()->Statements(); + if (!statements.empty()) { + auto argType = statements.at(0)->AsReturnStatement()->Argument(); + if (argType->IsStringLiteral()) { + returnType = "String"; + } else if (argType->IsNumberLiteral()) { + returnType = "Number"; + } else if (argType->IsBooleanLiteral()) { + returnType = "Boolean"; + } else { + returnType = "void"; + } + } + + return "(() => " + returnType + ")"; +} + +std::string GetNameForValue(const ir::AstNode *propertyNode) +{ + auto valueType = propertyNode->AsClassProperty()->Value(); + if (valueType == nullptr) { + return "undefined"; + } + + if (valueType->IsStringLiteral()) { + return "String"; + } + if (valueType->IsNumberLiteral()) { + return "Number"; + } + if (valueType->IsBooleanLiteral()) { + return "Boolean"; + } + if (valueType->IsArrowFunctionExpression()) { + return GetNameForFunctionExpression(valueType); + } + + return "undefined"; +} + +void GetParameterListAndFunctionBody(std::string ¶meterList, std::string &functionBody, + const std::vector &nodeList, bool isSuper) +{ + std::vector strVec = {}; + for (auto propertyNode : nodeList) { + auto nodeName = GetIdentifierName(propertyNode); + auto propertyName = FilterSubstring(nodeName, ""); + ark::es2panda::ir::TypeNode *typeAnnotation = nullptr; + if (propertyNode->IsETSParameterExpression()) { + typeAnnotation = propertyNode->AsETSParameterExpression()->TypeAnnotation(); + } else if (propertyNode->IsClassProperty()) { + typeAnnotation = propertyNode->AsClassProperty()->TypeAnnotation(); + } + + std::string propertyType; + if (typeAnnotation == nullptr) { + propertyType = GetNameForValue(propertyNode); + } else { + propertyType = GetNameForTypeNode(typeAnnotation); + } + + auto str = propertyName; + str += ": "; + str += propertyType; + str += ", "; + + if (parameterList.find(str) == std::string::npos) { + parameterList += str; + } + strVec.push_back(propertyName); + } + + auto body = GetFunctionBody(strVec, isSuper); + functionBody += body; +} + +bool HasBaseNode(ir::AstNode *classNode) +{ + return nullptr != ark::es2panda::lsp::GetEffectiveBaseTypeNode(classNode); } -std::string CollectConstructorInfo(const std::vector &classProperties, +std::string CollectConstructorInfo(ir::AstNode *classNode, const std::vector &classProperties, const std::vector &extendedClassProperties) { std::string constructorInfoText = "constructor("; std::string parameterList; std::string functionBody; - if (!extendedClassProperties.empty()) { + if (HasBaseNode(classNode)) { GetParameterListAndFunctionBody(parameterList, functionBody, extendedClassProperties, true); } GetParameterListAndFunctionBody(parameterList, functionBody, classProperties, false); @@ -189,14 +277,14 @@ std::vector GetRefactorActionsToGenerateConstructor(es2panda_Co return {}; } - if (HasConstructorNode(classDeclaration)) { + if (GetConstructorNode(classDeclaration) != nullptr) { return {}; } std::vector classProperties = GetClassProperties(classDeclaration, properties); std::vector extendedClassProperties = GetExtendedClassProperties(classDeclaration); - std::string text = CollectConstructorInfo(classProperties, extendedClassProperties); + std::string text = CollectConstructorInfo(classDeclaration, classProperties, extendedClassProperties); size_t insertPosition = 0; GetInsertNodePosition(classDeclaration, insertPosition); diff --git a/ets2panda/lsp/src/quick_info.cpp b/ets2panda/lsp/src/quick_info.cpp index 4ddcbee32d..858c7e9bb6 100644 --- a/ets2panda/lsp/src/quick_info.cpp +++ b/ets2panda/lsp/src/quick_info.cpp @@ -405,6 +405,16 @@ std::string GetNameForUnionType(const ir::TypeNode *unionType) std::string GetNameForTypeReference(const ir::TypeNode *typeReference) { + auto type = typeReference->AsETSTypeReference()->Part(); + if (type != nullptr && type->IsETSTypeReferencePart()) { + auto tmp = type->AsETSTypeReferencePart()->Name(); + if (tmp != nullptr && tmp->IsTSQualifiedName()) { + auto leftStr = tmp->AsTSQualifiedName()->Left()->AsIdentifier()->Name().Mutf8(); + auto rightStr = tmp->AsTSQualifiedName()->Right()->AsIdentifier()->Name().Mutf8(); + return leftStr + "." + rightStr; + } + } + std::string typeParamNames; auto typeParam = typeReference->AsETSTypeReference()->Part()->TypeParams(); if (typeParam != nullptr && typeParam->IsTSTypeParameterInstantiation()) { diff --git a/ets2panda/test/unit/lsp/get_constructor_test.cpp b/ets2panda/test/unit/lsp/get_constructor_test.cpp index 4c408c131b..7976967dc0 100644 --- a/ets2panda/test/unit/lsp/get_constructor_test.cpp +++ b/ets2panda/test/unit/lsp/get_constructor_test.cpp @@ -51,15 +51,29 @@ void AssertClassConstructorInfo(const std::vector &fileTextChan ASSERT_FALSE(check) << "The newText is not expected."; } +std::vector CreateExpectedFileTextChanges(const std::string &expectedFileName, size_t expectedPosition, + const std::string &expectedText) +{ + std::vector expectedFileTextChanges; + + TextSpan span(expectedPosition, expectedText.size()); + std::vector textChanges; + textChanges.emplace_back(TextChange(span, expectedText)); + FileTextChanges textChange(expectedFileName, textChanges); + expectedFileTextChanges.push_back(textChange); + + return expectedFileTextChanges; +} + TEST_F(LSPClassInfoTests, getClassConstructorInfo1) { std::vector fileNames = {"getClassConstructorInfo1.ets"}; std::vector fileContents = { R"( class FooParent { - f: number = 0; - str: string = "aaa"; - constructor (f: number, str: string) { + f: Number = 0; + str: String = "aaa"; + constructor (f: Number, str: String) { this.f = f; this.str = str; } @@ -67,15 +81,15 @@ class FooParent { enum Colors {Red = "#FF0000", Green = "#00FF00", Blue = "#0000FF"}; export class Foo extends FooParent { - name: string = "unassigned"; - isActive: boolean = true; - items: string[] = ["aaa", "bbb"]; - point: [number, number] = [0, 0]; + name: String = "unassigned"; + isActive: Boolean = true; + items: String[] = ["aaa", "bbb"]; + point: Number[] = [0, 0]; primaryColor: Colors = Colors.Blue; - optionalValue?:string|null|undefined; - x: number = 1; - static y: number = 2; - z: number = 3; + optionalValue?:String|null|undefined; + x: Number = 1; + static y: Number = 2; + z: Number = 3; };)"}; auto filePaths = CreateTempFile(fileNames, fileContents); @@ -84,20 +98,19 @@ export class Foo extends FooParent { LSPAPI const *lspApi = GetImpl(); size_t const offset = 400; - std::vector properties = {"name", "x", "z"}; + std::vector properties = {"name", "x", "primaryColor", "isActive", "items", "point", "optionalValue"}; Initializer initializer = Initializer(); auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); - std::vector expectedFileTextChanges; - std::string text = - "constructor(f: number, str: string, name: string, x: number, z: number) {\n super(f, str);\n this.name = " - "name;\n this.x = x;\n this.z = z;\n}"; - size_t const insertPosition = 269; - TextSpan span(insertPosition, text.size()); - std::vector textChanges; - textChanges.emplace_back(TextChange(span, text)); - FileTextChanges textChange(filePaths.at(0), textChanges); - expectedFileTextChanges.push_back(textChange); + + std::string expectedText = + "constructor(f: Number, str: String, name: String, x: Number, primaryColor: Colors, isActive: Boolean, " + "items: Array, point: Array, optionalValue: String|null|undefined) {\n super(f, str);\n" + " this.name = name;\n this.x = x;\n this.primaryColor = primaryColor;\n this.isActive = isActive;\n" + " this.items = items;\n this.point = point;\n this.optionalValue = optionalValue;\n}"; + size_t const expectedPosition = 269; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); initializer.DestroyContext(ctx); } @@ -108,8 +121,8 @@ TEST_F(LSPClassInfoTests, getClassConstructorInfo2) std::vector texts = { R"( class Foo { - f: number = 0; - str: string = "aaa"; + f: Number = 0; + str: String = "aaa"; };)"}; auto filePaths = CreateTempFile(files, texts); @@ -122,14 +135,11 @@ class Foo { Initializer initializer = Initializer(); auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); - std::vector expectedFileTextChanges; - std::string text = "constructor(f: number, str: string) {\n this.f = f;\n this.str = str;\n}"; - size_t const insertPosition = 17; - TextSpan span(insertPosition, text.size()); - std::vector textChanges; - textChanges.emplace_back(TextChange(span, text)); - FileTextChanges textChange(filePaths.at(0), textChanges); - expectedFileTextChanges.push_back(textChange); + + std::string expectedText = "constructor(f: Number, str: String) {\n this.f = f;\n this.str = str;\n}"; + size_t const expectedPosition = 17; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); initializer.DestroyContext(ctx); } @@ -152,14 +162,11 @@ class Foo { Initializer initializer = Initializer(); auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); - std::vector expectedFileTextChanges; - std::string text = "constructor() {\n}"; - size_t const insertPosition = 13; - TextSpan span(insertPosition, text.size()); - std::vector textChanges; - textChanges.emplace_back(TextChange(span, text)); - FileTextChanges textChange(filePaths.at(0), textChanges); - expectedFileTextChanges.push_back(textChange); + + std::string expectedText = "constructor() {\n}"; + size_t const expectedPosition = 13; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); initializer.DestroyContext(ctx); } @@ -171,9 +178,9 @@ TEST_F(LSPClassInfoTests, getClassConstructorInfo4) R"( namespace space { export class classInSpace { - c: number = 2; + c: Number = 2; - function print() { + print(): Number { return 2; } } @@ -189,14 +196,452 @@ namespace space { Initializer initializer = Initializer(); auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); - std::vector expectedFileTextChanges; - std::string text = "constructor(c: number) {\n this.c = c;\n}"; - size_t const insertPosition = 59; - TextSpan span(insertPosition, text.size()); - std::vector textChanges; - textChanges.emplace_back(TextChange(span, text)); - FileTextChanges textChange(filePaths.at(0), textChanges); - expectedFileTextChanges.push_back(textChange); + + std::string expectedText = "constructor(c: Number) {\n this.c = c;\n}"; + size_t const expectedPosition = 59; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo5) +{ + std::vector files = {"getClassConstructorInfo5.ets"}; + std::vector texts = { + R"( +interface Address { + street: String; + city: String; +} + +class Engine { + horsepower: Number; + + constructor(horsepower: Number) { + this.horsepower = horsepower; + } +} + +enum Color {Red, Green, Blue} +class Car { + name: String = "Alice"; + address: Address = { street: "111", city: "222" }; + tupleProperty: [String, Number] = ["TypeScript", 4.5]; + enumProperty: Color = Color.Red; + onClick: () => void = () => console.log("Function called"); + engine: Engine = new Engine(1); +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 230; + std::vector properties = {"name", "address", "tupleProperty", "enumProperty", "onClick", "engine"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(name: String, address: Address, tupleProperty: undefined, enumProperty: Color, " + "onClick: (() => void), engine: Engine) {\n this.name = name;\n this.address = address;\n " + "this.tupleProperty = tupleProperty;\n this.enumProperty = enumProperty;\n this.onClick = onClick;\n " + "this.engine = engine;\n}"; + size_t const expectedPosition = 233; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo6) +{ + std::vector files = {"getClassConstructorInfo6.ets"}; + std::vector texts = { + R"( +class Animal { + name: String; + num: Number + constructor(name: String, num: Number) { + this.name = name; + this.num = num; + } +}; + +class Mammal extends Animal { + age: Number; + flag: Boolean; + constructor(name: String, num: Number, age: Number, flag: Boolean) { + super(name, num); + this.age = age; + this.flag = flag; + } +}; + +class Dog extends Mammal { + breed: String; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 406; + std::vector properties = {"breed"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(name: String, num: Number, age: Number, flag: Boolean, breed: String) {\n super(name, num, age, " + "flag);\n this.breed = breed;\n}"; + size_t const expectedPosition = 411; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo7) +{ + std::vector files = {"getClassConstructorInfo7.ets"}; + std::vector texts = { + R"( +interface AA { + aa: Number; + + getAA(): Number; +} + +class BaseNN { + aa: Number; + + constructor(aa: Number) { + this.aa = aa; + } + + getAA(): Number { + return 1; + } +} + +class MM extends BaseNN implements AA { + aa: Number; + + getAA(): Number { + return super.getAA(); + } +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 230; + std::vector properties = {"aa"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = "constructor(aa: Number) {\n super(aa);\n this.aa = aa;\n}"; + size_t const expectedPosition = 241; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo8) +{ + std::vector files = {"getClassConstructorInfo8.ets"}; + std::vector texts = { + R"( +abstract class AA { + test: Number; +} + +class NN extends AA { + jkk: String = ""; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 70; + std::vector properties = {"jkk"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = "constructor(jkk: String) {\n super();\n this.jkk = jkk;\n}"; + size_t const expectedPosition = 68; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo9) +{ + std::vector files = {"getClassConstructorInfo9.ets"}; + std::vector texts = { + R"( +abstract class AA2 { + test: Number; + private kn: String; + das: String; + + constructor(test: Number, kn: String) { + this.test = test; + this.kn = kn; + } +} + +class NN2 extends AA2 { + jkk: String; + wwa: Number; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 192; + std::vector properties = {"jkk", "wwa"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(test: Number, kn: String, jkk: String, wwa: Number) {\n super(test, kn);\n this.jkk = jkk;\n " + "this.wwa = wwa;\n}"; + size_t const expectedPosition = 211; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo10) +{ + std::vector files = {"getClassConstructorInfo10.ets"}; + std::vector texts = { + R"( +abstract class TY { + abstract a: String|Number; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 34; + std::vector properties = {"a"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = "constructor() {\n}"; + size_t const expectedPosition = 34; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo11) +{ + std::vector files = {"getClassConstructorInfo11.ets"}; + std::vector texts = { + R"( +import CommonEventManager from '@ohos.commonEventManager'; + +interface SubscribeInfoType { + events: String[]; +} + +class CommonEventRegister { + subscriber: CommonEventManager.CommonEventSubscriber | null = null; + public subscribeInfo: SubscribeInfoType; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 141; + std::vector properties = {"subscriber", "subscribeInfo"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(subscriber: CommonEventManager.CommonEventSubscriber|null, subscribeInfo: SubscribeInfoType) " + "{\n this.subscriber = subscriber;\n this.subscribeInfo = subscribeInfo;\n}"; + size_t const expectedPosition = 148; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo12) +{ + std::vector files = {"getClassConstructorInfo12.ets", "getClassConstructorInfo13.ets"}; + std::vector texts = { + R"( +import {AAA} from "./getClassConstructorInfo13.ets"; + +class BBB extends AAA { + score: Number; +})", + R"( +export class AAA { + name: String; + age: Number; + constructor(name: String, age: Number) { + this.name = name; + this.age = age; + } +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 2; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 77; + std::vector properties = {"score"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(name: String, age: Number, score: Number) " + "{\n super(name, age);\n this.score = score;\n}"; + size_t const expectedPosition = 83; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo13) +{ + std::vector files = {"getClassConstructorInfo14.ets"}; + std::vector texts = { + R"( +class KKK { + tr: String; + + constructor(tr: String) { + this.tr = tr; + } +} + +class NNN extends KKK { +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 111; + std::vector properties = {}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = "constructor(tr: String) {\n super(tr);\n}"; + size_t const expectedPosition = 114; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo14) +{ + std::vector files = {"getClassConstructorInfo15.ets"}; + std::vector texts = { + R"( +class ok { + p1: Number = 0; + p2: String = ""; + static p3: String = ""; + readonly p4: String = ""; + private p5: String = ""; + protected p6: String = ""; + p7: undefined; + p8: null = null; +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 11; + std::vector properties = {"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(p1: Number, p2: String, p4: String, p5: String, p6: String, p7: undefined, p8: null) {\n this.p1 " + "= p1;\n this.p2 = p2;\n this.p4 = p4;\n this.p5 = p5;\n this.p6 = p6;\n this.p7 = p7;\n this.p8 = " + "p8;\n}"; + size_t const expectedPosition = 16; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); + AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); + initializer.DestroyContext(ctx); +} + +TEST_F(LSPClassInfoTests, getClassConstructorInfo15) +{ + std::vector files = {"getClassConstructorInfo16.ets"}; + std::vector texts = { + R"( +class Demo { + name = 'jack'; + age = 25; + flag = false; + doTask1 = () => 34; + doTask2 = () => "hello"; + doTask3 = () => false; + doTask4 = () => console.log("Function called"); +})"}; + auto filePaths = CreateTempFile(files, texts); + + int const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 11; + std::vector properties = {"name", "age", "flag", "doTask1", "doTask2", "doTask3", "doTask4"}; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto res = lspApi->getClassConstructorInfo(ctx, offset, properties); + + std::string expectedText = + "constructor(name: String, age: Number, flag: Boolean, doTask1: (() => Number), doTask2: (() => String), " + "doTask3: (() => Boolean), doTask4: (() => void)) {\n this.name = name;\n this.age = age;\n this.flag = " + "flag;\n this.doTask1 = doTask1;\n this.doTask2 = doTask2;\n this.doTask3 = doTask3;\n this.doTask4 = " + "doTask4;\n}"; + size_t const expectedPosition = 18; + std::vector expectedFileTextChanges = + CreateExpectedFileTextChanges(filePaths.at(0), expectedPosition, expectedText); AssertClassConstructorInfo(res.GetFileTextChanges(), expectedFileTextChanges); initializer.DestroyContext(ctx); } -- Gitee From 0555cc7d38aa7e1e536bd0bdd0cbcc757e68e824 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Fri, 6 Jun 2025 15:20:09 +0800 Subject: [PATCH 055/747] Fix for IsConcurrentDeprecated Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICD38U Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 38 +++++------- .../linter/test/concurrent/@ohos.taskpool.ets | 25 ++++++++ .../concurrent/@ohos.taskpool.ets.args.json | 18 ++++++ .../test/concurrent/@ohos.taskpool.ets.json | 17 ++++++ .../no_support_isconcurrent.ets.arkts2.json | 20 ------- .../concurrent/no_support_isconcurrent2.ets | 42 ++++++++++++++ .../no_support_isconcurrent2.ets.args.json | 19 ++++++ .../no_support_isconcurrent2.ets.arkts2.json | 58 +++++++++++++++++++ .../no_support_isconcurrent2.ets.json | 17 ++++++ 9 files changed, 212 insertions(+), 42 deletions(-) create mode 100755 ets2panda/linter/test/concurrent/@ohos.taskpool.ets create mode 100755 ets2panda/linter/test/concurrent/@ohos.taskpool.ets.args.json create mode 100755 ets2panda/linter/test/concurrent/@ohos.taskpool.ets.json create mode 100755 ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets create mode 100755 ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.args.json create mode 100755 ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.arkts2.json create mode 100755 ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ec2c5e4463..564091114a 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -47,7 +47,6 @@ import { PROPERTY_HAS_NO_INITIALIZER_ERROR_CODE } from './utils/consts/PropertyH import { CONCURRENT_DECORATOR, ISCONCURRENT, - TASKPOOL, SENDABLE_DECORATOR, SENDABLE_DECORATOR_NODES, SENDABLE_FUNCTION_UNSUPPORTED_STAGES_IN_API12, @@ -1499,36 +1498,31 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!ts.isCallExpression(node.parent)) { return; } - const methodName = node.name.getText(); if (methodName !== ISCONCURRENT) { return; } - - const symbol = this.tsUtils.trueSymbolAtLocation(node.expression); - if (!symbol) { + const moduleSpecifier = this.findModuleSpecifierforDepricatedIsConcurrent(node); + if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) { return; } + if ( + TASKPOOL_MODULES.some((moduleName) => { + return TsUtils.removeOrReplaceQuotes(moduleSpecifier.getText(), false) === moduleName; + }) + ) { + this.incrementCounters(node.name, FaultID.IsConcurrentDeprecated); + } + } - if (symbol.name === TASKPOOL) { - const decl = TsUtils.getDeclaration(symbol); - - if (!decl) { - return; - } - - const sourceFile = decl.getSourceFile(); - const fileName = path.basename(sourceFile.fileName); - - if ( - TASKPOOL_MODULES.some((moduleName) => { - return fileName.startsWith(moduleName); - }) - ) { - this.incrementCounters(node.name, FaultID.IsConcurrentDeprecated); - } + findModuleSpecifierforDepricatedIsConcurrent(node: ts.PropertyAccessExpression): ts.Expression | undefined { + let symbol = this.tsUtils.trueSymbolAtLocation(node.expression); + if (symbol && 'unknown' === symbol.name) { + symbol = this.tsTypeChecker.getSymbolAtLocation(node.expression); } + const importDecl = ts.findAncestor(TsUtils.getDeclaration(symbol), ts.isImportDeclaration); + return importDecl?.moduleSpecifier; } checkFunctionProperty( diff --git a/ets2panda/linter/test/concurrent/@ohos.taskpool.ets b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets new file mode 100755 index 0000000000..a2a9094098 --- /dev/null +++ b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +type func = ()=>void +export namespace taskpool{ + export function isConcurrent(param:func):boolean { + return true + } +} +export namespace otherTaskPool{ + export function isConcurrent(param:func):boolean { + return true + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.args.json b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.args.json new file mode 100755 index 0000000000..0adede204e --- /dev/null +++ b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.args.json @@ -0,0 +1,18 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + } +} diff --git a/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.json b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.json new file mode 100755 index 0000000000..9f305c86d7 --- /dev/null +++ b/ets2panda/linter/test/concurrent/@ohos.taskpool.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json b/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json index 9b627b9d72..428032b2d8 100644 --- a/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent.ets.arkts2.json @@ -23,26 +23,6 @@ "suggest": "", "rule": "Usage of standard library is restricted(arkts-limited-stdlib-no-concurrent-decorator)", "severity": "ERROR" - }, - { - "line": 23, - "column": 32, - "endLine": 23, - "endColumn": 44, - "problem": "IsConcurrentDeprecated", - "suggest": "", - "rule": "isConcurrent is not supported (arkts-limited-stdlib-no-support-isConcurrent)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 27, - "endLine": 25, - "endColumn": 39, - "problem": "IsConcurrentDeprecated", - "suggest": "", - "rule": "isConcurrent is not supported (arkts-limited-stdlib-no-support-isConcurrent)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets new file mode 100755 index 0000000000..2db768e0e8 --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { taskpool } from '@ohos.taskpool'; +import { taskpool as taskpool2 } from './@ohos.taskpool'; +import { otherTaskPool as taskpool1 } from './@ohos.taskpool'; + +function test1(){ +} +function isConcurrent() {} + +typeof taskpool.isConcurrent() ; //error +function test(){ + taskpool.isConcurrent(test5()) ; //error +} + +console.log(''+taskpool2.isConcurrent(test1)); + +taskpool2.isConcurrent(test1) +taskpool2.isConcurrent(test1) +taskpool2.isConcurrent(isConcurrent) +function test5(){ + taskpool2.isConcurrent(test1) + taskpool2.isConcurrent(test1) + taskpool2.isConcurrent(isConcurrent) +} +class Demo{ + get(){ + return taskpool1.isConcurrent(test); + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.args.json b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.args.json new file mode 100755 index 0000000000..e2b903f0aa --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.args.json @@ -0,0 +1,19 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "" + } + } \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.arkts2.json b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.arkts2.json new file mode 100755 index 0000000000..b418f42b21 --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.arkts2.json @@ -0,0 +1,58 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 15, + "column": 1, + "endLine": 15, + "endColumn": 43, + "problem": "LimitedStdLibNoImportConcurrency", + "suggest": "", + "rule": "Import Concurrency is not required (arkts-limited-stdlib-no-import-concurrency)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 17, + "endLine": 23, + "endColumn": 29, + "problem": "IsConcurrentDeprecated", + "suggest": "", + "rule": "isConcurrent is not supported (arkts-limited-stdlib-no-support-isConcurrent)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 12, + "endLine": 25, + "endColumn": 24, + "problem": "IsConcurrentDeprecated", + "suggest": "", + "rule": "isConcurrent is not supported (arkts-limited-stdlib-no-support-isConcurrent)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 25, + "endLine": 25, + "endColumn": 32, + "problem": "LimitedVoidType", + "suggest": "", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.json b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.json new file mode 100755 index 0000000000..b9331d05ba --- /dev/null +++ b/ets2panda/linter/test/concurrent/no_support_isconcurrent2.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] + } \ No newline at end of file -- Gitee From f5fc2fbaf24d727b4fa4eadc7bf3aac27c2b4754 Mon Sep 17 00:00:00 2001 From: zengzengran Date: Fri, 6 Jun 2025 23:51:36 +0800 Subject: [PATCH 056/747] Allow "use static" on files first line Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICACF5 Description: Allow use "use static" on the first line of source files and declaration files 1. In parser phase, first step is to attempt to load "use static" -> StringLiteral and add it to topstatements. 2. In TopLevelStatements phase, check topstatements. If the first statement is "use static", remove it. Tested-by: ninja tests (passed) ets_testrunner (passed) Signed-off-by: zengzengran # --- .../ets/topLevelStmts/topLevelStmts.cpp | 21 ++++++++++++++++ ets2panda/compiler/scripts/signatures.yaml | 2 ++ ets2panda/parser/ETSparser.cpp | 19 ++++++++++++++ ets2panda/parser/ETSparser.h | 1 + .../compiler/ets/use_static_flag/export1.ets | 17 +++++++++++++ .../compiler/ets/use_static_flag/export2.ets | 17 +++++++++++++ .../use_static_flag/flag_after_copyright.ets | 18 +++++++++++++ .../use_static_flag/flag_after_importdecl.ets | 20 +++++++++++++++ .../flag_before_importdecl.ets | 18 +++++++++++++ .../use_static_flag/flag_in_first_line.ets | 17 +++++++++++++ .../use_static_flag/flag_in_first_line_2.ets | 17 +++++++++++++ .../flag_in_first_line_2_neg.ets | 19 ++++++++++++++ .../flag_in_first_line_3_neg.ets | 19 ++++++++++++++ .../flag_in_first_line_neg.ets | 19 ++++++++++++++ .../flag_middle_importdecl_neg.ets | 20 +++++++++++++++ .../package/flag_before_package.ets | 17 +++++++++++++ .../package/flag_before_package2.ets | 17 +++++++++++++ .../package_2_neg/flag_before_package.ets | 24 ++++++++++++++++++ .../package_3_neg/flag_before_package.ets | 25 +++++++++++++++++++ .../package_neg/flag_package.ets | 20 +++++++++++++++ .../package_neg/flag_package2.ets | 19 ++++++++++++++ .../srcdumper/srcdumper-ets-ignored.txt | 2 ++ 22 files changed, 368 insertions(+) create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/export1.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/export2.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_copyright.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_importdecl.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_before_importdecl.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_3_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/flag_middle_importdecl_neg.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package2.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package_2_neg/flag_before_package.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package_3_neg/flag_before_package.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package.ets create mode 100644 ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package2.ets diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp index fbd267cee5..f07a9a464b 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp @@ -72,8 +72,29 @@ static void DeclareNamespaceExportAdjust(parser::Program *program, const std::st name); } +static void CheckFileHeaderFlag(parser::Program *program) +{ + auto &statements = program->Ast()->StatementsForUpdates(); + if (statements.empty()) { + return; + } + + if (!statements.front()->IsExpressionStatement()) { + return; + } + + // If further processing based on "use static" is required later, such as throwing a warning or modifying the node, + // perform the operation here. + auto *expansion = statements.front()->AsExpressionStatement()->GetExpression(); + if (expansion->IsStringLiteral() && expansion->AsStringLiteral()->Str() == Signatures::STATIC_PROGRAM_FLAG) { + statements.erase(statements.begin()); + return; + } +} + bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *program) { + CheckFileHeaderFlag(program); auto imports = ImportExportDecls(program->VarBinder()->AsETSBinder(), ctx->parser->AsETSParser()); imports.ParseDefaultSources(); if (!CheckProgramSourcesConsistency(program)) { diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 496aa8e961..fee43e4209 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -218,6 +218,8 @@ defines: - name: 'InterfaceObjectLiteral' ref: INTERFACE_OBJ_LITERAL comment: ETS annotation type + - name: 'use static' + ref: STATIC_PROGRAM_FLAG packages: - name: 'std.core' diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 4c4715eb46..2d5df77c03 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -121,6 +121,7 @@ void ETSParser::ParseProgram(ScriptKind kind) } ArenaVector statements(Allocator()->Adapter()); + ParseFileHeaderFlag(startLoc, &statements); auto decl = ParsePackageDeclaration(); if (decl != nullptr) { statements.emplace_back(decl); @@ -147,6 +148,23 @@ void ETSParser::ParseProgram(ScriptKind kind) GetProgram()->SetAst(script); } +void ETSParser::ParseFileHeaderFlag(lexer::SourcePosition startLoc, ArenaVector *statements) +{ + if (Lexer()->GetToken().KeywordType() != lexer::TokenType::LITERAL_STRING || + Lexer()->GetToken().String() != compiler::Signatures::STATIC_PROGRAM_FLAG) { + return; + } + + ir::Expression *fileHeaderFlag = ParseStringLiteral(); + auto *exprStatementNode = AllocNode(fileHeaderFlag); + + exprStatementNode->SetRange({startLoc, fileHeaderFlag->End()}); + ConsumeSemicolon(exprStatementNode); + if (statements != nullptr) { + statements->push_back(exprStatementNode); + } +} + ir::ETSModule *ETSParser::ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements) { ETSNolintParser etsnolintParser(this); @@ -398,6 +416,7 @@ parser::Program *ETSParser::ParseSource(const SourceFile &sourceFile) Lexer()->NextToken(); ArenaVector statements(Allocator()->Adapter()); + ParseFileHeaderFlag(startLoc, nullptr); auto decl = ParsePackageDeclaration(); ir::ETSModule *script = nullptr; if (decl != nullptr) { diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index a7a53a7933..1d7b1ee848 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -208,6 +208,7 @@ private: ArenaVector &directImportsFromMainSource); parser::Program *ParseSource(const SourceFile &sourceFile); ir::ETSModule *ParseETSGlobalScript(lexer::SourcePosition startLoc, ArenaVector &statements); + void ParseFileHeaderFlag(lexer::SourcePosition startLoc, ArenaVector *statements); ir::ETSModule *ParseImportsAndReExportOnly(lexer::SourcePosition startLoc, ArenaVector &statements); ir::AstNode *ParseImportDefaultSpecifier(ArenaVector *specifiers) override; diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/export1.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/export1.ets new file mode 100644 index 0000000000..3b6361ce1a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/export1.ets @@ -0,0 +1,17 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class A{} diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/export2.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/export2.ets new file mode 100644 index 0000000000..dd2d2b0a2b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/export2.ets @@ -0,0 +1,17 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class B{} diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_copyright.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_copyright.ets new file mode 100644 index 0000000000..f5862745c1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_copyright.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +"use static" + +class A{} diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_importdecl.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_importdecl.ets new file mode 100644 index 0000000000..7245e8367d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_after_importdecl.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { A as A } from "./export1.ets" +import { B as B } from "./export2.ets" + +"use static" +let str:String = "use static" diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_before_importdecl.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_before_importdecl.ets new file mode 100644 index 0000000000..730bab7c5d --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_before_importdecl.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +"use static" +import {A as A} from "./export1.ets" +import {B as B} from "./export2.ets" diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line.ets new file mode 100644 index 0000000000..34045c2ff1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line.ets @@ -0,0 +1,17 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A{} diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2.ets new file mode 100644 index 0000000000..c14b258b49 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2.ets @@ -0,0 +1,17 @@ +'use static' +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A{} diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2_neg.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2_neg.ets new file mode 100644 index 0000000000..df09abb5e1 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_2_neg.ets @@ -0,0 +1,19 @@ +'use statics' +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { A as A } from "./export1.ets" + +/* @@? 17:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_3_neg.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_3_neg.ets new file mode 100644 index 0000000000..1b1cd257ac --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_3_neg.ets @@ -0,0 +1,19 @@ +"uses static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { A as A } from "./export1.ets" + +/* @@? 17:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_neg.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_neg.ets new file mode 100644 index 0000000000..e0a410adc7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_in_first_line_neg.ets @@ -0,0 +1,19 @@ +'uses static' +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { A as A } from "./export1.ets" + +/* @@? 17:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/flag_middle_importdecl_neg.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_middle_importdecl_neg.ets new file mode 100644 index 0000000000..b048662c57 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/flag_middle_importdecl_neg.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {A as A} from "./export1.ets" +"use static" +import {B as B} from "./export2.ets" + +/* @@? 18:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package.ets new file mode 100644 index 0000000000..07508594ee --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package.ets @@ -0,0 +1,17 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage; diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package2.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package2.ets new file mode 100644 index 0000000000..07508594ee --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package/flag_before_package2.ets @@ -0,0 +1,17 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage; diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package_2_neg/flag_before_package.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package_2_neg/flag_before_package.ets new file mode 100644 index 0000000000..ee44269d82 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package_2_neg/flag_before_package.ets @@ -0,0 +1,24 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage3; + +let str2:String = "use static" +import {A as A} from "../export1.ets" +import {B as B} from "../export2.ets" + +/* @@? 20:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ +/* @@? 21:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package_3_neg/flag_before_package.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package_3_neg/flag_before_package.ets new file mode 100644 index 0000000000..55490f06d0 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package_3_neg/flag_before_package.ets @@ -0,0 +1,25 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage3; + +"use static" +import {A as A} from "../export1.ets" +import {B as B} from "../export2.ets" + +/* @@? 19:1 Error SyntaxError: Invalid package toplevel statement */ +/* @@? 20:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ +/* @@? 21:1 Error SyntaxError: Import declarations can only be used on the top level and before any other declaration, top level statement or directive. */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package.ets new file mode 100644 index 0000000000..ae374bb21f --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage2; + +"use static" + +/* @@? 18:1 Error SyntaxError: Invalid package toplevel statement */ diff --git a/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package2.ets b/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package2.ets new file mode 100644 index 0000000000..551145bbe7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/use_static_flag/package_neg/flag_package2.ets @@ -0,0 +1,19 @@ +"use static" +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package usestaticpackage2; + +/* @@? flag_package.ets:18:1 Error SyntaxError: Invalid package toplevel statement */ diff --git a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt index 218f408204..47504eb951 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -177,6 +177,8 @@ ast/compiler/ets/namespace_tests/namespace.ets ast/compiler/ets/namespace_tests/namespace_ambient_export01.ets ast/compiler/ets/namespace_tests/namespace_ambient_export02.ets ast/compiler/ets/namespace_tests/namespace_ambient_export03.ets +ast/compiler/ets/use_static_flag/flag_after_importdecl.ets +ast/compiler/ets/use_static_flag/flag_before_importdecl.ets runtime/ets/namespace_tests/namespace_import_type_test/namespace_import.ets runtime/ets/namespace_tests/namespace_initializer.ets runtime/ets/interface_with_optional_property_cycle_import/class_file.ets -- Gitee From e56c68779afaac0690f002b001e1bb91ec87a6e8 Mon Sep 17 00:00:00 2001 From: lihao Date: Fri, 6 Jun 2025 14:48:31 +0800 Subject: [PATCH 057/747] load es2panda by absolute path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: [新需求]: 使用绝对路径加载es2panda https://gitee.com/openharmony/developtools_ace_ets2bundle/issues/ICD3FM Signed-off-by: lihao --- ets2panda/driver/build_system/src/init/process_build_config.ts | 1 + ets2panda/driver/build_system/src/types.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/ets2panda/driver/build_system/src/init/process_build_config.ts b/ets2panda/driver/build_system/src/init/process_build_config.ts index 0f6109ef23..24b0f0e57c 100644 --- a/ets2panda/driver/build_system/src/init/process_build_config.ts +++ b/ets2panda/driver/build_system/src/init/process_build_config.ts @@ -141,4 +141,5 @@ function initKoalaWrapper(buildConfig: BuildConfig): void { const { arkts, arktsGlobal } = require(koalaWrapperPath); buildConfig.arkts = arkts; buildConfig.arktsGlobal = arktsGlobal; + buildConfig.arktsGlobal.es2panda._SetUpSoPath(buildConfig.pandaSdkPath); } diff --git a/ets2panda/driver/build_system/src/types.ts b/ets2panda/driver/build_system/src/types.ts index 0afb84da07..e375e7d7d8 100644 --- a/ets2panda/driver/build_system/src/types.ts +++ b/ets2panda/driver/build_system/src/types.ts @@ -58,6 +58,7 @@ export interface ArkTSGlobal { _MemFinalize: Function; _CreateGlobalContext: Function; _DestroyGlobalContext: Function; + _SetUpSoPath: Function; } } -- Gitee From 45c74f0d7159a857db4781736454da4a1a8b5979 Mon Sep 17 00:00:00 2001 From: nikozer Date: Tue, 3 Jun 2025 14:13:46 +0300 Subject: [PATCH 058/747] transfer stdlib from no-primitives Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICAZUI Test: ninja etsstdlib Signed-off-by: nikozer --- ets2panda/driver/build_system/src/build/build_mode.ts | 2 +- ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets | 4 ++-- ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets | 4 ++-- ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets | 2 +- ets2panda/test/ast/parser/ets/type_from_utility_type.ets | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ets2panda/driver/build_system/src/build/build_mode.ts b/ets2panda/driver/build_system/src/build/build_mode.ts index accdafbcca..b1643a8d9c 100644 --- a/ets2panda/driver/build_system/src/build/build_mode.ts +++ b/ets2panda/driver/build_system/src/build/build_mode.ts @@ -26,6 +26,6 @@ export class BuildMode extends BaseMode { } public async run(): Promise { - await super.runConcunrent(); + await super.run(); } } \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets index 982bba0c4e..2566f9cbb7 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets @@ -17,6 +17,6 @@ function main(){ let a: Record/* @@ label */ = { "key1": 1, "key2": 2 - } + } } -/* @@@ label Error TypeError: Type Char|String is not assignable to constraint type Numeric|String */ +/* @@@ label Error TypeError: Type Char|String is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets index 71687363c5..7d56f11a52 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets @@ -19,6 +19,6 @@ function main(){ let a: Record/* @@ label */ = { 1: 1, 2: 2 - } + } } -/* @@@ label Error TypeError: Type A|Double is not assignable to constraint type Numeric|String */ +/* @@@ label Error TypeError: Type A|Double is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets index 316c665343..e8ea8a181e 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets @@ -18,4 +18,4 @@ class A{} function main(){ let a: Record/* @@ label */ } -/* @@@ label Error TypeError: Type BigInt is not assignable to constraint type Numeric|String */ +/* @@@ label Error TypeError: Type BigInt is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ diff --git a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets index 6b220807a6..a41765f81a 100644 --- a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets +++ b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets @@ -34,5 +34,5 @@ /* @@? 30:19 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 30:29 Error TypeError: No static $_invoke method and static $_instantiate method in Record. Record() is not allowed. */ /* @@? 30:29 Error TypeError: Type 'Record' has no call signatures. */ - /* @@? 31:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String */ - /* @@? 32:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String */ \ No newline at end of file + /* @@? 31:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ + /* @@? 32:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ \ No newline at end of file -- Gitee From 788059a097b75036923b94b6e2cadb84920f8339 Mon Sep 17 00:00:00 2001 From: Khil Sergey Date: Sat, 7 Jun 2025 07:46:59 +0300 Subject: [PATCH 059/747] fix typo in toplvl Issue:#ICDBBF Signed-off-by: Khil Sergey --- ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp index f07a9a464b..80439e2eff 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp @@ -56,7 +56,7 @@ static void AddExportModifierForInterface(ir::AstNode *const ast) it->AsTSInterfaceDeclaration()->AddModifier(ir::ModifierFlags::EXPORT); } } -}; +} static void DeclareNamespaceExportAdjust(parser::Program *program, const std::string_view &name) { -- Gitee From 2c8ac346703921a7d60060f8e3a58e9dbdc2e114 Mon Sep 17 00:00:00 2001 From: lijincheng Date: Thu, 5 Jun 2025 12:25:20 +0800 Subject: [PATCH 060/747] Bugfix for json annotation 1. move Setannotation outside Issue:https://gitee.com/openharmony/arkcompiler_runtime_core/issues/ICAATS Signed-off-by: lijincheng --- ets2panda/compiler/core/ETSemitter.cpp | 5 ++++- .../test/runtime/ets/AnnotationOfClassPropertyInherit.ets | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 8f0b822ef9..eee0620420 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -437,11 +437,14 @@ void ETSEmitter::GenClassField(const ir::ClassProperty *prop, pandasm::Record &c field.type = PandasmTypeWithRank(prop->TsType()); field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers())); + if (!external) { + field.metadata->SetAnnotations(GenCustomAnnotations(prop->Annotations(), field.name)); + } + if (external || prop->IsDeclare()) { field.metadata->SetAttribute(Signatures::EXTERNAL); } else if (prop->TsType()->IsETSPrimitiveType() || prop->TsType()->IsETSStringType()) { EmitDefaultFieldValue(field, prop->Value()); - field.metadata->SetAnnotations(GenCustomAnnotations(prop->Annotations(), field.name)); } classRecord.fieldList.emplace_back(std::move(field)); diff --git a/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.ets b/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.ets index f7f39edabb..1a10d2134b 100644 --- a/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.ets +++ b/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.ets @@ -13,12 +13,12 @@ * limitations under the License. */ -@interface JSONRename { +@interface JSONRenameTest { name:string = "" } class A { - @JSONRename("ID") + @JSONRenameTest("ID") name2: string = "" pwd2: string = "" } -- Gitee From 1de9a4b96ad00b663a7068918e7fd78f715b6010 Mon Sep 17 00:00:00 2001 From: zmw Date: Sat, 7 Jun 2025 14:53:23 +0800 Subject: [PATCH 061/747] Fix assert string to bool Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDBZ7 Description: Fix assert string to bool Signed-off-by: zmw --- ets2panda/lsp/src/code_fix_provider.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ets2panda/lsp/src/code_fix_provider.cpp b/ets2panda/lsp/src/code_fix_provider.cpp index 1843912767..0aacb84467 100644 --- a/ets2panda/lsp/src/code_fix_provider.cpp +++ b/ets2panda/lsp/src/code_fix_provider.cpp @@ -28,9 +28,8 @@ namespace ark::es2panda::lsp { void CodeFixProvider::RegisterCodeFix(const std::string &aliasName, std::unique_ptr registration) { - if (aliasName.empty()) { - ASSERT("Alias name cannot be empty"); - } + (void)aliasName; + ASSERT(!aliasName.empty()); auto shared = std::shared_ptr(std::move(registration)); for (auto error : shared->GetErrorCodes()) { -- Gitee From b985f08a7d26b93a7428ff5848033ee5ebeab3c8 Mon Sep 17 00:00:00 2001 From: c30058867 Date: Fri, 6 Jun 2025 22:02:37 +0800 Subject: [PATCH 062/747] Fix sdk-no-literal-as-property-name Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICD9N6 Signed-off-by: caiy --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 50 +++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ec2c5e4463..03268fdcb8 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -1424,7 +1424,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } - private isJsRelated(node: ts.Expression): boolean { + private isJsRelated(node: ts.Expression): boolean { if (this.tsUtils.isJsImport(node)) { return true; } @@ -1466,8 +1466,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } return current; - } - + }; + const firstObjNode = getFirstObjectNode(propertyAccessNode); const isJsObject = this.isJsRelated(firstObjNode); if (!isJsObject) { @@ -3161,12 +3161,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { ): boolean { const apiParamCout = sdkFuncArgs.length; const memberParamCout = memberParams.length; - if (apiParamCout > memberParamCout && sdkFuncArgs[memberParamCout + 1]) { + if (apiParamCout > memberParamCout && sdkFuncArgs[memberParamCout]) { return false; } for (let i = 0; i < apiParamCout; i++) { - const typeName = memberParams[i].type?.getText(); + const typeName = memberParams[i]?.type?.getText(); if (!typeName?.match(sdkFuncArgs[i].type)) { return false; } @@ -5218,7 +5218,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.handleNoTuplesArrays(node, targetType, exprType); this.handleObjectLiteralAssignmentToClass(tsAsExpr); } - + private isExemptedAsExpression(node: ts.AsExpression): boolean { if (!ts.isElementAccessExpression(node.expression)) { return false; @@ -6045,7 +6045,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (ts.isNewExpression(rhsExpr) && ts.isIdentifier(rhsExpr.expression) && rhsExpr.expression.text === 'Promise') { const isReturnStatement = ts.isReturnStatement(rhsExpr.parent); const enclosingFunction = ts.findAncestor(rhsExpr, ts.isFunctionLike); - const isAsyncFunction = enclosingFunction && (enclosingFunction.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false); + const isAsyncFunction = + enclosingFunction && + (enclosingFunction.modifiers?.some((m) => { + return m.kind === ts.SyntaxKind.AsyncKeyword; + }) || + false); if (isReturnStatement && isAsyncFunction) { return; } @@ -7587,7 +7592,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } if (ts.isPropertySignature(node)) { - return this.tsTypeChecker.getTypeAtLocation(node.type!).getSymbol(); + return this.tsTypeChecker.getSymbolAtLocation(node); } const nodesWithResolvableType = [ @@ -7625,38 +7630,27 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!ts.isTypeReferenceNode(typeNode)) { return undefined; } - const symbol = this.tsTypeChecker.getTypeAtLocation(typeNode).getSymbol(); - if (!symbol) { - return this.resolveTypeNoSymbol(typeNode); - } - const declarations = symbol.getDeclarations(); - if (declarations && declarations.length > 0) { - const declaration = declarations[0]; - if (ts.isTypeAliasDeclaration(declaration)) { - return this.resolveTypeNodeSymbol(declaration.type); - } else if (ts.isInterfaceDeclaration(declaration)) { - const heritageSymbol = this.processQuotedHyphenPropsDeprecatedOnInterfaceDeclaration(declaration); - return heritageSymbol; - } - } - return this.tsTypeChecker.getTypeAtLocation(typeNode).getSymbol(); + return this.resolveTypeNoSymbol(typeNode); } private resolveTypeNoSymbol(typeNode: ts.TypeReferenceNode): ts.Symbol | undefined { if (!typeNode.typeName) { return undefined; } + if (ts.isQualifiedName(typeNode.typeName)) { return this.tsTypeChecker.getSymbolAtLocation(typeNode.typeName.right); } - const sym = this.tsUtils.trueSymbolAtLocation(typeNode.typeName); - if (sym) { - const globalDeclaration = sym.getDeclarations()?.[0]; - if (globalDeclaration && ts.isTypeAliasDeclaration(globalDeclaration)) { + + const symbol = this.tsUtils.trueSymbolAtLocation(typeNode.typeName); + if (symbol?.declarations && symbol.declarations.length > 0) { + const globalDeclaration = symbol.declarations[0]; + if (ts.isTypeAliasDeclaration(globalDeclaration)) { return this.resolveTypeNodeSymbol(globalDeclaration.type); + } else if (ts.isInterfaceDeclaration(globalDeclaration)) { + return this.processQuotedHyphenPropsDeprecatedOnInterfaceDeclaration(globalDeclaration); } } - return this.tsTypeChecker.getTypeAtLocation(typeNode).getSymbol(); } -- Gitee From d65e980411b5b7b4d6b71f1732378f447596ec20 Mon Sep 17 00:00:00 2001 From: sniperc96 Date: Wed, 4 Jun 2025 11:48:53 +0800 Subject: [PATCH 063/747] add autofix for arkui-no-xxxprop-decorator Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCICE Signed-off-by: sniperc96 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 7 +- .../linter/src/lib/autofixes/AutofixTitles.ts | 3 + .../linter/src/lib/autofixes/Autofixer.ts | 12 +- .../src/lib/utils/consts/ArkuiConstants.ts | 6 +- .../src/lib/utils/consts/ArkuiImportList.ts | 3 + ..._decorators_and_interfaces_1.ets.args.json | 4 +- ...ecorators_and_interfaces_1.ets.arkts2.json | 30 - ...corators_and_interfaces_1.ets.autofix.json | 207 +++++ ...ecorators_and_interfaces_1.ets.migrate.ets | 43 + ...corators_and_interfaces_1.ets.migrate.json | 48 + ..._decorators_and_interfaces_4.ets.args.json | 4 +- ...ecorators_and_interfaces_4.ets.arkts2.json | 30 - ...corators_and_interfaces_4.ets.autofix.json | 846 ++++++++++++++++++ ...ecorators_and_interfaces_4.ets.migrate.ets | 112 +++ ...corators_and_interfaces_4.ets.migrate.json | 78 ++ 15 files changed, 1366 insertions(+), 67 deletions(-) create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.autofix.json create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.json create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.autofix.json create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ec2c5e4463..071080738e 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8969,15 +8969,16 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } + const autofix = this.autofixer?.fixPropDecorator(decorators[0], decoratorName); switch (decoratorName) { case PropDecoratorName.Prop: - this.incrementCounters(node, FaultID.PropDecoratorNotSupported); + this.incrementCounters(node, FaultID.PropDecoratorNotSupported, autofix); break; case PropDecoratorName.StorageProp: - this.incrementCounters(node, FaultID.StoragePropDecoratorNotSupported); + this.incrementCounters(node, FaultID.StoragePropDecoratorNotSupported, autofix); break; case PropDecoratorName.LocalStorageProp: - this.incrementCounters(node, FaultID.LocalStoragePropDecoratorNotSupported); + this.incrementCounters(node, FaultID.LocalStoragePropDecoratorNotSupported, autofix); break; default: } diff --git a/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts b/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts index 8b54a99d03..50d470573a 100644 --- a/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts +++ b/ets2panda/linter/src/lib/autofixes/AutofixTitles.ts @@ -52,6 +52,9 @@ export const cookBookRefToFixTitle: Map = new Map([ [260, '"@Entry" annotaion fixed'], [263, '"@Provide" annotation fixed'], [275, 'Custom layout need add decorator'], + [281, '"@Prop" transform to "@PropRef"'], + [282, '"@StorageProp" transform to "@StoragePropRef"'], + [283, '"@LocalStorageProp" transform to "@LocalStoragePropRef"'], [300, 'Replace calling method of the TS-like `Function` type'], [330, 'Convert import named objects from JS to ESValue'], [332, 'Using the ESValue interface to access properties'], diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index b0e3f2289e..8c171d38d2 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -39,7 +39,8 @@ import { GET_LOCAL_STORAGE_FUNC_NAME, PROVIDE_DECORATOR_NAME, PROVIDE_ALIAS_PROPERTY_NAME, - PROVIDE_ALLOW_OVERRIDE_PROPERTY_NAME + PROVIDE_ALLOW_OVERRIDE_PROPERTY_NAME, + NEW_PROP_DECORATOR_SUFFIX } from '../utils/consts/ArkuiConstants'; import { ES_VALUE } from '../utils/consts/ESObject'; import type { IncrementDecrementNodeInfo } from '../utils/consts/InteropAPI'; @@ -4822,4 +4823,13 @@ export class Autofixer { void this; return [{ start: node.getStart(), end: node.getEnd(), replacementText: `${node.getText()}.0` }]; } + + fixPropDecorator(node: ts.Decorator, decoratorName: string): Autofix[] { + const newDecorator = ts.factory.createDecorator( + ts.factory.createIdentifier(decoratorName + NEW_PROP_DECORATOR_SUFFIX) + ); + + const text = this.printer.printNode(ts.EmitHint.Unspecified, newDecorator, node.getSourceFile()); + return [{ start: node.getStart(), end: node.getEnd(), replacementText: text }]; + } } diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts index 159e986494..369c37a835 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiConstants.ts @@ -25,6 +25,7 @@ export const VALUE_IDENTIFIER = 'value'; export const INDENT_STEP = 2; export const MAKE_OBSERVED = 'makeObserved'; export const ARKUI_STATE_MANAGEMENT = '@ohos.arkui.StateManagement'; +export const NEW_PROP_DECORATOR_SUFFIX = 'Ref'; export enum CustomDecoratorName { Extend = 'Extend', @@ -70,7 +71,10 @@ export const skipImportDecoratorName: Set = new Set([ 'Styles', 'Sendable', 'Concurrent', - 'LocalBuilder' + 'LocalBuilder', + 'Prop', + 'StorageProp', + 'LocalStorageProp' ]); export const customLayoutFunctionName: Set = new Set(['onMeasureSize', 'onPlaceChildren']); diff --git a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts index 2a9e201f68..9ae6e8d95e 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkuiImportList.ts @@ -687,6 +687,7 @@ export const arkuiImportList: Set = new Set([ 'LocalStorage', 'LocalStorageLink', 'LocalStorageProp', + 'LocalStoragePropRef', 'LocalizedAlignRuleOptions', 'LocalizedAlignment', 'LocalizedBarrierDirection', @@ -1054,6 +1055,7 @@ export const arkuiImportList: Set = new Set([ 'ProgressStyleOptions', 'ProgressType', 'Prop', + 'PropRef', 'ProtectedResourceType', 'Provide', 'ProvideOptions', @@ -1321,6 +1323,7 @@ export const arkuiImportList: Set = new Set([ 'Storage', 'StorageLink', 'StorageProp', + 'StoragePropRef', 'StyleOptions', 'StyledString', 'StyledStringChangeValue', diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json index 4acc088d1d..ee0734c0fc 100644 --- a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.args.json @@ -14,6 +14,8 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" } } \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json index 2bf08fd4cc..401a2080f7 100644 --- a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.arkts2.json @@ -74,16 +74,6 @@ "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", "severity": "ERROR" }, - { - "line": 24, - "column": 4, - "endLine": 24, - "endColumn": 8, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" - }, { "line": 25, "column": 4, @@ -113,26 +103,6 @@ "suggest": "", "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", "severity": "ERROR" - }, - { - "line": 34, - "column": 4, - "endLine": 34, - "endColumn": 15, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" - }, - { - "line": 35, - "column": 4, - "endLine": 35, - "endColumn": 20, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.autofix.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.autofix.json new file mode 100644 index 0000000000..ce347e8be8 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.autofix.json @@ -0,0 +1,207 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 18, + "column": 17, + "endLine": 18, + "endColumn": 18, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 654, + "end": 655, + "replacementText": "0.0", + "line": 18, + "column": 17, + "endLine": 18, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 24, + "column": 3, + "endLine": 24, + "endColumn": 33, + "problem": "PropDecoratorNotSupported", + "autofix": [ + { + "start": 704, + "end": 709, + "replacementText": "@PropRef", + "line": 24, + "column": 3, + "endLine": 24, + "endColumn": 33 + } + ], + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 3, + "endLine": 34, + "endColumn": 49, + "problem": "StoragePropDecoratorNotSupported", + "autofix": [ + { + "start": 895, + "end": 916, + "replacementText": "@StoragePropRef", + "line": 34, + "column": 3, + "endLine": 34, + "endColumn": 49 + } + ], + "suggest": "", + "rule": "\"@StorageProp\" decorator is not supported (arkui-no-storageprop-decorator)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 3, + "endLine": 35, + "endColumn": 54, + "problem": "LocalStoragePropDecoratorNotSupported", + "autofix": [ + { + "start": 944, + "end": 970, + "replacementText": "@LocalStoragePropRef", + "line": 35, + "column": 3, + "endLine": 35, + "endColumn": 54 + } + ], + "suggest": "", + "rule": "\"@LocalStorageProp\" decorator is not supported (arkui-no-localstorageprop-decorator)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 2, + "endLine": 21, + "endColumn": 7, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI';", + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 2, + "endLine": 22, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI';", + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 4, + "endLine": 25, + "endColumn": 15, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI';", + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 4, + "endLine": 26, + "endColumn": 20, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI';", + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI';", + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.ets new file mode 100644 index 0000000000..15f5527cbf --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PropRef, StoragePropRef, LocalStoragePropRef } from '@kit.ArkUI'; + +import { Entry, Component, StorageLink, LocalStorageLink } from '@kit.ArkUI'; + +class User { + name: string = "" + age: number = 0.0 +} + +@Entry +@Component +struct FatherComponent { + @PropRef user1: User = new User() + @StorageLink("user2") user2: User = new User() + @LocalStorageLink("user3") user3: User = new User() + + build() { + } +} + +@Component +struct ChildComponent { + @StoragePropRef user2: User = new User() + @LocalStoragePropRef user3: User = new User() + + build() { + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.json new file mode 100644 index 0000000000..671d92eb76 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_1.ets.migrate.json @@ -0,0 +1,48 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 28, + "column": 3, + "endLine": 28, + "endColumn": 11, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 3, + "endLine": 38, + "endColumn": 18, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 3, + "endLine": 39, + "endColumn": 23, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json index 4acc088d1d..ee0734c0fc 100644 --- a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json @@ -14,6 +14,8 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" } } \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json index 552209810c..cccb54838c 100644 --- a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.arkts2.json @@ -254,16 +254,6 @@ "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", "severity": "ERROR" }, - { - "line": 58, - "column": 4, - "endLine": 58, - "endColumn": 8, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" - }, { "line": 61, "column": 5, @@ -324,16 +314,6 @@ "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", "severity": "ERROR" }, - { - "line": 76, - "column": 4, - "endLine": 76, - "endColumn": 8, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" - }, { "line": 79, "column": 5, @@ -394,16 +374,6 @@ "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", "severity": "ERROR" }, - { - "line": 94, - "column": 4, - "endLine": 94, - "endColumn": 8, - "problem": "UIInterfaceImport", - "suggest": "", - "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", - "severity": "ERROR" - }, { "line": 97, "column": 5, diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.autofix.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.autofix.json new file mode 100644 index 0000000000..8f95ab1674 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.autofix.json @@ -0,0 +1,846 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 22, + "column": 57, + "endLine": 22, + "endColumn": 58, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 751, + "end": 752, + "replacementText": "0.0", + "line": 22, + "column": 57, + "endLine": 22, + "endColumn": 58 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 25, + "endLine": 26, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 57, + "endLine": 34, + "endColumn": 58, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 984, + "end": 985, + "replacementText": "0.0", + "line": 34, + "column": 57, + "endLine": 34, + "endColumn": 58 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 25, + "endLine": 38, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 57, + "endLine": 46, + "endColumn": 58, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1217, + "end": 1218, + "replacementText": "0.0", + "line": 46, + "column": 57, + "endLine": 46, + "endColumn": 58 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 25, + "endLine": 50, + "endColumn": 52, + "problem": "PropNeedCallMethodForDeepCopy", + "suggest": "", + "rule": "Parameters decorated with \"@Prop\" need to call the specific method when receiving data to ensure deep copy of the data (arkui-prop-need-call-method-for-deep-copy)", + "severity": "ERROR" + }, + { + "line": 58, + "column": 3, + "endLine": 58, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "autofix": [ + { + "start": 1396, + "end": 1401, + "replacementText": "@PropRef", + "line": 58, + "column": 3, + "endLine": 58, + "endColumn": 41 + } + ], + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 3, + "endLine": 76, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "autofix": [ + { + "start": 1710, + "end": 1715, + "replacementText": "@PropRef", + "line": 76, + "column": 3, + "endLine": 76, + "endColumn": 41 + } + ], + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 83, + "column": 31, + "endLine": 83, + "endColumn": 32, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1895, + "end": 1896, + "replacementText": "1.0", + "line": 83, + "column": 31, + "endLine": 83, + "endColumn": 32 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 86, + "column": 31, + "endLine": 86, + "endColumn": 32, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1977, + "end": 1978, + "replacementText": "1.0", + "line": 86, + "column": 31, + "endLine": 86, + "endColumn": 32 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 94, + "column": 3, + "endLine": 94, + "endColumn": 41, + "problem": "PropDecoratorNotSupported", + "autofix": [ + { + "start": 2040, + "end": 2045, + "replacementText": "@PropRef", + "line": 94, + "column": 3, + "endLine": 94, + "endColumn": 41 + } + ], + "suggest": "", + "rule": "\"@Prop\" decorator is not supported (arkui-no-prop-decorator)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 2, + "endLine": 20, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 4, + "endLine": 22, + "endColumn": 9, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 25, + "column": 5, + "endLine": 25, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 7, + "endLine": 27, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 2, + "endLine": 32, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 4, + "endLine": 34, + "endColumn": 9, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 5, + "endLine": 37, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 7, + "endLine": 39, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 2, + "endLine": 44, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 46, + "column": 4, + "endLine": 46, + "endColumn": 9, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 49, + "column": 5, + "endLine": 49, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 51, + "column": 7, + "endLine": 51, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 2, + "endLine": 56, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 61, + "column": 5, + "endLine": 61, + "endColumn": 8, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 7, + "endLine": 62, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 63, + "column": 7, + "endLine": 63, + "endColumn": 12, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 7, + "endLine": 64, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 67, + "column": 7, + "endLine": 67, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 74, + "column": 2, + "endLine": 74, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 5, + "endLine": 79, + "endColumn": 8, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 7, + "endLine": 80, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 81, + "column": 7, + "endLine": 81, + "endColumn": 12, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 7, + "endLine": 82, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 85, + "column": 7, + "endLine": 85, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 92, + "column": 2, + "endLine": 92, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 97, + "column": 5, + "endLine": 97, + "endColumn": 8, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 98, + "column": 7, + "endLine": 98, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 99, + "column": 7, + "endLine": 99, + "endColumn": 12, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 100, + "column": 7, + "endLine": 100, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI';", + "line": 103, + "column": 7, + "endLine": 103, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.ets b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.ets new file mode 100644 index 0000000000..7183356197 --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.ets @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { PropRef } from '@kit.ArkUI'; + +import { Component, State, Column, Text, Row, Blank, Button } from '@kit.ArkUI'; + +interface ChildComponentOptions { + count: number; +} + +@Component +struct SuperComponent1 { + @State countOptions: ChildComponentOptions = { count: 0.0 } + + build() { + Column() { + ChildComponent1({ options1: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct SuperComponent2 { + @State countOptions: ChildComponentOptions = { count: 0.0 } + + build() { + Column() { + ChildComponent2({ options2: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct SuperComponent3 { + @State countOptions: ChildComponentOptions = { count: 0.0 } + + build() { + Column() { + ChildComponent3({ options3: this.countOptions }) + Text(`${this.countOptions.count}`) + } + } +} + +@Component +struct ChildComponent1 { + @PropRef options1: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options1.count}`) + Blank() + Button('+').onClick(() => { + this.options1.count++; + }) + Button('-').onClick(() => { + this.options1.count--; + }) + } + } +} + +@Component +struct ChildComponent2 { + @PropRef options2: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options2.count}`) + Blank() + Button('change1').onClick(() => { + this.options2.count = 1.0; + }) + Button('change2').onClick(() => { + this.options2.count = 1.0; + }) + } + } +} + +@Component +struct ChildComponent3 { + @PropRef options3: ChildComponentOptions; + + build() { + Row() { + Text(`${this.options3.count}`) + Blank() + Button('+').onClick(() => { + ++this.options3.count; + }) + Button('-').onClick(() => { + --this.options3.count; + }) + } + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.json new file mode 100644 index 0000000000..e9031d32bc --- /dev/null +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.migrate.json @@ -0,0 +1,78 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 62, + "column": 3, + "endLine": 62, + "endColumn": 11, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 3, + "endLine": 80, + "endColumn": 11, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + }, + { + "line": 98, + "column": 3, + "endLine": 98, + "endColumn": 11, + "problem": "DecoratorsNotSupported", + "suggest": "", + "rule": "Decorators are not supported(arkts-no-ts-decorators)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 12, + "endLine": 62, + "endColumn": 20, + "problem": "StrictDiagnostic", + "suggest": "Property 'options1' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'options1' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 80, + "column": 12, + "endLine": 80, + "endColumn": 20, + "problem": "StrictDiagnostic", + "suggest": "Property 'options2' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'options2' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + }, + { + "line": 98, + "column": 12, + "endLine": 98, + "endColumn": 20, + "problem": "StrictDiagnostic", + "suggest": "Property 'options3' has no initializer and is not definitely assigned in the constructor.", + "rule": "Property 'options3' has no initializer and is not definitely assigned in the constructor.", + "severity": "ERROR" + } + ] +} \ No newline at end of file -- Gitee From 0d63d8a670698d48228b72db4fac58cdef91c187 Mon Sep 17 00:00:00 2001 From: sniperc96 Date: Sat, 7 Jun 2025 17:55:29 +0800 Subject: [PATCH 064/747] fix bug:arkui-no-bidirectional-data-binding Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDDJO Signed-off-by: sniperc96 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 46 ++--- .../test/main/double_excla_binding_3.ets | 32 ++++ .../main/double_excla_binding_3.ets.args.json | 21 +++ .../double_excla_binding_3.ets.arkts2.json | 88 ++++++++++ .../double_excla_binding_3.ets.autofix.json | 165 ++++++++++++++++++ .../test/main/double_excla_binding_3.ets.json | 17 ++ .../double_excla_binding_3.ets.migrate.ets | 34 ++++ .../double_excla_binding_3.ets.migrate.json | 17 ++ 8 files changed, 400 insertions(+), 20 deletions(-) create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.args.json create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.autofix.json create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.json create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.json diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ec2c5e4463..19ff79d1f8 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -6576,6 +6576,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { !ts.isNonNullExpression(node) || !ts.isNonNullExpression(node.expression) || ts.isNonNullExpression(node.parent) || + ts.isPropertyAccessExpression(node.parent) || ts.isNonNullExpression(node.expression.expression) ) { return; @@ -6583,26 +6584,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const statement = ts.findAncestor(node, ts.isExpressionStatement); if (statement && this.isCustomComponent(statement)) { - let currentParam: ts.Identifier | undefined; - if (ts.isPropertyAccessExpression(node.expression.expression)) { - currentParam = node.expression.expression.name as ts.Identifier; - } - - let customParam: ts.Identifier | undefined; - if (ts.isPropertyAssignment(node.parent)) { - customParam = node.parent.name as ts.Identifier; - } - - if (!currentParam || !customParam) { - return; - } - - const originalExpr = node.parent.parent; - if (!ts.isObjectLiteralExpression(originalExpr)) { - return; - } - const autofix = this.autofixer?.fixCustomBidirectionalBinding(originalExpr, currentParam, customParam); - this.incrementCounters(node, FaultID.DoubleExclaBindingNotSupported, autofix); + this.handleCustomBidirectionalBinding(node, node.expression); } else { const autofix = this.autofixer?.fixNativeBidirectionalBinding(node, this.interfacesNeedToImport); this.incrementCounters(node, FaultID.DoubleExclaBindingNotSupported, autofix); @@ -6631,6 +6613,30 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return this.interfacesAlreadyImported.has(callExpr.expression.getText()); } + private handleCustomBidirectionalBinding(firstExpr: ts.NonNullExpression, secondExpr: ts.NonNullExpression): void { + let currentParam: ts.Identifier | undefined; + if (ts.isPropertyAccessExpression(secondExpr.expression)) { + currentParam = secondExpr.expression.name as ts.Identifier; + } + + let customParam: ts.Identifier | undefined; + if (ts.isPropertyAssignment(firstExpr.parent)) { + customParam = firstExpr.parent.name as ts.Identifier; + } + + if (!currentParam || !customParam) { + return; + } + + const originalExpr = firstExpr.parent.parent; + if (!ts.isObjectLiteralExpression(originalExpr)) { + return; + } + + const autofix = this.autofixer?.fixCustomBidirectionalBinding(originalExpr, currentParam, customParam); + this.incrementCounters(firstExpr, FaultID.DoubleExclaBindingNotSupported, autofix); + } + private handleDoubleDollar(node: ts.Node): void { if (!this.options.arkts2) { return; diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets b/ets2panda/linter/test/main/double_excla_binding_3.ets new file mode 100644 index 0000000000..8c9dcc1e87 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class User { + name: string = "Jack" +} + +@Entry +@Component +struct MyComponent { + @State user: User = new User() + + build() { + Row() { + Text(this.user!.name) + Text(this.user!!.name) + Text(this.user!!!.name) + } + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.args.json b/ets2panda/linter/test/main/double_excla_binding_3.ets.args.json new file mode 100644 index 0000000000..30973c00a2 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.args.json @@ -0,0 +1,21 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.arkts2.json b/ets2panda/linter/test/main/double_excla_binding_3.ets.arkts2.json new file mode 100644 index 0000000000..592f7eb23d --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.arkts2.json @@ -0,0 +1,88 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 20, + "column": 2, + "endLine": 20, + "endColumn": 7, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 2, + "endLine": 21, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 4, + "endLine": 23, + "endColumn": 9, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 8, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 7, + "endLine": 27, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 7, + "endLine": 28, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11, + "problem": "UIInterfaceImport", + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.autofix.json b/ets2panda/linter/test/main/double_excla_binding_3.ets.autofix.json new file mode 100644 index 0000000000..31a6345741 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.autofix.json @@ -0,0 +1,165 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 20, + "column": 2, + "endLine": 20, + "endColumn": 7, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 21, + "column": 2, + "endLine": 21, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 4, + "endLine": 23, + "endColumn": 9, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 8, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 7, + "endLine": 27, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 28, + "column": 7, + "endLine": 28, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11, + "problem": "UIInterfaceImport", + "autofix": [ + { + "start": 603, + "end": 603, + "replacementText": "\n\nimport { Entry, Component, State, Row, Text } from '@kit.ArkUI';", + "line": 29, + "column": 7, + "endLine": 29, + "endColumn": 11 + } + ], + "suggest": "", + "rule": "ArkUI interface should be imported before using (arkui-modular-interface)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.json b/ets2panda/linter/test/main/double_excla_binding_3.ets.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.ets b/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.ets new file mode 100644 index 0000000000..b646a64c49 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entry, Component, State, Row, Text } from '@kit.ArkUI'; + +class User { + name: string = "Jack" +} + +@Entry +@Component +struct MyComponent { + @State user: User = new User() + + build() { + Row() { + Text(this.user!.name) + Text(this.user!!.name) + Text(this.user!!!.name) + } + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.json b/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.json new file mode 100644 index 0000000000..b7a8809e02 --- /dev/null +++ b/ets2panda/linter/test/main/double_excla_binding_3.ets.migrate.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee From a7732490ee28b991181240897e228d4f298658c5 Mon Sep 17 00:00:00 2001 From: ZhongNing Date: Thu, 5 Jun 2025 19:32:26 +0800 Subject: [PATCH 065/747] fix arkts-method-inherit-rule Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCJ2A Test scenarios: fix bug Signed-off-by: ZhongNing --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 80 +++++++-- .../linter/test/main/method_inheritance.ets | 129 +++++++++++++- .../main/method_inheritance.ets.arkts2.json | 160 ++++++++++++++++++ 3 files changed, 352 insertions(+), 17 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e2ebe7badf..5db2ab9255 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -3586,42 +3586,73 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const classType = this.tsTypeChecker.getTypeAtLocation(classDecl); - const baseTypes = classType.getBaseTypes(); - if (!baseTypes || baseTypes.length === 0) { + const allBaseTypes = this.getAllBaseTypes(classType, classDecl); + if (!allBaseTypes || allBaseTypes.length === 0) { return; } const methodName = node.name.text; - for (const baseType of baseTypes) { + for (const baseType of allBaseTypes) { const baseMethod = baseType.getProperty(methodName); if (!baseMethod) { continue; } - const baseMethodDecl = baseMethod.declarations?.find(ts.isMethodDeclaration); + const baseMethodDecl = baseMethod.declarations?.find((d) => { + return ts.isMethodDeclaration(d) || ts.isMethodSignature(d); + }) as ts.MethodDeclaration | ts.MethodSignature | undefined; + if (!baseMethodDecl) { continue; } - // Check parameter compatibility this.checkMethodParameters(node, baseMethodDecl); - // Check return type compatibility this.checkMethodReturnType(node, baseMethodDecl); break; } } + private getAllBaseTypes(type: ts.Type, classDecl: ts.ClassDeclaration): ts.Type[] | undefined { + const baseClasses = type.getBaseTypes() || []; + if (!classDecl.heritageClauses) { + return baseClasses; + } + const interfaces: ts.Type[] = []; + for (const clause of classDecl.heritageClauses) { + if (clause.token !== ts.SyntaxKind.ImplementsKeyword) { + continue; + } + for (const typeNode of clause.types) { + const interfaceType = this.tsTypeChecker.getTypeAtLocation(typeNode); + interfaces.push(interfaceType); + const parentInterfaces = interfaceType.getBaseTypes(); + if (parentInterfaces) { + interfaces.push(...parentInterfaces); + } + } + } + return [...baseClasses, ...interfaces]; + } + /** - * Checks if child parameters accept at least as many types as parent parameters. - * (Child parameter type should be same or wider than parent.) + * Checks method parameter compatibility + * Derived parameter types must be same or wider than base (contravariance principle) */ - private checkMethodParameters(derivedMethod: ts.MethodDeclaration, baseMethod: ts.MethodDeclaration): void { + private checkMethodParameters( + derivedMethod: ts.MethodDeclaration, + baseMethod: ts.MethodDeclaration | ts.MethodSignature + ): void { const derivedParams = derivedMethod.parameters; const baseParams = baseMethod.parameters; + if (derivedParams.length !== baseParams.length) { + this.incrementCounters(derivedMethod.name, FaultID.MethodInheritRule); + return; + } + const paramCount = Math.min(derivedParams.length, baseParams.length); for (let i = 0; i < paramCount; i++) { @@ -3635,10 +3666,22 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } /** - * Checks return type covariance between base and derived methods. - * (Derived return type must be assignable to base return type.) + * Checks return type compatibility + * Derived return type must be same or narrower than base (covariance principle) */ - private checkMethodReturnType(derivedMethod: ts.MethodDeclaration, baseMethod: ts.MethodDeclaration): void { + private checkMethodReturnType( + derivedMethod: ts.MethodDeclaration, + baseMethod: ts.MethodDeclaration | ts.MethodSignature + ): void { + if ( + this.IsVoidTypeOnActualReturnType(baseMethod) && + derivedMethod.type && + !this.IsVoidTypeOnActualReturnType(derivedMethod) + ) { + this.incrementCounters(derivedMethod.type, FaultID.MethodInheritRule); + return; + } + if (!baseMethod.type || !derivedMethod.type) { return; } @@ -3651,6 +3694,19 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } + private IsVoidTypeOnActualReturnType(method: ts.MethodDeclaration | ts.MethodSignature): boolean | undefined { + let type: ts.Type | undefined; + if (method.type) { + type = this.tsTypeChecker.getTypeAtLocation(method.type); + } else { + const signature = this.tsTypeChecker.getSignatureFromDeclaration(method); + if (signature) { + type = this.tsTypeChecker.getReturnTypeOfSignature(signature); + } + } + return type && TsUtils.isVoidType(type); + } + /** * Child type should include all types of parent type (be same or wider). * Returns true if every type in baseType is also included in derivedType. diff --git a/ets2panda/linter/test/main/method_inheritance.ets b/ets2panda/linter/test/main/method_inheritance.ets index ff1895fc91..c92fa1f0d9 100644 --- a/ets2panda/linter/test/main/method_inheritance.ets +++ b/ets2panda/linter/test/main/method_inheritance.ets @@ -18,7 +18,7 @@ abstract class Y { } class X extends Y { - async getDataByName(name: string, albumUri: string): Promise { + async getDataByName(name: string, albumUri: string): Promise { // error 2 return; } } @@ -38,7 +38,7 @@ abstract class W { } class Q extends W { - async getDataByName(name: string | number, albumUri: string | number): Promise { + async getDataByName(name: string | number, albumUri: string | number): Promise {// error 1 return; }; } @@ -48,7 +48,7 @@ abstract class BaseClass3 { } class IncorrectWiderReturn extends BaseClass3 { - compute(value: string): string | number { + compute(value: string): string | number {// error 1 return value.length > 5 ? value : 0; } } @@ -58,7 +58,7 @@ abstract class BaseClass4 { } class IncorrectMultipleParamMismatch extends BaseClass4 { - setValues(x: string, y: boolean): void { + setValues(x: string, y: boolean): void {// error 2 console.log(x, y); } } @@ -68,7 +68,7 @@ abstract class BaseClass5 { } class IncorrectBothMismatch extends BaseClass5 { - transform(data: number): number | string { + transform(data: number): number | string {// error 2 return data > 10 ? data : "too small"; } } @@ -97,3 +97,122 @@ class CorrectBothWiderParamNarrowReturn extends BaseClass { } +class A1 { + a: number = 0 +} +class B1 { + a: number = 0 +} +class C { + a: number = 0 +} + +class Base { + foo(obj: A1 | B1): void { + console.log("base") + } + foo2(obj: A1 | B1): void { + console.log("base") + } + foo3(obj: A1 | B1 | C): void { + console.log("base") + } +} + +// extends +class Derived extends Base { + foo(obj: A1): void { // error 1 + console.log("Derived:" + obj.a) + } + foo2(): void { // error 1 + console.log("Derived:") + } + foo3(obj: A1 | B1): void { // error 1 + console.log("Derived:") + } +} + +interface BaseI { + foo(obj: A1 | B1):void; + foo2(obj: A1): void; + foo3(obj: A1 | B1 | C): void; +} + +// implements +class Derived2 implements BaseI { + foo(obj: A1): void { // error 1 + console.log("Drived"); + } + foo2(): void { // error 1 + console.log("Drived"); + } + foo3(obj: A1 | B1): void { // error 1 + console.log("Drived"); + } +} + +class Base2 { + foo(): A1|B1 { + console.log("base") + return new A1(); + } + foo2(){ + console.log("base") + // return new A(); + } + foo3(): A1 { + console.log("base") + return new A1(); + } + foo4():void{ + console.log("base") + // return new A(); + } +} + +//extends +class Derived3 extends Base2 { + foo(): A1|B1|C{ // error 1 + console.log("Derived:") + return new A1(); + } + + foo2(): A1{ // error 1 + console.log("Derived:") + return new A1(); + } + + foo3(): A1|B1 { // error 1 + console.log("Derived:") + return new A1(); + } + foo4(): A1{ // error 1 + console.log("Derived:") + return new A1(); + } +} + + +interface Base3 { + foo(): A1|B1 ; + foo2(): void; + foo3(): A1; +} + +// implements +class Derived4 implements Base3 { + foo(): A1|B1|C{ // error 1 + console.log("Derived:") + return new A1(); + } + + foo2(): A1{ // error 1 + console.log("Derived:") + return new A1(); + } + + foo3(): A1|B1 { // error 1 + console.log("Derived:") + return new A1(); + } +} diff --git a/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json b/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json index 717bb1ec00..a25dd05807 100644 --- a/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json +++ b/ets2panda/linter/test/main/method_inheritance.ets.arkts2.json @@ -133,6 +133,166 @@ "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 101, + "column": 15, + "endLine": 101, + "endColumn": 16, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 104, + "column": 15, + "endLine": 104, + "endColumn": 16, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 107, + "column": 15, + "endLine": 107, + "endColumn": 16, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 124, + "column": 7, + "endLine": 124, + "endColumn": 14, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 127, + "column": 3, + "endLine": 127, + "endColumn": 7, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 130, + "column": 8, + "endLine": 130, + "endColumn": 20, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 143, + "column": 7, + "endLine": 143, + "endColumn": 14, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 146, + "column": 3, + "endLine": 146, + "endColumn": 7, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 8, + "endLine": 149, + "endColumn": 20, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 175, + "column": 10, + "endLine": 175, + "endColumn": 17, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 180, + "column": 11, + "endLine": 180, + "endColumn": 13, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 185, + "column": 11, + "endLine": 185, + "endColumn": 16, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 189, + "column": 11, + "endLine": 189, + "endColumn": 13, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 204, + "column": 10, + "endLine": 204, + "endColumn": 17, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 209, + "column": 11, + "endLine": 209, + "endColumn": 13, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" + }, + { + "line": 214, + "column": 11, + "endLine": 214, + "endColumn": 16, + "problem": "MethodInheritRule", + "suggest": "", + "rule": "Overridden method parameters and return types must respect type inheritance principles (arkts-method-inherit-rule)", + "severity": "ERROR" } ] } \ No newline at end of file -- Gitee From 21046ab148c33daa0eb15198c295af11e38ff402 Mon Sep 17 00:00:00 2001 From: xudan16 Date: Mon, 9 Jun 2025 14:44:00 +0800 Subject: [PATCH 066/747] fix error in bind this rule Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDNT3 Signed-off-by: xudan16 --- .../src/checker/migration/ThisBindCheck.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts index af8657687c..b4921ec648 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts @@ -29,6 +29,7 @@ import { ArkNewExpr, ArkClass, ClassSignature, + ArkReturnStmt, } from 'arkanalyzer'; import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; import { BaseChecker, BaseMetaData } from '../BaseChecker'; @@ -115,7 +116,18 @@ export class ThisBindCheck implements BaseChecker { private useThisInBody(method: ArkMethod): boolean { const thisInstance = (method.getThisInstance() as Local)!; - return thisInstance.getUsedStmts().length > 0; + const usedStmts = thisInstance.getUsedStmts(); + if (method.getName() !== 'constructor') { + return usedStmts.length > 0; + } + // constructor方法一定会有return this语句,此句若为ArkAnalyzer为constructor方法自动生成,则不在检查范围内 + for (const stmt of usedStmts) { + if (stmt instanceof ArkReturnStmt && stmt.getOriginPositionInfo().getLineNo() <= 0) { + continue; + } + return true; + } + return false; } private isSafeUse(v: Value): boolean { -- Gitee From 047b3e55465c4f92564b9365282d925b8e1ccc83 Mon Sep 17 00:00:00 2001 From: lijunru Date: Mon, 9 Jun 2025 15:06:18 +0800 Subject: [PATCH 067/747] Fix might be unused parameter Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDOG3 Signed-off-by: lijunru --- ets2panda/lsp/src/isolated_declaration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ets2panda/lsp/src/isolated_declaration.cpp b/ets2panda/lsp/src/isolated_declaration.cpp index 621b219c41..d4df74d45d 100644 --- a/ets2panda/lsp/src/isolated_declaration.cpp +++ b/ets2panda/lsp/src/isolated_declaration.cpp @@ -49,7 +49,8 @@ std::optional GenUnionType(const checker::ETSUnionType *unionType, const char splitChar); template -std::vector FilterUnionTypes(const ArenaVector &originTypes, checker::ETSChecker *checker) +std::vector FilterUnionTypes(const ArenaVector &originTypes, + [[maybe_unused]] checker::ETSChecker *checker) { if (originTypes.empty()) { return {}; -- Gitee From 8a700433472e560fa889a9ab6e2e1a67a5de31f8 Mon Sep 17 00:00:00 2001 From: zhongning5 Date: Thu, 5 Jun 2025 13:47:38 +0800 Subject: [PATCH 068/747] fix arkts-unsupport-prop-name-from-value Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCLTN Test scenarios:Fix bugs for fix arkts-unsupport-prop-name-from-value Signed-off-by: zhongning5 --- ets2panda/linter/src/lib/TypeScriptLinter.ts | 18 +++-- .../test/main/class_as_object.ets.arkts2.json | 20 ++++++ .../literals_as_prop_names.ets.arkts2.json | 50 +++++++++++++ .../literals_as_prop_names.ets.autofix.json | 50 +++++++++++++ .../literals_as_prop_names.ets.migrate.json | 10 +++ .../linter/test/main/prop_name_from_value.ets | 31 +++++++- .../main/prop_name_from_value.ets.arkts2.json | 70 +++++++++++++++++++ .../property_access_by_index.ets.arkts2.json | 30 ++++++++ 8 files changed, 271 insertions(+), 8 deletions(-) diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index e2ebe7badf..fb5a2c8428 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -8928,22 +8928,30 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - if (!ts.isIdentifier(node.expression) || !ts.isNumericLiteral(node.argumentExpression)) { - return; - } - const symbol = this.tsUtils.trueSymbolAtLocation(node.expression); if (!symbol?.declarations) { return; } for (const decl of symbol.declarations) { - if (ts.isEnumDeclaration(decl)) { + if (ts.isEnumDeclaration(decl) && this.shouldIncrementCounters(node)) { this.incrementCounters(node, FaultID.UnsupportPropNameFromValue); return; } } } + private shouldIncrementCounters(node: ts.ElementAccessExpression): boolean { + const indexExpr = node.argumentExpression; + if (!indexExpr) { + return false; + } + if (ts.isStringLiteral(indexExpr) || ts.isNumericLiteral(indexExpr)) { + return true; + } + const type = this.tsTypeChecker.getTypeAtLocation(indexExpr); + const typeString = this.tsTypeChecker.typeToString(type); + return typeString === 'number' || typeString === 'string'; + } private handleMakeObserved(node: ts.PropertyAccessExpression): void { if (!this.options.arkts2) { diff --git a/ets2panda/linter/test/main/class_as_object.ets.arkts2.json b/ets2panda/linter/test/main/class_as_object.ets.arkts2.json index 3bf41adaeb..40f9e25a11 100644 --- a/ets2panda/linter/test/main/class_as_object.ets.arkts2.json +++ b/ets2panda/linter/test/main/class_as_object.ets.arkts2.json @@ -334,6 +334,26 @@ "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, + { + "line": 102, + "column": 13, + "endLine": 102, + "endColumn": 23, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 114, + "column": 18, + "endLine": 114, + "endColumn": 25, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 116, "column": 10, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json index 0293db338b..79102a9b70 100755 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json @@ -304,6 +304,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 86, + "column": 1, + "endLine": 86, + "endColumn": 33, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 1, + "endLine": 88, + "endColumn": 40, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 92, "column": 4, @@ -364,6 +384,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 105, + "column": 14, + "endLine": 105, + "endColumn": 31, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 106, "column": 5, @@ -374,6 +404,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 106, + "column": 15, + "endLine": 106, + "endColumn": 35, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 109, "column": 1, @@ -394,6 +434,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 118, + "column": 18, + "endLine": 118, + "endColumn": 35, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 125, "column": 22, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json index 4c937491cd..82e0ac288a 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json @@ -697,6 +697,26 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 86, + "column": 1, + "endLine": 86, + "endColumn": 33, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 88, + "column": 1, + "endLine": 88, + "endColumn": 40, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 92, "column": 4, @@ -841,6 +861,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 105, + "column": 14, + "endLine": 105, + "endColumn": 31, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 106, "column": 5, @@ -862,6 +892,16 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 106, + "column": 15, + "endLine": 106, + "endColumn": 35, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 109, "column": 1, @@ -913,6 +953,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 118, + "column": 18, + "endLine": 118, + "endColumn": 35, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 125, "column": 22, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json index 112cbe6bb0..97c0791cc5 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json @@ -94,6 +94,16 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 92, + "column": 1, + "endLine": 92, + "endColumn": 33, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 28, "column": 11, diff --git a/ets2panda/linter/test/main/prop_name_from_value.ets b/ets2panda/linter/test/main/prop_name_from_value.ets index bdfdc1a80d..63c685415b 100644 --- a/ets2panda/linter/test/main/prop_name_from_value.ets +++ b/ets2panda/linter/test/main/prop_name_from_value.ets @@ -20,6 +20,31 @@ enum TEST { } const arr = ['a', 'b', 'c']; -const val = TEST[1]; -const value: number = TEST.A; //legal -const arrVal = arr[1]; //legal \ No newline at end of file +const val = TEST[1]; //error +const value: number = TEST.A; +const arrVal = arr[1]; +let a = 1; +let b = 2.3; +let c = "str"; +let d3 = TEST[TEST.A]; +let d4 = TEST[a]; //error +let d5 = TEST[b]; //error +let d2 = TEST['A']; //error +enum E { A, B, C } +console.log(E[E.A]); +function foo(e: E) { + console.log(E[e]); +} +foo(E.B); +console.log(E[2 as E]); +enum Color { Red, Green = 10, Blue } +enum E1 { One = 1, one = 1, oNe = 1 } +console.log(E1[1 as E1]) +let c1: Color = Color.Green; +console.log(c1.toString()) +console.log(Color[c1]); +enum G { + A = 1, + B = 2 +} +console.log(G[G.A]); \ No newline at end of file diff --git a/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json b/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json index 62d4d681bf..8cd1ddc908 100644 --- a/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json +++ b/ets2panda/linter/test/main/prop_name_from_value.ets.arkts2.json @@ -33,6 +33,76 @@ "suggest": "", "rule": "Array bound not checked. (arkts-runtime-array-check)", "severity": "ERROR" + }, + { + "line": 26, + "column": 5, + "endLine": 26, + "endColumn": 10, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 9, + "endLine": 26, + "endColumn": 10, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 27, + "column": 5, + "endLine": 27, + "endColumn": 12, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 10, + "endLine": 30, + "endColumn": 17, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 10, + "endLine": 31, + "endColumn": 17, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 5, + "endLine": 32, + "endColumn": 19, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 10, + "endLine": 32, + "endColumn": 19, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json b/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json index eaf2af73c9..2a1abb3490 100644 --- a/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json +++ b/ets2panda/linter/test/main/property_access_by_index.ets.arkts2.json @@ -684,6 +684,36 @@ "rule": "Array bound not checked. (arkts-runtime-array-check)", "severity": "ERROR" }, + { + "line": 97, + "column": 1, + "endLine": 97, + "endColumn": 18, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 98, + "column": 1, + "endLine": 98, + "endColumn": 17, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 99, + "column": 1, + "endLine": 99, + "endColumn": 17, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 105, "column": 31, -- Gitee From e759a08e780e22fef985c8aa57f34370bccb31be Mon Sep 17 00:00:00 2001 From: xudan16 Date: Sun, 8 Jun 2025 10:47:31 +0800 Subject: [PATCH 069/747] sync homecheck to fix some issues Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDFCK Signed-off-by: xudan16 --- ets2panda/linter/arkanalyzer/OAT.xml | 1 + ets2panda/linter/arkanalyzer/src/Config.ts | 1 + ets2panda/linter/arkanalyzer/src/Scene.ts | 31 ++- .../callgraph/algorithm/AbstractAnalysis.ts | 19 +- .../algorithm/ClassHierarchyAnalysis.ts | 7 +- .../callgraph/algorithm/RapidTypeAnalysis.ts | 3 +- .../src/callgraph/common/Statistics.ts | 5 +- .../src/callgraph/model/CallGraph.ts | 66 +----- .../src/callgraph/model/CallSite.ts | 64 ++++++ .../model/builder/CallGraphBuilder.ts | 21 +- .../src/callgraph/pointerAnalysis/PTAUtils.ts | 1 + .../callgraph/pointerAnalysis/PagBuilder.ts | 38 ++-- .../pointerAnalysis/PointerAnalysis.ts | 3 +- .../pointerAnalysis/PointerAnalysisConfig.ts | 9 + .../linter/arkanalyzer/src/core/base/Expr.ts | 39 +++- .../linter/arkanalyzer/src/core/base/Local.ts | 10 +- .../src/core/common/ArkIRTransformer.ts | 9 - .../src/core/common/IRInference.ts | 22 +- .../arkanalyzer/src/core/common/ModelUtils.ts | 24 +-- .../arkanalyzer/src/core/common/SdkUtils.ts | 40 ++-- .../src/core/common/TypeInference.ts | 55 +++-- .../arkanalyzer/src/core/common/ValueUtil.ts | 8 + .../src/core/dataflow/DataflowSolver.ts | 3 +- .../src/core/graph/builder/CfgBuilder.ts | 3 + .../src/core/graph/builder/TrapBuilder.ts | 47 +++-- .../arkanalyzer/src/core/model/ArkImport.ts | 2 +- .../arkanalyzer/src/core/model/ArkMethod.ts | 82 +++++--- .../src/core/model/builder/ArkClassBuilder.ts | 16 +- .../src/core/model/builder/ArkFieldBuilder.ts | 4 +- .../src/core/model/builder/ArkFileBuilder.ts | 4 +- .../core/model/builder/ArkMethodBuilder.ts | 11 +- .../core/model/builder/ArkNamespaceBuilder.ts | 8 +- .../src/core/model/builder/BodyBuilder.ts | 2 + .../arkanalyzer/src/save/JsonPrinter.ts | 104 +++++++--- .../arkanalyzer/src/utils/SparseBitVector.ts | 1 - ets2panda/linter/arkanalyzer/typedoc.json | 1 + ets2panda/linter/homecheck/src/Index.ts | 2 +- .../checker/migration/AppStorageGetCheck.ts | 2 +- .../checker/migration/CustomBuilderCheck.ts | 4 +- .../checker/migration/InteropAssignCheck.ts | 6 +- .../migration/InteropBackwardDFACheck.ts | 2 +- .../migration/InteropBoxedTypeCheck.ts | 2 +- .../migration/InteropJSModifyPropertyCheck.ts | 6 +- .../checker/migration/ModifyStateVarCheck.ts | 2 +- .../src/checker/migration/NoTSLikeAsCheck.ts | 196 +++++++++--------- .../checker/migration/ObjectLiteralCheck.ts | 7 +- .../migration/ObservedDecoratorCheck.ts | 6 +- .../src/checker/migration/ThisBindCheck.ts | 2 +- .../homecheck/src/checker/migration/Utils.ts | 33 ++- .../src/tools/migrationTool/MigrationTool.ts | 12 +- .../src/utils/common/CheckerStorage.ts | 5 + .../homecheck/src/utils/common/FileUtils.ts | 4 +- ets2panda/linter/src/cli/LinterCLI.ts | 3 +- 53 files changed, 661 insertions(+), 397 deletions(-) create mode 100644 ets2panda/linter/arkanalyzer/src/callgraph/model/CallSite.ts diff --git a/ets2panda/linter/arkanalyzer/OAT.xml b/ets2panda/linter/arkanalyzer/OAT.xml index 6420939360..a33eba98c9 100644 --- a/ets2panda/linter/arkanalyzer/OAT.xml +++ b/ets2panda/linter/arkanalyzer/OAT.xml @@ -19,6 +19,7 @@ + diff --git a/ets2panda/linter/arkanalyzer/src/Config.ts b/ets2panda/linter/arkanalyzer/src/Config.ts index bff8ddf474..1a222ff665 100644 --- a/ets2panda/linter/arkanalyzer/src/Config.ts +++ b/ets2panda/linter/arkanalyzer/src/Config.ts @@ -86,6 +86,7 @@ export class SceneConfig { public buildConfig(targetProjectName: string, targetProjectDirectory: string, sdks: Sdk[], fullFilePath?: string[]): void { this.targetProjectName = targetProjectName; this.targetProjectDirectory = targetProjectDirectory; + this.projectFiles = getAllFiles(targetProjectDirectory, this.options.supportFileExts!, this.options.ignoreFileNames); this.sdksObj = sdks; if (fullFilePath) { this.projectFiles.push(...fullFilePath); diff --git a/ets2panda/linter/arkanalyzer/src/Scene.ts b/ets2panda/linter/arkanalyzer/src/Scene.ts index 72c7828226..84ef44b99a 100644 --- a/ets2panda/linter/arkanalyzer/src/Scene.ts +++ b/ets2panda/linter/arkanalyzer/src/Scene.ts @@ -41,6 +41,8 @@ import { ImportInfo } from './core/model/ArkImport'; import { ALL, CONSTRUCTOR_NAME, TSCONFIG_JSON } from './core/common/TSConst'; import { BUILD_PROFILE_JSON5, OH_PACKAGE_JSON5 } from './core/common/EtsConst'; import { SdkUtils } from './core/common/SdkUtils'; +import { PointerAnalysisConfig } from './callgraph/pointerAnalysis/PointerAnalysisConfig'; +import { ValueUtil } from './core/common/ValueUtil'; const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'Scene'); @@ -99,6 +101,17 @@ export class Scene { constructor() {} + /* + * Set all static field to be null, then all related objects could be freed by GC. + * This method could be called before drop Scene. + */ + public dispose(): void { + PointerAnalysisConfig.dispose(); + SdkUtils.dispose(); + ValueUtil.dispose(); + ModelUtils.dispose(); + } + public getOptions(): SceneOptions { return this.options; } @@ -322,12 +335,13 @@ export class Scene { } } + ModelUtils.dispose(); this.buildStage = SceneBuildStage.METHOD_DONE; } private genArkFiles(): void { this.projectFiles.forEach(file => { - logger.info('=== parse file:', file); + logger.trace('=== parse file:', file); try { const arkFile: ArkFile = new ArkFile(FileUtils.getFileLanguage(file, this.fileLanguages)); arkFile.setScene(this); @@ -469,9 +483,11 @@ export class Scene { } private findDependenciesByRule(originPath: string, arkFile: ArkFile): void { - const extNameArray = ['.ets', '.ts', '.d.ets', '.d.ts', '.js']; - if (!this.findFilesByPathArray(originPath, this.indexPathArray, arkFile) && !this.findFilesByExtNameArray(originPath, extNameArray, arkFile)) { - logger.info(originPath + 'module mapperInfo is not found!'); + if ( + !this.findFilesByPathArray(originPath, this.indexPathArray, arkFile) && + !this.findFilesByExtNameArray(originPath, this.options.supportFileExts!, arkFile) + ) { + logger.trace(originPath + 'module mapperInfo is not found!'); } } @@ -542,7 +558,7 @@ export class Scene { this.addFileNode2DependencyGrap(originPath, arkFile); } if (!this.findFilesByPathArray(originPath, this.indexPathArray, arkFile)) { - logger.info(originPath + 'module mapperInfo is not found!'); + logger.trace(originPath + 'module mapperInfo is not found!'); } } } @@ -574,7 +590,7 @@ export class Scene { private buildSdk(sdkName: string, sdkPath: string): void { const allFiles = getAllFiles(sdkPath, this.options.supportFileExts!, this.options.ignoreFileNames); allFiles.forEach(file => { - logger.info('=== parse sdk file:', file); + logger.trace('=== parse sdk file:', file); try { const arkFile: ArkFile = new ArkFile(FileUtils.getFileLanguage(file, this.fileLanguages)); arkFile.setScene(this); @@ -1044,6 +1060,7 @@ export class Scene { this.getMethodsMap(true); this.buildStage = SceneBuildStage.TYPE_INFERRED; } + SdkUtils.dispose(); } /** @@ -1458,7 +1475,7 @@ export class ModuleScene { private genArkFiles(supportFileExts: string[]): void { getAllFiles(this.modulePath, supportFileExts, this.projectScene.getOptions().ignoreFileNames).forEach(file => { - logger.info('=== parse file:', file); + logger.trace('=== parse file:', file); try { const arkFile: ArkFile = new ArkFile(FileUtils.getFileLanguage(file, this.projectScene.getFileLanguages())); arkFile.setScene(this.projectScene); diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/AbstractAnalysis.ts b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/AbstractAnalysis.ts index 4fb8a6f7b7..9a3e7fa8e1 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/AbstractAnalysis.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/AbstractAnalysis.ts @@ -30,13 +30,14 @@ const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'CG'); export abstract class AbstractAnalysis { protected scene: Scene; - protected cg!: CallGraph; + protected cg: CallGraph; protected cgBuilder!: CallGraphBuilder; protected workList: FuncID[] = []; protected processedMethod!: IPtsCollection; - constructor(s: Scene) { + constructor(s: Scene, cg: CallGraph) { this.scene = s; + this.cg = cg; } public getScene(): Scene { @@ -96,11 +97,13 @@ export abstract class AbstractAnalysis { } public projectStart(displayGeneratedMethod: boolean): void { - this.scene.getMethods().forEach((method) => { - let cgNode = this.cg.getCallGraphNodeByMethod(method.getSignature()) as CallGraphNode; + this.cgBuilder.buildCGNodes(this.scene.getMethods()); + + for (let n of this.cg.getNodesIter()) { + let cgNode = n as CallGraphNode; if (cgNode.isSdkMethod()) { - return; + continue; } this.preProcessMethod(cgNode.getID()); @@ -108,7 +111,9 @@ export abstract class AbstractAnalysis { this.processMethod(cgNode.getID()).forEach((cs: CallSite) => { this.processCallSite(cgNode.getID(), cs, displayGeneratedMethod, true); }); - }); + } + + this.cgBuilder.setEntries(); } private processCallSite(method: FuncID, cs: CallSite, displayGeneratedMethod: boolean, isProject: boolean = false): void { @@ -128,7 +133,7 @@ export abstract class AbstractAnalysis { if (displayGeneratedMethod || !me?.isGenerated()) { this.workList.push(cs.calleeFuncID); - logger.info(`New workList item ${cs.calleeFuncID}: ${this.cg.getArkMethodByFuncID(cs.calleeFuncID)?.getSignature().toString()}`); + logger.trace(`New workList item ${cs.calleeFuncID}: ${this.cg.getArkMethodByFuncID(cs.calleeFuncID)?.getSignature().toString()}`); } } diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/ClassHierarchyAnalysis.ts b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/ClassHierarchyAnalysis.ts index 029d85541e..df58f9e571 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/ClassHierarchyAnalysis.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/ClassHierarchyAnalysis.ts @@ -20,11 +20,12 @@ import { ArkClass } from '../../core/model/ArkClass'; import { NodeID } from '../../core/graph/BaseExplicitGraph'; import { CallGraph, CallSite } from '../model/CallGraph'; import { AbstractAnalysis } from './AbstractAnalysis'; +import { CallGraphBuilder } from '../model/builder/CallGraphBuilder'; export class ClassHierarchyAnalysis extends AbstractAnalysis { - constructor(scene: Scene, cg: CallGraph) { - super(scene); - this.cg = cg; + constructor(scene: Scene, cg: CallGraph, cb: CallGraphBuilder) { + super(scene, cg); + this.cgBuilder = cb; } public resolveCall(callerMethod: NodeID, invokeStmt: Stmt): CallSite[] { diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/RapidTypeAnalysis.ts b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/RapidTypeAnalysis.ts index b4ecc267ac..b14816d26b 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/RapidTypeAnalysis.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/algorithm/RapidTypeAnalysis.ts @@ -33,8 +33,7 @@ export class RapidTypeAnalysis extends AbstractAnalysis { private ignoredCalls: Map> = new Map(); constructor(scene: Scene, cg: CallGraph) { - super(scene); - this.cg = cg; + super(scene, cg); } public resolveCall(callerMethod: NodeID, invokeStmt: Stmt): CallSite[] { diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/common/Statistics.ts b/ets2panda/linter/arkanalyzer/src/callgraph/common/Statistics.ts index 61246908ad..112539b168 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/common/Statistics.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/common/Statistics.ts @@ -196,6 +196,7 @@ export class CGStat extends StatTraits { numVirtual: number = 0; numIntrinsic: number = 0; numConstructor: number = 0; + numBlank: number = 0; public startStat(): void { this.startTime = new Date().getTime(); @@ -221,6 +222,7 @@ export class CGStat extends StatTraits { this.numIntrinsic++; break; default: + this.numBlank++; } this.numTotalNode++; } @@ -232,7 +234,8 @@ export class CGStat extends StatTraits { output = output + `Real function\t\t${this.numReal}\n`; output = output + `Intrinsic function\t${this.numIntrinsic}\n`; output = output + `Constructor function\t${this.numConstructor}\n`; - output = output + `Blank function\t\t${this.numVirtual}\n`; + output = output + `Virtual function\t\t${this.numVirtual}\n`; + output = output + `Blank function\t\t${this.numBlank}\n`; output = output + `Total\t\t\t${this.numTotalNode}\n`; return output; } diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/model/CallGraph.ts b/ets2panda/linter/arkanalyzer/src/callgraph/model/CallGraph.ts index 954f47804a..0ddeb63007 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/model/CallGraph.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/model/CallGraph.ts @@ -15,63 +15,27 @@ import { MethodSignature } from '../../core/model/ArkSignature'; import { Stmt } from '../../core/base/Stmt'; -import { Value } from '../../core/base/Value'; import { Scene } from '../../Scene'; import { ArkMethod } from '../../core/model/ArkMethod'; import { GraphPrinter } from '../../save/GraphPrinter'; import { PrinterBuilder } from '../../save/PrinterBuilder'; import { BaseEdge, BaseNode, BaseExplicitGraph, NodeID } from '../../core/graph/BaseExplicitGraph'; import { CGStat } from '../common/Statistics'; -import { ContextID } from '../pointerAnalysis/Context'; import { UNKNOWN_FILE_NAME } from '../../core/common/Const'; +import { CallSite, CallSiteID, DynCallSite, ICallSite } from './CallSite'; export type Method = MethodSignature; -export type CallSiteID = number; export type FuncID = number; type StmtSet = Set; +export { CallSite, DynCallSite, ICallSite }; + export enum CallGraphNodeKind { - real, + real, // method from project and has body vitual, - intrinsic, - constructor, -} - -export class CallSite { - public callStmt: Stmt; - public args: Value[] | undefined; - public calleeFuncID: FuncID; - public callerFuncID: FuncID; - - constructor(s: Stmt, a: Value[] | undefined, ce: FuncID, cr: FuncID) { - this.callStmt = s; - this.args = a; - this.calleeFuncID = ce; - this.callerFuncID = cr; - } -} - -export class DynCallSite { - public callerFuncID: FuncID; - public callStmt: Stmt; - public args: Value[] | undefined; - public protentialCalleeFuncID: FuncID | undefined; - - constructor(caller: FuncID, s: Stmt, a: Value[] | undefined, ptcCallee: FuncID | undefined) { - this.callerFuncID = caller; - this.callStmt = s; - this.args = a; - this.protentialCalleeFuncID = ptcCallee; - } -} - -export class CSCallSite extends CallSite { - public cid: ContextID; - - constructor(id: ContextID, cs: CallSite) { - super(cs.callStmt, cs.args, cs.calleeFuncID, cs.callerFuncID); - this.cid = id; - } + intrinsic, // method created by AA, which arkMethod.isGenrated is true + constructor, // constructor + blank, // method without body } export class CallGraphEdge extends BaseEdge { @@ -119,7 +83,6 @@ export class CallGraphEdge extends BaseEdge { export class CallGraphNode extends BaseNode { private method: Method; private ifSdkMethod: boolean = false; - private isBlank: boolean = false; constructor(id: number, m: Method, k: CallGraphNodeKind = CallGraphNodeKind.real) { super(id, k); @@ -139,11 +102,7 @@ export class CallGraphNode extends BaseNode { } public get isBlankMethod(): boolean { - return this.isBlank; - } - - public set isBlankMethod(is: boolean) { - this.isBlank = is; + return this.kind === CallGraphNodeKind.blank; } public getDotAttr(): string { @@ -195,11 +154,6 @@ export class CallGraph extends BaseExplicitGraph { // check if sdk method cgNode.setSdkMethod(this.scene.hasSdkFile(method.getDeclaringClassSignature().getDeclaringFileSignature())); - let arkMethod = this.scene.getMethod(method); - if (!arkMethod || !arkMethod.getCfg()) { - cgNode.isBlankMethod = true; - } - this.addNode(cgNode); this.methodToCGNodeMap.set(method.toString(), cgNode.getID()); this.cgStat.addNodeStat(kind); @@ -285,7 +239,7 @@ export class CallGraph extends BaseExplicitGraph { } let args = callStmt.getInvokeExpr()?.getArgs(); - let cs = new DynCallSite(callerNode.getID(), callStmt, args, calleeNode?.getID()); + let cs = new DynCallSite(callStmt, args, calleeNode?.getID(), callerNode.getID()); this.stmtToDynCallSitemap.set(callStmt, cs); } @@ -467,4 +421,4 @@ export class CallGraph extends BaseExplicitGraph { public getGraphName(): string { return 'CG'; } -} +} \ No newline at end of file diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/model/CallSite.ts b/ets2panda/linter/arkanalyzer/src/callgraph/model/CallSite.ts new file mode 100644 index 0000000000..40dbb3b492 --- /dev/null +++ b/ets2panda/linter/arkanalyzer/src/callgraph/model/CallSite.ts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Stmt } from '../../core/base/Stmt'; +import { Value } from '../../core/base/Value'; +import { ContextID } from '../pointerAnalysis/Context'; +import { FuncID } from './CallGraph'; + +export type CallSiteID = number; + +export interface ICallSite { + callStmt: Stmt; + args: Value[] | undefined; + callerFuncID: FuncID; +} + +export class CallSite implements ICallSite { + public callStmt: Stmt; + public args: Value[] | undefined; + public calleeFuncID: FuncID; + public callerFuncID: FuncID; + + constructor(s: Stmt, a: Value[] | undefined, ce: FuncID, cr: FuncID) { + this.callStmt = s; + this.args = a; + this.calleeFuncID = ce; + this.callerFuncID = cr; + } +} + +export class DynCallSite implements ICallSite { + public callStmt: Stmt; + public args: Value[] | undefined; + public protentialCalleeFuncID: FuncID | undefined; + public callerFuncID: FuncID; + + constructor(s: Stmt, a: Value[] | undefined, ptcCallee: FuncID | undefined, caller: FuncID) { + this.callerFuncID = caller; + this.callStmt = s; + this.args = a; + this.protentialCalleeFuncID = ptcCallee; + } +} + +export class CSCallSite extends CallSite { + public cid: ContextID; + + constructor(id: ContextID, cs: CallSite) { + super(cs.callStmt, cs.args, cs.calleeFuncID, cs.callerFuncID); + this.cid = id; + } +} \ No newline at end of file diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/model/builder/CallGraphBuilder.ts b/ets2panda/linter/arkanalyzer/src/callgraph/model/builder/CallGraphBuilder.ts index c631c4333f..5947b9c66e 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/model/builder/CallGraphBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/model/builder/CallGraphBuilder.ts @@ -38,19 +38,27 @@ export class CallGraphBuilder { this.setEntries(); } - public buildDirectCallGraph(methods: ArkMethod[]): void { + /* + * Create CG Node for ArkMethods + */ + public buildCGNodes(methods: ArkMethod[]): void { for (const method of methods) { let m = method.getSignature(); let kind = CallGraphNodeKind.real; if (method.isGenerated()) { kind = CallGraphNodeKind.intrinsic; - } - if (method.getName() === 'constructor') { + } else if (method.getBody() === undefined || method.getCfg() === undefined) { + kind = CallGraphNodeKind.blank; + } else if (method.getName() === 'constructor') { kind = CallGraphNodeKind.constructor; } this.cg.addCallGraphNode(m, kind); } + } + + public buildDirectCallGraph(methods: ArkMethod[]): void { + this.buildCGNodes(methods); for (const method of methods) { let cfg = method.getCfg(); @@ -70,8 +78,7 @@ export class CallGraphBuilder { if (callee && invokeExpr instanceof ArkStaticInvokeExpr) { this.cg.addDirectOrSpecialCallEdge(method.getSignature(), callee, stmt); } else if ( - callee && - invokeExpr instanceof ArkInstanceInvokeExpr && + callee && invokeExpr instanceof ArkInstanceInvokeExpr && (this.isConstructor(callee) || this.scene.getMethod(callee)?.isGenerated()) ) { this.cg.addDirectOrSpecialCallEdge(method.getSignature(), callee, stmt, false); @@ -89,12 +96,12 @@ export class CallGraphBuilder { }); this.cg.setEntries(cgEntries); - let classHierarchyAnalysis: ClassHierarchyAnalysis = new ClassHierarchyAnalysis(this.scene, this.cg); + let classHierarchyAnalysis: ClassHierarchyAnalysis = new ClassHierarchyAnalysis(this.scene, this.cg, this); classHierarchyAnalysis.start(displayGeneratedMethod); } public buildCHA4WholeProject(displayGeneratedMethod: boolean = false): void { - let classHierarchyAnalysis: ClassHierarchyAnalysis = new ClassHierarchyAnalysis(this.scene, this.cg); + let classHierarchyAnalysis: ClassHierarchyAnalysis = new ClassHierarchyAnalysis(this.scene, this.cg, this); classHierarchyAnalysis.projectStart(displayGeneratedMethod); } diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PTAUtils.ts b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PTAUtils.ts index a8940d5d3c..0c120d6000 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PTAUtils.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PTAUtils.ts @@ -51,6 +51,7 @@ export function getBuiltInApiType(method: MethodSignature): BuiltApiType { return BuiltApiType.FunctionApply; case 'bind': return BuiltApiType.FunctionBind; + default: } } } diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PagBuilder.ts b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PagBuilder.ts index bd3917b090..5249cd8d2c 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PagBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PagBuilder.ts @@ -13,7 +13,7 @@ * limitations under the License. */ -import { CallGraph, CallGraphNode, CallGraphNodeKind, CallSite, DynCallSite, FuncID } from '../model/CallGraph'; +import { CallGraph, CallGraphNode, CallGraphNodeKind, CallSite, DynCallSite, FuncID, ICallSite } from '../model/CallGraph'; import { Scene } from '../../Scene'; import { ArkAssignStmt, ArkInvokeStmt, ArkReturnStmt, Stmt } from '../../core/base/Stmt'; import { @@ -527,7 +527,7 @@ export class PagBuilder { }); } - public addDynamicCallEdge(cs: DynCallSite | CallSite, baseClassPTNode: NodeID, cid: ContextID): NodeID[] { + public addDynamicCallEdge(cs: ICallSite, baseClassPTNode: NodeID, cid: ContextID): NodeID[] { let srcNodes: NodeID[] = []; let ivkExpr = cs.callStmt.getInvokeExpr(); @@ -577,7 +577,7 @@ export class PagBuilder { * all possible callee methods of a dynamic call site * handle both PtrInvokeExpr and InstanceInvokeExpr */ - private getDynamicCallee(ptNode: PagNode, value: Value, ivkExpr: AbstractInvokeExpr, cs: DynCallSite | CallSite): ArkMethod[] { + private getDynamicCallee(ptNode: PagNode, value: Value, ivkExpr: AbstractInvokeExpr, cs: ICallSite): ArkMethod[] { let callee: ArkMethod[] = []; if (ptNode instanceof PagFuncNode) { @@ -646,7 +646,10 @@ export class PagBuilder { // Pass base's pts to callee's this pointer if (!dstCGNode.isSdkMethod() && ivkExpr instanceof ArkInstanceInvokeExpr) { let srcBaseNode = this.addThisRefCallEdge(baseClassPTNode, cid, ivkExpr.getBase(), callee!, calleeCid, staticCS.callerFuncID); - srcNodes.push(srcBaseNode); + + if (srcBaseNode !== -1) { + srcNodes.push(srcBaseNode); + } } else if (!dstCGNode.isSdkMethod() && ivkExpr instanceof ArkPtrInvokeExpr) { let originCS = (ptNode as PagFuncNode).getCS(); if (!originCS) { @@ -712,6 +715,7 @@ export class PagBuilder { */ this.handleFunctionBind(staticCS, cid, baseClassPTNode, srcNodes); break; + default: } return srcNodes; @@ -799,7 +803,11 @@ export class PagBuilder { private addThisEdge(staticCS: CallSite, cid: ContextID, realCallee: ArkMethod, srcNodes: NodeID[], baseClassPTNode: NodeID, calleeCid: ContextID): void { if (!(staticCS.args![0] instanceof NullConstant) && !realCallee.isStatic()) { - srcNodes.push(this.addThisRefCallEdge(baseClassPTNode, cid, staticCS.args![0] as Local, realCallee, calleeCid, staticCS.callerFuncID)); + let srcNodeID = this.addThisRefCallEdge(baseClassPTNode, cid, staticCS.args![0] as Local, realCallee, calleeCid, staticCS.callerFuncID); + + if (srcNodeID !== -1) { + srcNodes.push(srcNodeID); + } } } @@ -915,6 +923,10 @@ export class PagBuilder { callerFunID: FuncID ): NodeID { let thisRefNodeID = this.recordThisRefNode(baseClassPTNode, callee, calleeCid); + if (thisRefNodeID === -1) { + return -1; + } + let thisRefNode = this.pag.getNode(thisRefNodeID) as PagThisRefNode; let srcBaseLocal = baseLocal; srcBaseLocal = this.getRealThisLocal(srcBaseLocal, callerFunID); @@ -1233,7 +1245,7 @@ export class PagBuilder { let sdkParamInvokeStmt = new ArkInvokeStmt(new ArkPtrInvokeExpr((arg.getType() as FunctionType).getMethodSignature(), paramValue as Local, [])); // create new DynCallSite - let sdkParamCallSite = new DynCallSite(funcID, sdkParamInvokeStmt, undefined, undefined); + let sdkParamCallSite = new DynCallSite(sdkParamInvokeStmt, undefined, undefined, funcID); dstPagNode.addRelatedDynCallSite(sdkParamCallSite); } @@ -1542,7 +1554,7 @@ export class PagBuilder { * process Storage API * @returns boolean: check if the cs represent a Storage API, no matter the API will success or fail */ - private processStorage(cs: CallSite | DynCallSite, calleeCGNode: CallGraphNode, cid: ContextID): boolean { + private processStorage(cs: ICallSite, calleeCGNode: CallGraphNode, cid: ContextID): boolean { let storageName = calleeCGNode.getMethod().getDeclaringClassSignature().getClassName(); let storageType: StorageType = this.getStorageType(storageName, cs, cid); @@ -1570,7 +1582,7 @@ export class PagBuilder { return false; } - private processStorageSetOrCreate(cs: CallSite | DynCallSite, cid: ContextID): void { + private processStorageSetOrCreate(cs: ICallSite, cid: ContextID): void { let propertyStr = this.getPropertyName(cs.args![0]); if (!propertyStr) { return; @@ -1583,7 +1595,7 @@ export class PagBuilder { this.addPropertyLinkEdge(propertyNode, storageObj, cid, cs.callStmt, StorageLinkEdgeType.Local2Property); } - private processStorageLink(cs: CallSite | DynCallSite, cid: ContextID): void { + private processStorageLink(cs: ICallSite, cid: ContextID): void { let propertyStr = this.getPropertyName(cs.args![0]); if (!propertyStr) { return; @@ -1601,7 +1613,7 @@ export class PagBuilder { this.pag.addPagEdge(linkedOpNode, propertyNode, PagEdgeKind.Copy); } - private processStorageProp(cs: CallSite | DynCallSite, cid: ContextID): void { + private processStorageProp(cs: ICallSite, cid: ContextID): void { let propertyStr = this.getPropertyName(cs.args![0]); if (!propertyStr) { return; @@ -1618,7 +1630,7 @@ export class PagBuilder { this.pag.addPagEdge(propertyNode, linkedOpNode, PagEdgeKind.Copy); } - private processStorageSet(cs: CallSite | DynCallSite, cid: ContextID): void { + private processStorageSet(cs: ICallSite, cid: ContextID): void { let ivkExpr: AbstractInvokeExpr = cs.callStmt.getInvokeExpr()!; if (ivkExpr instanceof ArkInstanceInvokeExpr) { let base = ivkExpr.getBase(); @@ -1634,7 +1646,7 @@ export class PagBuilder { } } - private processStorageGet(cs: CallSite | DynCallSite, cid: ContextID): void { + private processStorageGet(cs: ICallSite, cid: ContextID): void { if (!(cs.callStmt instanceof ArkAssignStmt)) { return; } @@ -1686,7 +1698,7 @@ export class PagBuilder { * @param cid: for search PAG node in SubscribedAbstractProperty * @returns StorageType enum */ - private getStorageType(storageName: string, cs: CallSite | DynCallSite, cid: ContextID): StorageType { + private getStorageType(storageName: string, cs: ICallSite, cid: ContextID): StorageType { switch (storageName) { case 'AppStorage': return StorageType.APP_STORAGE; diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysis.ts b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysis.ts index 902a05b902..4fc4a16471 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysis.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysis.ts @@ -47,9 +47,8 @@ export class PointerAnalysis extends AbstractAnalysis { private config: PointerAnalysisConfig; constructor(p: Pag, cg: CallGraph, s: Scene, config: PointerAnalysisConfig) { - super(s); + super(s, cg); this.pag = p; - this.cg = cg; this.ptd = new DiffPTData>(config.ptsCollectionCtor); this.pagBuilder = new PagBuilder(this.pag, this.cg, s, config.kLimit, config.analysisScale); this.cgBuilder = new CallGraphBuilder(this.cg, s); diff --git a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysisConfig.ts b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysisConfig.ts index 1e68c981db..0dad1053cf 100644 --- a/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysisConfig.ts +++ b/ets2panda/linter/arkanalyzer/src/callgraph/pointerAnalysis/PointerAnalysisConfig.ts @@ -64,6 +64,15 @@ export class PointerAnalysisConfig { } } + /* + * Set static field to be null, then all related objects could be freed by GC. + * Class PointerAnalysisConfig has been exported by ArkAnalyzer, the dispose method should be called by users themselves before free this class. + */ + public static dispose(): void { + // @ts-ignore + this.instance = null; + } + /* * Create Singleton instance * The instance can be created multi-times and be overwrited diff --git a/ets2panda/linter/arkanalyzer/src/core/base/Expr.ts b/ets2panda/linter/arkanalyzer/src/core/base/Expr.ts index dcf4695331..310e822863 100644 --- a/ets2panda/linter/arkanalyzer/src/core/base/Expr.ts +++ b/ets2panda/linter/arkanalyzer/src/core/base/Expr.ts @@ -40,8 +40,9 @@ import { ArkMethod } from '../model/ArkMethod'; import { UNKNOWN_FILE_NAME } from '../common/Const'; import { IRInference } from '../common/IRInference'; import { ImportInfo } from '../model/ArkImport'; -import { ArkClass } from '../model/ArkClass'; +import { ArkClass, ClassCategory } from '../model/ArkClass'; import { ArkField } from '../model/ArkField'; +import { ModelUtils } from '../common/ModelUtils'; /** * @category core/base/expr @@ -342,14 +343,30 @@ export class ArkNewExpr extends AbstractExpr { const classSignature = this.classType.getClassSignature(); if (classSignature.getDeclaringFileSignature().getFileName() === UNKNOWN_FILE_NAME) { const className = classSignature.getClassName(); - let type = TypeInference.inferUnclearRefName(className, arkMethod.getDeclaringArkClass()); + let type: Type | null | undefined = ModelUtils.findDeclaredLocal(new Local(className), arkMethod, 1)?.getType(); + if (TypeInference.isUnclearType(type)) { + type = TypeInference.inferUnclearRefName(className, arkMethod.getDeclaringArkClass()); + } if (type && type instanceof ClassType) { - let realGenericTypes = this.classType.getRealGenericTypes(); - this.classType = realGenericTypes ? new ClassType(type.getClassSignature(), realGenericTypes) : type; + const instanceType = this.constructorSignature(type, arkMethod) ?? type; + this.classType.setClassSignature(instanceType.getClassSignature()); + TypeInference.inferRealGenericTypes(this.classType.getRealGenericTypes(), arkMethod.getDeclaringArkClass()); } } return this; } + + private constructorSignature(type: ClassType, arkMethod: ArkMethod): ClassType | undefined { + const classConstructor = arkMethod.getDeclaringArkFile().getScene().getClass(type.getClassSignature()); + if (classConstructor?.getCategory() === ClassCategory.INTERFACE) { + const type = classConstructor.getMethodWithName('construct-signature')?.getReturnType(); + if (type) { + const returnType = TypeInference.replaceAliasType(type); + return returnType instanceof ClassType ? returnType : undefined; + } + } + return undefined; + } } export class ArkNewArrayExpr extends AbstractExpr { @@ -695,9 +712,13 @@ export abstract class AbstractBinopExpr extends AbstractExpr { case '^': case '<<': case '>>': + if (op1Type === NumberType.getInstance() && op2Type === NumberType.getInstance()) { + type = NumberType.getInstance(); + } if (op1Type === BigIntType.getInstance() && op2Type === BigIntType.getInstance()) { type = BigIntType.getInstance(); } + break; case '>>>': if (op1Type === NumberType.getInstance() && op2Type === NumberType.getInstance()) { type = NumberType.getInstance(); @@ -1042,10 +1063,14 @@ export class AliasTypeExpr extends AbstractExpr { public getType(): Type { function getTypeOfImportInfo(importInfo: ImportInfo): Type { const arkExport = importInfo.getLazyExportInfo()?.getArkExport(); - if (arkExport) { - return TypeInference.parseArkExport2Type(arkExport) ?? UnknownType.getInstance(); + const importClauseName = importInfo.getImportClauseName(); + let type; + if (importClauseName.includes('.') && arkExport instanceof ArkClass) { + type = TypeInference.inferUnclearRefName(importClauseName, arkExport); + } else if (arkExport) { + type = TypeInference.parseArkExport2Type(arkExport); } - return UnknownType.getInstance(); + return type ?? UnknownType.getInstance(); } const operator = this.getOriginalObject(); diff --git a/ets2panda/linter/arkanalyzer/src/core/base/Local.ts b/ets2panda/linter/arkanalyzer/src/core/base/Local.ts index aa4fbebdf0..10bb189627 100644 --- a/ets2panda/linter/arkanalyzer/src/core/base/Local.ts +++ b/ets2panda/linter/arkanalyzer/src/core/base/Local.ts @@ -14,7 +14,7 @@ */ import { Stmt } from './Stmt'; -import { ClassType, Type, UnknownType } from './Type'; +import { ClassType, FunctionType, Type, UnknownType } from './Type'; import { Value } from './Value'; import { TypeInference } from '../common/TypeInference'; import { ArkExport, ExportType } from '../model/ArkExport'; @@ -54,11 +54,17 @@ export class Local implements Value, ArkExport { const declaringArkClass = arkMethod.getDeclaringArkClass(); this.type = new ClassType(declaringArkClass.getSignature(), declaringArkClass.getRealTypes()); } else if (TypeInference.isUnclearType(this.type)) { - const type = TypeInference.inferBaseType(this.name, arkMethod.getDeclaringArkClass()) ?? ModelUtils.findDeclaredLocal(this, arkMethod)?.getType(); + const type = TypeInference.inferBaseType(this.name, arkMethod.getDeclaringArkClass()) ?? + ModelUtils.findDeclaredLocal(this, arkMethod)?.getType(); if (type) { this.type = type; } } + if (this.type instanceof FunctionType) { + this.type.getMethodSignature().getMethodSubSignature().getParameters() + .forEach(p => TypeInference.inferParameterType(p, arkMethod)); + TypeInference.inferSignatureReturnType(this.type.getMethodSignature(), arkMethod); + } return this; } diff --git a/ets2panda/linter/arkanalyzer/src/core/common/ArkIRTransformer.ts b/ets2panda/linter/arkanalyzer/src/core/common/ArkIRTransformer.ts index 31f9ecf635..c0a61f1f5d 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/ArkIRTransformer.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/ArkIRTransformer.ts @@ -46,7 +46,6 @@ import { DEFAULT, PROMISE } from './TSConst'; import { buildGenericType, buildModifiers, buildTypeParameters } from '../model/builder/builderUtils'; import { ArkValueTransformer } from './ArkValueTransformer'; import { ImportInfo } from '../model/ArkImport'; -import { TypeInference } from './TypeInference'; import { AbstractTypeExpr } from '../base/TypeExpr'; import { buildNormalArkClassFromArkMethod } from '../model/builder/ArkClassBuilder'; import { ArkClass } from '../model/ArkClass'; @@ -339,12 +338,6 @@ export class ArkIRTransformer { let expr: AliasTypeExpr; if (ts.isImportTypeNode(rightOp)) { expr = this.resolveImportTypeNode(rightOp); - const typeObject = expr.getOriginalObject(); - if (typeObject instanceof ImportInfo && typeObject.getLazyExportInfo() !== null) { - const arkExport = typeObject.getLazyExportInfo()!.getArkExport(); - rightType = TypeInference.parseArkExport2Type(arkExport) ?? UnknownType.getInstance(); - aliasType.setOriginalType(rightType); - } } else if (ts.isTypeQueryNode(rightOp)) { const localName = rightOp.exprName.getText(this.sourceFile); const originalLocal = Array.from(this.arkValueTransformer.getLocals()).find(local => local.getName() === localName); @@ -402,8 +395,6 @@ export class ArkIRTransformer { importInfo.build(importClauseName, importType, importFrom, LineColPosition.buildFromNode(importTypeNode, this.sourceFile), 0); importInfo.setDeclaringArkFile(this.declaringMethod.getDeclaringArkFile()); - // Function getLazyExportInfo will automatically try to infer the export info if it's undefined at the beginning. - importInfo.getLazyExportInfo(); return new AliasTypeExpr(importInfo, importTypeNode.isTypeOf); } diff --git a/ets2panda/linter/arkanalyzer/src/core/common/IRInference.ts b/ets2panda/linter/arkanalyzer/src/core/common/IRInference.ts index 0808347490..a9642db052 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/IRInference.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/IRInference.ts @@ -63,8 +63,7 @@ import { ArkArrayRef, ArkInstanceFieldRef, ArkParameterRef, - ArkStaticFieldRef, - GlobalRef + ArkStaticFieldRef } from '../base/Ref'; import { Value } from '../base/Value'; import { Constant } from '../base/Constant'; @@ -130,6 +129,7 @@ export class IRInference { } return 0; }); + arkClass.getAllHeritageClasses(); methods.forEach(arkMethod => TypeInference.inferTypeInMethod(arkMethod)); }); this.inferExportInfos(file); @@ -283,6 +283,11 @@ export class IRInference { private static inferBase(instance: ArkInstanceFieldRef | ArkInstanceInvokeExpr, arkMethod: ArkMethod): void { const base = instance.getBase(); if (base.getName() === THIS_NAME) { + const name = instance instanceof ArkInstanceFieldRef ? instance.getFieldName() : + instance.getMethodSignature().getMethodSubSignature().getMethodName(); + if (name.includes('.')) { + return; + } const declaringArkClass = arkMethod.getDeclaringArkClass(); if (declaringArkClass.isAnonymousClass()) { let newBase = this.inferThisLocal(arkMethod); @@ -293,14 +298,6 @@ export class IRInference { base.setType(new ClassType(declaringArkClass.getSignature(), declaringArkClass.getRealTypes())); } } else { - const value = arkMethod.getBody()?.getUsedGlobals()?.get(base.getName()); - if (value instanceof GlobalRef && !value.getRef()) { - const arkExport = ModelUtils.findGlobalRef(base.getName(), arkMethod); - if (arkExport instanceof Local) { - arkExport.getUsedStmts().push(...base.getUsedStmts()); - value.setRef(arkExport); - } - } this.inferLocal(instance.getBase(), arkMethod); } } @@ -686,7 +683,7 @@ export class IRInference { private static assignAnonMethod(anonMethod: ArkMethod | null, declaredMethod: ArkMethod | null): void { if (declaredMethod && anonMethod) { - anonMethod.setImplementationSignature(declaredMethod.matchMethodSignature(anonMethod.getSubSignature().getParameters())); + anonMethod.setDeclareSignatures(declaredMethod.matchMethodSignature(anonMethod.getSubSignature().getParameters())); } } @@ -815,7 +812,8 @@ export class IRInference { public static inferParameterRef(ref: ArkParameterRef, arkMethod: ArkMethod): AbstractRef { const paramType = ref.getType(); if (paramType instanceof UnknownType || paramType instanceof UnclearReferenceType) { - const type1 = arkMethod.getSignature().getMethodSubSignature().getParameters()[ref.getIndex()]?.getType(); + const signature = arkMethod.getDeclareSignatures()?.at(0) ?? arkMethod.getSignature(); + const type1 = signature.getMethodSubSignature().getParameters()[ref.getIndex()]?.getType(); if (!TypeInference.isUnclearType(type1)) { ref.setType(type1); return ref; diff --git a/ets2panda/linter/arkanalyzer/src/core/common/ModelUtils.ts b/ets2panda/linter/arkanalyzer/src/core/common/ModelUtils.ts index 7b90129608..41eb1a39f4 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/ModelUtils.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/ModelUtils.ts @@ -37,14 +37,7 @@ import path from 'path'; import { Sdk } from '../../Config'; import { ALL, DEFAULT, THIS_NAME } from './TSConst'; import { buildDefaultExportInfo } from '../model/builder/ArkExportBuilder'; -import { - AnnotationNamespaceType, - ClassType, - FunctionType, - Type, - UnclearReferenceType, - UnknownType -} from '../base/Type'; +import { AnnotationNamespaceType, ClassType, FunctionType, Type, UnclearReferenceType, UnknownType } from '../base/Type'; import { Scene } from '../../Scene'; import { DEFAULT_ARK_CLASS_NAME, DEFAULT_ARK_METHOD_NAME, NAME_DELIMITER, TEMP_LOCAL_PREFIX } from './Const'; import { EMPTY_STRING } from './ValueUtil'; @@ -56,6 +49,14 @@ import { SdkUtils } from './SdkUtils'; export class ModelUtils { public static implicitArkUIBuilderMethods: Set = new Set(); + /* + * Set static field to be null, then all related objects could be freed by GC. + * Static field implicitArkUIBuilderMethods is only internally used by ArkAnalyzer build method body, the dispose method should be called after build all body. + */ + public static dispose(): void { + this.implicitArkUIBuilderMethods.clear(); + } + public static getMethodSignatureFromArkClass(arkClass: ArkClass, methodName: string): MethodSignature | null { for (const arkMethod of arkClass.getMethods()) { if (arkMethod.getName() === methodName) { @@ -570,8 +571,7 @@ export function getArkFile(im: FromInfo): ArkFile | null | undefined { export function findExportInfo(fromInfo: FromInfo): ExportInfo | null { let file = getArkFile(fromInfo); if (!file) { - logger.warn(`${fromInfo.getOriginName()} ${fromInfo.getFrom()} file not found: - ${fromInfo.getDeclaringArkFile()?.getFileSignature()?.toString()}`); + logger.warn(`${fromInfo.getOriginName()} ${fromInfo.getFrom()} file not found: ${fromInfo.getDeclaringArkFile()?.getFileSignature()?.toString()}`); return null; } if (fileSignatureCompare(file.getFileSignature(), fromInfo.getDeclaringArkFile().getFileSignature())) { @@ -623,8 +623,8 @@ export function findArkExport(exportInfo: ExportInfo | undefined): ArkExport | n if (arkExport) { exportInfo.setArkExport(arkExport); } else { - logger.warn(`${exportInfo.getExportClauseName()} get arkExport fail from ${exportInfo.getFrom()} at - ${exportInfo.getDeclaringArkFile().getFileSignature().toString()}`); + const file = exportInfo.getDeclaringArkFile().getFileSignature().toString(); + logger.warn(`${exportInfo.getExportClauseName()} get arkExport fail from ${exportInfo.getFrom()} at ${file}`); } return arkExport || null; } diff --git a/ets2panda/linter/arkanalyzer/src/core/common/SdkUtils.ts b/ets2panda/linter/arkanalyzer/src/core/common/SdkUtils.ts index 84f1859878..644983c544 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/SdkUtils.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/SdkUtils.ts @@ -28,11 +28,22 @@ import { ClassType } from '../base/Type'; import { AbstractFieldRef } from '../base/Ref'; import { ArkNamespace } from '../model/ArkNamespace'; import { TypeInference } from './TypeInference'; +import Logger, { LOG_MODULE_TYPE } from '../../utils/logger'; + +const logger = Logger.getLogger(LOG_MODULE_TYPE.ARKANALYZER, 'SdkUtils'); export class SdkUtils { private static sdkImportMap: Map = new Map(); + /* + * Set static field to be null, then all related objects could be freed by GC. + * Class SdkUtils is only internally used by ArkAnalyzer type inference, the dispose method should be called at the end of type inference. + */ + public static dispose(): void { + this.sdkImportMap.clear(); + } + public static buildSdkImportMap(file: ArkFile): void { const fileName = path.basename(file.getName()); if (fileName.startsWith('@')) { @@ -84,15 +95,18 @@ export class SdkUtils { private static loadClass(globalMap: Map, cls: ArkClass): void { const old = globalMap.get(cls.getName()); - if (old instanceof ArkClass) { + if (old instanceof ArkClass && old.getDeclaringArkFile().getProjectName() === cls.getDeclaringArkFile().getProjectName()) { if (old.getCategory() === ClassCategory.CLASS) { - this.copyMethod(cls, old); + this.copyMembers(cls, old); } else { - this.copyMethod(old, cls); + this.copyMembers(old, cls); globalMap.delete(cls.getName()); globalMap.set(cls.getName(), cls); } - } else if (!old) { + } else { + if (old) { + logger.error(`${old.getSignature()} is override`); + } globalMap.set(cls.getName(), cls); } } @@ -105,10 +119,7 @@ export class SdkUtils { const instance = globalMap.get(name + 'Interface'); const attr = globalMap.get(name + COMPONENT_ATTRIBUTE); if (attr instanceof ArkClass && instance instanceof ArkClass) { - instance - .getMethods() - .filter(m => !attr.getMethodWithName(m.getName())) - .forEach(m => attr.addMethod(m)); + this.copyMembers(instance, attr); globalMap.set(name, attr); return; } @@ -119,15 +130,12 @@ export class SdkUtils { } else if (old instanceof ArkClass && local.getType() instanceof ClassType) { const localConstructor = scene.getClass((local.getType() as ClassType).getClassSignature()); if (localConstructor) { - localConstructor - .getMethods() - .filter(m => !old.getMethodWithName(m.getName())) - .forEach(m => old.addMethod(m)); + this.copyMembers(localConstructor, old); } } } - private static copyMethod(from: ArkClass, to: ArkClass): void { + private static copyMembers(from: ArkClass, to: ArkClass): void { from.getMethods().forEach(method => { const dist = method.isStatic() ? to.getStaticMethodWithName(method.getName()) : to.getMethodWithName(method.getName()); const distSignatures = dist?.getDeclareSignatures(); @@ -137,6 +145,12 @@ export class SdkUtils { to.addMethod(method); } }); + from.getFields().forEach(field => { + const dist = field.isStatic() ? to.getStaticFieldWithName(field.getName()) : to.getFieldWithName(field.getName()); + if (!dist) { + to.addField(field); + } + }); } public static computeGlobalThis(leftOp: AbstractFieldRef, arkMethod: ArkMethod): void { diff --git a/ets2panda/linter/arkanalyzer/src/core/common/TypeInference.ts b/ets2panda/linter/arkanalyzer/src/core/common/TypeInference.ts index e754272cbf..07fc7faf50 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/TypeInference.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/TypeInference.ts @@ -16,7 +16,14 @@ import Logger, { LOG_MODULE_TYPE } from '../../utils/logger'; import { AbstractExpr, ArkInstanceInvokeExpr, ArkPtrInvokeExpr, ArkStaticInvokeExpr } from '../base/Expr'; import { Local } from '../base/Local'; -import { AbstractFieldRef, AbstractRef, ArkArrayRef, ArkInstanceFieldRef, ArkParameterRef, ArkStaticFieldRef } from '../base/Ref'; +import { + AbstractFieldRef, + AbstractRef, + ArkArrayRef, + ArkInstanceFieldRef, + ArkParameterRef, + ArkStaticFieldRef, GlobalRef +} from '../base/Ref'; import { ArkAliasTypeDefineStmt, ArkAssignStmt, ArkReturnStmt, Stmt } from '../base/Stmt'; import { AliasType, @@ -54,7 +61,7 @@ import { ANY_KEYWORD, BIGINT_KEYWORD, BOOLEAN_KEYWORD, - CONSTRUCTOR_NAME, + CONSTRUCTOR_NAME, DEFAULT, GLOBAL_THIS_NAME, NEVER_KEYWORD, NULL_KEYWORD, @@ -157,7 +164,7 @@ export class TypeInference { type = leftOpType; } } else if (leftOpType instanceof AnnotationNamespaceType) { - type = this.inferUnclearRefName(leftOpType.getOriginType(), declaringArkClass); + type = this.inferBaseType(leftOpType.getOriginType(), declaringArkClass); } else if (leftOpType instanceof UnclearReferenceType) { type = this.inferUnclearRefType(leftOpType, declaringArkClass); } @@ -185,6 +192,15 @@ export class TypeInference { signatures.forEach(s => this.inferSignatureReturnType(s, arkMethod)); return; } + body.getUsedGlobals()?.forEach((value, key) => { + if (value instanceof GlobalRef && !value.getRef()) { + const arkExport = ModelUtils.findGlobalRef(key, arkMethod); + if (arkExport instanceof Local) { + arkExport.getUsedStmts().push(...value.getUsedStmts()); + value.setRef(arkExport); + } + } + }); const cfg = body.getCfg(); for (const block of cfg.getBlocks()) { for (const stmt of block.getStmts()) { @@ -387,7 +403,8 @@ export class TypeInference { public static isUnclearType(type: Type | null | undefined): boolean { // TODO: For UnionType, IntersectionType and TupleType, it should recurse check every item of them. - if (!type || type instanceof UnknownType || type instanceof UnclearReferenceType || type instanceof NullType || type instanceof UndefinedType) { + if (!type || type instanceof UnknownType || type instanceof UnclearReferenceType || type instanceof NullType || + type instanceof UndefinedType || type instanceof GenericType) { return true; } else if ( type instanceof ClassType && @@ -488,7 +505,7 @@ export class TypeInference { return value.getType(); } - private static inferParameterType(param: MethodParameter, arkMethod: ArkMethod): void { + public static inferParameterType(param: MethodParameter, arkMethod: ArkMethod): void { let pType = param.getType(); const arkClass = arkMethod.getDeclaringArkClass(); let type; @@ -703,7 +720,7 @@ export class TypeInference { } propertyType = new EnumValueType(property.getSignature(), constant); } else { - propertyType = property.getType(); + propertyType = this.replaceTypeWithReal(property.getType(), baseType.getRealGenericTypes()); } } else if (property) { propertyType = this.parseArkExport2Type(property); @@ -728,6 +745,8 @@ export class TypeInference { public static inferBaseType(baseName: string, arkClass: ArkClass): Type | null { if (SUPER_NAME === baseName) { return this.parseArkExport2Type(arkClass.getSuperClass()); + } else if (DEFAULT === baseName) { + return this.parseArkExport2Type(arkClass.getDeclaringArkFile().getExportInfoBy(DEFAULT)?.getArkExport()); } const field = ModelUtils.getDefaultClass(arkClass)?.getDefaultArkMethod()?.getBody()?.getLocals()?.get(baseName); if (field && !this.isUnclearType(field.getType())) { @@ -750,14 +769,12 @@ export class TypeInference { ModelUtils.getClassWithName(typeName, arkClass) ?? ModelUtils.getDefaultClass(arkClass)?.getDefaultArkMethod()?.getBody()?.getAliasTypeByName(typeName) ?? ModelUtils.getArkExportInImportInfoWithName(typeName, arkClass.getDeclaringArkFile()); - if (arkExport instanceof ArkClass || arkExport instanceof AliasType) { - return this.parseArkExport2Type(arkExport); - } - if (!arkClass.getDeclaringArkFile().getImportInfoBy(typeName)) { + if (!arkExport && !arkClass.getDeclaringArkFile().getImportInfoBy(typeName)) { arkExport = arkClass.getDeclaringArkFile().getScene().getSdkGlobal(typeName); } - if (arkExport instanceof ArkClass || arkExport instanceof AliasType) { - return this.parseArkExport2Type(arkExport); + const type = this.parseArkExport2Type(arkExport); + if (type instanceof ClassType || type instanceof AliasType) { + return type; } return null; } @@ -860,12 +877,14 @@ export class TypeInference { .getParameters() .filter(p => !p.getName().startsWith(LEXICAL_ENV_NAME_PREFIX)) .forEach((p, i) => { - let type = params?.[i]?.getType(); - if (type instanceof GenericType && realTypes) { - type = realTypes?.[type.getIndex()]; - } - if (type) { - p.setType(type); + if (this.isUnclearType(p.getType())) { + let type = params?.[i]?.getType(); + if (type instanceof GenericType && realTypes) { + type = realTypes?.[type.getIndex()]; + } + if (type) { + p.setType(type); + } } }); } diff --git a/ets2panda/linter/arkanalyzer/src/core/common/ValueUtil.ts b/ets2panda/linter/arkanalyzer/src/core/common/ValueUtil.ts index 1731b701b0..8a29e565b8 100644 --- a/ets2panda/linter/arkanalyzer/src/core/common/ValueUtil.ts +++ b/ets2panda/linter/arkanalyzer/src/core/common/ValueUtil.ts @@ -21,6 +21,14 @@ export class ValueUtil { private static readonly NumberConstantCache: Map = new Map(); public static readonly EMPTY_STRING_CONSTANT = new StringConstant(EMPTY_STRING); + /* + * Set static field to be null, then all related objects could be freed by GC. + * Class SdkUtils is only internally used by ArkAnalyzer, the dispose method should be called by users themselves before drop Scene. + */ + public static dispose(): void { + this.NumberConstantCache.clear(); + } + public static getOrCreateNumberConst(n: number): Constant { let constant = this.NumberConstantCache.get(n); if (constant === undefined) { diff --git a/ets2panda/linter/arkanalyzer/src/core/dataflow/DataflowSolver.ts b/ets2panda/linter/arkanalyzer/src/core/dataflow/DataflowSolver.ts index 523dd9a41b..325fa23634 100644 --- a/ets2panda/linter/arkanalyzer/src/core/dataflow/DataflowSolver.ts +++ b/ets2panda/linter/arkanalyzer/src/core/dataflow/DataflowSolver.ts @@ -24,6 +24,7 @@ import { CallGraph } from '../../callgraph/model/CallGraph'; import { ClassHierarchyAnalysis } from '../../callgraph/algorithm/ClassHierarchyAnalysis'; import { addCfg2Stmt } from '../../utils/entryMethodUtils'; import { getRecallMethodInParam } from './Util'; +import { CallGraphBuilder } from '../../callgraph/model/builder/CallGraphBuilder'; /* this program is roughly an implementation of the paper: Practical Extensions to the IFDS Algorithm. @@ -88,7 +89,7 @@ export abstract class DataflowSolver { // build CHA let cg = new CallGraph(this.scene); - this.CHA = new ClassHierarchyAnalysis(this.scene, cg); + this.CHA = new ClassHierarchyAnalysis(this.scene, cg, new CallGraphBuilder(cg, this.scene)); this.buildStmtMapInClass(); this.setCfg4AllStmt(); return; diff --git a/ets2panda/linter/arkanalyzer/src/core/graph/builder/CfgBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/graph/builder/CfgBuilder.ts index 5cd44402ec..13ff5584cc 100644 --- a/ets2panda/linter/arkanalyzer/src/core/graph/builder/CfgBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/graph/builder/CfgBuilder.ts @@ -677,6 +677,9 @@ export class CfgBuilder { for (let i = stmt.nexts.length - 1; i >= 0; i--) { stmtQueue.push(stmt.nexts[i]); } + if (stmt.afterSwitch && stmt.afterSwitch.lasts.size == 0) { + stmtQueue.push(stmt.afterSwitch); + } } else if (stmt instanceof TryStatementBuilder) { if (stmt.finallyStatement) { stmtQueue.push(stmt.finallyStatement); diff --git a/ets2panda/linter/arkanalyzer/src/core/graph/builder/TrapBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/graph/builder/TrapBuilder.ts index 160df9fdc0..9094994dc5 100644 --- a/ets2panda/linter/arkanalyzer/src/core/graph/builder/TrapBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/graph/builder/TrapBuilder.ts @@ -19,7 +19,15 @@ import { Trap } from '../../base/Trap'; import { ArkCaughtExceptionRef } from '../../base/Ref'; import { UnknownType } from '../../base/Type'; import { FullPosition } from '../../base/Position'; -import { ArkAssignStmt, ArkIfStmt, ArkInvokeStmt, ArkReturnStmt, ArkReturnVoidStmt, ArkThrowStmt, Stmt } from '../../base/Stmt'; +import { + ArkAssignStmt, + ArkIfStmt, + ArkInvokeStmt, + ArkReturnStmt, + ArkReturnVoidStmt, + ArkThrowStmt, + Stmt, +} from '../../base/Stmt'; import { BlockBuilder, TryStatementBuilder } from './CfgBuilder'; import Logger, { LOG_MODULE_TYPE } from '../../../utils/logger'; @@ -217,16 +225,17 @@ export class TrapBuilder { bfsBlocks.push(currBlock); const childList = currBlockBuilder.nexts; - if (childList.length === 0 || (childList.length !== 0 && childList[0] === endBlockBuilder)) { - if (childList[0] === endBlockBuilder) { - tailBlocks.push(currBlock); - continue; - } - } if (childList.length !== 0) { for (const child of childList) { - queue.push(child); + // A tail block's successor may be within the traversal range + if (child === endBlockBuilder) { + tailBlocks.push(currBlock); + } else { + queue.push(child); + } } + } else { + tailBlocks.push(currBlock); } } return { bfsBlocks, tailBlocks }; @@ -247,19 +256,16 @@ export class TrapBuilder { copyFinallyBfsBlocks[0].getPredecessors().splice(0, finallyPredecessorsCnt); const throwStmt = new ArkThrowStmt(exceptionValue); let copyFinallyTailBlocks = copyFinallyBfsBlocks.splice(copyFinallyBfsBlocks.length - finallyTailBlocks.length, finallyTailBlocks.length); - copyFinallyTailBlocks.forEach((copyFinallyTailBlock: BasicBlock) => { - const successorsCnt = copyFinallyTailBlock.getSuccessors().length; - copyFinallyTailBlock.getSuccessors().splice(0, successorsCnt); - }); if (copyFinallyTailBlocks.length > 1) { const newCopyFinallyTailBlock = new BasicBlock(); copyFinallyTailBlocks.forEach((copyFinallyTailBlock: BasicBlock) => { copyFinallyTailBlock.addSuccessorBlock(newCopyFinallyTailBlock); newCopyFinallyTailBlock.addPredecessorBlock(copyFinallyTailBlock); }); + copyFinallyBfsBlocks.push(...copyFinallyTailBlocks); copyFinallyTailBlocks = [newCopyFinallyTailBlock]; } - copyFinallyTailBlocks[0]?.addStmt(throwStmt); + copyFinallyTailBlocks[0].addStmt(throwStmt); copyFinallyBfsBlocks.push(...copyFinallyTailBlocks); copyFinallyBfsBlocks.forEach((copyFinallyBfsBlock: BasicBlock) => { basicBlockSet.add(copyFinallyBfsBlock); @@ -281,12 +287,19 @@ export class TrapBuilder { for (const sourceBlock of sourceBlocks) { const targetBlock = sourceToTarget.get(sourceBlock)!; for (const predecessor of sourceBlock.getPredecessors()) { - const targetPredecessor = sourceToTarget.get(predecessor)!; - targetBlock.addPredecessorBlock(targetPredecessor); + const targetPredecessor = sourceToTarget.get(predecessor); + // Only include blocks within the copy range, so that predecessor and successor relationships to + // external blocks can be trimmed + if (targetPredecessor) { + targetBlock.addPredecessorBlock(targetPredecessor); + } + } for (const successor of sourceBlock.getSuccessors()) { - const targetSuccessor = sourceToTarget.get(successor)!; - targetBlock.addSuccessorBlock(targetSuccessor); + const targetSuccessor = sourceToTarget.get(successor); + if (targetSuccessor) { + targetBlock.addSuccessorBlock(targetSuccessor); + } } } return targetBlocks; diff --git a/ets2panda/linter/arkanalyzer/src/core/model/ArkImport.ts b/ets2panda/linter/arkanalyzer/src/core/model/ArkImport.ts index 8ff3ff50ac..05c5c24a80 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/ArkImport.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/ArkImport.ts @@ -72,7 +72,7 @@ export class ImportInfo extends ArkBaseModel implements FromInfo { * @returns The export information. If there is no export information, the return will be a **null**. */ public getLazyExportInfo(): ExportInfo | null { - if (this.lazyExportInfo === undefined) { + if (this.lazyExportInfo === undefined && this.declaringArkFile.getScene().getStage() >= 2) { this.lazyExportInfo = findExportInfo(this); } return this.lazyExportInfo || null; diff --git a/ets2panda/linter/arkanalyzer/src/core/model/ArkMethod.ts b/ets2panda/linter/arkanalyzer/src/core/model/ArkMethod.ts index f3476d3567..12682223ba 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/ArkMethod.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/ArkMethod.ts @@ -15,7 +15,16 @@ import { ArkParameterRef, ArkThisRef } from '../base/Ref'; import { ArkAssignStmt, ArkReturnStmt, Stmt } from '../base/Stmt'; -import { ClassType, EnumValueType, FunctionType, GenericType, LiteralType, Type, UnionType } from '../base/Type'; +import { + AliasType, + ClassType, + EnumValueType, + FunctionType, + GenericType, + LiteralType, + Type, + UnionType +} from '../base/Type'; import { Value } from '../base/Value'; import { Cfg } from '../graph/Cfg'; import { ViewTree } from '../graph/ViewTree'; @@ -24,17 +33,17 @@ import { ArkClass, ClassCategory } from './ArkClass'; import { MethodSignature, MethodSubSignature } from './ArkSignature'; import { BodyBuilder } from './builder/BodyBuilder'; import { ArkExport, ExportType } from './ArkExport'; -import { ANONYMOUS_METHOD_PREFIX, DEFAULT_ARK_METHOD_NAME } from '../common/Const'; +import { ANONYMOUS_METHOD_PREFIX, DEFAULT_ARK_METHOD_NAME, LEXICAL_ENV_NAME_PREFIX } from '../common/Const'; import { getColNo, getLineNo, LineCol, setCol, setLine } from '../base/Position'; import { ArkBaseModel, ModifierType } from './ArkBaseModel'; import { ArkError, ArkErrorCode } from '../common/ArkError'; import { CALL_BACK } from '../common/EtsConst'; -import { Scene } from '../../Scene'; import { Constant } from '../base/Constant'; import { Local } from '../base/Local'; import { ArkFile, Language } from './ArkFile'; import { CONSTRUCTOR_NAME } from '../common/TSConst'; import { MethodParameter } from './builder/ArkMethodBuilder'; +import { TypeInference } from '../common/TypeInference'; export const arkMethodNodeKind = [ 'MethodDeclaration', @@ -623,45 +632,41 @@ export class ArkMethod extends ArkBaseModel implements ArkExport { } return args.length >= min && args.length <= max; }); - const scene = this.getDeclaringArkFile().getScene(); return ( - signatures?.find(p => { - const parameters = p.getMethodSubSignature().getParameters(); - for (let i = 0; i < parameters.length; i++) { - if (!args[i]) { - return parameters[i].isOptional(); - } - const isMatched = this.matchParam(parameters[i].getType(), args[i], scene); - if (!isMatched) { - return false; - } - } - return true; - }) ?? + signatures?.find(p => this.isMatched(p.getMethodSubSignature().getParameters(), args)) ?? signatures?.[0] ?? this.getSignature() ); } - private matchParam(paramType: Type, arg: Value, scene: Scene): boolean { - const argType = arg.getType(); - if (arg instanceof Local) { - const stmt = arg.getDeclaringStmt(); - if (stmt instanceof ArkAssignStmt && stmt.getRightOp() instanceof Constant) { - arg = stmt.getRightOp(); + private isMatched(parameters: MethodParameter[], args: Value[], isArrowFunc: boolean = false): boolean { + for (let i = 0; i < parameters.length; i++) { + if (!args[i]) { + return isArrowFunc ? true : parameters[i].isOptional(); } + const isMatched = this.matchParam(parameters[i].getType(), args[i]); + if (!isMatched) { + return false; + } + } + return true; + } + + private matchParam(paramType: Type, arg: Value): boolean { + arg = ArkMethod.parseArg(arg); + const argType = arg.getType(); + if (paramType instanceof AliasType && !(argType instanceof AliasType)) { + paramType = TypeInference.replaceAliasType(paramType); } if (paramType instanceof UnionType) { - let matched = false; - for (const e of paramType.getTypes()) { - if (argType.constructor === e.constructor) { - matched = true; - break; - } - } - return matched; + return !!paramType.getTypes().find(p => this.matchParam(p, arg)); } else if (argType instanceof FunctionType && paramType instanceof FunctionType) { - return argType.getMethodSignature().getParamLength() === paramType.getMethodSignature().getParamLength(); + if (argType.getMethodSignature().getParamLength() > paramType.getMethodSignature().getParamLength()) { + return false; + } + const parameters = paramType.getMethodSignature().getMethodSubSignature().getParameters(); + const args = argType.getMethodSignature().getMethodSubSignature().getParameters().filter(p => !p.getName().startsWith(LEXICAL_ENV_NAME_PREFIX)); + return this.isMatched(parameters, args, true); } else if (paramType instanceof ClassType && paramType.getClassSignature().getClassName().includes(CALL_BACK)) { return argType instanceof FunctionType; } else if (paramType instanceof LiteralType && arg instanceof Constant) { @@ -684,6 +689,19 @@ export class ArkMethod extends ArkBaseModel implements ArkExport { return argType.constructor === paramType.constructor; } + private static parseArg(arg: Value): Value { + if (arg instanceof Local) { + const stmt = arg.getDeclaringStmt(); + const argType = arg.getType(); + if (argType instanceof EnumValueType && argType.getConstant()) { + arg = argType.getConstant()!; + } else if (stmt instanceof ArkAssignStmt && stmt.getRightOp() instanceof Constant) { + arg = stmt.getRightOp(); + } + } + return arg; + } + public getOuterMethod(): ArkMethod | undefined { return this.outerMethod; } diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkClassBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkClassBuilder.ts index 7c3f169384..48a7217d1a 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkClassBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkClassBuilder.ts @@ -370,7 +370,17 @@ function buildArkClassMembers(clsNode: ClassLikeNode, cls: ArkClass, sourceFile: const instanceInitStmts: Stmt[] = []; let staticBlockId = 0; clsNode.members.forEach(member => { - if (ts.isPropertyDeclaration(member) || ts.isPropertySignature(member)) { + if ( + ts.isMethodDeclaration(member) || + ts.isConstructorDeclaration(member) || + ts.isMethodSignature(member) || + ts.isConstructSignatureDeclaration(member) || + ts.isAccessor(member) || + ts.isCallSignatureDeclaration(member) + ) { + // these node types have been handled at the beginning of this function by calling buildMethodsForClass + return; + } else if (ts.isPropertyDeclaration(member) || ts.isPropertySignature(member)) { const arkField = buildProperty2ArkField(member, sourceFile, cls); if (ts.isClassDeclaration(clsNode) || ts.isClassExpression(clsNode) || ts.isStructDeclaration(clsNode)) { if (arkField.isStatic()) { @@ -395,9 +405,9 @@ function buildArkClassMembers(clsNode: ClassLikeNode, cls: ArkClass, sourceFile: const staticBlockInvokeExpr = new ArkStaticInvokeExpr(currStaticBlockMethodSig, []); staticInitStmts.push(new ArkInvokeStmt(staticBlockInvokeExpr)); } else if (ts.isSemicolonClassElement(member)) { - logger.debug('Skip these members.'); + logger.trace('Skip these members.'); } else { - logger.warn('Please contact developers to support new member type!'); + logger.warn(`Please contact developers to support new member in class: ${cls.getSignature().toString()}, member: ${member.getText()}!`); } }); if (ts.isClassDeclaration(clsNode) || ts.isClassExpression(clsNode) || ts.isStructDeclaration(clsNode)) { diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFieldBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFieldBuilder.ts index ede55e7c93..b41b7dd419 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFieldBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFieldBuilder.ts @@ -47,7 +47,7 @@ export function buildProperty2ArkField( } else if (ts.isPropertyAccessExpression(member.name.expression)) { fieldName = handlePropertyAccessExpression(member.name.expression); } else { - logger.warn('Other property expression type found!'); + logger.warn(`Other property expression type found: ${member.name.expression.getText()}!`); } } else if (member.name && (ts.isIdentifier(member.name) || ts.isLiteralExpression(member.name))) { fieldName = member.name.text; @@ -56,7 +56,7 @@ export function buildProperty2ArkField( fieldName = propertyName.substring(1); field.addModifier(ModifierType.PRIVATE); } else { - logger.warn('Other type of property name found!'); + logger.warn(`Other type of property name found: ${member.getText()}!`); } let fieldType: Type = UnknownType.getInstance(); diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFileBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFileBuilder.ts index 1e201453b1..386cbca085 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFileBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkFileBuilder.ts @@ -110,7 +110,7 @@ function buildArkFile(arkFile: ArkFile, astRoot: ts.SourceFile): void { } // TODO: Check else if (ts.isMethodDeclaration(child)) { - logger.warn('This is a MethodDeclaration in ArkFile.'); + logger.trace('This is a MethodDeclaration in ArkFile.'); let mthd: ArkMethod = new ArkMethod(); buildArkMethodFromArkClass(child, arkFile.getDefaultClass(), mthd, astRoot); @@ -143,7 +143,7 @@ function buildArkFile(arkFile: ArkFile, astRoot: ts.SourceFile): void { } else if (ts.isExpressionStatement(child) && ts.isStringLiteral(child.expression)) { child.expression.text.trim() === ARKTS_STATIC_MARK && arkFile.setLanguage(Language.ARKTS1_2); } else { - logger.info('Child joined default method of arkFile: ', ts.SyntaxKind[child.kind]); + logger.trace('Child joined default method of arkFile: ', ts.SyntaxKind[child.kind]); } }); diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkMethodBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkMethodBuilder.ts index 29221c377c..cb00c3dff7 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkMethodBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkMethodBuilder.ts @@ -113,14 +113,13 @@ export function buildArkMethodFromArkClass( mtd.setImplementationSignature(methodSignature); mtd.setLine(line + 1); mtd.setColumn(character + 1); + let bodyBuilder = new BodyBuilder(mtd.getSignature(), methodNode, mtd, sourceFile); + mtd.setBodyBuilder(bodyBuilder); } else { mtd.setDeclareSignatures(methodSignature); mtd.setDeclareLinesAndCols([line + 1], [character + 1]); } - let bodyBuilder = new BodyBuilder(mtd.getSignature(), methodNode, mtd, sourceFile); - mtd.setBodyBuilder(bodyBuilder); - if (mtd.hasBuilderDecorator()) { mtd.setViewTree(buildViewTree(mtd)); } else if (declaringClass.hasComponentDecorator() && mtd.getSubSignature().toString() === 'build()' && !mtd.isStatic()) { @@ -430,10 +429,11 @@ export function addInitInConstructor(constructor: ArkMethod): void { if (!thisLocal) { return; } - const blocks = constructor.getCfg()?.getBlocks(); - if (!blocks) { + const cfg = constructor.getCfg(); + if (cfg === undefined) { return; } + const blocks = cfg.getBlocks(); const firstBlockStmts = [...blocks][0].getStmts(); let index = 0; for (let i = 0; i < firstBlockStmts.length; i++) { @@ -454,6 +454,7 @@ export function addInitInConstructor(constructor: ArkMethod): void { const initInvokeStmt = new ArkInvokeStmt( new ArkInstanceInvokeExpr(thisLocal, constructor.getDeclaringArkClass().getInstanceInitMethod().getSignature(), []) ); + initInvokeStmt.setCfg(cfg); firstBlockStmts.splice(index, 0, initInvokeStmt); } diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkNamespaceBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkNamespaceBuilder.ts index 930a0bba21..b336fe921b 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkNamespaceBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/ArkNamespaceBuilder.ts @@ -69,12 +69,12 @@ export function buildArkNamespace(node: ts.ModuleDeclaration, declaringInstance: // NamespaceDeclaration extends ModuleDeclaration //TODO: Check else if (ts.isModuleDeclaration(node.body)) { - logger.warn('This ModuleBody is an NamespaceDeclaration.'); + logger.trace('This ModuleBody is an NamespaceDeclaration.'); let childNs: ArkNamespace = new ArkNamespace(); buildArkNamespace(node.body, ns, childNs, sourceFile); ns.addNamespace(childNs); } else if (ts.isIdentifier(node.body)) { - logger.warn('ModuleBody is Identifier.'); + logger.warn('ModuleBody is Identifier'); } else { logger.warn('JSDocNamespaceDeclaration found.'); } @@ -108,7 +108,7 @@ function buildNamespaceMembers(node: ts.ModuleBlock, namespace: ArkNamespace, so } // TODO: Check else if (ts.isMethodDeclaration(child)) { - logger.warn('This is a MethodDeclaration in ArkNamespace.'); + logger.trace('This is a MethodDeclaration in ArkNamespace.'); let mthd: ArkMethod = new ArkMethod(); buildArkMethodFromArkClass(child, namespace.getDefaultClass(), mthd, sourceFile); @@ -131,7 +131,7 @@ function buildNamespaceMembers(node: ts.ModuleBlock, namespace: ArkNamespace, so } else if (ts.isVariableStatement(child) && isExported(child.modifiers)) { buildExportVariableStatement(child, sourceFile, namespace.getDeclaringArkFile(), namespace).forEach(item => namespace.addExportInfo(item)); } else { - logger.info('Child joined default method of arkFile: ', ts.SyntaxKind[child.kind]); + logger.trace('Child joined default method of arkFile: ', ts.SyntaxKind[child.kind]); // join default method } }); diff --git a/ets2panda/linter/arkanalyzer/src/core/model/builder/BodyBuilder.ts b/ets2panda/linter/arkanalyzer/src/core/model/builder/BodyBuilder.ts index 77b28a411f..8a6286bd30 100644 --- a/ets2panda/linter/arkanalyzer/src/core/model/builder/BodyBuilder.ts +++ b/ets2panda/linter/arkanalyzer/src/core/model/builder/BodyBuilder.ts @@ -571,6 +571,7 @@ export class BodyBuilder { const closuresLocal = new Local(closuresParam.getName(), lexicalEnv); body.addLocal(closuresLocal.getName(), closuresLocal); let assignStmt = new ArkAssignStmt(closuresLocal, parameterRef); + assignStmt.setCfg(body.getCfg()); stmts.splice(index, 0, assignStmt); closuresLocal.setDeclaringStmt(assignStmt); @@ -590,6 +591,7 @@ export class BodyBuilder { index++; const closureFieldRef = new ClosureFieldRef(closuresParam, closure.getName(), closure.getType()); let assignStmt = new ArkAssignStmt(local, closureFieldRef); + assignStmt.setCfg(body.getCfg()); stmts.splice(index, 0, assignStmt); local.setDeclaringStmt(assignStmt); closuresLocal.addUsedStmt(assignStmt); diff --git a/ets2panda/linter/arkanalyzer/src/save/JsonPrinter.ts b/ets2panda/linter/arkanalyzer/src/save/JsonPrinter.ts index 283de26011..e9c2696bf8 100644 --- a/ets2panda/linter/arkanalyzer/src/save/JsonPrinter.ts +++ b/ets2panda/linter/arkanalyzer/src/save/JsonPrinter.ts @@ -22,20 +22,20 @@ import { ArkField } from '../core/model/ArkField'; import { AliasType, AnnotationNamespaceType, - AnnotationType, AnnotationTypeQueryType, AnyType, ArrayType, BigIntType, BooleanType, ClassType, + EnumValueType, FunctionType, GenericType, + IntersectionType, LiteralType, NeverType, NullType, NumberType, - PrimitiveType, StringType, TupleType, Type, @@ -46,11 +46,16 @@ import { VoidType, } from '../core/base/Type'; import { Value } from '../core/base/Value'; -import { ArkAssignStmt, ArkIfStmt, ArkInvokeStmt, ArkReturnStmt, ArkReturnVoidStmt, ArkThrowStmt, Stmt } from '../core/base/Stmt'; import { - AbstractBinopExpr, - AbstractExpr, - AbstractInvokeExpr, + ArkAssignStmt, + ArkIfStmt, + ArkInvokeStmt, + ArkReturnStmt, + ArkReturnVoidStmt, + ArkThrowStmt, + Stmt, +} from '../core/base/Stmt'; +import { ArkAwaitExpr, ArkCastExpr, ArkConditionExpr, @@ -73,13 +78,12 @@ import { ImportInfo } from '../core/model/ArkImport'; import { ExportInfo } from '../core/model/ArkExport'; import { AliasTypeSignature, ClassSignature, FieldSignature, FileSignature, MethodSignature, NamespaceSignature } from '../core/model/ArkSignature'; import { LineColPosition } from '../core/base/Position'; -import { AbstractFieldRef, AbstractRef, ArkArrayRef, ArkInstanceFieldRef, ArkParameterRef, ArkStaticFieldRef, ArkThisRef } from '../core/base/Ref'; +import { ArkArrayRef, ArkCaughtExceptionRef, ArkInstanceFieldRef, ArkParameterRef, ArkStaticFieldRef, ArkThisRef, ClosureFieldRef, GlobalRef } from '../core/base/Ref'; import { Local } from '../core/base/Local'; import { Cfg } from '../core/graph/Cfg'; import { BasicBlock } from '../core/graph/BasicBlock'; import { ArkBody } from '../core/model/ArkBody'; import { Decorator } from '../core/base/Decorator'; -import util from 'util'; export class JsonPrinter extends Printer { constructor(private arkFile: ArkFile) { @@ -113,8 +117,9 @@ export class JsonPrinter extends Printer { return { signature: this.serializeClassSignature(clazz.getSignature()), modifiers: clazz.getModifiers(), - decorators: clazz.getDecorators().map(decorator => this.serializeDecorator(decorator)), - typeParameters: clazz.getGenericsTypes()?.map(type => this.serializeType(type)), + decorators: clazz.getDecorators().map((decorator) => this.serializeDecorator(decorator)), + typeParameters: clazz.getGenericsTypes()?.map((type) => this.serializeType(type)), + category: clazz.getCategory(), superClassName: clazz.getSuperClassName(), implementedInterfaceNames: clazz.getImplementedInterfaceNames(), fields: clazz.getFields().map(field => this.serializeField(field)), @@ -155,6 +160,7 @@ export class JsonPrinter extends Printer { name: parameter.getName(), type: this.serializeType(parameter.getType()), isOptional: parameter.isOptional(), + isRest: parameter.hasDotDotDotToken(), }; } @@ -220,6 +226,11 @@ export class JsonPrinter extends Printer { _: 'UnionType', types: type.getTypes().map(type => this.serializeType(type)), }; + } else if (type instanceof IntersectionType) { + return { + _: 'IntersectionType', + types: type.getTypes().map((type) => this.serializeType(type)), + }; } else if (type instanceof TupleType) { return { _: 'TupleType', @@ -254,8 +265,6 @@ export class JsonPrinter extends Printer { _: 'LiteralType', literal: type.getLiteralName(), }; - } else if (type instanceof PrimitiveType) { - throw new Error('Unhandled PrimitiveType: ' + util.inspect(type, { showHidden: true, depth: null })); } else if (type instanceof ClassType) { return { _: 'ClassType', @@ -281,13 +290,13 @@ export class JsonPrinter extends Printer { typeParameters: type.getGenericTypes().map(type => this.serializeType(type)), }; } else if (type instanceof GenericType) { - let defaultType = type.getDefaultType(); let constraint = type.getConstraint(); + let defaultType = type.getDefaultType(); return { _: 'GenericType', name: type.getName(), - defaultType: defaultType && this.serializeType(defaultType), constraint: constraint && this.serializeType(constraint), + defaultType: defaultType && this.serializeType(defaultType), }; } else if (type instanceof AliasType) { return { @@ -307,10 +316,19 @@ export class JsonPrinter extends Printer { _: 'AnnotationTypeQueryType', originType: type.getOriginType(), }; - } else if (type instanceof AnnotationType) { - throw new Error('Unhandled AnnotationType: ' + util.inspect(type, { showHidden: true, depth: null })); + } else if (type instanceof EnumValueType) { + const c = type.getConstant(); + return { + _: 'EnumValueType', + signature: this.serializeFieldSignature(type.getFieldSignature()), + constant: c && this.serializeValue(c), + }; } else { - throw new Error('Unhandled Type: ' + util.inspect(type, { showHidden: true, depth: null })); + console.warn(`Unhandled Type: ${type.constructor.name} (${type.toString()})`); + return { + _: type.constructor.name, + text: type.toString(), + }; } } @@ -415,6 +433,13 @@ export class JsonPrinter extends Printer { }; } + private serializeConstant(constant: Constant): object { + return { + value: constant.getValue(), + type: this.serializeType(constant.getType()), + }; + } + private serializeValue(value: Value): object { if (value === undefined) { throw new Error('Value is undefined'); @@ -428,8 +453,7 @@ export class JsonPrinter extends Printer { } else if (value instanceof Constant) { return { _: 'Constant', - value: value.getValue(), - type: this.serializeType(value.getType()), + ...this.serializeConstant(value), }; } else if (value instanceof ArkNewExpr) { return { @@ -498,8 +522,6 @@ export class JsonPrinter extends Printer { left: this.serializeValue(value.getOp1()), right: this.serializeValue(value.getOp2()), }; - } else if (value instanceof AbstractBinopExpr) { - return new Error('Unhandled BinopExpr: ' + util.inspect(value, { showHidden: true, depth: null })); } else if (value instanceof ArkUnopExpr) { return { _: 'UnopExpr', @@ -526,8 +548,6 @@ export class JsonPrinter extends Printer { method: this.serializeMethodSignature(value.getMethodSignature()), args: value.getArgs().map(arg => this.serializeValue(arg)), }; - } else if (value instanceof AbstractInvokeExpr) { - throw new Error('Unhandled CallExpr: ' + util.inspect(value, { showHidden: true, depth: null })); } else if (value instanceof ArkThisRef) { return { _: 'ThisRef', @@ -546,6 +566,25 @@ export class JsonPrinter extends Printer { index: this.serializeValue(value.getIndex()), type: this.serializeType(value.getType()), }; + } else if (value instanceof ArkCaughtExceptionRef) { + return { + _: 'CaughtExceptionRef', + type: this.serializeType(value.getType()), + }; + } else if (value instanceof GlobalRef) { + let ref = value.getRef(); + return { + _: 'GlobalRef', + name: value.getName(), + ref: ref ? this.serializeValue(ref) : null, + }; + } else if (value instanceof ClosureFieldRef) { + return { + _: 'ClosureFieldRef', + base: this.serializeLocal(value.getBase()), + fieldName: value.getFieldName(), + type: this.serializeType(value.getType()), + }; } else if (value instanceof ArkInstanceFieldRef) { return { _: 'InstanceFieldRef', @@ -557,14 +596,13 @@ export class JsonPrinter extends Printer { _: 'StaticFieldRef', field: this.serializeFieldSignature(value.getFieldSignature()), }; - } else if (value instanceof AbstractFieldRef) { - throw new Error('Unhandled FieldRef: ' + util.inspect(value, { showHidden: true, depth: null })); - } else if (value instanceof AbstractRef) { - throw new Error('Unhandled Ref: ' + util.inspect(value, { showHidden: true, depth: null })); - } else if (value instanceof AbstractExpr) { - throw new Error('Unhandled Expr: ' + util.inspect(value, { showHidden: true, depth: null })); } else { - throw new Error('Unhandled Value: ' + util.inspect(value, { showHidden: true, depth: null })); + console.warn(`Unhandled Value: ${value.constructor.name} (${value.toString()})`); + return { + _: value.constructor.name, + text: value.toString(), + type: this.serializeType(value.getType()), + }; } } @@ -600,7 +638,11 @@ export class JsonPrinter extends Printer { arg: this.serializeValue(stmt.getOp()), }; } else { - throw new Error('Unhandled Stmt: ' + util.inspect(stmt, { showHidden: true, depth: null })); + console.warn(`Unhandled Stmt: ${stmt.constructor.name} (${stmt.toString()})`); + return { + _: stmt.constructor.name, + text: stmt.toString(), + }; } } } diff --git a/ets2panda/linter/arkanalyzer/src/utils/SparseBitVector.ts b/ets2panda/linter/arkanalyzer/src/utils/SparseBitVector.ts index fcb5c816ac..313fb88f35 100644 --- a/ets2panda/linter/arkanalyzer/src/utils/SparseBitVector.ts +++ b/ets2panda/linter/arkanalyzer/src/utils/SparseBitVector.ts @@ -538,7 +538,6 @@ export class SparseBitVector { return changed; } - // Dump as string toString(): string { let ar = [...this]; return ar.toString(); diff --git a/ets2panda/linter/arkanalyzer/typedoc.json b/ets2panda/linter/arkanalyzer/typedoc.json index 1b08d68d69..e582cf129b 100644 --- a/ets2panda/linter/arkanalyzer/typedoc.json +++ b/ets2panda/linter/arkanalyzer/typedoc.json @@ -16,6 +16,7 @@ ], "excludeInternal": true, "useTsLinkResolution": true, + "plugin": "typedoc-plugin-markdown", "out": "docs/api_docs", "readme": "./README.en.md" } \ No newline at end of file diff --git a/ets2panda/linter/homecheck/src/Index.ts b/ets2panda/linter/homecheck/src/Index.ts index 6ad78b6bfe..b3228e9bd5 100644 --- a/ets2panda/linter/homecheck/src/Index.ts +++ b/ets2panda/linter/homecheck/src/Index.ts @@ -42,4 +42,4 @@ export { Utils } from './utils/common/Utils'; // tools export { runTool, Tools } from './tools/toolEntry'; -export { MigrationTool } from './tools/migrationTool/MigrationTool'; +export { MigrationTool } from './tools/migrationTool/MigrationTool'; \ No newline at end of file diff --git a/ets2panda/linter/homecheck/src/checker/migration/AppStorageGetCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/AppStorageGetCheck.ts index 693f891412..8e1ef29f16 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/AppStorageGetCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/AppStorageGetCheck.ts @@ -139,7 +139,7 @@ export class AppStorageGetCheck implements BaseChecker { } private getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); diff --git a/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts index b8dcb06db7..ac46794b55 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts @@ -208,7 +208,7 @@ export class CustomBuilderCheck implements BaseChecker { } private getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); @@ -229,7 +229,7 @@ export class CustomBuilderCheck implements BaseChecker { fixPosition.endLine = endPosition.line; fixPosition.endCol = endPosition.col; } - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const sourceFile = AstTreeUtils.getASTNode(arkFile.getName(), arkFile.getCode()); const range = FixUtils.getRangeWithAst(sourceFile, fixPosition); ruleFix.range = range; diff --git a/ets2panda/linter/homecheck/src/checker/migration/InteropAssignCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/InteropAssignCheck.ts index d956fe529c..a17b9064ba 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/InteropAssignCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/InteropAssignCheck.ts @@ -98,7 +98,7 @@ export class InteropAssignCheck implements BaseChecker { callsites.forEach(cs => { let hasTargetArg = false; const invoke = cs.getInvokeExpr()!; - const csMethod = cs.getCfg()?.getDeclaringMethod(); + const csMethod = cs.getCfg().getDeclaringMethod(); invoke.getArgs().forEach(arg => { const argTy = arg.getType(); if (argTy instanceof PrimitiveType || this.isBoxedType(argTy)) { @@ -149,7 +149,7 @@ export class InteropAssignCheck implements BaseChecker { const desc = `${this.metaData.description} (${RULE_ID})`; const severity = this.metaData.severity; const ruleId = this.rule.ruleId; - const filePath = assign.getCfg()?.getDeclaringMethod().getDeclaringArkFile()?.getFilePath() ?? ''; + const filePath = assign.getCfg().getDeclaringMethod().getDeclaringArkFile()?.getFilePath() ?? ''; const defeats = new Defects(line, column, column, problem, desc, severity, ruleId, filePath, '', true, false, false); this.issues.push(new IssueReport(defeats, undefined)); }); @@ -265,8 +265,6 @@ export class InteropAssignCheck implements BaseChecker { } if (file) { return file.getLanguage(); - } else { - logger.error(`fail to identify which file the type definition ${type.toString()} is in.`); } return undefined; } diff --git a/ets2panda/linter/homecheck/src/checker/migration/InteropBackwardDFACheck.ts b/ets2panda/linter/homecheck/src/checker/migration/InteropBackwardDFACheck.ts index 9651894a32..85a045b7f0 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/InteropBackwardDFACheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/InteropBackwardDFACheck.ts @@ -214,7 +214,7 @@ export class InteropBackwardDFACheck implements BaseChecker { private reportIssue(objDefInfo: ObjDefInfo, apiLang: Language, isReflect: boolean) { const problemStmt = objDefInfo.problemStmt; - const problemStmtMtd = problemStmt.getCfg()?.getDeclaringMethod(); + const problemStmtMtd = problemStmt.getCfg().getDeclaringMethod(); const problemStmtLang = problemStmtMtd?.getLanguage(); const objLanguage = objDefInfo.objLanguage; if (objLanguage === Language.UNKNOWN || problemStmtLang === Language.UNKNOWN) { diff --git a/ets2panda/linter/homecheck/src/checker/migration/InteropBoxedTypeCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/InteropBoxedTypeCheck.ts index 42b4dc0973..d0a1c9b10f 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/InteropBoxedTypeCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/InteropBoxedTypeCheck.ts @@ -40,7 +40,7 @@ import { WarnInfo } from '../../utils/common/Utils'; import { Language } from 'arkanalyzer/lib/core/model/ArkFile'; import { getLanguageStr } from './Utils'; -const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'ObservedDecoratorCheck'); +const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'InteropBoxedTypeCheck'); const gMetaData: BaseMetaData = { severity: 1, ruleDocPath: '', diff --git a/ets2panda/linter/homecheck/src/checker/migration/InteropJSModifyPropertyCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/InteropJSModifyPropertyCheck.ts index 3b912361f2..16ea7584bc 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/InteropJSModifyPropertyCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/InteropJSModifyPropertyCheck.ts @@ -276,10 +276,8 @@ export class InteropJSModifyPropertyCheck implements BaseChecker { } if (file) { return file.getLanguage(); - } else { - logger.error(`fail to identify which file the type definition ${type.toString()} is in.`); - return Language.UNKNOWN; } + return Language.UNKNOWN; } private reportIssue(problemStmt: Stmt) { @@ -289,7 +287,7 @@ export class InteropJSModifyPropertyCheck implements BaseChecker { const desc = `${this.metaData.description} (${RULE_ID})`; const severity = this.metaData.severity; const ruleId = this.rule.ruleId; - const filePath = problemStmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile()?.getFilePath() ?? ''; + const filePath = problemStmt.getCfg().getDeclaringMethod().getDeclaringArkFile()?.getFilePath() ?? ''; const defeats = new Defects( line, column, diff --git a/ets2panda/linter/homecheck/src/checker/migration/ModifyStateVarCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/ModifyStateVarCheck.ts index c25cc59611..dfabd40fe0 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/ModifyStateVarCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/ModifyStateVarCheck.ts @@ -171,7 +171,7 @@ export class ModifyStateVarCheck implements BaseChecker { } private getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); diff --git a/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts index f45c63723c..7375978f11 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts @@ -37,6 +37,11 @@ import { BasicBlock, ArkIfStmt, ArkUnopExpr, + RelationalBinaryOperator, + LineColPosition, + UnaryOperator, + ArkNormalBinopExpr, + NormalBinaryOperator, } from 'arkanalyzer/lib'; import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; import { BaseChecker, BaseMetaData } from '../BaseChecker'; @@ -47,6 +52,7 @@ import { CALL_DEPTH_LIMIT, getGlobalsDefineInDefaultMethod, GlobalCallGraphHelpe import { WarnInfo } from '../../utils/common/Utils'; import { ClassCategory } from 'arkanalyzer/lib/core/model/ArkClass'; import { Language } from 'arkanalyzer/lib/core/model/ArkFile'; +import { BooleanConstant } from 'arkanalyzer/lib/core/base/Constant'; const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'NoTSLikeAsCheck'); const gMetaData: BaseMetaData = { @@ -55,6 +61,12 @@ const gMetaData: BaseMetaData = { description: '', }; +enum TypeAssuranceCondition { + Positive, + Negative, + NotExist, +} + export class NoTSLikeAsCheck implements BaseChecker { readonly metaData: BaseMetaData = gMetaData; public rule: Rule; @@ -181,21 +193,19 @@ export class NoTSLikeAsCheck implements BaseChecker { return false; } for (const block of cfg.getBlocks()) { - // 这里仅判断了cast op是否进行了instanceof判断,如果op是由op1赋值,op1进行了instanceof判断,此处不认为是做了有效检查 - // TODO: 还需进行复杂条件中包含类型守卫判断的情况,涉及&&,||等的复合 - const positiveCheck = this.isCastExprWithTypeAssurancePositive(block, castExpr); - const negativeCheck = this.isCastExprWithTypeAssuranceNegative(block, castExpr); - if (!(positiveCheck || negativeCheck)) { + // 这里仅判断了cast op是否进行了instanceof判断,如果op是由op1赋值,op1进行了instanceof判断,此处不认为是做了有效检查,因为此赋值链可能很长且中途发生类型变化,极易判断错误 + const checkRes = this.checkTypeAssuranceInBasicBlock(block, castExpr); + if (checkRes === TypeAssuranceCondition.NotExist) { continue; } let checkedBB: Set = new Set(); let needCheckBB: number[] = []; checkedBB.add(block.getId()); const allSuccessors = block.getSuccessors(); - if (allSuccessors.length > 0 && positiveCheck) { + if (allSuccessors.length > 0 && checkRes === TypeAssuranceCondition.Positive) { needCheckBB.push(allSuccessors[0].getId()); } - if (allSuccessors.length > 1 && negativeCheck) { + if (allSuccessors.length > 1 && checkRes === TypeAssuranceCondition.Negative) { needCheckBB.push(allSuccessors[1].getId()); } while (needCheckBB.length > 0) { @@ -221,26 +231,7 @@ export class NoTSLikeAsCheck implements BaseChecker { return false; } - private isStmtInBlock(stmt: Stmt, block: BasicBlock): boolean { - for (const s of block.getStmts()) { - if (s === stmt) { - return true; - } - } - return false; - } - - private getBlockWithId(id: number, cfg: Cfg): BasicBlock | null { - const blocks = cfg.getBlocks(); - for (const bb of blocks) { - if (bb.getId() === id) { - return bb; - } - } - return null; - } - - private isCastExprWithTypeAssurancePositive(bb: BasicBlock, castExpr: ArkCastExpr): boolean { + private checkTypeAssuranceInBasicBlock(bb: BasicBlock, castExpr: ArkCastExpr): TypeAssuranceCondition { for (const stmt of bb.getStmts()) { if (!(stmt instanceof ArkIfStmt)) { continue; @@ -248,98 +239,109 @@ export class NoTSLikeAsCheck implements BaseChecker { const conditionExpr = stmt.getConditionExpr(); const op1 = conditionExpr.getOp1(); const op2 = conditionExpr.getOp2(); - if (op1 instanceof Local) { - const declareStmt = op1.getDeclaringStmt(); - if (declareStmt !== null && this.isStmtWithTypeAssurancePositive(declareStmt, castExpr)) { - return true; - } - } - if (op2 instanceof Local) { - const declareStmt = op2.getDeclaringStmt(); - if (declareStmt !== null && this.isStmtWithTypeAssurancePositive(declareStmt, castExpr)) { - return true; - } + const operator = conditionExpr.getOperator(); + // 对于if (i instanceof A)这种条件语句,op1总是临时变量,op2总是false,操作符总是!= + if (!(op1 instanceof Local && op2 instanceof BooleanConstant && op2.getValue() === 'false' && operator === RelationalBinaryOperator.InEquality)) { + break; } + return this.checkTypeAssuranceWithLocal(op1, castExpr, stmt.getOriginPositionInfo(), true); } - return false; + return TypeAssuranceCondition.NotExist; } - private isCastExprWithTypeAssuranceNegative(bb: BasicBlock, castExpr: ArkCastExpr): boolean { - for (const stmt of bb.getStmts()) { - if (!(stmt instanceof ArkIfStmt)) { - continue; + private checkTypeAssuranceWithLocal(operand: Local, castExpr: ArkCastExpr, ifStmtPos: LineColPosition, shouldBe: boolean): TypeAssuranceCondition { + const declaringStmt = operand.getDeclaringStmt(); + if (declaringStmt === null) { + return TypeAssuranceCondition.NotExist; + } + // if语句中的所有条件遵从三地址码原则拆分成多个语句时,所有语句的位置信息是一致的,不一致时表示是条件语句之前的赋值或声明情况,不在本判断范围内 + const stmtPos = declaringStmt.getOriginPositionInfo(); + if (stmtPos.getLineNo() !== ifStmtPos.getLineNo() || stmtPos.getColNo() !== ifStmtPos.getColNo()) { + return TypeAssuranceCondition.NotExist; + } + if (!(declaringStmt instanceof ArkAssignStmt)) { + return TypeAssuranceCondition.NotExist; + } + const rightOp = declaringStmt.getRightOp(); + if (rightOp instanceof ArkInstanceOfExpr) { + if (this.isTypeAssuranceMatchCast(rightOp, castExpr)) { + if (shouldBe) { + return TypeAssuranceCondition.Positive; + } else { + return TypeAssuranceCondition.Negative; + } } - const conditionExpr = stmt.getConditionExpr(); - const op1 = conditionExpr.getOp1(); - const op2 = conditionExpr.getOp2(); - if (op1 instanceof Local) { - const declareStmt = op1.getDeclaringStmt(); - if (declareStmt !== null && this.isStmtWithTypeAssuranceNegative(declareStmt, castExpr)) { - return true; + return TypeAssuranceCondition.NotExist; + } + if (rightOp instanceof ArkUnopExpr && rightOp.getOperator() === UnaryOperator.LogicalNot) { + const unaryOp = rightOp.getOp(); + if (unaryOp instanceof Local) { + return this.checkTypeAssuranceWithLocal(unaryOp, castExpr, ifStmtPos, !shouldBe); + } + return TypeAssuranceCondition.NotExist; + } + if (rightOp instanceof ArkNormalBinopExpr) { + const op1 = rightOp.getOp1(); + const op2 = rightOp.getOp2(); + const operator = rightOp.getOperator(); + // 这里仅判断&&和||两种逻辑运算符的场景,其他场景在包含类型守卫判断的条件语句中不常见,暂不考虑 + let res: TypeAssuranceCondition; + if (operator === NormalBinaryOperator.LogicalAnd) { + if (op1 instanceof Local) { + res = this.checkTypeAssuranceWithLocal(op1, castExpr, ifStmtPos, shouldBe); + if (res !== TypeAssuranceCondition.NotExist) { + return res; + } } + if (op2 instanceof Local) { + res = this.checkTypeAssuranceWithLocal(op2, castExpr, ifStmtPos, shouldBe); + if (res !== TypeAssuranceCondition.NotExist) { + return res; + } + } + return TypeAssuranceCondition.NotExist; } - if (op2 instanceof Local) { - const declareStmt = op2.getDeclaringStmt(); - if (declareStmt !== null && this.isStmtWithTypeAssuranceNegative(declareStmt, castExpr)) { - return true; + if (operator === NormalBinaryOperator.LogicalOr) { + // a or b,不论a或b里是类型守卫判断,均无法保证分支中的类型明确 + if (shouldBe) { + return TypeAssuranceCondition.NotExist; } } } - return false; + return TypeAssuranceCondition.NotExist; } - private isStmtWithTypeAssurancePositive(declareStmt: Stmt, castExpr: ArkCastExpr): boolean { - if (!(declareStmt instanceof ArkAssignStmt)) { - return false; - } - const rightOp = declareStmt.getRightOp(); - if (!(rightOp instanceof ArkInstanceOfExpr)) { - return false; - } + private isTypeAssuranceMatchCast(instanceOfExpr: ArkInstanceOfExpr, castExpr: ArkCastExpr): boolean { const castOp = castExpr.getOp(); const castType = castExpr.getType(); - const instanceofType = rightOp.getCheckType(); + const instanceofType = instanceOfExpr.getCheckType(); if (castType.getTypeString() !== instanceofType.getTypeString()) { return false; } - const instanceofOp = rightOp.getOp(); + const instanceofOp = instanceOfExpr.getOp(); if (!(castOp instanceof Local && instanceofOp instanceof Local)) { return false; } return castOp.getName() === instanceofOp.getName(); } - private isStmtWithTypeAssuranceNegative(declareStmt: Stmt, castExpr: ArkCastExpr): boolean { - if (!(declareStmt instanceof ArkAssignStmt)) { - return false; - } - const rightOp = declareStmt.getRightOp(); - if (!(rightOp instanceof ArkUnopExpr && rightOp.getOperator() === '!')) { - return false; - } - const unaryOp = rightOp.getOp(); - if (!(unaryOp instanceof Local)) { - return false; - } - const unaryOpDeclareStmt = unaryOp.getDeclaringStmt(); - if (unaryOpDeclareStmt === null || !(unaryOpDeclareStmt instanceof ArkAssignStmt)) { - return false; - } - const unaryOpRightOp = unaryOpDeclareStmt.getRightOp(); - if (!(unaryOpRightOp instanceof ArkInstanceOfExpr)) { - return false; - } - const castOp = castExpr.getOp(); - const castType = castExpr.getType(); - const instanceofType = unaryOpRightOp.getCheckType(); - if (castType.getTypeString() !== instanceofType.getTypeString()) { - return false; + private isStmtInBlock(stmt: Stmt, block: BasicBlock): boolean { + for (const s of block.getStmts()) { + if (s === stmt) { + return true; + } } - const instanceofOp = unaryOpRightOp.getOp(); - if (!(castOp instanceof Local && instanceofOp instanceof Local)) { - return false; + return false; + } + + private getBlockWithId(id: number, cfg: Cfg): BasicBlock | null { + const blocks = cfg.getBlocks(); + for (const bb of blocks) { + if (bb.getId() === id) { + return bb; + } } - return castOp.getName() === instanceofOp.getName(); + return null; } private checkFromStmt( @@ -401,9 +403,7 @@ export class NoTSLikeAsCheck implements BaseChecker { const paramRef = this.isFromParameter(currentStmt); if (paramRef) { const paramIdx = paramRef.getIndex(); - const callsites = this.cg.getInvokeStmtByMethod( - currentStmt.getCfg().getDeclaringMethod().getSignature() - ); + const callsites = this.cg.getInvokeStmtByMethod(currentStmt.getCfg().getDeclaringMethod().getSignature()); this.processCallsites(callsites); const argDefs = this.collectArgDefs(paramIdx, callsites); for (const stmt of argDefs) { @@ -568,7 +568,7 @@ export class NoTSLikeAsCheck implements BaseChecker { } private getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); diff --git a/ets2panda/linter/homecheck/src/checker/migration/ObjectLiteralCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/ObjectLiteralCheck.ts index 66a5c66380..b582c90aaf 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/ObjectLiteralCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/ObjectLiteralCheck.ts @@ -68,7 +68,7 @@ export class ObjectLiteralCheck implements BaseChecker { for (let arkFile of scene.getFiles()) { const topLevelVarMap: Map = new Map(); - this.collectImportedVar(topLevelVarMap, arkFile); + this.collectImportedVar(topLevelVarMap, arkFile, scene); this.collectTopLevelVar(topLevelVarMap, arkFile, scene); const handleClass = (cls: ArkClass): void => { @@ -106,7 +106,7 @@ export class ObjectLiteralCheck implements BaseChecker { } } - private collectImportedVar(importVarMap: Map, file: ArkFile) { + private collectImportedVar(importVarMap: Map, file: ArkFile, scene: Scene) { file.getImportInfos().forEach(importInfo => { const exportInfo = importInfo.getLazyExportInfo(); if (exportInfo === null) { @@ -120,6 +120,7 @@ export class ObjectLiteralCheck implements BaseChecker { if (!declaringStmt) { return; } + DVFGHelper.buildSingleDVFG(declaringStmt.getCfg().getDeclaringMethod(), scene); importVarMap.set(arkExport.getName(), [declaringStmt]); }); } @@ -382,7 +383,7 @@ export class ObjectLiteralCheck implements BaseChecker { } private getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); diff --git a/ets2panda/linter/homecheck/src/checker/migration/ObservedDecoratorCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/ObservedDecoratorCheck.ts index a6a56e9b4d..8f9c5cdb03 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/ObservedDecoratorCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/ObservedDecoratorCheck.ts @@ -266,7 +266,7 @@ export class ObservedDecoratorCheck implements BaseChecker { canFindAllTargets: boolean = true ): string { if (issueClass === null || !canFindAllTargets) { - return `can not find all classes, please check this field manually`; + return `can not find all classes, please check this field manually (arkui-data-observation)`; } const fieldLine = field.getOriginPosition().getLineNo(); const fieldColumn = field.getOriginPosition().getColNo(); @@ -275,10 +275,10 @@ export class ObservedDecoratorCheck implements BaseChecker { const issueClassSig = issueClass.getDeclaringArkFile().getFileSignature(); let res = `but it's not be annotated by @Observed (arkui-data-observation)`; if (fileSignatureCompare(fieldFileSig, issueClassSig)) { - res = `The class is used by state property in [${fieldLine}, ${fieldColumn}], ` + res; + res = `Class ${issueClass.getName()} is used by state property in [${fieldLine}, ${fieldColumn}], ` + res; } else { const filePath = path.normalize(fieldFileSig.getFileName()); - res = `The class is used by state property in file ${filePath} [${fieldLine}, ${fieldColumn}], ` + res; + res = `Class ${issueClass.getName()} is used by state property in file ${filePath} [${fieldLine}, ${fieldColumn}], ` + res; } return res; } diff --git a/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts index af8657687c..b290beab8f 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/ThisBindCheck.ts @@ -348,7 +348,7 @@ export class ThisBindCheck implements BaseChecker { } private getLineAndColumn(stmt: ArkAssignStmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); diff --git a/ets2panda/linter/homecheck/src/checker/migration/Utils.ts b/ets2panda/linter/homecheck/src/checker/migration/Utils.ts index 0992bcbe88..02f114bd0f 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/Utils.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/Utils.ts @@ -13,7 +13,18 @@ * limitations under the License. */ -import { ArkAssignStmt, ArkMethod, CallGraph, CallGraphBuilder, Local, LOG_MODULE_TYPE, Logger, Scene, Stmt, Value } from 'arkanalyzer/lib'; +import { + ArkAssignStmt, + ArkMethod, + CallGraph, + CallGraphBuilder, + Local, + LOG_MODULE_TYPE, + Logger, + Scene, + Stmt, + Value, +} from 'arkanalyzer/lib'; import { WarnInfo } from '../../utils/common/Utils'; import { Language } from 'arkanalyzer/lib/core/model/ArkFile'; import { DVFG, DVFGNode } from 'arkanalyzer/lib/VFG/DVFG'; @@ -25,6 +36,10 @@ export const CALL_DEPTH_LIMIT = 2; export class CallGraphHelper { private static cgInstance: CallGraph | null = null; + public static dispose(): void { + this.cgInstance = null; + } + public static getCGInstance(scene: Scene): CallGraph { if (!this.cgInstance) { this.cgInstance = new CallGraph(scene); @@ -36,6 +51,10 @@ export class CallGraphHelper { export class GlobalCallGraphHelper { private static cgInstance: CallGraph | null = null; + public static dispose(): void { + this.cgInstance = null; + } + public static getCGInstance(scene: Scene): CallGraph { if (!this.cgInstance) { this.cgInstance = new CallGraph(scene); @@ -51,6 +70,14 @@ export class DVFGHelper { private static dvfgBuilder: DVFGBuilder; private static built: Set = new Set(); + public static dispose(): void { + // @ts-ignore + this.dvfgInstance = null; + // @ts-ignore + this.dvfgBuilder = null; + this.built.clear(); + } + private static createDVFGInstance(scene: Scene): void { if (!this.dvfgInstance) { this.dvfgInstance = new DVFG(GlobalCallGraphHelper.getCGInstance(scene)); @@ -117,7 +144,7 @@ export function getLanguageStr(language: Language): string { } export function getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { - const arkFile = stmt.getCfg()?.getDeclaringMethod().getDeclaringArkFile(); + const arkFile = stmt.getCfg().getDeclaringMethod().getDeclaringArkFile(); const originPosition = stmt.getOperandOriginalPosition(operand); if (arkFile && originPosition) { const originPath = arkFile.getFilePath(); @@ -126,7 +153,7 @@ export function getLineAndColumn(stmt: Stmt, operand: Value): WarnInfo { const endCol = startCol; return { line, startCol, endCol, filePath: originPath }; } else { - logger.debug('ArkFile is null.'); + logger.debug('ArkFile or operand position is null.'); } return { line: -1, startCol: -1, endCol: -1, filePath: '' }; } diff --git a/ets2panda/linter/homecheck/src/tools/migrationTool/MigrationTool.ts b/ets2panda/linter/homecheck/src/tools/migrationTool/MigrationTool.ts index 5c3f6478ed..7be52a159a 100644 --- a/ets2panda/linter/homecheck/src/tools/migrationTool/MigrationTool.ts +++ b/ets2panda/linter/homecheck/src/tools/migrationTool/MigrationTool.ts @@ -21,7 +21,8 @@ import { CheckerStorage } from '../../utils/common/CheckerStorage'; import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; import { FileUtils } from '../../utils/common/FileUtils'; import { DefaultMessage } from '../../model/Message'; -import { FileIssues } from "../../model/Defects"; +import { FileIssues } from '../../model/Defects'; +import { CallGraphHelper, DVFGHelper, GlobalCallGraphHelper } from '../../checker/migration/Utils'; const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'MigrationTool'); @@ -68,7 +69,16 @@ export class MigrationTool { await this.checkEntry.runAll(); let result = this.checkEntry.sortIssues(); + this.dispose(); logger.info(`MigrationTool run end`); return result; } + + private dispose(): void { + CallGraphHelper.dispose(); + GlobalCallGraphHelper.dispose(); + DVFGHelper.dispose(); + CheckerStorage.dispose(); + this.checkEntry.scene.dispose(); + } } \ No newline at end of file diff --git a/ets2panda/linter/homecheck/src/utils/common/CheckerStorage.ts b/ets2panda/linter/homecheck/src/utils/common/CheckerStorage.ts index f3bedd5017..922b716e95 100644 --- a/ets2panda/linter/homecheck/src/utils/common/CheckerStorage.ts +++ b/ets2panda/linter/homecheck/src/utils/common/CheckerStorage.ts @@ -21,6 +21,11 @@ export class CheckerStorage { private apiVersion: number = 16; private product: string = ''; + public static dispose(): void { + // @ts-ignore + this.instance = null; + } + /** * 获取 CheckerStorage 的单例实例 * @returns {CheckerStorage} CheckerStorage 的单例实例 diff --git a/ets2panda/linter/homecheck/src/utils/common/FileUtils.ts b/ets2panda/linter/homecheck/src/utils/common/FileUtils.ts index 48b06a414d..f17425f284 100644 --- a/ets2panda/linter/homecheck/src/utils/common/FileUtils.ts +++ b/ets2panda/linter/homecheck/src/utils/common/FileUtils.ts @@ -232,7 +232,7 @@ export class FileUtils { } private static shouldSkipFile(fileName: string): boolean { - return ['oh_modules', 'node_modules', 'hvigorfile.ts', 'ohosTest'].includes(fileName); + return ['oh_modules', 'node_modules', 'hvigorfile.ts', 'hvigorfile.js', 'hvigor-wrapper.js', 'ohosTest'].includes(fileName); } private static shouldAddFile(filePath: string, exts: string[]): boolean { @@ -310,4 +310,4 @@ export class FileUtils { export enum WriteFileMode { OVERWRITE, APPEND -} \ No newline at end of file +} diff --git a/ets2panda/linter/src/cli/LinterCLI.ts b/ets2panda/linter/src/cli/LinterCLI.ts index 45bd9fddcd..b7c4dc169c 100644 --- a/ets2panda/linter/src/cli/LinterCLI.ts +++ b/ets2panda/linter/src/cli/LinterCLI.ts @@ -58,9 +58,10 @@ async function runIdeInteractiveMode(cmdOptions: CommandLineOptions): Promise Date: Tue, 10 Jun 2025 10:01:14 +0800 Subject: [PATCH 070/747] Update Kfl 0609 Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDVLQ Signed-off-by: chenlong --- test262/ignored-test262-fastverify-x64-aot-pgo.txt | 3 +++ test262/ignored-test262-other-fastverify-qemu-int.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test262/ignored-test262-fastverify-x64-aot-pgo.txt b/test262/ignored-test262-fastverify-x64-aot-pgo.txt index 3850582fdc..7a848c57ea 100644 --- a/test262/ignored-test262-fastverify-x64-aot-pgo.txt +++ b/test262/ignored-test262-fastverify-x64-aot-pgo.txt @@ -1 +1,4 @@ # Known failure list for test262 - fastverify-x64-aot-pgo + +#19208 +test262/data/test_es2021/language/module-code/instn-iee-err-circular-as.js \ No newline at end of file diff --git a/test262/ignored-test262-other-fastverify-qemu-int.txt b/test262/ignored-test262-other-fastverify-qemu-int.txt index c3f6889c84..4c0ee96b91 100644 --- a/test262/ignored-test262-other-fastverify-qemu-int.txt +++ b/test262/ignored-test262-other-fastverify-qemu-int.txt @@ -57,3 +57,6 @@ test262/data/other_tests/built-ins/Date/prototype/setSeconds/this-value-invalid- #21819 test262/data/other_tests/built-ins/parseFloat/S15.1.2.3_A6.js test262/data/other_tests/built-ins/parseInt/S15.1.2.2_A8.js + +#25907 +test262/data/other_tests/language/expressions/class/elements/syntax/valid/grammar-privatename-classelementname-initializer-alt.js -- Gitee From 75d5646fbe0258f39a691cc18faa202c5bfeb643 Mon Sep 17 00:00:00 2001 From: Tamas Toth Date: Tue, 3 Jun 2025 12:55:24 +0200 Subject: [PATCH 071/747] Throw error when setter return type is void Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCAJQ Fixes #25831 internal issue Change-Id: I185d3df441f95b639d335c198d12b6b6f4ec1ebf Signed-off-by: Tamas Toth --- ets2panda/parser/ETSparserClasses.cpp | 5 ++++ .../parser/ets/setter_with_return_type.ets | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 ets2panda/test/ast/parser/ets/setter_with_return_type.ets diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 0876670671..f85dfa2b20 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -833,6 +833,11 @@ ir::MethodDefinition *ETSParser::ParseInterfaceGetterSetterMethod(const ir::Modi method->Function()->SetIdent(method->Id()->Clone(Allocator(), nullptr)); method->Function()->AddModifier(method->Modifiers()); + bool hasReturn = method->Function()->ReturnTypeAnnotation() != nullptr; + if (hasReturn && methodKind == ir::MethodDefinitionKind::SET) { + LogError(diagnostic::SETTER_NO_RETURN_TYPE, {}, method->Function()->Range().start); + } + return method; } diff --git a/ets2panda/test/ast/parser/ets/setter_with_return_type.ets b/ets2panda/test/ast/parser/ets/setter_with_return_type.ets new file mode 100644 index 0000000000..6764147803 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/setter_with_return_type.ets @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class C{ + n: number = 42 +} + +interface I{ + get n(): number + set n(v:number):void +} + +class D extends C implements I{ +} + +/* @@? 22:10 Error SyntaxError: Setter must not have return type even if it is void. */ -- Gitee From 94d13a1465eaa3f9920dd74be19eecf243de4dba Mon Sep 17 00:00:00 2001 From: Shimenkov Mikhail Date: Fri, 14 Feb 2025 19:20:50 +0300 Subject: [PATCH 072/747] Remove primitive types Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/IBZQDX Reason: Need a more consistent type system Description: Remove primitive types from user-visible language (boxed types remain). Primitive types are reintroduced in a lowering at the end of the pipeline, just before code generation. Tests: all the tests are passed Signed-off-by: Georgy Bronnikov Signed-off-by: Shimenkov Mikhail Signed-off-by: Lirisman Karina Signed-off-by: Ermolaeva Varvara Signed-off-by: Kaskov Mikhail Signed-off-by: Kofanov Daniil Signed-off-by: Zelentsov Dmitry Signed-off-by: Xu Xinjie Signed-off-by: Afanasyev Vadim Signed-off-by: Kopyl Vasily Signed-off-by: Sergey Andreev Signed-off-by: Artemyev Andrey Signed-off-by: Khramov Maxim Signed-off-by: Akmaev Aleksey Signed-off-by: nikozer Change-Id: Icfba321cd153d8b7f3d3e9f379c99b20ef47f625 Signed-off-by: Zelentsov Dmitry --- ets2panda/BUILD.gn | 6 +- ets2panda/CMakeLists.txt | 6 +- ets2panda/ast_verifier/helpers.cpp | 6 +- ets2panda/checker/ETSAnalyzer.cpp | 430 +- ets2panda/checker/ETSAnalyzer.h | 1 - ets2panda/checker/ETSAnalyzerHelpers.cpp | 87 +- ets2panda/checker/ETSAnalyzerHelpers.h | 12 +- ets2panda/checker/ETSchecker.cpp | 26 +- ets2panda/checker/ETSchecker.h | 73 +- ets2panda/checker/ets/aliveAnalyzer.cpp | 7 +- ets2panda/checker/ets/arithmetic.cpp | 803 ++- ets2panda/checker/ets/arithmetic.h | 215 +- ets2panda/checker/ets/assignAnalyzer.cpp | 5 +- ets2panda/checker/ets/castingContext.cpp | 10 +- ets2panda/checker/ets/conversion.cpp | 49 - ets2panda/checker/ets/conversion.h | 4 - ets2panda/checker/ets/etsWarningAnalyzer.cpp | 153 - ets2panda/checker/ets/etsWarningAnalyzer.h | 8 - ets2panda/checker/ets/function.cpp | 259 +- ets2panda/checker/ets/helpers.cpp | 271 +- ets2panda/checker/ets/narrowingConverter.h | 201 - ets2panda/checker/ets/object.cpp | 155 +- ets2panda/checker/ets/typeCheckingHelpers.cpp | 190 +- ets2panda/checker/ets/typeCreation.cpp | 26 - ets2panda/checker/ets/typeRelationContext.cpp | 20 +- ets2panda/checker/ets/typeRelationContext.h | 13 +- ets2panda/checker/ets/validateHelpers.cpp | 15 - ets2panda/checker/ets/wideningConverter.h | 109 +- ets2panda/checker/types/ets/byteType.cpp | 48 +- ets2panda/checker/types/ets/byteType.h | 7 +- ets2panda/checker/types/ets/charType.cpp | 42 +- ets2panda/checker/types/ets/charType.h | 7 +- ets2panda/checker/types/ets/doubleType.cpp | 36 +- ets2panda/checker/types/ets/doubleType.h | 8 +- ets2panda/checker/types/ets/etsAnyType.cpp | 4 +- ets2panda/checker/types/ets/etsAnyType.h | 5 - ets2panda/checker/types/ets/etsArrayType.cpp | 2 +- ets2panda/checker/types/ets/etsArrayType.h | 5 - .../types/ets/etsAsyncFuncReturnType.cpp | 12 +- .../types/ets/etsAsyncFuncReturnType.h | 1 + .../checker/types/ets/etsBooleanType.cpp | 11 +- ets2panda/checker/types/ets/etsBooleanType.h | 7 +- .../checker/types/ets/etsDynamicType.cpp | 2 +- ets2panda/checker/types/ets/etsDynamicType.h | 2 +- ets2panda/checker/types/ets/etsEnumType.cpp | 9 +- ets2panda/checker/types/ets/etsEnumType.h | 98 +- .../checker/types/ets/etsFunctionType.cpp | 18 +- ets2panda/checker/types/ets/etsFunctionType.h | 5 - ets2panda/checker/types/ets/etsNeverType.h | 7 +- ets2panda/checker/types/ets/etsNullishTypes.h | 12 +- ets2panda/checker/types/ets/etsObjectType.cpp | 171 +- ets2panda/checker/types/ets/etsObjectType.h | 27 +- .../types/ets/etsObjectTypeConstants.h | 18 +- .../types/ets/etsResizableArrayType.cpp | 15 +- .../checker/types/ets/etsResizableArrayType.h | 4 +- ets2panda/checker/types/ets/etsStringType.cpp | 1 - ets2panda/checker/types/ets/etsStringType.h | 5 - ets2panda/checker/types/ets/etsTupleType.cpp | 4 +- ets2panda/checker/types/ets/etsTupleType.h | 5 - .../checker/types/ets/etsTypeAliasType.h | 5 - ets2panda/checker/types/ets/etsUnionType.cpp | 506 +- ets2panda/checker/types/ets/etsUnionType.h | 53 +- ets2panda/checker/types/ets/etsVoidType.cpp | 7 +- ets2panda/checker/types/ets/etsVoidType.h | 3 +- ets2panda/checker/types/ets/floatType.cpp | 44 +- ets2panda/checker/types/ets/floatType.h | 8 +- ets2panda/checker/types/ets/intType.cpp | 42 +- ets2panda/checker/types/ets/intType.h | 7 +- ets2panda/checker/types/ets/longType.cpp | 44 +- ets2panda/checker/types/ets/longType.h | 7 +- ets2panda/checker/types/ets/shortType.cpp | 44 +- ets2panda/checker/types/ets/shortType.h | 7 +- ets2panda/checker/types/ets/types.h | 1 + ets2panda/checker/types/globalTypesHolder.cpp | 6 + ets2panda/checker/types/globalTypesHolder.h | 4 +- ets2panda/checker/types/signature.h | 6 + ets2panda/checker/types/type.cpp | 35 +- ets2panda/checker/types/type.h | 24 +- ets2panda/checker/types/typeRelation.cpp | 40 +- ets2panda/checker/types/typeRelation.h | 13 +- ets2panda/compiler/base/condition.cpp | 1 + ets2panda/compiler/base/lreference.cpp | 14 +- ets2panda/compiler/core/ETSCompiler.cpp | 162 +- ets2panda/compiler/core/ETSCompiler.h | 5 +- .../compiler/core/ETSCompilerUnrechable.cpp | 5 - ets2panda/compiler/core/ETSGen.cpp | 235 +- ets2panda/compiler/core/ETSGen.h | 10 +- ets2panda/compiler/core/ETSemitter.cpp | 251 +- ets2panda/compiler/core/ETSemitter.h | 3 - ets2panda/compiler/core/compilerImpl.cpp | 21 +- ets2panda/compiler/lowering/checkerPhase.h | 2 +- .../lowering/ets/arrayLiteralLowering.cpp | 28 +- .../lowering/ets/asyncMethodLowering.cpp | 1 + .../lowering/ets/boxedTypeLowering.cpp | 90 - .../compiler/lowering/ets/boxingForLocals.cpp | 19 +- .../ets/constantExpressionLowering.cpp | 1549 +++-- .../lowering/ets/constantExpressionLowering.h | 75 +- .../ets/convertPrimitiveCastMethodCall.cpp | 1 - .../compiler/lowering/ets/enumLowering.cpp | 30 +- .../compiler/lowering/ets/enumLowering.h | 23 +- .../lowering/ets/enumPostCheckLowering.cpp | 43 +- .../lowering/ets/enumPostCheckLowering.h | 2 +- .../enumPropertiesInAnnotationsLowering.cpp | 84 + .../enumPropertiesInAnnotationsLowering.h} | 30 +- .../compiler/lowering/ets/expandBrackets.cpp | 17 +- .../ets/extensionAccessorLowering.cpp | 2 - .../lowering/ets/genericBridgesLowering.cpp | 18 +- .../lowering/ets/genericBridgesLowering.h | 2 +- .../ets/interfacePropertyDeclarations.cpp | 1 + .../compiler/lowering/ets/lambdaLowering.cpp | 35 +- .../lowering/ets/objectIndexAccess.cpp | 3 - .../compiler/lowering/ets/opAssignment.cpp | 131 +- .../compiler/lowering/ets/opAssignment.h | 5 +- .../lowering/ets/primitiveConversionPhase.cpp | 117 + .../lowering/ets/primitiveConversionPhase.h | 36 + .../compiler/lowering/ets/recordLowering.cpp | 29 +- .../compiler/lowering/ets/recordLowering.h | 4 +- .../lowering/ets/resizableArrayLowering.cpp | 23 +- .../lowering/ets/restArgsLowering.cpp | 23 +- .../compiler/lowering/ets/spreadLowering.cpp | 5 +- .../lowering/ets/stringComparison.cpp | 2 +- .../lowering/ets/stringConstructorLowering.h | 4 +- .../ets/topLevelStmts/globalClassHandler.cpp | 122 +- .../ets/topLevelStmts/globalClassHandler.h | 41 +- .../ets/topLevelStmts/topLevelStmts.cpp | 4 +- .../compiler/lowering/ets/unboxLowering.cpp | 1559 +++++ .../{boxedTypeLowering.h => unboxLowering.h} | 15 +- .../compiler/lowering/ets/unionLowering.cpp | 64 - ets2panda/compiler/lowering/phase.cpp | 9 +- .../lowering/scopesInit/scopesInitPhase.cpp | 2 +- ets2panda/compiler/lowering/util.cpp | 9 + ets2panda/compiler/lowering/util.h | 4 + ets2panda/compiler/scripts/signatures.yaml | 21 + ets2panda/compiler/templates/signatures.h.erb | 11 + .../methodBuilder.cpp | 3 +- ets2panda/evaluate/irCheckHelper.cpp | 10 +- ets2panda/ir/astNode.cpp | 37 +- ets2panda/ir/astNode.h | 8 +- ets2panda/ir/astNodeFlags.h | 28 - ets2panda/ir/base/classDefinition.h | 6 +- .../ir/ets/etsNewArrayInstanceExpression.cpp | 3 +- .../ir/ets/etsNewArrayInstanceExpression.h | 16 - .../etsNewMultiDimArrayInstanceExpression.cpp | 3 +- .../etsNewMultiDimArrayInstanceExpression.h | 16 - ets2panda/ir/ets/etsPrimitiveType.cpp | 16 +- ets2panda/ir/ets/etsTuple.cpp | 6 +- ets2panda/ir/expressions/arrayExpression.cpp | 29 +- ets2panda/ir/expressions/arrayExpression.h | 18 +- ets2panda/ir/expressions/binaryExpression.h | 3 - ets2panda/ir/expressions/identifier.cpp | 3 +- ets2panda/ir/expressions/literal.h | 13 + .../ir/expressions/literals/bigIntLiteral.cpp | 1 + .../expressions/literals/booleanLiteral.cpp | 1 + .../ir/expressions/literals/charLiteral.cpp | 18 +- .../ir/expressions/literals/nullLiteral.cpp | 1 + .../ir/expressions/literals/numberLiteral.cpp | 19 + .../ir/expressions/literals/numberLiteral.h | 1 - .../ir/expressions/literals/regExpLiteral.cpp | 1 + .../ir/expressions/literals/stringLiteral.cpp | 1 + .../expressions/literals/undefinedLiteral.cpp | 1 + ets2panda/ir/expressions/memberExpression.cpp | 48 +- ets2panda/ir/expressions/objectExpression.cpp | 2 +- ets2panda/ir/expressions/objectExpression.h | 13 +- ets2panda/ir/expressions/unaryExpression.h | 7 +- ets2panda/ir/srcDump.cpp | 12 +- ets2panda/ir/srcDump.h | 2 + ets2panda/ir/statements/annotationUsage.cpp | 2 +- ets2panda/ir/statements/forOfStatement.cpp | 7 +- ets2panda/ir/statements/ifStatement.h | 5 + ets2panda/ir/statements/returnStatement.cpp | 1 - .../ir/statements/switchCaseStatement.cpp | 2 +- ets2panda/ir/statements/whileStatement.h | 5 + ets2panda/ir/typed.h | 12 + ets2panda/lexer/lexer.h | 1 + ets2panda/lexer/token/number.h | 119 +- ets2panda/lsp/src/isolated_declaration.cpp | 3 +- ets2panda/parser/ETSparserExpressions.cpp | 23 +- ets2panda/public/es2panda_lib.cpp | 4 +- .../public/headers_parser/supported_types.py | 1 - ets2panda/public/public.h | 2 +- ets2panda/scripts/arkui.properties | 2 +- .../ast/compiler/ets/DeclareCheckAssign.ets | 3 +- .../annotationDecl_bad_initializer08.ets | 8 +- .../annotationUsage_bad_param09.ets | 8 +- .../ets/FixedArray/lambda_type_mismatch.ets | 6 +- ..._specific_method_with_empty_rest_param.ets | 2 +- .../same_assembly_overload/callExpr_pos.ets | 1 - .../overload_signature_pos_2.ets | 5 +- .../FixedArray/spreadMultiArrayInTuple.ets | 29 + .../ets/FixedArray/unionCommonMember_neg.ets | 3 +- .../test/ast/compiler/ets/FunctionType10.ets | 2 +- .../test/ast/compiler/ets/FunctionType3.ets | 2 +- .../ets/TypeError_recursive_parameter_1.ets | 2 +- .../ets/TypeError_recursive_parameter_2.ets | 2 +- .../Retension_invalid_params.ets | 1 + .../annotationDecl_bad_initializer08.ets | 8 +- .../annotationUsage_as_type10.ets | 2 +- .../annotationUsage_bad_param07.ets | 4 +- .../annotationUsage_bad_param09.ets | 8 +- .../annotationUsage_unordered_params.ets | 4 +- .../annotation_as_negative_case.ets | 6 +- .../test/ast/compiler/ets/assert_bad.ets | 4 +- .../test/ast/compiler/ets/async_import_3.ets | 2 +- .../ets/boxed_primitives_overloading.sts} | 19 +- .../ast/compiler/ets/boxingConversion1.ets | 6 +- .../ast/compiler/ets/boxingConversion4.ets | 11 +- .../cast_NonNullishType_to_PrimitiveType1.ets | 2 - .../cast_NonNullishType_to_PrimitiveType2.ets | 2 - .../cast_NonNullishType_to_PrimitiveType3.ets | 1 - .../cast_TypeParameter_to_PrimitiveType1.ets | 1 - .../cast_TypeParameter_to_PrimitiveType2.ets | 1 - .../cast_TypeParameter_to_PrimitiveType3.ets | 1 - .../ets/cast_UnionType_to_PrimitiveType1.ets | 2 - .../ets/cast_UnionType_to_PrimitiveType2.ets | 1 - .../ets/cast_UnionType_to_PrimitiveType3.ets | 1 - ..._primitives_invoke_context_and_unions.sts} | 26 +- .../compiler/ets/circular_variable_init.ets | 2 +- ...n_call-context_Int-to-Double_typeerror.ets | 4 +- .../ast/compiler/ets/declareType_neg_2.ets | 3 +- .../ast/compiler/ets/division-by-zero.ets} | 15 +- .../compiler/ets/enum-to-int-conversion.ets | 4 +- .../ets/enum_expressions}/constant_char.ets | 2 + .../constant_char_asexpression.ets | 10 + .../enum-initialize-with-enum1.ets | 4 +- .../enum-initialize-with-enum2.ets | 27 + .../ast/compiler/ets/etsObjectToString0.ets | 2 +- .../ast/compiler/ets/etsObjectToString4.ets | 2 +- .../ets/explicit_cast_boxed_expressions.ets | 96 +- ...sorNameDuplicatedWithExtensionFunction.ets | 10 +- ...sionAccessorNameDuplicatedWithFunction.ets | 10 +- ...ension_function_access_protected_field.ets | 2 +- .../extension_function_called_by_class.ets | 10 +- ...function_duplicated_with_private_field.ets | 10 +- .../extension_function_miss_signature.ets | 6 +- .../extension_function_primitive.ets | 2 +- .../extension_function_return_this_neg.ets | 2 +- .../ets/genericObjectLiteral_neg_1.ets | 2 +- .../ets/genericObjectLiteral_neg_2.ets | 2 +- .../ets/genericObjectLiteral_neg_3.ets | 2 +- .../compiler/ets/generic_typealias_5_neg.ets | 2 +- .../generics_primitive_type_param_neg_1.ets | 3 +- .../ast/compiler/ets/greater_than_neg.ets | 8 +- .../compiler/ets/identifierReference10.ets | 2 +- .../compiler/ets/identifierReference12.ets | 2 +- .../compiler/ets/identifierReference16.ets | 2 +- .../ast/compiler/ets/identifierReference3.ets | 2 +- .../ast/compiler/ets/identifierReference9.ets | 2 +- .../package_test_6/package_module_1.ets | 2 +- .../package_test_6/package_module_2.ets | 2 +- .../package_test_9/package_module.ets | 2 +- .../package_module_with_semantic_error.ets | 2 +- .../package_module_with_syntax_error.ets | 2 +- .../package_with_both_errors.ets | 2 +- .../import_chain_with_errors/import_1.ets | 4 +- .../import_chain_with_errors/import_2.ets | 3 +- .../import_chain_with_errors/master_file.ets | 8 +- .../import_in_package_with_error.ets | 2 +- .../package_with_errors_1.ets | 2 +- .../package_with_errors_2.ets | 2 +- .../ets/inferTypeOfArrayNegative3.ets | 3 +- .../ast/compiler/ets/infinityNarrowing.ets | 10 +- .../invalidIndirectInheritanceFromClass.ets | 2 +- ...nvalidIndirectInheritanceFromInterface.ets | 2 +- .../ets/invalidInheritanceFromClass.ets | 2 +- .../ets/invalidInheritanceFromInterface.ets | 2 +- ...tBlockStatementDifferentTypeInfunction.ets | 2 +- .../test/ast/compiler/ets/lambdaFunction5.ets | 2 +- ...on-class-and-interface-in-signatures_6.ets | 4 +- ...ericWithNullableTypeParamToNonNullable.ets | 3 +- ...pace_access_violation_import_conflicts.ets | 2 +- .../namespace_tests/namespace_as_type10.ets | 2 +- .../compiler/ets/null_coalescing_neg_01.ets | 52 + .../ets/objectLiteralPrimitiveContextType.ets | 2 +- .../ets/objectLiteralWrongValueType.ets | 2 +- .../ets/objectLiteral_abstract_class.ets | 2 +- .../test/ast/compiler/ets/override11.ets | 4 +- .../test/ast/compiler/ets/override14.ets | 2 - .../test/ast/compiler/ets/override15.ets | 4 +- ets2panda/test/ast/compiler/ets/override3.ets | 4 +- ets2panda/test/ast/compiler/ets/override7.ets | 4 +- .../ets/overrideModifierNotOverriding.ets | 2 +- .../ets/package_invalid_initializer/P3/P3.ets | 2 +- .../ets/recordWithLambdaFunction2.ets | 4 +- .../ast/compiler/ets/recursive_class_neg.ets | 6 +- .../ets/recursive_interface_neg_1.ets | 2 +- .../ets/recursive_interface_neg_2.ets | 2 +- .../compiler/ets/recursive_union_neg_1.ets | 2 +- .../ets/resolve_func_name_union_type.ets | 1 - .../ets/resolve_func_name_union_type_1.ets | 1 + .../same_assembly_overload/callExpr_pos.ets | 2 +- .../overload_signature_neg_1.ets | 3 +- .../overload_signature_neg_2.ets | 4 +- .../overload_signature_pos_1.ets | 5 +- .../overload_signature_pos_2.ets | 5 +- .../ast/compiler/ets/switchcaseDuplicate.ets | 6 +- .../ast/compiler/ets/tuple_types_10_neg.ets | 2 +- .../ast/compiler/ets/tuple_types_11_neg.ets | 2 +- .../ast/compiler/ets/tuple_types_1_neg.ets | 2 +- .../ast/compiler/ets/tuple_types_6_neg.ets | 3 +- .../ast/compiler/ets/tuple_types_9_neg.ets | 2 +- .../type_error_processing/type_handlers.ets | 3 - .../compiler/ets/unionCommonMember_neg.ets | 15 +- .../ets/unmatch_arg_for_trailing_lambda.ets | 8 +- .../validate_signatures_throw_type_error.ets | 6 +- ...signatures_throw_type_error_more_param.ets | 2 +- .../ets/voidTypeInBinaryOperation.ets | 4 +- .../FunctionalTypeAsArrayElement.ets | 2 +- .../ets/FixedArray/InvalidStatements3.ets | 3 +- .../ets/FixedArray/MultipleParserErrors.ets | 6 +- .../ast/parser/ets/FixedArray/StringFasta.ets | 32 +- .../ast/parser/ets/FixedArray/array_type.ets | 1 - .../ets_never_type_without_affect_other.ets | 5 +- .../ast/parser/ets/FixedArray/for_of_02.ets | 2 +- .../FixedArray/illegal_union_member_exp.ets | 2 + .../parser/ets/FixedArray/invalidTypes.ets | 7 +- .../FixedArray/n_arrayHoldingNullValue.ets | 4 +- .../ets/FixedArray/nonIntegralIndex.ets | 2 +- .../predefined_non_primitive_types.ets | 3 +- .../Readonly-with-ArrayType-test1.ets | 4 +- .../Readonly-with-ArrayType-test4.ets | 2 +- .../ets/FixedArray/record_object_value.ets | 4 +- .../ets/FixedArray/tuple_type_2_neg.ets | 1 - .../ets/FixedArray/unexpected_token_31.ets | 2 +- .../ets/FixedArray/unexpected_token_36.ets | 1 - .../ets/FixedArray/unexpected_token_42.ets | 2 +- .../ets/FixedArray/unexpected_token_47.ets | 2 +- .../ast/parser/ets/InvalidExpressions1.ets | 2 +- .../ast/parser/ets/InvalidStatements3.ets | 1 - .../ast/parser/ets/MultipleClassErrors.ets | 2 +- .../ast/parser/ets/MultipleParserErrors.ets | 6 +- ets2panda/test/ast/parser/ets/StringFasta.ets | 32 +- .../test/ast/parser/ets/accessor_call.ets | 2 +- .../test/ast/parser/ets/ambiguous_call_2.ets | 4 +- .../annotationDecl_bad_initializer06.ets | 1 + .../annotationUsage_bad_param02.ets | 1 + .../annotationUsage_bad_param04.ets | 1 + .../annotationUsage_bad_param05.ets | 1 + .../annotationUsage_bad_param06.ets | 1 + .../annotations_tests/annotationUsage_tmp.ets | 3 +- ets2panda/test/ast/parser/ets/array_type.ets | 1 - .../ets/assert_with_not_boolean_type_1.ets | 2 +- .../ets/assert_with_not_boolean_type_2.ets | 4 +- ...nctional_variable_to_functional_type_1.ets | 2 +- ...all_expression_for_non_functional_type.ets | 3 +- .../parser/ets/class_optional_property.ets | 2 +- .../ast/parser/ets/constFloatInSwitch.ets | 4 +- .../ets/constant_expression_divide_zero.ets | 4 +- .../test/ast/parser/ets/cycle_constructor.ets | 4 +- .../ast/parser/ets/declare_class_bad_1.ets | 2 +- .../ast/parser/ets/declare_class_bad_3.ets | 2 +- .../ast/parser/ets/declare_namespace_5.ets | 1 + .../ast/parser/ets/differentTypeCompare.ets | 2 +- .../dynamic_class_ctor_decl_import_bad.ets | 4 +- .../dynamic_class_field_decl_import_bad_1.ets | 2 +- .../dynamic_class_field_decl_import_bad_2.ets | 2 +- ...dynamic_class_method_decl_import_bad_1.ets | 2 +- ...dynamic_class_method_decl_import_bad_2.ets | 2 +- ets2panda/test/ast/parser/ets/enum15.ets | 1 + ets2panda/test/ast/parser/ets/enum29.ets | 8 + ets2panda/test/ast/parser/ets/enum30.ets | 6 + ets2panda/test/ast/parser/ets/enum31.ets | 4 +- .../ast/parser/ets/enum_default_negative1.ets | 1 + .../ets_never_type_without_affect_other.ets | 5 +- .../test/ast/parser/ets/for_await_of_loop.ets | 1 - ets2panda/test/ast/parser/ets/for_of_02.ets | 2 +- ets2panda/test/ast/parser/ets/for_of_04.ets | 1 + .../ast/parser/ets/for_of_loop_variable.ets | 8 +- .../ets/function_implicit_return_type4.ets | 4 +- .../ets/function_implicit_return_type7.ets | 4 +- .../test/ast/parser/ets/generic_error.ets | 2 +- .../ast/parser/ets/generic_lambda_err2.ets | 12 +- .../ets/generics_type_param_constraint_8.ets | 2 +- .../ets/getter_setter_access_modifiers_2.ets | 8 +- .../parser/ets/illegal_union_member_exp.ets | 3 + .../imported_module_1.ets | 1 - .../imported_module_2.ets | 2 +- .../import_type_error_in_class.ets | 2 +- .../import_type_error_top_level.ets | 2 +- ...ment-on-nullish-type-undefined-invalid.ets | 3 +- .../increment-on-nullish-type-undefined.ets | 2 - .../ets/index_not_support_such_type.ets | 10 +- .../ets/instanceof_with_not_object_type.ets | 3 +- .../ets/interface_private_function_1.ets | 4 +- .../test/ast/parser/ets/invalidEnums.ets | 1 - .../test/ast/parser/ets/keyof_annotation.ets | 13 +- .../test/ast/parser/ets/keyof_array_tuple.ets | 24 +- .../test/ast/parser/ets/keyof_constraint.ets | 2 +- .../test/ast/parser/ets/keyof_parameter.ets | 12 +- .../parser/ets/lambda-type-inference-neg.ets | 3 +- .../lambda-type-inference-overloaded-1.ets | 5 +- .../parser/ets/lambda_infer_type_neg_1.ets | 4 +- ...ambda_omit_parentheses_parameter_neg_3.ets | 2 +- ets2panda/test/ast/parser/ets/loops.ets | 1 - .../test/ast/parser/ets/new_object_1.ets | 3 +- .../test/ast/parser/ets/new_object_2.ets | 4 +- .../parser/ets/non_constant_expression.ets | 2 +- .../parser/ets/non_proper_index_method.ets | 10 +- .../parser/ets/overrideFuncWithGetter_n.ets | 6 +- .../test/ast/parser/ets/override_method.ets | 6 +- .../ets/partialPrimitiveConversion_n.ets | 4 +- .../parser/ets/partial_not_reference_type.ets | 4 +- .../ets/predefined_non_primitive_types.ets | 5 +- .../parser/ets/primitive_type_method_1.ets | 3 +- .../parser/ets/primitive_type_method_2.ets | 3 +- .../ets/privateSuperConstructorCall.ets | 4 +- .../Readonly-Array-test1.ets | 2 +- .../Readonly-Array-test3.ets | 4 +- .../Readonly-with-ArrayType-test1.ets | 4 +- .../Readonly-with-ArrayType-test2.ets | 4 +- .../Readonly-with-ArrayType-test3.ets | 2 +- .../Readonly-with-ArrayType-test4.ets | 2 +- .../readonly-parameter-test2.ets | 2 +- .../readonly-parameter-test3.ets | 2 +- .../readonly-parameter-test4.ets | 4 +- .../readonly-parameter-test5.ets | 4 +- .../test/ast/parser/ets/recordIndexing.ets | 14 +- .../ast/parser/ets/recordKeyTypeCheck01.ets | 2 +- .../ast/parser/ets/recordKeyTypeCheck02.ets | 2 +- .../ast/parser/ets/recordKeyTypeCheck03.ets | 2 +- .../ast/parser/ets/record_object_value.ets | 8 +- .../test/ast/parser/ets/rest_parameter_06.ets | 2 +- .../test/ast/parser/ets/rest_parameter_07.ets | 6 +- .../test/ast/parser/ets/rest_parameter_08.ets | 6 +- .../test/ast/parser/ets/rest_parameter_13.ets | 4 +- .../ets/return_null_and_type_not_match.ets | 4 +- .../ast/parser/ets/return_type_non_match.ets | 5 +- .../ast/parser/ets/single_statement_1.ets | 8 + .../ast/parser/ets/single_statement_2.ets | 8 + ...witch_const_int_compare_char_duplicate.ets | 2 +- ...witch_readonly_member_number_duplicate.ets | 2 +- .../test/ast/parser/ets/trailing_comma_2.ets | 6 +- .../extra_trailing_lambda_1.ets | 2 +- .../ets/type_decution_unnecessary_boxing.ets | 3 +- .../ast/parser/ets/type_from_utility_type.ets | 9 +- .../test/ast/parser/ets/type_references.ets | 3 +- ets2panda/test/ast/parser/ets/types_decls.ets | 8 +- .../ast/parser/ets/unexpected_token_22.ets | 3 - .../ast/parser/ets/unexpected_token_29.ets | 2 +- .../ast/parser/ets/unexpected_token_31.ets | 2 +- .../ast/parser/ets/unexpected_token_35.ets | 2 +- .../ast/parser/ets/unexpected_token_36.ets | 1 - .../ast/parser/ets/unexpected_token_41.ets | 5 +- .../ast/parser/ets/unexpected_token_42.ets | 2 +- .../ast/parser/ets/unexpected_token_43.ets | 2 +- .../ast/parser/ets/unexpected_token_53.ets | 1 - .../ast/parser/ets/unexpected_token_55.ets | 1 - .../ast/parser/ets/unexpected_token_61.ets | 1 - .../ast/parser/ets/visible_signatures_1.ets | 5 +- .../ast/parser/ets/wrong_context_class_1.ets | 4 +- .../ast/parser/ets/wrong_context_class_2.ets | 4 +- .../parser/ets/wrong_context_function_1.ets | 4 +- .../parser/ets/wrong_context_function_2.ets | 2 +- .../ets/boxingConversion2-expected.txt | 164 +- .../test/compiler/ets/boxingConversion2.ets | 6 +- .../boxingUnboxingExpressions-expected.txt | 12 +- .../ets/boxingUnboxingExpressions.ets | 4 +- .../ets/conversion-w-ASExpr-expected.txt | 308 +- .../test/compiler/ets/conversion-w-ASExpr.ets | 10 +- .../ets/conversion_w_functions-expected.txt | 1365 +++-- .../compiler/ets/conversion_w_functions.ets | 26 +- .../ets/dynamicLambdaJSValue-expected.txt | 2 +- .../ets/dynamic_instanceof_error-expected.txt | 1 - .../ets/generic_arrayaslist-expected.txt | 189 +- .../test/compiler/ets/generic_arrayaslist.ets | 4 +- .../ets/implicit-conversion-expected.txt | 553 +- .../test/compiler/ets/implicit-conversion.ets | 14 +- ...rted_function_return_type_lib-expected.txt | 2 +- .../ets/instanceof_object_long-expected.txt | 1 - .../ets/lambda_unresolved_ref_1-expected.txt | 178 +- .../compiler/ets/lambda_unresolved_ref_1.ets | 4 +- .../ets/launch_expression-expected.txt | 10 +- .../test/compiler/ets/override16-expected.txt | 77 +- ets2panda/test/compiler/ets/override16.ets | 2 +- .../test/compiler/ets/override17-expected.txt | 77 +- ets2panda/test/compiler/ets/override17.ets | 2 +- .../ets/switchStatementBoxing-expected.txt | 5 +- ...tchStatementCorrectConversion-expected.txt | 5 +- .../compiler/ets/tuple_types_1-expected.txt | 2 +- .../compiler/ets/tuple_types_15-expected.txt | 2 +- .../parser/ets/AccessBinaryTrees-expected.txt | 160 +- .../test/parser/ets/AccessNBody-expected.txt | 1259 +--- ets2panda/test/parser/ets/AccessNBody.ets | 6 +- .../test/parser/ets/AccessNSieve-expected.txt | 289 +- .../ets/Bitops3BitBitsInByte-expected.txt | 39 +- .../parser/ets/BitopsBitsInByte-expected.txt | 39 +- .../parser/ets/BitopsBitwiseAnd-expected.txt | 39 +- .../parser/ets/BitopsNSieveBits-expected.txt | 43 +- .../ets/ControlFlowRecursive-expected.txt | 121 +- .../test/parser/ets/MathCordic-expected.txt | 435 +- ets2panda/test/parser/ets/MathCordic.ets | 8 +- .../parser/ets/MathPartialSums-expected.txt | 159 +- .../parser/ets/MathSpectralNorm-expected.txt | 39 +- .../test/parser/ets/Morph3d-expected.txt | 557 +- .../test/parser/ets/StringBase64-expected.txt | 817 +-- ets2panda/test/parser/ets/StringBase64.ets | 6 +- ets2panda/test/parser/ets/assert-expected.txt | 2 +- ets2panda/test/parser/ets/assign-expected.txt | 5 +- .../test/parser/ets/binary_op-expected.txt | 52 +- .../parser/ets/binary_operations-expected.txt | 1354 +---- .../test/parser/ets/binary_operations.ets | 4 +- .../test/parser/ets/boolean_cond-expected.txt | 36 +- .../parser/ets/cast_expressions-expected.txt | 5185 +++++++++++------ .../test/parser/ets/cast_expressions.ets | 162 +- .../parser/ets/cast_expressions5-expected.txt | 71 +- .../test/parser/ets/cast_expressions5.ets | 2 +- .../test/parser/ets/class_init-expected.txt | 36 +- .../conditionalExpressionType-expected.txt | 818 +-- .../parser/ets/conditionalExpressionType.ets | 2 +- .../ets/default_parameter5-expected.txt | 2 +- .../test/parser/ets/field_decl-expected.txt | 4 +- ets2panda/test/parser/ets/field_decl.ets | 2 +- .../ets/float_pont_format_2-expected.txt | 36 +- .../ets/float_pont_format_3-expected.txt | 36 +- .../ets/float_pont_format_4-expected.txt | 36 +- .../ets/float_pont_format_5-expected.txt | 36 +- .../ets/float_pont_format_6-expected.txt | 36 +- .../ets/float_pont_format_7-expected.txt | 166 +- .../ets/float_pont_format_8-expected.txt | 548 +- .../parser/ets/float_separator_1-expected.txt | 6 +- .../test/parser/ets/float_separator_1.ets | 2 +- .../parser/ets/for_with_break-expected.txt | 2 +- ...unction_implicit_return_type8-expected.txt | 6 +- ...unction_implicit_return_type9-expected.txt | 6 +- .../imported_module_2-expected.txt | 4 +- .../imported_module_2.ets | 2 +- .../packages/package_module_1-expected.txt | 4 +- .../packages/package_module_2-expected.txt | 8 +- .../packages/package_module_2.ets | 2 +- .../ets/labeledDoWhileStatement-expected.txt | 2 +- .../ets/labeledForStatement-expected.txt | 2 +- .../ets/labeledWhileStatement-expected.txt | 2 +- .../ets/lambda-type-inference-expected.txt | 262 +- .../test/parser/ets/lambda-type-inference.ets | 4 +- .../parentheses_expression_value-expected.txt | 2 +- .../parser/ets/rethrow-func-1-expected.txt | 37 +- .../test/parser/ets/simple_types-expected.txt | 81 +- ets2panda/test/parser/ets/simple_types.ets | 2 +- .../parser/ets/string_template_1-expected.txt | 2 +- .../parser/ets/string_template_2-expected.txt | 108 +- .../parser/ets/string_template_3-expected.txt | 133 +- .../parser/ets/string_template_4-expected.txt | 97 +- .../test/parser/ets/switch2-expected.txt | 3 + .../ets/switch_char_compare_num-expected.txt | 1 + .../ets/switch_readonly_member-expected.txt | 78 +- ..._readonly_member_compare_char-expected.txt | 78 +- ...eadonly_member_compare_char_2-expected.txt | 78 +- .../parser/ets/test_type_alias6-expected.txt | 2 +- .../parser/ets/this_cmp_object-expected.txt | 50 +- .../ets/tupleIndexWithNumbers-expected.txt | 10 +- .../test/parser/ets/tuple_type_1-expected.txt | 34 +- .../test/parser/ets/type_cast-expected.txt | 213 +- ets2panda/test/parser/ets/type_cast.ets | 6 +- .../test/parser/ets/unary_op-expected.txt | 86 +- .../test/parser/ets/var_declare-expected.txt | 6 +- ets2panda/test/parser/ets/var_declare.ets | 2 +- ets2panda/test/runtime/ets/ArrayLiteral.ets | 2 +- ets2panda/test/runtime/ets/CastPrimitive.ets | 114 +- .../test/runtime/ets/EnumConstExpression1.ets | 4 +- .../test/runtime/ets/NullishCoalescing_01.ets | 4 +- ets2panda/test/runtime/ets/StringBase64.ets | 6 +- .../test/runtime/ets/UpdateExpression.ets | 12 +- .../annotation_tests/annotationConstAs.ets | 14 +- .../ets/boxed_primitives_overloading.ets} | 18 +- .../code_point_at.ets | 4 +- .../test/runtime/ets/constant_boolean.ets | 6 +- .../runtime/ets/conversionFromInfinity.ets | 50 +- .../test/runtime/ets/enum_string_init.ets | 4 - .../ets/explicit_cast_boxed_expressions.ets | 96 +- ...ate_initialization_with_object_literal.ets | 1 - ...e_initialization_without_assignment_02.ets | 2 +- ets2panda/test/runtime/ets/instanceof.ets | 4 +- .../ets/lambda_type_with_rest_param.ets | 4 +- .../runtime/ets/lambda_with_rest_param.ets | 2 +- .../lambda_with_rest_param_resizablearray.ets | 2 +- .../runtime/ets/lambda_with_restparameter.ets | 6 +- .../ets/lambda_with_restparameter_object.ets | 4 +- ...a_with_restparameter_object_fixedarray.ets | 6 +- ...bda_with_restparameter_predefinedtypes.ets | 12 +- .../runtime/ets/stringliteral_to_char.ets | 4 +- .../runtime/ets/type_from_primitive_type.ets | 21 +- .../astchecker/astchecker-ets-ignored.txt | 53 +- .../ets-runtime/ets-runtime-ignored.txt | 45 +- .../test-lists/parser/parser-ets-ignored.txt | 24 + .../test-lists/parser/parser-js-ignored.txt | 17 + ets2panda/test/tsconfig/CMakeLists.txt | 7 +- .../test-decl/typecheck-decl/expected.json | 2 +- .../test/unit/annotations/CMakeLists.txt | 7 +- .../mutiple_annotations_for_function.cpp | 29 +- ets2panda/test/unit/lowerings/CMakeLists.txt | 6 +- .../test/unit/lowerings/const_expression.cpp | 16 +- ets2panda/test/unit/lsp/get_diagnostics.cpp | 4 +- .../get_type_of_symbol_at_location_test.cpp | 31 +- ets2panda/test/unit/lsp/inlay_hints_test.cpp | 2 +- ...plugin_proceed_to_state_ast_node_check.cpp | 4 +- ...st_node_transform_children_recursively.cpp | 1 + ..._proceed_to_state_create_as_expression.cpp | 4 +- ..._state_create_ets_parameter_expression.cpp | 2 + ...gin_proceed_to_state_member_expression.cpp | 8 +- ...ceed_to_state_rerun_scopes_after_check.cpp | 1 + ...ugin_proceed_to_state_this_into_method.cpp | 4 +- .../plugin_conversion_rule_part_ii.cpp | 17 - .../test/unit/public/ast_builder_test.cpp | 52 +- .../test/unit/rest_parameter_flag_test.cpp | 4 +- ets2panda/test/unit/sizeof_node_test.cpp | 11 +- .../test/unit/union_normalization_test_1.cpp | 6 +- .../test/unit/union_normalization_test_2.cpp | 4 +- .../util/ast-builders/numberLiteralBuilder.h | 4 +- ets2panda/util/diagnostic/semantic.yaml | 48 +- ets2panda/util/diagnostic/syntax.yaml | 2 +- ets2panda/util/diagnostic/warning.yaml | 10 +- ets2panda/util/diagnosticEngine.cpp | 4 - ets2panda/util/diagnosticEngine.h | 1 - ets2panda/util/helpers.cpp | 54 + ets2panda/util/helpers.h | 9 + ets2panda/util/options.yaml | 2 +- ets2panda/varbinder/scope.cpp | 5 +- ets2panda/varbinder/variable.cpp | 4 +- 617 files changed, 13782 insertions(+), 15687 deletions(-) delete mode 100644 ets2panda/checker/ets/narrowingConverter.h delete mode 100644 ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp create mode 100644 ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp rename ets2panda/{checker/ets/narrowingWideningConverter.h => compiler/lowering/ets/enumPropertiesInAnnotationsLowering.h} (43%) create mode 100644 ets2panda/compiler/lowering/ets/primitiveConversionPhase.cpp create mode 100644 ets2panda/compiler/lowering/ets/primitiveConversionPhase.h create mode 100644 ets2panda/compiler/lowering/ets/unboxLowering.cpp rename ets2panda/compiler/lowering/ets/{boxedTypeLowering.h => unboxLowering.h} (70%) create mode 100644 ets2panda/test/ast/compiler/ets/FixedArray/spreadMultiArrayInTuple.ets rename ets2panda/{checker/ets/narrowingConverter.cpp => test/ast/compiler/ets/boxed_primitives_overloading.sts} (54%) rename ets2panda/test/{runtime/ets/enum-initialize-with-enum2.ets => ast/compiler/ets/cast_boxed_primitives_invoke_context_and_unions.sts} (65%) rename ets2panda/{checker/ets/narrowingWideningConverter.cpp => test/ast/compiler/ets/division-by-zero.ets} (51%) rename ets2panda/test/{runtime/ets => ast/compiler/ets/enum_expressions}/constant_char.ets (84%) rename ets2panda/test/{runtime/ets => ast/compiler/ets/enum_expressions}/constant_char_asexpression.ets (60%) rename ets2panda/test/{runtime/ets => ast/compiler/ets/enum_expressions}/enum-initialize-with-enum1.ets (79%) create mode 100644 ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum2.ets create mode 100644 ets2panda/test/ast/compiler/ets/null_coalescing_neg_01.ets rename ets2panda/test/{ast/parser/ets/optional_primitive.ets => runtime/ets/boxed_primitives_overloading.ets} (59%) diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 0982392c38..42c9d7f055 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -78,8 +78,6 @@ libes2panda_sources = [ "checker/ets/etsWarningAnalyzer.cpp", "checker/ets/function.cpp", "checker/ets/helpers.cpp", - "checker/ets/narrowingConverter.cpp", - "checker/ets/narrowingWideningConverter.cpp", "checker/ets/object.cpp", "checker/ets/typeCheckingHelpers.cpp", "checker/ets/typeConverter.cpp", @@ -207,7 +205,6 @@ libes2panda_sources = [ "compiler/lowering/ets/arrayLiteralLowering.cpp", "compiler/lowering/ets/asyncMethodLowering.cpp", "compiler/lowering/ets/bigintLowering.cpp", - "compiler/lowering/ets/boxedTypeLowering.cpp", "compiler/lowering/ets/boxingForLocals.cpp", "compiler/lowering/ets/capturedVariables.cpp", "compiler/lowering/ets/cfgBuilderPhase.cpp", @@ -219,6 +216,7 @@ libes2panda_sources = [ "compiler/lowering/ets/dynamicImportLowering.cpp", "compiler/lowering/ets/enumLowering.cpp", "compiler/lowering/ets/enumPostCheckLowering.cpp", + "compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp", "compiler/lowering/ets/expandBrackets.cpp", "compiler/lowering/ets/exportAnonymousConst.cpp", "compiler/lowering/ets/expressionLambdaLowering.cpp", @@ -238,6 +236,7 @@ libes2panda_sources = [ "compiler/lowering/ets/optionalLowering.cpp", "compiler/lowering/ets/packageImplicitImport.cpp", "compiler/lowering/ets/partialExportClassGen.cpp", + "compiler/lowering/ets/primitiveConversionPhase.cpp", "compiler/lowering/ets/promiseVoid.cpp", "compiler/lowering/ets/recordLowering.cpp", "compiler/lowering/ets/resizableArrayLowering.cpp", @@ -253,6 +252,7 @@ libes2panda_sources = [ "compiler/lowering/ets/topLevelStmts/importExportDecls.cpp", "compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp", "compiler/lowering/ets/typeFromLowering.cpp", + "compiler/lowering/ets/unboxLowering.cpp", "compiler/lowering/ets/unionLowering.cpp", "compiler/lowering/ets/annotationCopyLowering.cpp", "compiler/lowering/ets/annotationCopyPostLowering.cpp", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 3cef5f00dc..695f3a76f9 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -277,7 +277,6 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/extensionAccessorLowering.cpp compiler/lowering/ets/genericBridgesLowering.cpp compiler/lowering/ets/arrayLiteralLowering.cpp - compiler/lowering/ets/boxedTypeLowering.cpp compiler/lowering/ets/boxingForLocals.cpp compiler/lowering/ets/capturedVariables.cpp compiler/lowering/ets/cfgBuilderPhase.cpp @@ -319,9 +318,12 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/typeFromLowering.cpp compiler/lowering/ets/enumLowering.cpp compiler/lowering/ets/enumPostCheckLowering.cpp + compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp compiler/lowering/ets/setJumpTarget.cpp compiler/lowering/ets/annotationCopyLowering.cpp compiler/lowering/ets/annotationCopyPostLowering.cpp + compiler/lowering/ets/primitiveConversionPhase.cpp + compiler/lowering/ets/unboxLowering.cpp ir/astDump.cpp ir/srcDump.cpp ir/astNode.cpp @@ -556,8 +558,6 @@ set(ES2PANDA_LIB_SRC checker/ets/validateHelpers.cpp checker/ets/typeCheckingHelpers.cpp checker/ets/helpers.cpp - checker/ets/narrowingConverter.cpp - checker/ets/narrowingWideningConverter.cpp checker/ets/object.cpp checker/ets/typeConverter.cpp checker/ets/typeCreation.cpp diff --git a/ets2panda/ast_verifier/helpers.cpp b/ets2panda/ast_verifier/helpers.cpp index 13d55e496c..d8a9998848 100644 --- a/ets2panda/ast_verifier/helpers.cpp +++ b/ets2panda/ast_verifier/helpers.cpp @@ -55,8 +55,7 @@ bool IsBooleanType(const ir::AstNode *ast) return false; } - if (typedAst->TsType()->HasTypeFlag(checker::TypeFlag::ETS_OBJECT) && - ast->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { + if (typedAst->TsType()->HasTypeFlag(checker::TypeFlag::ETS_OBJECT)) { return typedAst->TsType()->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_BOOLEAN); } @@ -89,8 +88,7 @@ bool IsValidTypeForBinaryOp(const ir::AstNode *ast, bool isBitwise) return true; } - if (typedAst->TsType()->HasTypeFlag(checker::TypeFlag::ETS_OBJECT) && - ast->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { + if (typedAst->TsType()->HasTypeFlag(checker::TypeFlag::ETS_OBJECT)) { return typedAst->TsType()->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_TYPE) && !typedAst->TsType()->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_BOOLEAN); } diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index f5b0778cde..43ab9c71bf 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -29,6 +29,8 @@ namespace ark::es2panda::checker { +static Type *GetAppropriatePreferredType(Type *originalType, std::function const &predicate); + ETSChecker *ETSAnalyzer::GetETSChecker() const { return static_cast(GetChecker()); @@ -437,17 +439,20 @@ static bool NeedCreateETSResizableArrayType(ETSChecker *checker, Type *type) checker::Type *ETSAnalyzer::Check(ir::ETSNewArrayInstanceExpression *expr) const { + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + ETSChecker *checker = GetETSChecker(); auto *elementType = expr->TypeReference()->GetType(checker); checker->ValidateArrayIndex(expr->Dimension(), true); CheckArrayElementType(checker, expr); - GetUnionPreferredType(expr, expr->GetPreferredType()); - - auto *preferredType = expr->GetPreferredType(); + auto *preferredType = GetAppropriatePreferredType( + expr->PreferredType(), [](Type *tp) -> bool { return tp->IsETSArrayType() || tp->IsETSResizableArrayType(); }); - if (NeedCreateETSResizableArrayType(checker, expr->GetPreferredType()) || + if (NeedCreateETSResizableArrayType(checker, expr->PreferredType()) || preferredType == nullptr || preferredType->IsETSResizableArrayType()) { expr->SetTsType(checker->CreateETSResizableArrayType(elementType)); } else { @@ -538,6 +543,9 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *expr) const { + if (expr->TsType() != nullptr) { + return expr->TsType(); + } ETSChecker *checker = GetETSChecker(); CheckArrayElementType(checker, expr); @@ -548,11 +556,10 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewMultiDimArrayInstanceExpression *exp checker->ValidateArrayIndex(dim, true); fixedArrayType = checker->CreateETSArrayType(fixedArrayType); } - GetUnionPreferredType(expr, expr->GetPreferredType()); + auto *preferredType = GetAppropriatePreferredType( + expr->PreferredType(), [](Type *tp) -> bool { return tp->IsETSArrayType() || tp->IsETSResizableArrayType(); }); - auto *preferredType = expr->GetPreferredType(); - if (NeedCreateETSResizableArrayType(checker, expr->GetPreferredType()) || - preferredType->IsETSResizableArrayType()) { + if (NeedCreateETSResizableArrayType(checker, preferredType) || preferredType->IsETSResizableArrayType()) { expr->SetTsType(checker->CreateETSMultiDimResizableArrayType(elementType, expr->Dimensions().size())); } else { expr->SetTsType(fixedArrayType); @@ -665,11 +672,6 @@ checker::Type *ETSAnalyzer::Check(ir::ETSKeyofType *node) const // compile methods for EXPRESSIONS in alphabetical order -checker::Type *ETSAnalyzer::GetPreferredType(ir::ArrayExpression *expr) const -{ - return expr->preferredType_; -} - static void AddSpreadElementTypes(ETSChecker *checker, ir::SpreadElement *const element, ArenaVector> &elementTypes) { @@ -709,7 +711,12 @@ static ArenaVector> GetElementTypes(ETSCheck { ArenaVector> elementTypes(checker->ProgramAllocator()->Adapter()); - for (std::size_t idx = 0; idx < expr->Elements().size(); ++idx) { + auto *const exprPreferredType = expr->PreferredType(); + auto *const exprTupleType = exprPreferredType->IsETSTupleType() ? exprPreferredType->AsETSTupleType() : nullptr; + checker::Type *elemPreferredType = + exprPreferredType->IsETSTupleType() ? nullptr : checker->GetElementTypeOfArray(exprPreferredType); + + for (std::size_t idx = 0U; idx < expr->Elements().size(); ++idx) { ir::Expression *const element = expr->Elements()[idx]; if (element->IsSpreadElement()) { @@ -717,23 +724,16 @@ static ArenaVector> GetElementTypes(ETSCheck continue; } - auto *const exprPreferredType = expr->GetPreferredType(); - - if (expr->GetPreferredType()->IsETSTupleType() && - idx < expr->GetPreferredType()->AsETSTupleType()->GetTupleSize() && - !ValidArrayExprSizeForTupleSize(checker, exprPreferredType->AsETSTupleType()->GetTypeAtIndex(idx), - element)) { - elementTypes.emplace_back(checker->GlobalTypeError(), element); - continue; - } - - if (element->IsArrayExpression() || element->IsObjectExpression()) { - auto *const targetPreferredType = exprPreferredType->IsETSTupleType() - ? exprPreferredType->AsETSTupleType()->GetTypeAtIndex(idx) - : checker->GetElementTypeOfArray(exprPreferredType); - ETSChecker::SetPreferredTypeIfPossible(element, targetPreferredType); + if (exprTupleType != nullptr && exprPreferredType->IsETSTupleType()) { + if (idx >= exprTupleType->GetTupleSize() || + !ValidArrayExprSizeForTupleSize(checker, exprTupleType->GetTypeAtIndex(idx), element)) { + elementTypes.emplace_back(element->SetTsType(checker->GlobalTypeError()), element); + continue; + } + elemPreferredType = exprTupleType->GetTypeAtIndex(idx); } + element->SetPreferredType(elemPreferredType); elementTypes.emplace_back(element->Check(checker), element); } @@ -843,41 +843,43 @@ static bool CheckArrayExpressionElements(ETSChecker *checker, ir::ArrayExpressio [](auto &pair) { return pair.first->IsTypeError(); }); for (std::size_t idx = 0; idx < arrayExprElementTypes.size(); ++idx) { - allElementsAssignable &= CheckElement(checker, arrayExpr->GetPreferredType(), arrayExprElementTypes, idx); + allElementsAssignable &= CheckElement(checker, arrayExpr->PreferredType(), arrayExprElementTypes, idx); } return allElementsAssignable; } -static bool IsPossibleArrayExpressionType(Type const *type) +static Type *GetAppropriatePreferredType(Type *originalType, std::function const &predicate) { - return type->IsETSArrayType() || type->IsETSTupleType() || type->IsETSResizableArrayType(); -} + if (originalType == nullptr) { + return nullptr; + } -void ETSAnalyzer::GetUnionPreferredType(ir::Expression *expr, Type *originalType) const -{ - if (originalType == nullptr || !originalType->IsETSUnionType()) { - return; + while (originalType->IsETSTypeAliasType()) { + if (predicate(originalType)) { + return originalType; + } + originalType = originalType->AsETSTypeAliasType()->GetTargetType(); + } + + if (predicate(originalType)) { + return originalType; } - checker::Type *preferredType = nullptr; + + if (!originalType->IsETSUnionType()) { + return nullptr; + } + + Type *preferredType = nullptr; for (auto &type : originalType->AsETSUnionType()->ConstituentTypes()) { - if (IsPossibleArrayExpressionType(type)) { + if (predicate(type)) { if (preferredType != nullptr) { - preferredType = nullptr; - break; + return nullptr; // ambiguity } preferredType = type; } } - if (expr->IsArrayExpression()) { - expr->AsArrayExpression()->SetPreferredType(preferredType); - } else if (expr->IsETSNewArrayInstanceExpression()) { - expr->AsETSNewArrayInstanceExpression()->SetPreferredType(preferredType); - } else if (expr->IsETSNewMultiDimArrayInstanceExpression()) { - expr->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredType(preferredType); - } else { - ES2PANDA_UNREACHABLE(); - } + return preferredType; } checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const @@ -887,43 +889,35 @@ checker::Type *ETSAnalyzer::Check(ir::ArrayExpression *expr) const return expr->TsType(); } - if (expr->GetPreferredType() != nullptr) { - if (expr->GetPreferredType()->IsETSTypeAliasType()) { - expr->SetPreferredType(expr->GetPreferredType()->AsETSTypeAliasType()->GetTargetType()); - } - - if (expr->GetPreferredType()->IsETSUnionType()) { - GetUnionPreferredType(expr, expr->GetPreferredType()); - } - - if (expr->GetPreferredType() != nullptr && !IsPossibleArrayExpressionType(expr->GetPreferredType())) { - expr->SetPreferredType(nullptr); - } - } + auto *preferredType = GetAppropriatePreferredType(expr->PreferredType(), [](Type *tp) -> bool { + return tp->IsETSArrayType() || tp->IsETSResizableArrayType() || tp->IsETSTupleType(); + }); - if (!IsArrayExpressionValidInitializerForType(checker, expr->GetPreferredType())) { - checker->LogError(diagnostic::UNEXPECTED_ARRAY, {expr->GetPreferredType()}, expr->Start()); + if (!IsArrayExpressionValidInitializerForType(checker, preferredType)) { + checker->LogError(diagnostic::UNEXPECTED_ARRAY, {expr->PreferredType()}, expr->Start()); return checker->InvalidateType(expr); } if (!expr->Elements().empty()) { - if (expr->GetPreferredType() == nullptr || expr->GetPreferredType() == checker->GlobalETSObjectType()) { - expr->SetPreferredType(InferPreferredTypeFromElements(checker, expr)); + if (preferredType == nullptr || preferredType == checker->GlobalETSObjectType()) { + preferredType = InferPreferredTypeFromElements(checker, expr); } + expr->SetPreferredType(preferredType); + if (!CheckArrayExpressionElements(checker, expr)) { return checker->InvalidateType(expr); } } - if (expr->GetPreferredType() == nullptr) { + if (preferredType == nullptr) { return checker->TypeError(expr, diagnostic::UNRESOLVABLE_ARRAY, expr->Start()); } - expr->SetTsType(expr->GetPreferredType()); - if (!expr->GetPreferredType()->IsETSResizableArrayType() && !expr->TsType()->IsETSTupleType()) { - ES2PANDA_ASSERT(expr->TsType()->IsETSArrayType()); - const auto *const arrayType = expr->TsType()->AsETSArrayType(); + expr->SetTsType(preferredType); + if (!preferredType->IsETSResizableArrayType() && !preferredType->IsETSTupleType()) { + ES2PANDA_ASSERT(preferredType->IsETSArrayType()); + const auto *const arrayType = preferredType->AsETSArrayType(); checker->CreateBuiltinArraySignature(arrayType, arrayType->Rank()); } return expr->TsType(); @@ -1060,7 +1054,10 @@ checker::Type *ETSAnalyzer::GetSmartType(ir::AssignmentExpression *expr, checker if (expr->Left()->IsIdentifier() && expr->Target() != nullptr) { // Now try to define the actual type of Identifier so that smart cast can be used in further checker // processing - smartType = checker->ResolveSmartType(rightType, leftType); + auto const value = expr->Right()->IsNumberLiteral() + ? std::make_optional(expr->Right()->AsNumberLiteral()->Number().GetDouble()) + : std::nullopt; + smartType = checker->ResolveSmartType(rightType, leftType, value); auto const *const variable = expr->Target(); // Add/Remove/Modify smart cast for identifier @@ -1144,22 +1141,15 @@ static checker::Type *HandleSubstitution(ETSChecker *checker, ir::AssignmentExpr leftType->IsETSTupleType() || leftType->IsETSUnionType(); if (expr->Right()->IsArrayExpression() && possibleInferredTypeOfArray) { checker->ModifyPreferredType(expr->Right()->AsArrayExpression(), leftType); - } - - if (expr->Right()->IsETSNewArrayInstanceExpression()) { - expr->Right()->AsETSNewArrayInstanceExpression()->SetPreferredType(leftType); - } - - if (expr->Right()->IsETSNewMultiDimArrayInstanceExpression()) { - expr->Right()->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredType(leftType); - } - - if (expr->Right()->IsObjectExpression()) { - expr->Right()->AsObjectExpression()->SetPreferredType(leftType); - } - - if (expr->Right()->IsArrowFunctionExpression() && (leftType->IsETSArrowType() || leftType->IsETSUnionType())) { - expr->Right()->AsArrowFunctionExpression()->SetPreferredType(leftType); + } else if (expr->Right()->IsArrowFunctionExpression() && + (leftType->IsETSArrowType() || leftType->IsETSUnionType())) { + if (auto *preferredType = GetAppropriatePreferredType(leftType, [](Type *tp) { return tp->IsETSArrowType(); }); + preferredType != nullptr) { + checker->TryInferTypeForLambdaTypeAlias(expr->Right()->AsArrowFunctionExpression(), + preferredType->AsETSFunctionType()); + } + } else { + expr->Right()->SetPreferredType(leftType); } return expr->Right()->Check(checker); @@ -1186,10 +1176,7 @@ std::tuple ETSAnalyzer::CheckAssignmentExprOperatorTyp case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { std::tie(std::ignore, expr->operationType_) = checker->CheckBinaryOperator( expr->Left(), expr->Right(), expr, expr->OperatorType(), expr->Start(), true); - - auto unboxedLeft = checker->MaybeUnboxInRelation(leftType); - sourceType = unboxedLeft == nullptr ? leftType : unboxedLeft; - + sourceType = leftType; relationNode = expr; break; } @@ -1300,10 +1287,10 @@ checker::Type *ETSAnalyzer::Check(ir::BinaryExpression *expr) const } } - checker::Type *newTsType {nullptr}; - std::tie(newTsType, expr->operationType_) = + auto [newTsType, operationType] = checker->CheckBinaryOperator(expr->Left(), expr->Right(), expr, expr->OperatorType(), expr->Start()); - expr->SetTsType(newTsType); + expr->SetTsType(checker->MaybeBoxType(newTsType)); + expr->SetOperationType(checker->MaybeBoxType(operationType)); checker->Context().CheckBinarySmartCastCondition(expr); @@ -1583,6 +1570,45 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const return expr->TsType(); } +static bool IsNumericType(ETSChecker *checker, Type *type) +{ + return checker->Relation()->IsSupertypeOf(checker->GetGlobalTypesHolder()->GlobalNumericBuiltinType(), type); +} + +static Type *BiggerNumericType(ETSChecker *checker, Type *t1, Type *t2) +{ + ES2PANDA_ASSERT(IsNumericType(checker, t1)); + ES2PANDA_ASSERT(IsNumericType(checker, t2)); + + auto *rel = checker->Relation(); + + if (rel->IsSupertypeOf(checker->GlobalDoubleBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalDoubleBuiltinType(), t2)) { + return checker->GlobalDoubleBuiltinType(); + } + if (rel->IsSupertypeOf(checker->GlobalFloatBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalFloatBuiltinType(), t2)) { + return checker->GlobalFloatBuiltinType(); + } + if (rel->IsSupertypeOf(checker->GlobalLongBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalLongBuiltinType(), t2)) { + return checker->GlobalLongBuiltinType(); + } + if (rel->IsSupertypeOf(checker->GlobalIntBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalIntBuiltinType(), t2)) { + return checker->GlobalIntBuiltinType(); + } + if (rel->IsSupertypeOf(checker->GlobalShortBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalShortBuiltinType(), t2)) { + return checker->GlobalShortBuiltinType(); + } + if (rel->IsSupertypeOf(checker->GlobalByteBuiltinType(), t1) || + rel->IsSupertypeOf(checker->GlobalByteBuiltinType(), t2)) { + return checker->GlobalByteBuiltinType(); + } + ES2PANDA_UNREACHABLE(); +} + checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const { if (expr->TsType() != nullptr) { @@ -1620,21 +1646,10 @@ checker::Type *ETSAnalyzer::Check(ir::ConditionalExpression *expr) const if (checker->IsTypeIdenticalTo(consequentType, alternateType)) { expr->SetTsType(checker->GetNonConstantType(consequentType)); + } else if (IsNumericType(GetETSChecker(), consequentType) && IsNumericType(GetETSChecker(), alternateType)) { + expr->SetTsType(BiggerNumericType(GetETSChecker(), consequentType, alternateType)); } else { - // If possible and required update number literal type to the proper value (identical to left-side type) - if (alternate->IsNumberLiteral() && - checker->AdjustNumberLiteralType(alternate->AsNumberLiteral(), alternateType, consequentType)) { - expr->SetTsType(consequentType); - } else if (consequent->IsNumberLiteral() && - checker->AdjustNumberLiteralType(consequent->AsNumberLiteral(), consequentType, alternateType)) { - expr->SetTsType(alternateType); - } else { - expr->SetTsType(checker->CreateETSUnionType({consequentType, alternateType})); - if (expr->TsType()->IsETSReferenceType()) { - checker->MaybeBoxExpression(expr->Consequent()); - checker->MaybeBoxExpression(expr->Alternate()); - } - } + expr->SetTsType(checker->CreateETSUnionType({consequentType, alternateType})); } // Restore smart casts to initial state. @@ -1662,16 +1677,28 @@ static Type *TransformTypeForMethodReference(ETSChecker *checker, ir::Expression return type; // type is actually used as method } - if (type->AsETSFunctionType()->CallSignatures().at(0)->HasSignatureFlag(SignatureFlags::PRIVATE)) { + auto *const functionType = type->AsETSFunctionType(); + auto &signatures = functionType->CallSignatures(); + + if (signatures.at(0)->HasSignatureFlag(SignatureFlags::PRIVATE)) { checker->LogError(diagnostic::PRIVATE_METHOD_AS_VALUE, getUseSite()); return checker->GlobalTypeError(); } - if (type->AsETSFunctionType()->CallSignatures().size() > 1) { + auto it = signatures.begin(); + while (it != signatures.end()) { + if ((*it)->HasSignatureFlag(SignatureFlags::ABSTRACT)) { + it = signatures.erase(it); + } else { + ++it; + } + } + + if (signatures.size() > 1U) { checker->LogError(diagnostic::OVERLOADED_METHOD_AS_VALUE, getUseSite()); return checker->GlobalTypeError(); } - return type->AsETSFunctionType()->MethodToArrow(checker); + return functionType->MethodToArrow(checker); } checker::Type *ETSAnalyzer::Check(ir::Identifier *expr) const @@ -1744,7 +1771,7 @@ checker::Type *ETSAnalyzer::ResolveMemberExpressionByBaseType(ETSChecker *checke if (baseType->IsETSArrayType()) { if (expr->Property()->AsIdentifier()->Name().Is("length")) { - return expr->AdjustType(checker, checker->GlobalIntType()); + return expr->AdjustType(checker, checker->GlobalIntBuiltinType()); } return expr->SetAndAdjustType(checker, checker->GlobalETSObjectType()); @@ -1834,11 +1861,6 @@ checker::Type *ETSAnalyzer::Check(ir::MemberExpression *expr) const return ResolveMemberExpressionByBaseType(checker, baseType, expr); } -checker::Type *ETSAnalyzer::PreferredType(ir::ObjectExpression *expr) const -{ - return expr->preferredType_; -} - checker::Type *ETSAnalyzer::CheckDynamic(ir::ObjectExpression *expr) const { ETSChecker *checker = GetETSChecker(); @@ -1884,7 +1906,7 @@ static void SetTypeforRecordProperties(const ir::ObjectExpression *expr, checker for (auto *const recordProperty : recordProperties) { auto *const recordPropertyExpr = recordProperty->AsProperty()->Value(); - ETSChecker::SetPreferredTypeIfPossible(recordPropertyExpr, valueType); + recordPropertyExpr->SetPreferredType(valueType); recordPropertyExpr->Check(checker); } } @@ -2342,7 +2364,7 @@ void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, return; } - ETSChecker::SetPreferredTypeIfPossible(value, propType); + value->SetPreferredType(propType); key->SetTsType(propType); value->SetTsType(value->Check(checker)); @@ -2536,9 +2558,7 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const auto argType = expr->argument_->Check(checker); const auto isCondExpr = expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK; - checker::Type *operandType = checker->ApplyUnaryOperatorPromotion(argType, true, true, isCondExpr); - auto unboxedOperandType = - isCondExpr ? checker->MaybeUnboxConditionalInRelation(argType) : checker->MaybeUnboxInRelation(argType); + checker::Type *operandType = checker->ApplyUnaryOperatorPromotion(argType, isCondExpr); if (argType != nullptr && argType->IsETSBigIntType() && argType->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) { switch (expr->OperatorType()) { @@ -2571,11 +2591,6 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const } } - if ((argType != nullptr) && argType->IsETSObjectType() && (unboxedOperandType != nullptr) && - unboxedOperandType->IsETSPrimitiveType()) { - expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedOperandType)); - } - SetTsTypeForUnaryExpression(checker, expr, operandType); checker->Context().CheckUnarySmartCastCondition(expr); @@ -2627,11 +2642,6 @@ checker::Type *ETSAnalyzer::Check(ir::UpdateExpression *expr) const return expr->SetTsType(checker->GlobalTypeError()); } - if (operandType->IsETSObjectType()) { - expr->Argument()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(unboxedType) | - checker->GetBoxingFlag(unboxedType)); - } - return expr->SetTsType(operandType); } @@ -2647,7 +2657,9 @@ checker::Type *ETSAnalyzer::Check(ir::BooleanLiteral *expr) const { ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { - expr->SetTsType(checker->CreateETSBooleanType(expr->Value())); + auto type = checker->GlobalETSBooleanBuiltinType()->Clone(GetChecker()); + type->AddTypeFlag(TypeFlag::CONSTANT); + expr->SetTsType(type); } return expr->TsType(); } @@ -2656,7 +2668,9 @@ checker::Type *ETSAnalyzer::Check(ir::CharLiteral *expr) const { ETSChecker *checker = GetETSChecker(); if (expr->TsType() == nullptr) { - expr->SetTsType(checker->ProgramAllocator()->New(expr->Char())); + auto type = checker->GlobalCharBuiltinType()->Clone(GetChecker()); + type->AddTypeFlag(TypeFlag::CONSTANT); + expr->SetTsType(type); } return expr->TsType(); } @@ -2670,26 +2684,62 @@ checker::Type *ETSAnalyzer::Check(ir::NullLiteral *expr) const return expr->TsType(); } -checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const +static bool CheckIfLiteralValueIsAppropriate(ETSChecker *checker, Type *type, ir::NumberLiteral *expr) { - ETSChecker *checker = GetETSChecker(); - if (expr->Number().IsInt()) { - expr->SetTsType(checker->CreateIntType(expr->Number().GetInt())); - return expr->TsType(); + auto number = expr->Number(); + auto relation = checker->Relation(); + if (relation->IsSupertypeOf(checker->GetGlobalTypesHolder()->GlobalIntegralBuiltinType(), type)) { + if (number.IsReal()) { + return false; + } + auto val = number.GetValueAndCastTo(); + if (relation->IsIdenticalTo(type, checker->GlobalByteBuiltinType())) { + return val >= std::numeric_limits::min() && val <= std::numeric_limits::max(); + } + if (relation->IsIdenticalTo(type, checker->GlobalShortBuiltinType())) { + return val >= std::numeric_limits::min() && val <= std::numeric_limits::max(); + } + if (relation->IsIdenticalTo(type, checker->GlobalIntBuiltinType())) { + return val >= std::numeric_limits::min() && val <= std::numeric_limits::max(); + } + } else if (number.IsDouble()) { + return relation->IsIdenticalTo(checker->GlobalDoubleBuiltinType(), type); } + return true; +} - if (expr->Number().IsLong()) { - expr->SetTsType(checker->CreateLongType(expr->Number().GetLong())); +checker::Type *ETSAnalyzer::Check(ir::NumberLiteral *expr) const +{ + if (expr->TsType() != nullptr) { return expr->TsType(); } - if (expr->Number().IsFloat()) { - expr->SetTsType(checker->CreateFloatType(expr->Number().GetFloat())); - return expr->TsType(); + ETSChecker *checker = GetETSChecker(); + Type *type; + + if (auto *preferredType = + GetAppropriatePreferredType(expr->PreferredType(), [&](Type *tp) { return checker->CheckIfNumeric(tp); }); + preferredType != nullptr && !expr->IsFolded() && + CheckIfLiteralValueIsAppropriate(checker, preferredType, expr)) { + type = preferredType->Clone(checker); + } else if (expr->Number().IsInt()) { + type = checker->GlobalIntBuiltinType()->Clone(checker); + } else if (expr->Number().IsLong()) { + type = checker->GlobalLongBuiltinType()->Clone(checker); + } else if (expr->Number().IsFloat()) { + type = checker->GlobalFloatBuiltinType()->Clone(checker); + } else if (expr->Number().IsDouble()) { + type = checker->GlobalDoubleBuiltinType()->Clone(checker); + } else if (expr->Number().IsShort()) { + type = checker->GlobalShortBuiltinType()->Clone(checker); + } else if (expr->Number().IsByte()) { + type = checker->GlobalByteBuiltinType()->Clone(checker); + } else { + return checker->GlobalTypeError(); } - expr->SetTsType(checker->CreateDoubleType(expr->Number().GetDouble())); - return expr->TsType(); + type->AddTypeFlag(TypeFlag::CONSTANT); + return expr->SetTsType(type); } checker::Type *ETSAnalyzer::Check(ir::StringLiteral *expr) const @@ -2853,6 +2903,21 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationDeclaration *st) const return ReturnTypeForStatement(st); } +static void ProcessRequiredFields(ArenaUnorderedMap &fieldMap, + ir::AnnotationUsage *st, ETSChecker *checker) +{ + for (const auto &entry : fieldMap) { + if (entry.second->Value() == nullptr) { + checker->LogError(diagnostic::ANNOT_FIELD_NO_VAL, {entry.first}, st->Start()); + continue; + } + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto *clone = entry.second->Clone(checker->Allocator(), st); + st->AddProperty(clone); + clone->Check(checker); + } +} + checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const { if (st->Expr()->TsType() != nullptr) { @@ -2889,7 +2954,7 @@ checker::Type *ETSAnalyzer::Check(ir::AnnotationUsage *st) const checker->CheckMultiplePropertiesAnnotation(st, st->GetBaseName()->Name(), fieldMap); } - checker->ProcessRequiredFields(fieldMap, st, checker); + ProcessRequiredFields(fieldMap, st, checker); return ReturnTypeForStatement(st); } @@ -2951,7 +3016,7 @@ static bool ValidateAndProcessIteratorType(ETSChecker *checker, Type *elemType, relation->SetNode(ident); if (auto ctx = checker::AssignmentContext(checker->Relation(), ident, elemType, iterType, ident->Start(), std::nullopt, TypeRelationFlag::NO_THROW); - !ctx.IsAssignable()) { + !ctx.IsAssignable() && !relation->IsLegalBoxedPrimitiveConversion(iterType, elemType)) { checker->LogError(diagnostic::ITERATOR_ELEMENT_TYPE_MISMATCH, {elemType, iterType}, st->Start()); return false; } @@ -2986,7 +3051,7 @@ checker::Type *ETSAnalyzer::Check(ir::ForOfStatement *const st) const checker::Type *elemType = nullptr; if (exprType->IsETSStringType()) { - elemType = checker->GetGlobalTypesHolder()->GlobalCharType(); + elemType = checker->GlobalCharBuiltinType(); } else if (exprType->IsETSArrayType() || exprType->IsETSResizableArrayType()) { elemType = checker->GetElementTypeOfArray(exprType); } else if (exprType->IsETSObjectType() || exprType->IsETSUnionType() || exprType->IsETSTypeParameter()) { @@ -3155,24 +3220,11 @@ bool ETSAnalyzer::CheckInferredFunctionReturnType(ir::ReturnStatement *st, ir::S return false; } - if (st->argument_->IsObjectExpression()) { - st->argument_->AsObjectExpression()->SetPreferredType(funcReturnType); - } if (st->argument_->IsMemberExpression()) { checker->SetArrayPreferredTypeForNestedMemberExpressions(st->argument_->AsMemberExpression(), funcReturnType); - } - - if (st->argument_->IsArrayExpression()) { - st->argument_->AsArrayExpression()->SetPreferredType(funcReturnType); - } - - if (st->argument_->IsETSNewArrayInstanceExpression()) { - st->argument_->AsETSNewArrayInstanceExpression()->SetPreferredType(funcReturnType); - } - - if (st->argument_->IsETSNewMultiDimArrayInstanceExpression()) { - st->argument_->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredType(funcReturnType); + } else { + st->argument_->SetPreferredType(funcReturnType); } checker::Type *argumentType = st->argument_->Check(checker); @@ -3198,13 +3250,14 @@ checker::Type *ETSAnalyzer::GetFunctionReturnType(ir::ReturnStatement *st, ir::S } else { // Case when function's return type should be inferred from return statement(s): if (containingFunc->Signature()->HasSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE)) { - InferReturnType(checker, containingFunc, funcReturnType, - st->argument_); // This removes the NEED_RETURN_TYPE flag, so only the first return - // statement going to land here... + funcReturnType = InferReturnType(checker, containingFunc, + st->argument_); // This removes the NEED_RETURN_TYPE flag, so only the + // first return statement going to land here... } else { // All subsequent return statements: - ProcessReturnStatements(checker, containingFunc, funcReturnType, st, - st->argument_); // and the remaining return statements will get processed here. + funcReturnType = + ProcessReturnStatements(checker, containingFunc, st, + st->argument_); // and the remaining return statements will get processed here. } } @@ -3258,9 +3311,8 @@ checker::Type *ETSAnalyzer::Check(ir::SwitchStatement *st) const checker::TypeRelationFlag::NONE); auto *comparedExprType = checker->CheckSwitchDiscriminant(st->Discriminant()); - auto unboxedDiscType = (st->Discriminant()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U - ? checker->MaybeUnboxInRelation(comparedExprType) - : comparedExprType; + // may have no meaning to unbox comparedExprType + auto unboxedDiscType = checker->MaybeUnboxType(comparedExprType); SmartCastArray smartCasts = checker->Context().CloneSmartCasts(); bool hasDefaultCase = false; @@ -3393,7 +3445,11 @@ checker::Type *ETSAnalyzer::Check(ir::VariableDeclarator *st) const // NOTE: T_S and K_o_t_l_i_n don't act in such way, but we can try - why not? :) auto *smartType = variableType; if (auto *const initType = st->Init() != nullptr ? st->Init()->TsType() : nullptr; initType != nullptr) { - smartType = checker->ResolveSmartType(initType, variableType); + auto const value = st->Init()->IsNumberLiteral() + ? std::make_optional(st->Init()->AsNumberLiteral()->Number().GetDouble()) + : std::nullopt; + + smartType = checker->ResolveSmartType(initType, variableType, value); // Set smart type for identifier if it differs from annotated type // Top-level and captured variables are not processed here! if (!checker->Relation()->IsIdenticalTo(variableType, smartType)) { @@ -3470,27 +3526,23 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const return checker->InvalidateType(expr); } - ETSChecker::SetPreferredTypeIfPossible(expr->Expr(), targetType); + expr->Expr()->SetPreferredType(targetType); auto const sourceType = expr->Expr()->Check(checker); if (sourceType->IsTypeError()) { return checker->InvalidateType(expr); } - // NOTE(vpukhov): #20510 lowering - if (targetType->IsETSPrimitiveType() && sourceType->IsETSReferenceType()) { - auto *const boxedTargetType = checker->MaybeBoxInRelation(targetType); - if (!checker->Relation()->IsIdenticalTo(sourceType, boxedTargetType)) { - expr->Expr()->AddAstNodeFlags(ir::AstNodeFlags::CHECKCAST); - } - } - if (sourceType->DefinitelyETSNullish() && !targetType->PossiblyETSNullish()) { - return checker->TypeError(expr, diagnostic::NULLISH_CAST_TO_NONNULLISH, expr->Start()); + return expr->SetTsType(checker->TypeError(expr, diagnostic::NULLISH_CAST_TO_NONNULLISH, expr->Start())); } const checker::CastingContext ctx( - checker->Relation(), diagnostic::INVALID_CAST, {sourceType, targetType}, + checker->Relation(), + sourceType->IsBuiltinNumeric() && targetType->IsBuiltinNumeric() ? diagnostic::IMPROPER_NUMERIC_CAST + : diagnostic::INVALID_CAST, + // CC-OFFNXT(G.FMT.03-CPP) project code style + {sourceType, targetType}, checker::CastingContext::ConstructorData {expr->Expr(), sourceType, targetType, expr->Expr()->Start()}); if (sourceType->IsETSDynamicType() && targetType->IsLambdaObject()) { @@ -3509,12 +3561,10 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const } if (targetType == checker->GetGlobalTypesHolder()->GlobalETSNeverType()) { - return checker->TypeError(expr, diagnostic::CAST_TO_NEVER, expr->Start()); + return expr->SetTsType(checker->TypeError(expr, diagnostic::CAST_TO_NEVER, expr->Start())); } - checker->ComputeApparentType(targetType); - expr->SetTsType(targetType); - return expr->TsType(); + return expr->SetTsType(targetType); } checker::Type *ETSAnalyzer::Check(ir::TSEnumDeclaration *st) const diff --git a/ets2panda/checker/ETSAnalyzer.h b/ets2panda/checker/ETSAnalyzer.h index c9a398b319..c4a0d46ba6 100644 --- a/ets2panda/checker/ETSAnalyzer.h +++ b/ets2panda/checker/ETSAnalyzer.h @@ -36,7 +36,6 @@ public: virtual checker::Type *Check(ir::nodeType *node) const override; // CC-OFF(G.PRE.02,G.PRE.09) name part AST_NODE_REINTERPRET_MAPPING(DECLARE_ETSANALYZER_CHECK_METHOD) #undef DECLARE_ETSANALYZER_CHECK_METHOD - checker::Type *PreferredType(ir::ObjectExpression *expr) const; checker::Type *CheckDynamic(ir::ObjectExpression *expr) const; checker::Type *GetPreferredType(ir::ArrayExpression *expr) const; void GetUnionPreferredType(ir::Expression *expr, Type *originalType) const; diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index bf00645a61..cec0d02e2d 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -509,26 +509,12 @@ ArenaVector GetUnionTypeSignatures(ETSChecker *checker, ch void ProcessExclamationMark(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType) { - if (checker->IsNullLikeOrVoidExpression(expr->Argument())) { - auto tsType = checker->CreateETSBooleanType(true); - tsType->AddTypeFlag(checker::TypeFlag::CONSTANT); - expr->SetTsType(tsType); - return; - } - if (operandType == nullptr || operandType->IsTypeError()) { expr->SetTsType(checker->GlobalTypeError()); return; } - auto exprRes = operandType->ResolveConditionExpr(); - if (std::get<0>(exprRes)) { - auto tsType = checker->CreateETSBooleanType(!std::get<1>(exprRes)); - tsType->AddTypeFlag(checker::TypeFlag::CONSTANT); - expr->SetTsType(tsType); - return; - } - expr->SetTsType(checker->GlobalETSBooleanType()); + expr->SetTsType(checker->GlobalETSBooleanBuiltinType()); } void SetTsTypeForUnaryExpression(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType) @@ -536,24 +522,19 @@ void SetTsTypeForUnaryExpression(ETSChecker *checker, ir::UnaryExpression *expr, switch (expr->OperatorType()) { case lexer::TokenType::PUNCTUATOR_MINUS: case lexer::TokenType::PUNCTUATOR_PLUS: { - if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { + if (operandType == nullptr || !operandType->IsETSObjectType() || + !operandType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::CONVERTIBLE_TO_NUMERIC)) { checker->LogError(diagnostic::OPERAND_NOT_NUMERIC, {}, expr->Argument()->Start()); expr->SetTsType(checker->GlobalTypeError()); break; } - if (operandType->HasTypeFlag(checker::TypeFlag::CONSTANT) && - expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS) { - expr->SetTsType(checker->NegateNumericType(operandType, expr)); - break; - } - expr->SetTsType(operandType); break; } case lexer::TokenType::PUNCTUATOR_TILDE: { - if (operandType == nullptr || !operandType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - checker->LogError(diagnostic::OPERAND_NOT_NUMERIC, {}, expr->Argument()->Start()); + if (operandType == nullptr || !operandType->IsETSObjectType() || + !operandType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::CONVERTIBLE_TO_NUMERIC)) { expr->SetTsType(checker->GlobalTypeError()); break; } @@ -613,11 +594,12 @@ checker::Type *GetIteratorType(ETSChecker *checker, checker::Type *elemType, ir: return iterType; } -bool CheckArgumentVoidType(checker::Type *&funcReturnType, ETSChecker *checker, const std::string &name, +bool CheckArgumentVoidType(checker::Type *funcReturnType, ETSChecker *checker, const std::string &name, ir::ReturnStatement *st) { if (name.find(compiler::Signatures::ETS_MAIN_WITH_MANGLE_BEGIN) != std::string::npos) { - if (!funcReturnType->IsETSVoidType() && !funcReturnType->IsIntType()) { + if (!funcReturnType->IsETSVoidType() && + !checker->Relation()->IsSupertypeOf(checker->GlobalIntBuiltinType(), funcReturnType)) { checker->LogError(diagnostic::MAIN_BAD_RETURN, {}, st->Start()); } } @@ -665,15 +647,14 @@ bool CheckReturnType(ETSChecker *checker, checker::Type *funcReturnType, checker return true; } -void InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, - ir::Expression *stArgument) +checker::Type *InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, ir::Expression *stArgument) { // First (or single) return statement in the function: - funcReturnType = + auto *funcReturnType = stArgument == nullptr ? checker->GlobalVoidType() : checker->GetNonConstantType(stArgument->Check(checker)); if (funcReturnType->IsTypeError()) { containingFunc->Signature()->RemoveSignatureFlag(checker::SignatureFlags::NEED_RETURN_TYPE); - return; + return funcReturnType; } /* @@ -695,8 +676,7 @@ void InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, ch // CC-OFFNXT(G.FMT.02) project code style .IsAssignable()) { checker->LogError(diagnostic::ARROW_TYPE_MISMATCH, {argumentType, funcReturnType}, stArgument->Start()); - funcReturnType = checker->GlobalTypeError(); - return; + return checker->GlobalTypeError(); } } @@ -705,9 +685,11 @@ void InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, ch containingFunc->Signature()->AddSignatureFlag(checker::SignatureFlags::INFERRED_RETURN_TYPE); checker->VarBinder()->AsETSBinder()->BuildFunctionName(containingFunc); - if (stArgument != nullptr && stArgument->IsObjectExpression()) { - stArgument->AsObjectExpression()->SetPreferredType(funcReturnType); + if (stArgument != nullptr) { + stArgument->SetPreferredType(funcReturnType); } + + return funcReturnType; } bool IsArrayExpressionValidInitializerForType(ETSChecker *checker, const Type *const arrayExprPreferredType) @@ -736,16 +718,16 @@ void CastPossibleTupleOnRHS(ETSChecker *checker, ir::AssignmentExpression *expr) } } -void ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, - ir::ReturnStatement *st, ir::Expression *stArgument) +checker::Type *ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containingFunc, ir::ReturnStatement *st, + ir::Expression *stArgument) { - funcReturnType = containingFunc->Signature()->ReturnType(); + auto *funcReturnType = containingFunc->Signature()->ReturnType(); if (stArgument == nullptr) { // previous return statement(s) have value if (!funcReturnType->IsETSVoidType() && funcReturnType != checker->GlobalVoidType()) { checker->LogError(diagnostic::MIXED_VOID_NONVOID, {}, st->Start()); - return; + return funcReturnType; } } else { if (stArgument->IsObjectExpression()) { @@ -761,12 +743,12 @@ void ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containing // previous return statement(s) don't have any value if (funcReturnType->IsETSVoidType() && !argumentType->IsETSVoidType()) { checker->LogError(diagnostic::MIXED_VOID_NONVOID, {}, stArgument->Start()); - return; + return funcReturnType; } const auto name = containingFunc->Scope()->InternalName().Mutf8(); if (!CheckArgumentVoidType(funcReturnType, checker, name, st)) { - return; + return funcReturnType; } auto *const relation = checker->Relation(); @@ -779,6 +761,7 @@ void ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containing relation->SetNode(nullptr); relation->SetFlags(checker::TypeRelationFlag::NONE); } + return funcReturnType; } bool CheckReturnTypeNecessity(ir::MethodDefinition *node) @@ -813,4 +796,28 @@ void CheckAllConstPropertyInitialized(checker::ETSChecker *checker, ir::ETSModul } } +// NOLINTBEGIN(readability-else-after-return) +std::tuple IsConstantTestValue(ir::Expression const *expr) +{ + if (expr->IsNullLiteral() || expr->IsUndefinedLiteral()) { + return {true, false}; + } else if (expr->IsBooleanLiteral()) { + return {true, expr->AsBooleanLiteral()->Value()}; + } else if (expr->IsStringLiteral()) { + return {true, expr->AsStringLiteral()->Str().Length() != 0}; + } else if (expr->IsCharLiteral()) { + return {true, expr->AsCharLiteral()->Char() != 0}; + } else if (expr->IsBigIntLiteral()) { + return {true, expr->AsBigIntLiteral()->Str() != "0"}; + } else if (expr->IsNumberLiteral()) { + auto num = expr->AsNumberLiteral()->Number(); + return {true, !num.IsZero()}; + } else if (expr->TsType()->IsETSEnumType() && expr->TsType()->IsConstantType()) { + // NOTE(gogabr): Should handle enum constants + return {false, false}; + } + return {false, false}; +} +// NOLINTEND(readability-else-after-return) + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ETSAnalyzerHelpers.h b/ets2panda/checker/ETSAnalyzerHelpers.h index 979d6413ac..37ac4ce4f2 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.h +++ b/ets2panda/checker/ETSAnalyzerHelpers.h @@ -52,18 +52,20 @@ ArenaVector GetUnionTypeSignatures(ETSChecker *checker, ch void ProcessExclamationMark(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType); void SetTsTypeForUnaryExpression(ETSChecker *checker, ir::UnaryExpression *expr, checker::Type *operandType); checker::Type *GetIteratorType(ETSChecker *checker, checker::Type *elemType, ir::AstNode *left); -bool CheckArgumentVoidType(checker::Type *&funcReturnType, ETSChecker *checker, const std::string &name, +bool CheckArgumentVoidType(checker::Type *funcReturnType, ETSChecker *checker, const std::string &name, ir::ReturnStatement *st); bool CheckReturnType(ETSChecker *checker, checker::Type *funcReturnType, checker::Type *argumentType, ir::Expression *stArgument, ir::ScriptFunction *containingFunc); -void InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, - ir::Expression *stArgument); +checker::Type *InferReturnType(ETSChecker *checker, ir::ScriptFunction *containingFunc, ir::Expression *stArgument); bool IsArrayExpressionValidInitializerForType(ETSChecker *checker, const Type *arrayExprPreferredType); void CastPossibleTupleOnRHS(ETSChecker *checker, ir::AssignmentExpression *expr); -void ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containingFunc, checker::Type *&funcReturnType, - ir::ReturnStatement *st, ir::Expression *stArgument); +checker::Type *ProcessReturnStatements(ETSChecker *checker, ir::ScriptFunction *containingFunc, ir::ReturnStatement *st, + ir::Expression *stArgument); bool CheckReturnTypeNecessity(ir::MethodDefinition *node); + void CheckAllConstPropertyInitialized(checker::ETSChecker *checker, ir::ETSModule *pkg); + +std::tuple IsConstantTestValue(ir::Expression const *expr); } // namespace ark::es2panda::checker #endif // ES2PANDA_CHECKER_ETSANALYZERHELPERS_H diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 3955fcc851..f345e2e86b 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -746,19 +746,20 @@ void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *callExpr) VarBinder()->AsETSBinder()->HandleCustomNodes(callExpr); } -Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type) +Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type) const noexcept { - switch (ETSType(type)) { - case checker::TypeFlag::FLOAT: { - return GlobalIntType(); - } - case checker::TypeFlag::DOUBLE: { - return GlobalLongType(); + if (type->IsETSObjectType()) { + auto const *objectType = type->AsETSObjectType(); + + if (objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) { + return GlobalIntBuiltinType(); } - default: { - return type; + + if (objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { + return GlobalLongBuiltinType(); } } + return type; } Signature *ETSChecker::FindExtensionSetterInMap(util::StringView name, ETSObjectType *type) @@ -780,4 +781,11 @@ void ETSChecker::InsertExtensionGetterToMap(util::StringView name, ETSObjectType { GetGlobalTypesHolder()->InsertExtensionGetterToMap(name, type, sig); } + +bool ETSChecker::TypeHasDefaultValue(Type *tp) const +{ + return tp->IsBuiltinNumeric() || tp->IsETSBooleanType() || tp->IsETSCharType() || + Relation()->IsSupertypeOf(GlobalETSUndefinedType(), tp); +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 79552cedb2..97ae5b8f2b 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -212,8 +212,7 @@ public: void ValidateImplementedInterface(ETSObjectType *type, Type *interface, std::unordered_set *extendsSet, const lexer::SourcePosition &pos); void ResolveDeclaredMembersOfObject(const Type *type); - lexer::Number ExtractNumericValue(Type const *const indexType); - std::optional GetTupleElementAccessValue(const Type *type); + std::optional GetTupleElementAccessValue(const ir::Expression *expr); bool ValidateArrayIndex(ir::Expression *expr, bool relaxed = false); bool ValidateTupleIndex(const ETSTupleType *tuple, ir::MemberExpression *expr, bool reportError = true); bool ValidateTupleIndexFromEtsObject(const ETSTupleType *const tuple, ir::MemberExpression *expr); @@ -296,6 +295,8 @@ public: void VariableTypeFromInitializer(varbinder::Variable *variable, Type *annotationType, Type *initType); + bool TypeHasDefaultValue(Type *tp) const; + // Type creation ByteType *CreateByteType(int8_t value); ETSBooleanType *CreateETSBooleanType(bool value); @@ -340,7 +341,6 @@ public: std::tuple CreateBuiltinArraySignatureInfo(const ETSArrayType *arrayType, size_t dim); Signature *CreateBuiltinArraySignature(const ETSArrayType *arrayType, size_t dim); - IntType *CreateIntTypeFromType(Type *type); std::tuple CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName); ETSObjectType *CreatePromiseOf(Type *type); @@ -349,7 +349,6 @@ public: SignatureInfo *CreateSignatureInfo(); // Arithmetic - Type *NegateNumericType(Type *type, ir::Expression *node); bool CheckBinaryOperatorForBigInt(Type *left, Type *right, lexer::TokenType op); [[nodiscard]] bool CheckBinaryPlusMultDivOperandsForUnionType(const Type *leftType, const Type *rightType, const ir::Expression *left, @@ -365,12 +364,9 @@ public: checker::Type *CheckBinaryOperatorMulDivMod( std::tuple op, bool isEqualOp, std::tuple types); - checker::Type *CheckBinaryOperatorForIntEnums(const checker::Type *const leftType, - const checker::Type *const rightType); + checker::Type *CheckBinaryBitwiseOperatorForIntEnums(const checker::Type *const leftType, const checker::Type *const rightType); - checker::Type *CheckBinaryOperatorPlusForEnums(const checker::Type *const leftType, - const checker::Type *const rightType); checker::Type *CheckBinaryOperatorPlus( std::tuple op, bool isEqualOp, std::tuple types); @@ -381,9 +377,8 @@ public: std::tuple op, bool isEqualOp, std::tuple types); // CC-OFFNXT(G.FUN.01-CPP) solid logic - checker::Type *CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, ir::BinaryExpression *expr, - checker::Type *leftType, checker::Type *rightType, Type *unboxedL, - Type *unboxedR); + checker::Type *CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, checker::Type *leftType, + checker::Type *rightType, Type *unboxedL, Type *unboxedR); std::tuple CheckBinaryOperatorStrictEqual(ir::Expression *left, lexer::TokenType operationType, lexer::SourcePosition pos, checker::Type *leftType, checker::Type *rightType); @@ -396,15 +391,12 @@ public: checker::Type *rightType); checker::Type *CheckBinaryOperatorNullishCoalescing(ir::Expression *left, ir::Expression *right, lexer::SourcePosition pos); + bool CheckIfNumeric(Type *type); bool AdjustNumberLiteralType(ir::NumberLiteral *literal, Type *literalType, Type *otherType); Type *HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); - Type *HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); - void FlagExpressionWithUnboxing(Type *type, Type *unboxedType, ir::Expression *typeExpression); - template - Type *PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); - - Type *HandleRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); + void SetGenerateValueOfFlags(std::tuple types, + std::tuple nodes); template Type *PerformRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType); @@ -420,7 +412,7 @@ public: bool TrailingLambdaTypeInference(Signature *signature, const ArenaVector &arguments); bool TypeInference(Signature *signature, const ArenaVector &arguments, TypeRelationFlag flags = TypeRelationFlag::NONE); - bool CheckLambdaTypeAnnotation(ir::AstNode *typeAnnotation, ir::ArrowFunctionExpression *arrowFuncExpr, + bool CheckLambdaTypeAnnotation(ir::ETSParameterExpression *param, ir::ArrowFunctionExpression *arrowFuncExpr, Type *parameterType, TypeRelationFlag flags); bool CheckLambdaInfer(ir::AstNode *typeAnnotation, ir::ArrowFunctionExpression *arrowFuncExpr, Type *const subParameterType); @@ -507,6 +499,7 @@ public: Signature *ResolvePotentialTrailingLambdaWithReceiver(ir::CallExpression *callExpr, ArenaVector const &signatures, ArenaVector &arguments); + Signature *MakeSignatureInvocable(Signature *sig, ir::CallExpression *callExpr); Signature *ResolveCallExpressionAndTrailingLambda(ArenaVector &signatures, ir::CallExpression *callExpr, const lexer::SourcePosition &pos, TypeRelationFlag reportFlag = TypeRelationFlag::NONE); @@ -527,8 +520,8 @@ public: Signature *CheckEveryAbstractSignatureIsOverridden(ETSFunctionType *target, ETSFunctionType *source); static Signature *GetSignatureFromMethodDefinition(const ir::MethodDefinition *methodDef); bool CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload, - const ir::MethodDefinition *currentFunc, bool omitSameAsm = false); - static bool CmpAssemblerTypesWithRank(Signature const *const sig1, Signature const *const sig2) noexcept; + const ir::MethodDefinition *currentFunc, bool omitSameAsm = false, + TypeRelationFlag relationFlags = TypeRelationFlag::NO_RETURN_TYPE_CHECK); static bool HasSameAssemblySignature(Signature const *const sig1, Signature const *const sig2) noexcept; static bool HasSameAssemblySignatures(ETSFunctionType const *const func1, ETSFunctionType const *const func2) noexcept; @@ -594,9 +587,6 @@ public: bool IsNullLikeOrVoidExpression(const ir::Expression *expr) const; bool IsConstantExpression(ir::Expression *expr, Type *type); void ValidateUnaryOperatorOperand(varbinder::Variable *variable); - bool ValidateAnnotationPropertyType(checker::Type *tsType); - void ProcessRequiredFields(ArenaUnorderedMap &fieldMap, - ir::AnnotationUsage *st, ETSChecker *checker) const; void CheckFunctionSignatureAnnotations(const ArenaVector ¶ms, ir::TSTypeParameterDeclaration *typeParams, ir::TypeNode *returnTypeAnnotation); @@ -617,15 +607,11 @@ public: void InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::ArrowFunctionExpression *init); checker::Type *ApplyConditionalOperatorPromotion(checker::ETSChecker *checker, checker::Type *unboxedL, checker::Type *unboxedR); - Type *ApplyUnaryOperatorPromotion(Type *type, bool createConst = true, bool doPromotion = true, - bool isCondExpr = false); + Type *ApplyUnaryOperatorPromotion(Type *type, bool isCondExpr = false); + Type *GetUnaryOperatorPromotedType(Type *type, const bool doPromotion = true); Type *HandleBooleanLogicalOperators(Type *leftType, Type *rightType, lexer::TokenType tokenType); - bool HandleLogicalPotentialResult(ir::Expression *left, ir::Expression *right, ir::BinaryExpression *expr, - checker::Type *leftType); - - checker::Type *FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags, - ir::Expression *init); + checker::Type *FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags); void CheckEnumType(ir::Expression *init, checker::Type *initType, const util::StringView &varName); checker::Type *CheckVariableDeclaration(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init, ir::ModifierFlags flags); @@ -657,11 +643,7 @@ public: Type *MaybeUnboxInRelation(Type *objectType); Type *MaybeUnboxConditionalInRelation(Type *objectType); Type *MaybeBoxInRelation(Type *objectType); - void AddBoxingUnboxingFlagsToNode(ir::AstNode *node, Type *boxingUnboxingType); - ir::BoxingUnboxingFlags GetBoxingFlag(Type *boxingType); - ir::BoxingUnboxingFlags GetUnboxingFlag(Type const *unboxingType) const; Type *MaybeBoxExpression(ir::Expression *expr); - Type *MaybeUnboxExpression(ir::Expression *expr); Type *MaybeBoxType(Type *type) const; Type *MaybeUnboxType(Type *type) const; Type const *MaybeBoxType(Type const *type) const; @@ -671,7 +653,6 @@ public: bool CompareIdentifiersValuesAreDifferent(ir::Expression *compareValue, const std::string &caseValue); void CheckIdentifierSwitchCase(ir::Expression *currentCase, ir::Expression *compareCase, const lexer::SourcePosition &pos); - std::string GetStringFromLiteral(ir::Expression *caseTest) const; varbinder::Variable *FindVariableInFunctionScope(util::StringView name); std::pair FindVariableInClassOrEnclosing( util::StringView name, const ETSObjectType *classType); @@ -684,8 +665,6 @@ public: bool IsSameDeclarationType(varbinder::LocalVariable *target, varbinder::LocalVariable *compare); void SaveCapturedVariable(varbinder::Variable *var, ir::Identifier *ident); bool SaveCapturedVariableInLocalClass(varbinder::Variable *var, ir::Identifier *ident); - void MaybeAddBoxingFlagInRelation(TypeRelation *relation, Type *target); - void MaybeAddUnboxingFlagInRelation(TypeRelation *relation, Type *source, Type *self); void CheckUnboxedTypeWidenable(TypeRelation *relation, Type *target, Type *self); void CheckUnboxedTypesAssignable(TypeRelation *relation, Type *source, Type *target); void CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target); @@ -710,7 +689,7 @@ public: bool IsExtensionAccessorFunctionType(const checker::Type *type); bool IsArrayExprSizeValidForTuple(const ir::ArrayExpression *arrayExpr, const ETSTupleType *tuple); void ModifyPreferredType(ir::ArrayExpression *arrayExpr, Type *newPreferredType); - Type *SelectGlobalIntegerTypeForNumeric(Type *type); + Type *SelectGlobalIntegerTypeForNumeric(Type *type) const noexcept; ir::ClassProperty *ClassPropToImplementationProp(ir::ClassProperty *classProp, varbinder::ClassScope *scope); ir::Expression *GenerateImplicitInstantiateArg(const std::string &className); @@ -730,7 +709,6 @@ public: void ETSObjectTypeDeclNode(ETSChecker *checker, ETSObjectType *const objectType); ir::CallExpression *CreateExtensionAccessorCall(ETSChecker *checker, ir::MemberExpression *expr, ArenaVector &&args); - static void SetPreferredTypeIfPossible(ir::Expression *expr, Type *targetType); Signature *FindRelativeExtensionGetter(ir::MemberExpression *const expr, ETSFunctionType *funcType); Signature *FindRelativeExtensionSetter(ir::MemberExpression *const expr, ETSFunctionType *funcType); Type *GetExtensionAccessorReturnType(ir::MemberExpression *expr); @@ -789,7 +767,8 @@ public: static NamedAccessMeta FormNamedAccessMetadata(varbinder::Variable const *prop); // Smart cast support - [[nodiscard]] checker::Type *ResolveSmartType(checker::Type *sourceType, checker::Type *targetType); + [[nodiscard]] checker::Type *ResolveSmartType(checker::Type *sourceType, checker::Type *targetType, + std::optional value = std::nullopt); [[nodiscard]] std::pair CheckTestNullishCondition(Type *testedType, Type *actualType, bool strict); [[nodiscard]] std::pair CheckTestObjectCondition(ETSObjectType *testedType, Type *actualType, bool strict); @@ -922,6 +901,11 @@ public: return arrowToFuncInterfaces_; } + void ClearApparentTypes() noexcept + { + apparentTypes_.clear(); + } + void CleanUp() override { Checker::CleanUp(); @@ -1046,15 +1030,6 @@ private: bool ComputeSuperType(ETSObjectType *type); - template - UType HandleModulo(UType leftValue, UType rightValue); - - template - Type *HandleBitWiseArithmetic(Type *leftValue, Type *rightValue, lexer::TokenType operationType); - - template - typename TargetType::UType GetOperand(Type *type); - template ETSObjectType *AsETSObjectType(Type *(GlobalTypesHolder::*typeFunctor)(Args...), Args... args) const; Signature *GetMostSpecificSignature(ArenaVector &compatibleSignatures, diff --git a/ets2panda/checker/ets/aliveAnalyzer.cpp b/ets2panda/checker/ets/aliveAnalyzer.cpp index 5714edf7ca..e3b69b9a5a 100644 --- a/ets2panda/checker/ets/aliveAnalyzer.cpp +++ b/ets2panda/checker/ets/aliveAnalyzer.cpp @@ -44,6 +44,7 @@ #include "ir/ets/etsNewClassInstanceExpression.h" #include "ir/ets/etsStructDeclaration.h" #include "ir/ts/tsInterfaceDeclaration.h" +#include "checker/ETSAnalyzerHelpers.h" #include "checker/types/globalTypesHolder.h" #include "varbinder/variable.h" #include "varbinder/declaration.h" @@ -282,7 +283,7 @@ void AliveAnalyzer::AnalyzeDoLoop(const ir::DoWhileStatement *doWhile) status_ = Or(status_, ResolveContinues(doWhile)); AnalyzeNode(doWhile->Test()); ES2PANDA_ASSERT(doWhile->Test()->TsType()); - const auto exprRes = doWhile->Test()->TsType()->ResolveConditionExpr(); + const auto exprRes = IsConstantTestValue(doWhile->Test()); status_ = And(status_, static_cast(!std::get<0>(exprRes) || !std::get<1>(exprRes))); status_ = Or(status_, ResolveBreaks(doWhile)); } @@ -292,7 +293,7 @@ void AliveAnalyzer::AnalyzeWhileLoop(const ir::WhileStatement *whileStmt) SetOldPendingExits(PendingExits()); AnalyzeNode(whileStmt->Test()); ES2PANDA_ASSERT(whileStmt->Test()->TsType()); - const auto exprRes = whileStmt->Test()->TsType()->ResolveConditionExpr(); + const auto exprRes = IsConstantTestValue(whileStmt->Test()); status_ = And(status_, static_cast(!std::get<0>(exprRes) || std::get<1>(exprRes))); AnalyzeStat(whileStmt->Body()); status_ = Or(status_, ResolveContinues(whileStmt)); @@ -311,7 +312,7 @@ void AliveAnalyzer::AnalyzeForLoop(const ir::ForUpdateStatement *forStmt) AnalyzeNode(forStmt->Test()); ES2PANDA_ASSERT(forStmt->Test()->TsType()); condType = forStmt->Test()->TsType(); - std::tie(resolveType, res) = forStmt->Test()->TsType()->ResolveConditionExpr(); + std::tie(resolveType, res) = IsConstantTestValue(forStmt->Test()); status_ = From(!resolveType || res); } else { status_ = LivenessStatus::ALIVE; diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index 61273a7daf..3f7cdeda3d 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -15,7 +15,7 @@ #include "arithmetic.h" -#include "checker/types/ts/nullType.h" +#include "checker/types/globalTypesHolder.h" #include "lexer/token/token.h" namespace ark::es2panda::checker { @@ -28,7 +28,7 @@ struct BinaryArithmOperands { checker::Type *reducedR; }; -static inline BinaryArithmOperands GetBinaryOperands(ETSChecker *checker, ir::BinaryExpression *expr) +static BinaryArithmOperands GetBinaryOperands(ETSChecker *checker, ir::BinaryExpression *expr) { auto typeL = expr->Left()->Check(checker); auto typeR = expr->Right()->Check(checker); @@ -48,20 +48,6 @@ static void LogOperatorCannotBeApplied(ETSChecker *checker, BinaryArithmOperands LogOperatorCannotBeApplied(checker, ops.expr->OperatorType(), ops.typeL, ops.typeR, ops.expr->Start()); } -static inline void UnboxOperands(ETSChecker *checker, BinaryArithmOperands const &ops) -{ - auto const unbox = [checker](ir::Expression *expr, Type *type, Type *reducedType) { - if (type != reducedType) { - expr->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(reducedType)); - } - if (reducedType->IsETSEnumType()) { - expr->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - } - }; - unbox(ops.expr->Left(), ops.typeL, ops.reducedL); - unbox(ops.expr->Right(), ops.typeR, ops.reducedR); -} - static inline void RepairTypeErrorsInOperands(Type **left, Type **right) { if (IsTypeError(*left)) { @@ -87,11 +73,31 @@ static inline void RepairTypeErrorWithDefault(Type **type, Type *dflt) } } -static Type *EffectiveTypeOfNumericOp(ETSChecker *checker, Type *left, Type *right) +static bool CheckOpArgsTypeEq(ETSChecker *checker, Type *left, Type *right, Type *type) { - ES2PANDA_ASSERT(left->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - right->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); + return ((left != nullptr) && (right != nullptr) && checker->IsTypeIdenticalTo(left, type) && + checker->IsTypeIdenticalTo(right, type)); +} + +static bool FindOpArgsType(ETSChecker *checker, Type *left, Type *right, Type *target) +{ + return (checker->Relation()->IsSupertypeOf(target, left) || checker->Relation()->IsSupertypeOf(target, right)); +} + +bool ETSChecker::CheckIfNumeric(Type *type) +{ + if (type == nullptr) { + return false; + } + if (type->IsETSPrimitiveType()) { + return type->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC); + } + auto *unboxed = MaybeUnboxInRelation(type); + return (unboxed != nullptr) && unboxed->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC); +} +static Type *EffectivePrimitiveTypeOfNumericOp(ETSChecker *checker, Type *left, Type *right) +{ if (left->IsDoubleType() || right->IsDoubleType()) { return checker->GlobalDoubleType(); } @@ -101,7 +107,10 @@ static Type *EffectiveTypeOfNumericOp(ETSChecker *checker, Type *left, Type *rig if (left->IsLongType() || right->IsLongType()) { return checker->GlobalLongType(); } - return checker->GlobalIntType(); + if (left->IsCharType() && right->IsCharType()) { + return checker->GlobalCharType(); + } + return checker->GlobalIntType(); // return int in case of primitive types by default } static Type *TryConvertToPrimitiveType(ETSChecker *checker, Type *type) @@ -111,99 +120,80 @@ static Type *TryConvertToPrimitiveType(ETSChecker *checker, Type *type) } if (type->IsETSIntEnumType()) { + // Pull out the type argument to BaseEnum + if (type->AsETSObjectType()->SuperType() != nullptr && + !type->AsETSObjectType()->SuperType()->TypeArguments().empty()) { + auto *baseEnumArg = type->AsETSObjectType()->SuperType()->TypeArguments()[0]; + return checker->MaybeUnboxInRelation(baseEnumArg); + } return checker->GlobalIntType(); } + if (type->IsETSStringEnumType()) { return checker->GlobalETSStringLiteralType(); } return checker->MaybeUnboxInRelation(type); } -static std::pair BinaryCoerceToPrimitives(ETSChecker *checker, Type *left, Type *right, - bool const promote) +static Type *EffectiveTypeOfNumericOp(ETSChecker *checker, Type *left, Type *right) { - Type *const unboxedL = TryConvertToPrimitiveType(checker, left); - Type *const unboxedR = TryConvertToPrimitiveType(checker, right); - if (unboxedL == nullptr || unboxedR == nullptr) { - return {nullptr, false}; - } - - bool const bothConst = unboxedL->IsConstantType() && unboxedR->IsConstantType(); + ES2PANDA_ASSERT(checker->CheckIfNumeric(left) && checker->CheckIfNumeric(right)); - if (!promote) { - return {unboxedR, bothConst}; + auto bothBoxed = left->IsETSUnboxableObject() && right->IsETSUnboxableObject(); + if (!bothBoxed) { + return EffectivePrimitiveTypeOfNumericOp(checker, left, right); } - if (unboxedL->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - unboxedR->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - return {EffectiveTypeOfNumericOp(checker, unboxedL, unboxedR), bothConst}; + auto globalTypesHolder = checker->GetGlobalTypesHolder(); + if (FindOpArgsType(checker, left, right, globalTypesHolder->GlobalDoubleBuiltinType())) { + return globalTypesHolder->GlobalDoubleBuiltinType(); + } + if (FindOpArgsType(checker, left, right, globalTypesHolder->GlobalFloatBuiltinType())) { + return globalTypesHolder->GlobalFloatBuiltinType(); } - return {unboxedR, bothConst}; + if (FindOpArgsType(checker, left, right, globalTypesHolder->GlobalLongBuiltinType())) { + return globalTypesHolder->GlobalLongBuiltinType(); + } + return globalTypesHolder->GlobalIntegerBuiltinType(); // return Int for Byte, Short, Int } -Type *ETSChecker::NegateNumericType(Type *type, ir::Expression *node) +static Type *BinaryGetPromotedType(ETSChecker *checker, Type *left, Type *right, bool const promote) { - ES2PANDA_ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); - - TypeFlag typeKind = ETSType(type); - Type *result = nullptr; - - switch (typeKind) { - case TypeFlag::BYTE: { - result = CreateByteType(-(type->AsByteType()->GetValue())); - break; - } - case TypeFlag::CHAR: { - result = CreateCharType(-(type->AsCharType()->GetValue())); - break; - } - case TypeFlag::SHORT: { - result = CreateShortType(-(type->AsShortType()->GetValue())); - break; - } - case TypeFlag::INT: { - result = CreateIntType(-(type->AsIntType()->GetValue())); - break; - } - case TypeFlag::LONG: { - result = CreateLongType(-(type->AsLongType()->GetValue())); - break; - } - case TypeFlag::FLOAT: { - result = CreateFloatType(-(type->AsFloatType()->GetValue())); - break; - } - case TypeFlag::DOUBLE: { - result = CreateDoubleType(-(type->AsDoubleType()->GetValue())); - break; - } - default: { - ES2PANDA_UNREACHABLE(); - } + Type *const unboxedL = TryConvertToPrimitiveType(checker, left); + Type *const unboxedR = TryConvertToPrimitiveType(checker, right); + if (unboxedL == nullptr || unboxedR == nullptr) { + return nullptr; } - node->SetTsType(result); - return result; -} + Type *typeL = left; + Type *typeR = right; -Type *ETSChecker::HandleRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) -{ - ES2PANDA_ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); + bool const bothBoxed = !typeL->IsETSPrimitiveType() && !typeR->IsETSPrimitiveType(); - if (left->IsDoubleType() || right->IsDoubleType()) { - return PerformRelationOperationOnTypes(left, right, operationType); + if (!promote) { + return typeR; } - if (left->IsFloatType() || right->IsFloatType()) { - return PerformRelationOperationOnTypes(left, right, operationType); + if (!bothBoxed) { + if (unboxedL->IsETSEnumType() || unboxedR->IsETSEnumType()) { + return nullptr; + } + if (!typeL->IsETSPrimitiveType()) { + typeL = checker->MaybeUnboxType(typeL); + } + if (!typeR->IsETSPrimitiveType()) { + typeR = checker->MaybeUnboxType(typeR); + } } - if (left->IsLongType() || right->IsLongType()) { - return PerformRelationOperationOnTypes(left, right, operationType); + if (checker->CheckIfNumeric(typeL) && checker->CheckIfNumeric(typeR)) { + return EffectiveTypeOfNumericOp(checker, typeL, typeR); + } + if (checker->CheckIfNumeric(typeR)) { + return typeR; } - return PerformRelationOperationOnTypes(left, right, operationType); + return typeL; } bool ETSChecker::CheckBinaryOperatorForBigInt(Type *left, Type *right, lexer::TokenType op) @@ -250,6 +240,53 @@ bool ETSChecker::CheckBinaryPlusMultDivOperandsForUnionType(const Type *leftType return true; } +void ETSChecker::SetGenerateValueOfFlags(std::tuple types, + std::tuple nodes) +{ + auto [leftType, rightType, _, __] = types; + auto [left, right] = nodes; + if (leftType->IsETSEnumType()) { + left->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + } + if (rightType->IsETSEnumType()) { + right->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + } +} + +static bool TypeIsAppropriateForArithmetic(const checker::Type *type, ETSChecker *checker) +{ + return type->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) || + (type->IsETSObjectType() && + checker->Relation()->IsSupertypeOf(checker->GetGlobalTypesHolder()->GlobalNumericBuiltinType(), type)); +} + +static checker::Type *CheckBinaryOperatorForIntEnums(ETSChecker *checker, checker::Type *const leftType, + checker::Type *const rightType) +{ + if (!leftType->IsETSEnumType() && !rightType->IsETSEnumType()) { + return nullptr; + } + if (TypeIsAppropriateForArithmetic(leftType, checker) && TypeIsAppropriateForArithmetic(rightType, checker)) { + Type *leftNumeric; + if (leftType->IsETSIntEnumType()) { + leftNumeric = checker->MaybeBoxInRelation(TryConvertToPrimitiveType(checker, leftType)); + } else { + leftNumeric = leftType; + } + + Type *rightNumeric; + if (rightType->IsETSIntEnumType()) { + rightNumeric = checker->MaybeBoxInRelation(TryConvertToPrimitiveType(checker, rightType)); + } else { + rightNumeric = rightType; + } + + return EffectiveTypeOfNumericOp(checker, leftNumeric, rightNumeric); + } + + return nullptr; +} + checker::Type *ETSChecker::CheckBinaryOperatorMulDivMod( std::tuple op, bool isEqualOp, std::tuple types) @@ -264,18 +301,13 @@ checker::Type *ETSChecker::CheckBinaryOperatorMulDivMod( return GlobalTypeError(); } - checker::Type *tsType {}; - auto const [promotedType, bothConst] = BinaryCoerceToPrimitives(this, unboxedL, unboxedR, !isEqualOp); - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - + auto const promotedType = BinaryGetPromotedType(this, leftType, rightType, !isEqualOp); if (!CheckBinaryPlusMultDivOperandsForUnionType(leftType, rightType, left, right)) { return GlobalTypeError(); } - if (promotedType == nullptr || !unboxedL->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) || - !unboxedR->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - auto type = CheckBinaryOperatorForIntEnums(leftType, rightType); + if (promotedType == nullptr || !CheckIfNumeric(leftType) || !CheckIfNumeric(rightType)) { + auto type = CheckBinaryOperatorForIntEnums(this, leftType, rightType); if (type != nullptr) { return type; } @@ -283,66 +315,42 @@ checker::Type *ETSChecker::CheckBinaryOperatorMulDivMod( return GlobalTypeError(); } - if (bothConst) { - tsType = HandleArithmeticOperationOnTypes(leftType, rightType, operationType); - } - - return (tsType != nullptr) ? tsType : promotedType; -} - -checker::Type *ETSChecker::CheckBinaryOperatorForIntEnums(const checker::Type *const leftType, - const checker::Type *const rightType) -{ - if (leftType->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - rightType->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - if (leftType->IsETSIntEnumType() && rightType->IsETSIntEnumType()) { - return GlobalIntType(); - } - if (leftType->IsFloatType() || rightType->IsFloatType()) { - return GlobalFloatType(); - } - if (leftType->IsDoubleType() || rightType->IsDoubleType()) { - return GlobalDoubleType(); - } - if (leftType->IsLongType() || rightType->IsLongType()) { - return GlobalLongType(); - } - return GlobalIntType(); - } - return nullptr; + return promotedType; } checker::Type *ETSChecker::CheckBinaryBitwiseOperatorForIntEnums(const checker::Type *const leftType, const checker::Type *const rightType) { - if (leftType->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - rightType->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { + if (!leftType->IsETSEnumType() && !rightType->IsETSEnumType()) { + return nullptr; + } + if (TypeIsAppropriateForArithmetic(leftType, this) && TypeIsAppropriateForArithmetic(rightType, this)) { if (leftType->IsETSIntEnumType() && rightType->IsETSIntEnumType()) { - return GlobalIntType(); + return GlobalIntBuiltinType(); } if (leftType->IsFloatType() || rightType->IsFloatType()) { - return GlobalIntType(); + return GlobalIntBuiltinType(); } if (leftType->IsDoubleType() || rightType->IsDoubleType()) { - return GlobalLongType(); + return GlobalLongBuiltinType(); } if (leftType->IsLongType() || rightType->IsLongType()) { - return GlobalLongType(); + return GlobalLongBuiltinType(); } - return GlobalIntType(); + return GlobalIntBuiltinType(); } return nullptr; } -checker::Type *ETSChecker::CheckBinaryOperatorPlusForEnums(const checker::Type *const leftType, - const checker::Type *const rightType) +static checker::Type *CheckBinaryOperatorPlusForEnums(ETSChecker *checker, checker::Type *const leftType, + checker::Type *const rightType) { - if (auto numericType = CheckBinaryOperatorForIntEnums(leftType, rightType); numericType != nullptr) { + if (auto numericType = CheckBinaryOperatorForIntEnums(checker, leftType, rightType); numericType != nullptr) { return numericType; } if ((leftType->IsETSStringEnumType() && (rightType->IsETSStringType() || rightType->IsETSStringEnumType())) || (rightType->IsETSStringEnumType() && (leftType->IsETSStringType() || leftType->IsETSStringEnumType()))) { - return GlobalETSStringLiteralType(); + return checker->GlobalETSStringLiteralType(); } return nullptr; } @@ -374,29 +382,19 @@ checker::Type *ETSChecker::CheckBinaryOperatorPlus( if (!CheckBinaryPlusMultDivOperandsForUnionType(leftType, rightType, left, right)) { return GlobalTypeError(); } - - auto const [promotedType, bothConst] = BinaryCoerceToPrimitives(this, unboxedL, unboxedR, !isEqualOp); - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - - if (promotedType == nullptr || !unboxedL->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) || - !unboxedR->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - auto type = CheckBinaryOperatorPlusForEnums(leftType, rightType); + auto const promotedType = BinaryGetPromotedType(this, leftType, rightType, !isEqualOp); + if (promotedType == nullptr || !CheckIfNumeric(rightType) || !CheckIfNumeric(leftType)) { + auto type = CheckBinaryOperatorPlusForEnums(this, leftType, rightType); if (type != nullptr) { return type; } LogError(diagnostic::BINOP_NONARITHMETIC_TYPE, {}, pos); - return GlobalTypeError(); - } - - if (bothConst) { - return HandleArithmeticOperationOnTypes(leftType, rightType, operationType); } return promotedType; } -static checker::Type *GetBitwiseCompatibleType(ETSChecker *checker, Type *const type) +[[maybe_unused]] static checker::Type *GetBitwiseCompatibleType(ETSChecker *checker, Type *const type) { switch (checker->ETSType(type)) { case TypeFlag::BYTE: { @@ -430,8 +428,8 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift( auto [left, right, operationType, pos] = op; auto [leftType, rightType, unboxedL, unboxedR] = types; - RepairTypeErrorWithDefault(&leftType, GlobalIntType()); - RepairTypeErrorWithDefault(&rightType, GlobalIntType()); + RepairTypeErrorWithDefault(&leftType, GlobalIntBuiltinType()); + RepairTypeErrorWithDefault(&rightType, GlobalIntBuiltinType()); RepairTypeErrorWithDefault(&unboxedL, GlobalIntType()); RepairTypeErrorWithDefault(&unboxedR, GlobalIntType()); @@ -440,15 +438,10 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift( return GlobalTypeError(); } - auto promotedLeftType = ApplyUnaryOperatorPromotion(unboxedL, false, !isEqualOp); - auto promotedRightType = ApplyUnaryOperatorPromotion(unboxedR, false, !isEqualOp); - - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - - if (promotedLeftType == nullptr || !promotedLeftType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) || - promotedRightType == nullptr || - !promotedRightType->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { + auto promotedLeftType = GetUnaryOperatorPromotedType(leftType, !isEqualOp); + auto promotedRightType = GetUnaryOperatorPromotedType(rightType, !isEqualOp); + if (promotedLeftType == nullptr || promotedRightType == nullptr || !CheckIfNumeric(promotedLeftType) || + !CheckIfNumeric(promotedRightType)) { auto type = CheckBinaryBitwiseOperatorForIntEnums(leftType, rightType); if (type != nullptr) { return type; @@ -457,10 +450,22 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift( return GlobalTypeError(); } - if (promotedLeftType->HasTypeFlag(TypeFlag::CONSTANT) && promotedRightType->HasTypeFlag(TypeFlag::CONSTANT)) { - return HandleBitwiseOperationOnTypes(promotedLeftType, promotedRightType, operationType); + auto isPrim = promotedLeftType->IsETSPrimitiveType(); + auto unboxedProm = MaybeUnboxType(promotedLeftType); + if (unboxedProm->IsFloatType() || unboxedProm->IsIntType()) { + return isPrim ? GlobalIntType() : GetGlobalTypesHolder()->GlobalIntegerBuiltinType(); } - return GetBitwiseCompatibleType(this, promotedLeftType); + + if (unboxedProm->IsLongType() || unboxedProm->IsDoubleType()) { + return isPrim ? GlobalLongType() : GetGlobalTypesHolder()->GlobalLongBuiltinType(); + } + + if (unboxedProm->IsByteType() || unboxedProm->IsShortType() || unboxedProm->IsCharType()) { + return promotedLeftType; + } + + ES2PANDA_UNREACHABLE(); + return nullptr; } checker::Type *ETSChecker::CheckBinaryOperatorBitwise( @@ -481,19 +486,12 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise( return GlobalTypeError(); } - if (unboxedL != nullptr && unboxedL->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN) && unboxedR != nullptr && - unboxedR->HasTypeFlag(checker::TypeFlag::ETS_BOOLEAN)) { - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - return HandleBooleanLogicalOperators(unboxedL, unboxedR, operationType); + if (CheckOpArgsTypeEq(this, unboxedL, unboxedR, GlobalETSBooleanType())) { + return GetGlobalTypesHolder()->GlobalETSBooleanBuiltinType(); } - auto const [promotedType, bothConst] = BinaryCoerceToPrimitives(this, unboxedL, unboxedR, !isEqualOp); - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - - if (promotedType == nullptr || !unboxedL->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) || - !unboxedR->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { + auto const promotedType = BinaryGetPromotedType(this, leftType, rightType, !isEqualOp); + if (promotedType == nullptr || !CheckIfNumeric(rightType) || !CheckIfNumeric(leftType)) { auto type = CheckBinaryBitwiseOperatorForIntEnums(leftType, rightType); if (type != nullptr) { return type; @@ -501,17 +499,27 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise( LogError(diagnostic::OP_NONNUMERIC, {}, pos); return GlobalTypeError(); } + SetGenerateValueOfFlags(types, {left, right}); + + auto isPrim = promotedType->IsETSPrimitiveType(); + auto unboxedProm = MaybeUnboxType(promotedType); + if (unboxedProm->IsFloatType() || unboxedProm->IsIntType()) { + return isPrim ? GlobalIntType() : GetGlobalTypesHolder()->GlobalIntegerBuiltinType(); + } - if (bothConst) { - return HandleBitwiseOperationOnTypes(leftType, rightType, operationType); + if (unboxedProm->IsLongType() || unboxedProm->IsDoubleType()) { + return isPrim ? GlobalLongType() : GetGlobalTypesHolder()->GlobalLongBuiltinType(); } - return SelectGlobalIntegerTypeForNumeric(promotedType); + if (unboxedProm->IsByteType() || unboxedProm->IsShortType() || unboxedProm->IsCharType()) { + return promotedType; + } + return nullptr; } checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, - ir::BinaryExpression *expr, checker::Type *leftType, - checker::Type *rightType, Type *unboxedL, Type *unboxedR) + checker::Type *leftType, checker::Type *rightType, Type *unboxedL, + Type *unboxedR) { RepairTypeErrorsInOperands(&leftType, &rightType); RepairTypeErrorsInOperands(&unboxedL, &unboxedR); @@ -524,42 +532,44 @@ checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir:: right->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); return CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)}); } - if (right->IsNumberLiteral() && AdjustNumberLiteralType(right->AsNumberLiteral(), rightType, leftType)) { + if (right->IsNumberLiteral()) { return leftType; } - if (left->IsNumberLiteral() && AdjustNumberLiteralType(left->AsNumberLiteral(), leftType, rightType)) { + if (left->IsNumberLiteral()) { return rightType; } - if (HandleLogicalPotentialResult(left, right, expr, leftType)) { - ES2PANDA_ASSERT(expr->Result()->TsType() != nullptr); - return expr->Result()->TsType(); - } - if (IsTypeIdenticalTo(leftType, rightType)) { return GetNonConstantType(leftType); } - if (IsTypeIdenticalTo(unboxedL, unboxedR)) { - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - return GetNonConstantType(unboxedL); - } + return CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)}); +} - if (unboxedL != nullptr && unboxedL->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && unboxedR != nullptr && - unboxedR->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); - return EffectiveTypeOfNumericOp(this, unboxedL, unboxedR); +static bool ContainsNumbers(ETSChecker *checker, Type *tp) +{ + auto isSubtypeOfNumeric = [checker](Type *tp2) { + return checker->Relation()->IsSupertypeOf(checker->GetGlobalTypesHolder()->GlobalNumericBuiltinType(), tp2); + }; + if (isSubtypeOfNumeric(tp)) { + return true; + } + if (tp->IsETSUnionType()) { + for (auto *constituent : tp->AsETSUnionType()->ConstituentTypes()) { + if (isSubtypeOfNumeric(constituent)) { + return true; + } + } } - return CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)}); + return false; } +// CC-OFFNXT(huge_cyclomatic_complexity, huge_cca_cyclomatic_complexity[C++]) solid logic // NOTE: code inside this function follows the broken logic bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, checker::Type *const rightType) { - auto isRelaxedType {[](checker::Type *const type) -> bool { + auto isRelaxedType {[&](checker::Type *const type) -> bool { return (type->IsETSObjectType() && type->AsETSObjectType()->IsGlobalETSObjectType()) || type->IsETSAnyType() || type->IsETSNullType() || type->IsETSUndefinedType(); }}; @@ -569,6 +579,18 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che return true; } + // Any two types that can be numeric are comparable + if (ContainsNumbers(this, leftType) && ContainsNumbers(this, rightType)) { + return true; + } + + // Boolean and any type that can be numeric or char are not comparable + if ((FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalNumericBuiltinType()) || + FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalCharBuiltinType())) && + FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalETSBooleanBuiltinType())) { + return false; + } + // NOTE (mxlgv): Skip for unions. Required implementation of the specification section: // 7.25.6 Reference Equality Based on Actual Type (Union Equality Operators) if (leftType->IsETSUnionType()) { @@ -595,6 +617,11 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che } } + if (FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalNumericBuiltinType()) && + (leftType->IsETSEnumType() || rightType->IsETSEnumType())) { + return true; + } + // 7.24.5 Enumeration Relational Operators return leftType->IsETSEnumType() == rightType->IsETSEnumType(); } @@ -666,13 +693,6 @@ static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOper return checker->CreateETSUnionType({typeL, typeR}); } - if (typeL->IsETSEnumType() && typeR->IsETSEnumType()) { - if (checker->Relation()->IsIdenticalTo(typeL, typeR)) { - return typeL; - } - return nullptr; - } - if (typeL->IsETSReferenceType() && typeR->IsETSReferenceType()) { checker->Relation()->SetNode(expr->Left()); if (!checker->CheckValidEqualReferenceType(typeL, typeR)) { @@ -698,8 +718,6 @@ static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands { [[maybe_unused]] auto const [expr, typeL, typeR, reducedL, reducedR] = ops; - expr->Left()->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - expr->Right()->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); if (typeL->IsTypeError()) { // both are errors return checker->GlobalTypeError(); } @@ -710,12 +728,13 @@ static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands if (reducedL->IsETSBooleanType() && reducedR->IsETSBooleanType()) { if (reducedL->IsConstantType() && reducedR->IsConstantType()) { - bool res = reducedL->AsETSBooleanType()->GetValue() == reducedR->AsETSBooleanType()->GetValue(); - res = ((expr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL) == res); - return checker->CreateETSBooleanType(res); + return checker->GetGlobalTypesHolder()->GlobalETSBooleanBuiltinType(); + } + if (checker->CheckIfNumeric(typeL) && checker->CheckIfNumeric(typeR) && typeL->IsETSUnboxableObject() && + typeR->IsETSUnboxableObject()) { + return typeL; } - UnboxOperands(checker, ops); - return checker->GlobalETSBooleanType(); + return reducedL; } return HandelReferenceBinaryEquality(checker, ops); @@ -752,7 +771,7 @@ std::tuple ETSChecker::CheckBinaryOperatorLessGreater(ir::Expres RepairTypeErrorsInOperands(&leftType, &rightType); RepairTypeErrorsInOperands(&unboxedL, &unboxedR); if (leftType->IsTypeError()) { // both are errors - return {GlobalETSBooleanType(), GlobalTypeError()}; + return {GlobalETSBooleanBuiltinType(), GlobalTypeError()}; } if ((leftType->IsETSUnionType() || rightType->IsETSUnionType()) && @@ -761,30 +780,30 @@ std::tuple ETSChecker::CheckBinaryOperatorLessGreater(ir::Expres operationType != lexer::TokenType::PUNCTUATOR_STRICT_EQUAL && operationType != lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL) { LogError(diagnostic::BINOP_UNION, {}, pos); - return {GlobalETSBooleanType(), leftType}; + return {GlobalETSBooleanBuiltinType(), leftType}; } - auto *const promotedType = std::get<0>(BinaryCoerceToPrimitives(this, unboxedL, unboxedR, !isEqualOp)); - FlagExpressionWithUnboxing(leftType, unboxedL, left); - FlagExpressionWithUnboxing(rightType, unboxedR, right); + auto const promotedType = BinaryGetPromotedType(this, leftType, rightType, !isEqualOp); if (leftType->IsETSUnionType() || rightType->IsETSUnionType()) { - return {GlobalETSBooleanType(), CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)})}; + return {GlobalETSBooleanBuiltinType(), + CreateETSUnionType({MaybeBoxExpression(left), MaybeBoxExpression(right)})}; } - if (promotedType != nullptr && (unboxedL->IsETSBooleanType() != unboxedR->IsETSBooleanType())) { + if (promotedType != nullptr && unboxedL != nullptr && unboxedR != nullptr && + unboxedL->IsETSBooleanType() != unboxedR->IsETSBooleanType()) { LogOperatorCannotBeApplied(this, operationType, leftType, rightType, pos); - return {GlobalETSBooleanType(), leftType}; + return {GlobalETSBooleanBuiltinType(), leftType}; } if (promotedType == nullptr) { if (!NonNumericTypesAreAppropriateForComparison(this, leftType, rightType)) { LogError(diagnostic::BINOP_INCOMPARABLE, {}, pos); } - return {GlobalETSBooleanType(), GlobalETSBooleanType()}; + return {GlobalETSBooleanBuiltinType(), GlobalETSBooleanBuiltinType()}; } - return {GlobalETSBooleanType(), promotedType}; + return {GlobalETSBooleanBuiltinType(), promotedType}; } std::tuple ETSChecker::CheckBinaryOperatorInstanceOf(lexer::SourcePosition pos, checker::Type *leftType, @@ -792,59 +811,137 @@ std::tuple ETSChecker::CheckBinaryOperatorInstanceOf(lexer::Sour { RepairTypeErrorsInOperands(&leftType, &rightType); if (leftType->IsTypeError()) { // both are errors - return {GlobalETSBooleanType(), GlobalTypeError()}; + return {GlobalETSBooleanBuiltinType(), GlobalTypeError()}; } - if (!IsReferenceType(leftType) || !IsReferenceType(rightType)) { + if (leftType->IsETSPrimitiveType() || rightType->IsETSPrimitiveType()) { LogError(diagnostic::BINOP_NOT_SAME, {}, pos); - return {GlobalETSBooleanType(), leftType}; + return {GlobalETSBooleanBuiltinType(), leftType}; } if (rightType->IsETSDynamicType() && !rightType->AsETSDynamicType()->HasDecl()) { LogError(diagnostic::INSTANCEOF_NOT_TYPE, {}, pos); - return {GlobalETSBooleanType(), leftType}; + return {GlobalETSBooleanBuiltinType(), leftType}; } checker::Type *opType = rightType->IsETSDynamicType() ? GlobalBuiltinJSValueType() : GlobalETSObjectType(); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ComputeApparentType(rightType); RemoveStatus(checker::CheckerStatus::IN_INSTANCEOF_CONTEXT); - return {GlobalETSBooleanType(), opType}; + return {GlobalETSBooleanBuiltinType(), opType}; +} + +template +static void ConvertNumberLiteralTo(ir::NumberLiteral *lit, Type *toType) +{ + auto &number = lit->Number(); + number.SetValue(number.GetValueAndCastTo()); + toType->AddTypeFlag(TypeFlag::CONSTANT); + lit->SetTsType(toType); +} + +template +static bool CheckNumberLiteralValue(ETSChecker *checker, ir::NumberLiteral const *const lit) +{ + auto const maxTo = static_cast(std::numeric_limits::max()); + auto const minTo = static_cast(std::numeric_limits::min()); + auto const val = lit->Number().GetValue(); + if (val < minTo || val > maxTo) { + checker->LogError(diagnostic::CONSTANT_VALUE_OUT_OF_RANGE, {}, lit->Start()); + return false; + } + return true; +} + +// Just to reduce the size of 'ConvertNumberLiteral' +static void ConvertIntegerNumberLiteral(ETSChecker *checker, ir::NumberLiteral *lit, ETSObjectType *fromType, + ETSObjectType *toType) +{ + if (toType->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) { + ConvertNumberLiteralTo(lit, checker->GlobalLongBuiltinType()->Clone(checker)); + } else if (toType->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { + if (!fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) || + CheckNumberLiteralValue(checker, lit)) { + ConvertNumberLiteralTo(lit, checker->GlobalIntBuiltinType()->Clone(checker)); + } + } else if (toType->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) { + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) && + !CheckNumberLiteralValue(checker, lit)) { + return; + } + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) && + !CheckNumberLiteralValue(checker, lit)) { + return; + } + ConvertNumberLiteralTo(lit, checker->GlobalShortBuiltinType()->Clone(checker)); + } else if (toType->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) { + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) && + !CheckNumberLiteralValue(checker, lit)) { + return; + } + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) && + !CheckNumberLiteralValue(checker, lit)) { + return; + } + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT) && + !CheckNumberLiteralValue(checker, lit)) { + return; + } + ConvertNumberLiteralTo(lit, checker->GlobalByteBuiltinType()->Clone(checker)); + } } -bool ETSChecker::AdjustNumberLiteralType(ir::NumberLiteral *const literal, Type *literalType, Type *const otherType) +static void ConvertNumberLiteral(ETSChecker *checker, ir::NumberLiteral *lit, ETSObjectType *toType) { - if (otherType->IsETSObjectType() && !otherType->IsETSEnumType()) { - auto *const objectType = otherType->AsETSObjectType(); - if (objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE) && !objectType->IsETSStringType()) { - literal->RemoveBoxingUnboxingFlags(GetBoxingFlag(literalType)); - literalType = MaybeUnboxInRelation(objectType); - literal->SetTsType(literalType); - literal->AddBoxingUnboxingFlags(GetBoxingFlag(literalType)); - return true; + ES2PANDA_ASSERT(toType->IsBuiltinNumeric() && lit->TsType()->IsBuiltinNumeric()); + + if (auto *fromType = lit->TsType()->AsETSObjectType(); !checker->Relation()->IsIdenticalTo(fromType, toType)) { + switch (static_cast(toType->ObjectFlags() & ETSObjectFlags::BUILTIN_NUMERIC)) { + case ETSObjectFlags::BUILTIN_DOUBLE: + ConvertNumberLiteralTo(lit, checker->GlobalDoubleBuiltinType()->Clone(checker)); + break; + + case ETSObjectFlags::BUILTIN_FLOAT: + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { + checker->LogError(diagnostic::INVALID_ASSIGNMNENT, {fromType, toType}, lit->Start()); + } else { + ConvertNumberLiteralTo(lit, checker->GlobalFloatBuiltinType()->Clone(checker)); + } + break; + + case ETSObjectFlags::BUILTIN_LONG: + case ETSObjectFlags::BUILTIN_INT: + case ETSObjectFlags::BUILTIN_SHORT: + case ETSObjectFlags::BUILTIN_BYTE: + if (fromType->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOATING_POINT)) { + checker->LogError(diagnostic::INVALID_ASSIGNMNENT, {fromType, toType}, lit->Start()); + } else { + ConvertIntegerNumberLiteral(checker, lit, fromType, toType); + } + break; + + default: + ES2PANDA_UNREACHABLE(); } } - return false; } Type *ETSChecker::CheckBinaryOperatorNullishCoalescing(ir::Expression *left, ir::Expression *right, lexer::SourcePosition pos) { auto *leftType = left->TsType(); - if (!IsReferenceType(leftType)) { + if (leftType->IsETSPrimitiveType()) { LogError(diagnostic::COALESCE_NOT_REF, {}, pos); - return leftType; } leftType = GetNonNullishType(leftType); - auto *rightType = MaybeBoxExpression(right); + auto *rightType = MaybeBoxType(right->TsType()); if (IsTypeIdenticalTo(leftType, rightType)) { return leftType; } // If possible and required update number literal type to the proper value (identical to left-side type) - if (right->IsNumberLiteral() && AdjustNumberLiteralType(right->AsNumberLiteral(), rightType, leftType)) { + if (right->IsNumberLiteral() && leftType->IsBuiltinNumeric()) { + ConvertNumberLiteral(this, right->AsNumberLiteral(), leftType->AsETSObjectType()); return leftType; } @@ -904,6 +1001,7 @@ struct TypeParams { Type *unboxedR; }; +// CC-OFFNXT(G.FUN.01, huge_method) solid logic static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, const BinaryOperatorParams &binaryParams, const TypeParams &typeParams) @@ -914,22 +1012,23 @@ static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, checker::Type *const leftType = typeParams.leftType; checker::Type *const rightType = typeParams.rightType; checker::Type *tsType {}; + BinaryArithmOperands ops = GetBinaryOperands(checker, binaryParams.expr->AsBinaryExpression()); BinaryArithmOperands opsRepaired = RepairTypeErrorsInOperands(ops); switch (binaryParams.operationType) { case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - tsType = checker->CheckBinaryOperatorLogical(left, right, binaryParams.expr->AsBinaryExpression(), leftType, - rightType, typeParams.unboxedL, typeParams.unboxedR); + tsType = checker->CheckBinaryOperatorLogical(left, right, leftType, rightType, typeParams.unboxedL, + typeParams.unboxedR); break; } case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - if (Type *res = CheckBinaryOperatorEqual(checker, opsRepaired); res != nullptr) { - return {checker->GlobalETSBooleanType(), res}; + if (auto res = CheckBinaryOperatorEqual(checker, opsRepaired); res != nullptr) { + return {checker->GetGlobalTypesHolder()->GlobalETSBooleanBuiltinType(), res}; } [[fallthrough]]; } @@ -957,123 +1056,70 @@ static std::tuple CheckBinaryOperatorHelper(ETSChecker *checker, return {tsType, tsType}; } -namespace { -bool IsStringEnum(const ir::Expression *expr) +static void TryAddValueOfFlagToStringEnumOperand(ir::Expression *op, const ir::Expression *otherOp) { - if (expr == nullptr) { - return false; + auto type = op->TsType(); + auto otherType = otherOp->TsType(); + if (type->IsETSStringEnumType() && (otherType->IsETSStringType() || otherType->IsETSStringEnumType())) { + op->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); } - - auto type = expr->TsType(); - if (type == nullptr) { - return false; - } - - return type->IsETSStringEnumType(); } -bool IsIntEnum(const ir::Expression *expr) +static void TryAddValueOfFlagToIntEnumOperand(ir::Expression *op, const ir::Expression *otherOp) { - if (expr == nullptr) { - return false; - } - - auto type = expr->TsType(); - if (type == nullptr) { - return false; + auto type = op->TsType(); + auto otherType = otherOp->TsType(); + if (type->IsETSIntEnumType() && + ((otherType->IsETSObjectType() && otherType->AsETSObjectType()->IsBoxedPrimitive()) || + otherType->IsETSIntEnumType())) { + op->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); } - - return type->IsETSIntEnumType(); } -bool CheckNumericOperatorContext(ir::Expression *expression, lexer::TokenType op) +static void CheckEnumInOperatorContext(ir::Expression *expression, lexer::TokenType opType, ir::Expression *left, + ir::Expression *right, ETSChecker *checker) { - const bool isMultiplicative = op == lexer::TokenType::PUNCTUATOR_MULTIPLY || - op == lexer::TokenType::PUNCTUATOR_DIVIDE || op == lexer::TokenType::PUNCTUATOR_MOD; - const bool isAdditive = op == lexer::TokenType::PUNCTUATOR_PLUS || op == lexer::TokenType::PUNCTUATOR_MINUS; - const bool isShift = op == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || - op == lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT || - op == lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT; - const bool isRelational = - op == lexer::TokenType::PUNCTUATOR_GREATER_THAN || op == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || - op == lexer::TokenType::PUNCTUATOR_LESS_THAN || op == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL; - const bool isEquality = op == lexer::TokenType::PUNCTUATOR_EQUAL || op == lexer::TokenType::PUNCTUATOR_NOT_EQUAL; - const bool isBitwise = op == lexer::TokenType::PUNCTUATOR_BITWISE_AND || - op == lexer::TokenType::PUNCTUATOR_BITWISE_OR || - op == lexer::TokenType::PUNCTUATOR_BITWISE_XOR; - const bool isConditionalAndOr = - op == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || op == lexer::TokenType::PUNCTUATOR_LOGICAL_OR; - - if (IsIntEnum(expression)) { - if (isMultiplicative || isAdditive || isShift || isRelational || isEquality || isBitwise || - isConditionalAndOr) { - expression->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - } - return true; - } - return false; -} + auto [lType, rType] = std::tuple {left->TsType(), right->TsType()}; -void CheckStringOperatorContext(ir::Expression *expression, checker::Type *otherType, lexer::TokenType op) -{ - const bool isEquality = op == lexer::TokenType::PUNCTUATOR_EQUAL || op == lexer::TokenType::PUNCTUATOR_NOT_EQUAL; - const bool isRelational = - op == lexer::TokenType::PUNCTUATOR_GREATER_THAN || op == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || - op == lexer::TokenType::PUNCTUATOR_LESS_THAN || op == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL; - if (IsStringEnum(expression) && (otherType->IsETSStringType() || otherType->IsETSStringEnumType())) { - if (op == lexer::TokenType::PUNCTUATOR_PLUS || isRelational || isEquality) { - expression->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); + switch (opType) { + case lexer::TokenType::PUNCTUATOR_GREATER_THAN: + case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: + case lexer::TokenType::PUNCTUATOR_LESS_THAN: + case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: + case lexer::TokenType::PUNCTUATOR_EQUAL: + case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { + if (lType->IsETSEnumType() && rType->IsETSEnumType() && !checker->Relation()->IsIdenticalTo(lType, rType)) { + checker->LogError(diagnostic::BINOP_INCOMPARABLE, {}, expression->Start()); + return; + } + [[fallthrough]]; } - } -} - -bool CheckRelationalOperatorsBetweenEnums(ir::Expression *left, ir::Expression *right, lexer::TokenType op) -{ - const bool isRelational = - op == lexer::TokenType::PUNCTUATOR_GREATER_THAN || op == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || - op == lexer::TokenType::PUNCTUATOR_LESS_THAN || op == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL; - const bool isEquality = op == lexer::TokenType::PUNCTUATOR_EQUAL || op == lexer::TokenType::PUNCTUATOR_NOT_EQUAL; - - if (((IsStringEnum(left) && IsStringEnum(right)) || - (IsIntEnum(left) && IsIntEnum(right)))) { // NOTE(psiket) In case of int enums it has been already checked in - // the CheckNumericOperatorContext function - if (isRelational || isEquality) { - left->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - right->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - return true; + case lexer::TokenType::PUNCTUATOR_PLUS: { + TryAddValueOfFlagToStringEnumOperand(left, right); + TryAddValueOfFlagToStringEnumOperand(right, left); + [[fallthrough]]; } - } - return false; -} - -void CheckNeedToGenerateGetValueForBinaryExpression(ir::Expression *expression) -{ - if (!expression->IsBinaryExpression()) { - return; - } - - auto binaryExpression = expression->AsBinaryExpression(); - auto op = binaryExpression->OperatorType(); - auto leftExp = binaryExpression->Left(); - auto rightExp = binaryExpression->Right(); - - // Numeric Operator Context - auto leftIsIntEnum = CheckNumericOperatorContext(leftExp, op); - auto rightIsIntEnum = CheckNumericOperatorContext(rightExp, op); - if (leftIsIntEnum || rightIsIntEnum) { - return; - } - - // String Operator Context - CheckStringOperatorContext(leftExp, rightExp->TsType(), op); - CheckStringOperatorContext(rightExp, leftExp->TsType(), op); - - // Relational operators if both are enumeration Types - if (CheckRelationalOperatorsBetweenEnums(leftExp, rightExp, op)) { - return; + case lexer::TokenType::PUNCTUATOR_MULTIPLY: + case lexer::TokenType::PUNCTUATOR_DIVIDE: + case lexer::TokenType::PUNCTUATOR_MOD: + case lexer::TokenType::PUNCTUATOR_MINUS: + case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: + case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: + case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: + case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: + case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { + TryAddValueOfFlagToIntEnumOperand(left, right); + TryAddValueOfFlagToIntEnumOperand(right, left); + break; + } + default: + // NOTE(dkofanov): What about the '+=' operation? + break; } } -} // namespace std::tuple ETSChecker::CheckArithmeticOperations( ir::Expression *expr, std::tuple op, @@ -1089,16 +1135,22 @@ std::tuple ETSChecker::CheckArithmeticOperations( if (rightType->IsETSUnionType()) { rightType = GetNonConstantType(rightType); } + CheckEnumInOperatorContext(expr, operationType, left, right, this); auto checkMap = GetCheckMap(); if (checkMap.find(operationType) != checkMap.end()) { auto check = checkMap[operationType]; auto tsType = check(this, std::make_tuple(left, right, operationType, pos), isEqualOp, std::make_tuple(leftType, rightType, unboxedL, unboxedR)); + if (tsType == nullptr) { + return {leftType, rightType}; + } + if (tsType->IsETSPrimitiveType()) { + tsType = MaybeBoxType(tsType); + } return {tsType, tsType}; } - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return CheckBinaryOperatorHelper(this, {left, right, expr, operationType, pos, isEqualOp}, {leftType, rightType, unboxedL, unboxedR}); } @@ -1147,8 +1199,6 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, return {leftType, leftType}; } - CheckNeedToGenerateGetValueForBinaryExpression(expr); - const bool isLogicalExtendedOperator = (operationType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) || (operationType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR); Type *unboxedL = @@ -1168,55 +1218,4 @@ std::tuple ETSChecker::CheckBinaryOperator(ir::Expression *left, std::make_tuple(leftType, rightType, unboxedL, unboxedR)); } -Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) -{ - ES2PANDA_ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); - - if (left->IsDoubleType() || right->IsDoubleType()) { - return PerformArithmeticOperationOnTypes(left, right, operationType); - } - - if (left->IsFloatType() || right->IsFloatType()) { - return PerformArithmeticOperationOnTypes(left, right, operationType); - } - - if (left->IsLongType() || right->IsLongType()) { - return PerformArithmeticOperationOnTypes(left, right, operationType); - } - - return PerformArithmeticOperationOnTypes(left, right, operationType); -} - -Type *ETSChecker::HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) -{ - ES2PANDA_ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC) && - right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); - - if (left->IsDoubleType() || right->IsDoubleType()) { - return HandleBitWiseArithmetic(left, right, operationType); - } - - if (left->IsFloatType() || right->IsFloatType()) { - return HandleBitWiseArithmetic(left, right, operationType); - } - - if (left->IsLongType() || right->IsLongType()) { - return HandleBitWiseArithmetic(left, right, operationType); - } - - return HandleBitWiseArithmetic(left, right, operationType); -} - -void ETSChecker::FlagExpressionWithUnboxing(Type *type, Type *unboxedType, ir::Expression *typeExpression) -{ - if (type->IsETSEnumType()) { - typeExpression->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); - return; - } - if (type->IsETSObjectType() && (unboxedType != nullptr)) { - typeExpression->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedType)); - } -} - } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/arithmetic.h b/ets2panda/checker/ets/arithmetic.h index aa9d61d049..6ca03978bb 100644 --- a/ets2panda/checker/ets/arithmetic.h +++ b/ets2panda/checker/ets/arithmetic.h @@ -18,167 +18,9 @@ #include "checker/ETSchecker.h" #include "checker/ETSAnalyzer.h" +#include "checker/types/globalTypesHolder.h" namespace ark::es2panda::checker { - -template -typename TargetType::UType ETSChecker::GetOperand(Type *type) -{ - switch (ETSType(type)) { - case TypeFlag::BYTE: { - return type->AsByteType()->GetValue(); - } - case TypeFlag::CHAR: { - return type->AsCharType()->GetValue(); - } - case TypeFlag::SHORT: { - return type->AsShortType()->GetValue(); - } - case TypeFlag::INT: { - return type->AsIntType()->GetValue(); - } - case TypeFlag::LONG: { - return type->AsLongType()->GetValue(); - } - case TypeFlag::FLOAT: { - return type->AsFloatType()->GetValue(); - } - case TypeFlag::DOUBLE: { - return type->AsDoubleType()->GetValue(); - } - case TypeFlag::ETS_BOOLEAN: { - return type->AsETSBooleanType()->GetValue(); - } - default: { - ES2PANDA_UNREACHABLE(); - } - } -} - -template -Type *ETSChecker::PerformRelationOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) -{ - using UType = typename TargetType::UType; - - UType leftValue = GetOperand(left); - UType rightValue = GetOperand(right); - - bool result {}; - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_LESS_THAN: { - result = leftValue < rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { - result = leftValue <= rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { - result = leftValue > rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: { - result = leftValue >= rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_EQUAL: { - result = leftValue == rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - result = leftValue != rightValue; - break; - } - default: { - ES2PANDA_UNREACHABLE(); - } - } - - return CreateETSBooleanType(result); -} - -template -Type *ETSChecker::PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operationType) -{ - using UType = typename TargetType::UType; - - UType leftValue = GetOperand(left); - UType rightValue = GetOperand(right); - auto result = leftValue; - auto isForbiddenZeroDivision = [&rightValue]() { return std::is_integral::value && rightValue == 0; }; - - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_PLUS: - case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: { - result = leftValue + rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: { - result = leftValue - rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_DIVIDE: - case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: { - if (isForbiddenZeroDivision()) { - return nullptr; - } - result = leftValue / rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_MULTIPLY: - case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: { - result = leftValue * rightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_MOD: - case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: { - if (isForbiddenZeroDivision()) { - return nullptr; - } - result = HandleModulo(leftValue, rightValue); - break; - } - default: { - ES2PANDA_UNREACHABLE(); - } - } - - return ProgramAllocator()->New(result); -} - -template <> -inline IntType::UType ark::es2panda::checker::ETSChecker::HandleModulo(IntType::UType leftValue, - IntType::UType rightValue) -{ - ES2PANDA_ASSERT(rightValue != 0); - return leftValue % rightValue; -} - -template <> -inline LongType::UType ark::es2panda::checker::ETSChecker::HandleModulo(LongType::UType leftValue, - LongType::UType rightValue) -{ - ES2PANDA_ASSERT(rightValue != 0); - return leftValue % rightValue; -} - -template <> -inline FloatType::UType ark::es2panda::checker::ETSChecker::HandleModulo(FloatType::UType leftValue, - FloatType::UType rightValue) -{ - return std::fmod(leftValue, rightValue); -} - -template <> -inline DoubleType::UType ark::es2panda::checker::ETSChecker::HandleModulo( - DoubleType::UType leftValue, DoubleType::UType rightValue) -{ - return std::fmod(leftValue, rightValue); -} - template inline IntegerUType CastIfFloat(FloatOrIntegerUType num) { @@ -188,61 +30,6 @@ inline IntegerUType CastIfFloat(FloatOrIntegerUType num) return num; } } - -template -Type *ETSChecker::HandleBitWiseArithmetic(Type *left, Type *right, lexer::TokenType operationType) -{ - using IntegerUType = typename IntegerType::UType; - using UnsignedUType = std::make_unsigned_t; - - UnsignedUType result = 0; - UnsignedUType unsignedLeftValue = CastIfFloat(GetOperand(left)); - UnsignedUType unsignedRightValue = CastIfFloat(GetOperand(right)); - - auto mask = std::numeric_limits::digits - 1U; - auto shift = unsignedRightValue & mask; - - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: { - result = unsignedLeftValue & unsignedRightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - result = unsignedLeftValue | unsignedRightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: { - result = unsignedLeftValue ^ unsignedRightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: { - static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); - result = unsignedLeftValue << shift; - break; - } - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(IntegerUType) == 4 || sizeof(IntegerUType) == 8); - result = static_cast(unsignedLeftValue) >> shift; // NOLINT(hicpp-signed-bitwise) - break; - } - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); - result = unsignedLeftValue >> shift; - break; - } - default: { - ES2PANDA_UNREACHABLE(); - } - } - - return ProgramAllocator()->New(result); -} } // namespace ark::es2panda::checker #endif diff --git a/ets2panda/checker/ets/assignAnalyzer.cpp b/ets2panda/checker/ets/assignAnalyzer.cpp index 9ed3378f8b..8b29b6e855 100644 --- a/ets2panda/checker/ets/assignAnalyzer.cpp +++ b/ets2panda/checker/ets/assignAnalyzer.cpp @@ -14,7 +14,6 @@ */ #include "assignAnalyzer.h" -#include #include "ir/base/classDefinition.h" #include "ir/base/classProperty.h" @@ -1352,8 +1351,8 @@ static bool IsDefaultValueType(const Type *type, bool isNonReadonlyField) if (type == nullptr) { return false; } - return (type->IsETSPrimitiveType() || type->IsETSNeverType() || type->IsETSUndefinedType() || - type->IsETSNullType() || + return (type->IsETSPrimitiveType() || (type->IsETSObjectType() && type->AsETSObjectType()->IsBoxedPrimitive()) || + type->IsETSNeverType() || type->IsETSUndefinedType() || type->IsETSNullType() || (type->PossiblyETSUndefined() && (!type->HasTypeFlag(checker::TypeFlag::GENERIC) || (isNonReadonlyField && !CHECK_GENERIC_NON_READONLY_PROPERTIES)))); } diff --git a/ets2panda/checker/ets/castingContext.cpp b/ets2panda/checker/ets/castingContext.cpp index 0f1c377aaa..d7a3e5f069 100644 --- a/ets2panda/checker/ets/castingContext.cpp +++ b/ets2panda/checker/ets/castingContext.cpp @@ -26,9 +26,8 @@ CastingContext::CastingContext(TypeRelation *relation, const diagnostic::Diagnos const SavedTypeRelationFlagsContext savedTypeRelationFlags(relation, flags_); relation->SetNode(data.node); - const bool isLegalBoxedPrimitiveConversion = relation->IsLegalBoxedPrimitiveConversion(data.target, data.source); relation->Result(false); - if (!relation->IsSupertypeOf(data.target, data.source) && !isLegalBoxedPrimitiveConversion) { + if (!relation->IsSupertypeOf(data.target, data.source)) { relation->IsCastableTo(data.source, data.target); // #22954 string comparison if (!relation->IsTrue() && data.source->ToString() == data.target->ToString()) { @@ -39,13 +38,6 @@ CastingContext::CastingContext(TypeRelation *relation, const diagnostic::Diagnos } } - if (isLegalBoxedPrimitiveConversion && !relation->IsTrue()) { - auto *const checker = relation->GetChecker()->AsETSChecker(); - Type *sourceUnboxedType = checker->MaybeUnboxType(data.source); - relation->GetNode()->AddBoxingUnboxingFlags(checker->GetUnboxingFlag(sourceUnboxedType)); - relation->GetNode()->AddBoxingUnboxingFlags(checker->GetBoxingFlag(data.target)); - } - uncheckedCast_ = relation->UncheckedCast(); relation->SetNode(nullptr); } diff --git a/ets2panda/checker/ets/conversion.cpp b/ets2panda/checker/ets/conversion.cpp index 345a1a4f67..90c5d2f5be 100644 --- a/ets2panda/checker/ets/conversion.cpp +++ b/ets2panda/checker/ets/conversion.cpp @@ -16,7 +16,6 @@ #include "conversion.h" #include "checker/ets/boxingConverter.h" -#include "checker/ets/narrowingConverter.h" #include "checker/ets/unboxingConverter.h" #include "checker/ets/wideningConverter.h" #include "checker/types/ets/etsTupleType.h" @@ -35,23 +34,6 @@ void WideningPrimitive(TypeRelation *const relation, Type *const source, Type *c WideningConverter(relation->GetChecker()->AsETSChecker(), relation, target, source); } -void NarrowingPrimitive(TypeRelation *const relation, Type *const source, Type *const target) -{ - ES2PANDA_ASSERT(source->IsETSPrimitiveType() && target->IsETSPrimitiveType()); - - NarrowingConverter(relation->GetChecker()->AsETSChecker(), relation, target, source); -} - -void WideningNarrowingPrimitive(TypeRelation *const relation, ByteType *const source, CharType *const target) -{ - auto *const tempInt = relation->GetChecker()->AsETSChecker()->GetGlobalTypesHolder()->GlobalIntType(); - WideningPrimitive(relation, source, tempInt); - if (!relation->IsTrue()) { - return; - } - NarrowingPrimitive(relation, tempInt, target); -} - void WideningReference(TypeRelation *const relation, ETSObjectType *const source, ETSObjectType *const target) { relation->IsSupertypeOf(target, source); @@ -253,13 +235,6 @@ void NarrowingReference(TypeRelation *const relation, ETSObjectType *const sourc NarrowingReferenceImpl(relation, source, target); } -static inline void RollbackBoxingIfFailed(TypeRelation *const relation) -{ - if (!relation->IsTrue()) { - relation->GetNode()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); - } -} - ETSObjectType *Boxing(TypeRelation *const relation, Type *const source) { auto *const etsChecker = relation->GetChecker()->AsETSChecker(); @@ -268,7 +243,6 @@ ETSObjectType *Boxing(TypeRelation *const relation, Type *const source) return nullptr; } auto *const boxedType = boxed.Result()->AsETSObjectType(); - relation->GetNode()->AddBoxingUnboxingFlags(etsChecker->GetBoxingFlag(boxedType)); return boxedType; } @@ -280,7 +254,6 @@ Type *Unboxing(TypeRelation *const relation, ETSObjectType *const source) return nullptr; } auto *const unboxedType = unboxed.Result(); - relation->GetNode()->AddBoxingUnboxingFlags(etsChecker->GetUnboxingFlag(unboxedType)); return unboxedType; } @@ -292,27 +265,6 @@ void UnboxingWideningPrimitive(TypeRelation *const relation, ETSObjectType *cons } ES2PANDA_ASSERT(unboxedSource != nullptr); WideningPrimitive(relation, target, unboxedSource); - RollbackBoxingIfFailed(relation); -} - -void UnboxingNarrowingPrimitive(TypeRelation *const relation, ETSObjectType *const source, Type *const target) -{ - auto *const unboxedSource = Unboxing(relation, source); - if (!relation->IsTrue()) { - return; - } - ES2PANDA_ASSERT(unboxedSource != nullptr); - NarrowingPrimitive(relation, target, unboxedSource); -} - -void UnboxingWideningNarrowingPrimitive(TypeRelation *const relation, ETSObjectType *const source, Type *const target) -{ - auto *const unboxedSource = Unboxing(relation, source); - if (!relation->IsTrue()) { - return; - } - ES2PANDA_ASSERT(unboxedSource != nullptr); - WideningNarrowingPrimitive(relation, unboxedSource->AsByteType(), target->AsCharType()); } void NarrowingReferenceUnboxing(TypeRelation *const relation, ETSObjectType *const source, Type *const target) @@ -337,7 +289,6 @@ void BoxingWideningReference(TypeRelation *const relation, Type *const source, E } ES2PANDA_ASSERT(boxedSource != nullptr); WideningReference(relation, boxedSource, target); - RollbackBoxingIfFailed(relation); } void String(TypeRelation *const relation, Type *const source) diff --git a/ets2panda/checker/ets/conversion.h b/ets2panda/checker/ets/conversion.h index cf75be4906..e78b65c087 100644 --- a/ets2panda/checker/ets/conversion.h +++ b/ets2panda/checker/ets/conversion.h @@ -23,8 +23,6 @@ namespace ark::es2panda::checker::conversion { void Identity(TypeRelation *relation, Type *source, Type *target); void WideningPrimitive(TypeRelation *relation, Type *source, Type *target); -void NarrowingPrimitive(TypeRelation *relation, Type *source, Type *target); -void WideningNarrowingPrimitive(TypeRelation *relation, ByteType *source, CharType *target); void WideningReference(TypeRelation *relation, ETSObjectType *source, ETSObjectType *target); void WideningReference(TypeRelation *relation, ETSArrayType *source, ETSObjectType *target); @@ -38,8 +36,6 @@ void NarrowingReference(TypeRelation *relation, ETSObjectType *source, ETSTupleT ETSObjectType *Boxing(TypeRelation *relation, Type *source); Type *Unboxing(TypeRelation *relation, ETSObjectType *source); -void UnboxingWideningNarrowingPrimitive(TypeRelation *relation, ETSObjectType *source, Type *target); -void UnboxingNarrowingPrimitive(TypeRelation *relation, ETSObjectType *source, Type *target); void UnboxingWideningPrimitive(TypeRelation *relation, ETSObjectType *source, Type *target); void NarrowingReferenceUnboxing(TypeRelation *relation, ETSObjectType *source, Type *target); void BoxingWideningReference(TypeRelation *relation, Type *source, ETSObjectType *target); diff --git a/ets2panda/checker/ets/etsWarningAnalyzer.cpp b/ets2panda/checker/ets/etsWarningAnalyzer.cpp index f8709512c2..fc451700cc 100644 --- a/ets2panda/checker/ets/etsWarningAnalyzer.cpp +++ b/ets2panda/checker/ets/etsWarningAnalyzer.cpp @@ -34,8 +34,6 @@ #include "ir/base/classDefinition.h" #include "ir/statements/forOfStatement.h" #include "ir/statements/variableDeclarator.h" -#include "ir/statements/variableDeclaration.h" -#include "ir/expressions/updateExpression.h" namespace ark::es2panda::checker { @@ -270,157 +268,6 @@ void ETSWarningAnalyzer::ETSWarningRemoveLambda(const ir::AstNode *node) node->Iterate([&](auto *childNode) { ETSWarningRemoveLambda(childNode); }); } -void ETSWarningAnalyzer::CheckTypeOfBoxing(const ir::AstNode *node) -{ - ES2PANDA_ASSERT(node != nullptr); - const auto flags = node->GetBoxingUnboxingFlags(); - if ((flags & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0) { - std::string diagnosticParam; - switch (static_cast(flags & ir::BoxingUnboxingFlags::BOXING_FLAG)) { - case ir::BoxingUnboxingFlags::BOX_TO_INT: - diagnosticParam = "Int"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN: - diagnosticParam = "Boolean"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_BYTE: - diagnosticParam = "Byte"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_CHAR: - diagnosticParam = "Char"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_DOUBLE: - diagnosticParam = "Double"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_FLOAT: - diagnosticParam = "Float"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_LONG: - diagnosticParam = "Long"; - break; - case ir::BoxingUnboxingFlags::BOX_TO_SHORT: - diagnosticParam = "Short"; - break; - default: - break; - } - - if (!diagnosticParam.empty()) { - util::DiagnosticMessageParams diagnosticParams = {diagnosticParam, GetBoxingUnboxingType(node)}; - LogWarning(diagnostic::IMPLICIT_BOXING_TO, diagnosticParams, node->Start()); - } - } -} - -void ETSWarningAnalyzer::CheckTypeOfUnboxing(const ir::AstNode *node) -{ - ES2PANDA_ASSERT(node != nullptr); - const auto flags = node->GetBoxingUnboxingFlags(); - if ((flags & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0) { - std::string diagnosticParam; - switch (static_cast(flags & ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { - case ir::BoxingUnboxingFlags::UNBOX_TO_INT: - diagnosticParam = "Int"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_BOOLEAN: - diagnosticParam = "Boolean"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_BYTE: - diagnosticParam = "Byte"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_CHAR: - diagnosticParam = "Char"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_DOUBLE: - diagnosticParam = "Double"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_FLOAT: - diagnosticParam = "Float"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_LONG: - diagnosticParam = "Long"; - break; - case ir::BoxingUnboxingFlags::UNBOX_TO_SHORT: - diagnosticParam = "Short"; - break; - default: - break; - } - - if (!diagnosticParam.empty()) { - util::DiagnosticMessageParams diagnosticParams = {diagnosticParam, GetBoxingUnboxingType(node)}; - LogWarning(diagnostic::IMPLICIT_BOXING_TO, diagnosticParams, node->Start()); - } - } -} - -void ETSWarningAnalyzer::CheckTypeOfBoxingUnboxing(const ir::AstNode *node) -{ - ES2PANDA_ASSERT(node != nullptr); - - CheckTypeOfBoxing(node); - CheckTypeOfUnboxing(node); -} - -std::string ETSWarningAnalyzer::GetBoxingUnboxingType(const ir::AstNode *node) -{ - ES2PANDA_ASSERT(node->Parent() != nullptr); - switch (node->Parent()->Type()) { - case ir::AstNodeType::VARIABLE_DECLARATOR: { - return " in Variable Declaration"; - } - case ir::AstNodeType::CALL_EXPRESSION: { - return " in Call Method/Function"; - } - case ir::AstNodeType::SWITCH_STATEMENT: { - return " in Switch-case Statement"; - } - case ir::AstNodeType::ASSIGNMENT_EXPRESSION: { - return " in Assignment Expression"; - } - case ir::AstNodeType::BINARY_EXPRESSION: { - return " in Binary Expression"; - } - case ir::AstNodeType::UNARY_EXPRESSION: { - return " in Unary Expression"; - } - case ir::AstNodeType::UPDATE_EXPRESSION: { - return " in Update Expression"; - } - case ir::AstNodeType::MEMBER_EXPRESSION: { - return " in Member Expression"; - } - default: - return ""; - } -} - -void ETSWarningAnalyzer::ETSWarningImplicitBoxingUnboxing(const ir::AstNode *node) -{ - ES2PANDA_ASSERT(node != nullptr); - - switch (node->Type()) { - case ir::AstNodeType::VARIABLE_DECLARATOR: - case ir::AstNodeType::SWITCH_STATEMENT: - case ir::AstNodeType::CALL_EXPRESSION: - case ir::AstNodeType::BINARY_EXPRESSION: - case ir::AstNodeType::ASSIGNMENT_EXPRESSION: - case ir::AstNodeType::UNARY_EXPRESSION: - case ir::AstNodeType::UPDATE_EXPRESSION: - case ir::AstNodeType::MEMBER_EXPRESSION: { - if (!program_->NodeContainsETSNolint(node, ETSWarnings::ETS_IMPLICIT_BOXING_UNBOXING)) { - node->Iterate([this](auto *childNode) { CheckTypeOfBoxingUnboxing(childNode); }); - } - break; - } - default: { - break; - } - } - - node->Iterate([&](auto *childNode) { ETSWarningImplicitBoxingUnboxing(childNode); }); -} - void ETSWarningAnalyzer::LogWarning(const diagnostic::DiagnosticKind &diagnostic, const lexer::SourcePosition &position) const { diff --git a/ets2panda/checker/ets/etsWarningAnalyzer.h b/ets2panda/checker/ets/etsWarningAnalyzer.h index 6a41550de3..8bfecef627 100644 --- a/ets2panda/checker/ets/etsWarningAnalyzer.h +++ b/ets2panda/checker/ets/etsWarningAnalyzer.h @@ -48,9 +48,6 @@ public: case ETSWarnings::ETS_REMOVE_LAMBDA: ETSWarningRemoveLambda(node); break; - case ETSWarnings::ETS_IMPLICIT_BOXING_UNBOXING: - ETSWarningImplicitBoxingUnboxing(node); - break; default: break; } @@ -63,12 +60,8 @@ private: void AnalyzeClassDefForFinalModifier(const ir::ClassDefinition *classDef); void AnalyzeClassMethodForFinalModifier(const ir::MethodDefinition *methodDef, const ir::ClassDefinition *classDef); - void CheckTypeOfBoxing(const ir::AstNode *node); - void CheckTypeOfUnboxing(const ir::AstNode *node); void CheckTopLevelExpressions(const ir::Expression *expression); void CheckProhibitedTopLevelStatements(const ir::Statement *statement); - std::string GetBoxingUnboxingType(const ir::AstNode *node); - void CheckTypeOfBoxingUnboxing(const ir::AstNode *node); void ETSWarningAnnotationUnusedGenericAliasWarn(const ir::AstNode *node); void ETSWarningSuggestFinal(const ir::AstNode *node); @@ -76,7 +69,6 @@ private: void ETSWarningBoostEqualityStatement(const ir::AstNode *node); void ETSWarningRemoveAsync(const ir::AstNode *node); void ETSWarningRemoveLambda(const ir::AstNode *node); - void ETSWarningImplicitBoxingUnboxing(const ir::AstNode *node); parser::Program *program_; util::DiagnosticEngine &diagnosticEngine_; diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 2e33f31436..40338b0c4a 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -16,6 +16,7 @@ #include "checker/types/ets/etsResizableArrayType.h" #include "checker/types/ets/etsTupleType.h" #include "generated/signatures.h" +#include "checker/ets/wideningConverter.h" #include "varbinder/ETSBinder.h" #include "checker/ETSchecker.h" #include "checker/ets/function_helpers.h" @@ -406,6 +407,20 @@ static void ClearPreferredTypeForArray(checker::ETSChecker *checker, ir::Express } } +static bool CheckArrowFunctionParamIfNeeded(ETSChecker *checker, Signature *substitutedSig, + const ArenaVector &arguments, TypeRelationFlag flags) +{ + if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0 && arguments.back()->IsArrowFunctionExpression()) { + ir::ScriptFunction *const lambda = arguments.back()->AsArrowFunctionExpression()->Function(); + auto targetParm = substitutedSig->GetSignatureInfo()->params.back()->Declaration()->Node(); + if (!checker->CheckLambdaAssignable(targetParm->AsETSParameterExpression(), lambda)) { + return false; + } + } + return true; +} + +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, const ArenaVector &arguments, TypeRelationFlag flags, const std::vector &argTypeInferenceRequired, bool reportError) @@ -420,11 +435,13 @@ bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, // #22952: infer optional parameter heuristics auto const paramType = GetNonNullishType(substitutedSig->Params()[index]->TsType()); if (argument->IsObjectExpression()) { - if (paramType->IsETSObjectType()) { - // No chance to check the argument at this point - continue; + if (!paramType->IsETSObjectType()) { + return false; } - return false; + if (paramType->AsETSObjectType()->IsBoxedPrimitive()) { + return false; + } + argument->SetPreferredType(paramType); } if (argument->IsMemberExpression()) { @@ -434,6 +451,9 @@ bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, LogError(diagnostic::SPREAD_ONTO_SINGLE_PARAM, {}, argument->Start()); } return false; + } else if (argument->IsNumberLiteral()) { + argument->SetTsType(nullptr); + argument->SetPreferredType(paramType); } if (argTypeInferenceRequired[index]) { @@ -460,14 +480,7 @@ bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig, } } - if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0 && arguments.back()->IsArrowFunctionExpression()) { - ir::ScriptFunction *const lambda = arguments.back()->AsArrowFunctionExpression()->Function(); - auto targetParm = substitutedSig->GetSignatureInfo()->params.back()->Declaration()->Node(); - if (!CheckLambdaAssignable(targetParm->AsETSParameterExpression(), lambda)) { - return false; - } - } - return true; + return CheckArrowFunctionParamIfNeeded(this, substitutedSig, arguments, flags); } bool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, @@ -477,7 +490,7 @@ bool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, i // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) Type *argumentType = argument->Check(this); - flags |= TypeRelationFlag::ONLY_CHECK_WIDENING; + flags |= (TypeRelationFlag::ONLY_CHECK_WIDENING); auto const invocationCtx = checker::InvocationContext(Relation(), argument, argumentType, targetType, argument->Start(), @@ -489,7 +502,9 @@ bool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, i bool ETSChecker::IsValidRestArgument(ir::Expression *const argument, Signature *const substitutedSig, const TypeRelationFlag flags, const std::size_t index) { + auto *restParamType = substitutedSig->RestVar()->TsType(); if (argument->IsObjectExpression()) { + argument->SetPreferredType(GetElementTypeOfArray(restParamType)); // Object literals should be checked separately afterwards after call resolution return true; } @@ -502,15 +517,14 @@ bool ETSChecker::IsValidRestArgument(ir::Expression *const argument, Signature * } const auto argumentType = argument->Check(this); - auto *restParam = substitutedSig->RestVar()->TsType(); - if (restParam->IsETSTupleType()) { + if (restParamType->IsETSTupleType()) { return false; } if (argument->HasAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST)) { return true; } - auto targetType = GetElementTypeOfArray(restParam); + auto targetType = GetElementTypeOfArray(restParamType); if (substitutedSig->OwnerVar() == nullptr) { targetType = MaybeBoxType(targetType); } @@ -581,9 +595,7 @@ bool ETSChecker::ValidateSignatureRestParams(Signature *substitutedSig, const Ar Type *targetType = substitutedSig->RestVar()->TsType(); // backing out of check that results in a signature mismatch would be difficult // so only attempt it if there is only one candidate signature - if (restArgument->IsArrayExpression()) { - restArgument->AsArrayExpression()->SetPreferredType(targetType); - } + restArgument->SetPreferredType(targetType); auto const argumentType = restArgument->Check(this); auto const invocationCtx = checker::InvocationContext( @@ -611,7 +623,9 @@ Signature *ETSChecker::ValidateSignature( // setting the boxing/unboxing flag for the arguments if needed. // So handle substitution arguments only in the case of unique function or collecting signature phase. Signature *const signature = - MaybeSubstituteTypeParameters(this, baseSignature, typeArguments, arguments, pos, flags); + ((flags & TypeRelationFlag::NO_SUBSTITUTION_NEEDED) != 0U) + ? baseSignature + : MaybeSubstituteTypeParameters(this, baseSignature, typeArguments, arguments, pos, flags); if (signature == nullptr) { return nullptr; } @@ -708,6 +722,7 @@ std::array GetFlagVariants() }; } +// CC-OFFNXT(huge_method) solid logic ArenaVector ETSChecker::CollectSignatures(ArenaVector &signatures, const ir::TSTypeParameterInstantiation *typeArguments, const ArenaVector &arguments, @@ -717,12 +732,20 @@ ArenaVector ETSChecker::CollectSignatures(ArenaVector std::vector argTypeInferenceRequired = FindTypeInferenceArguments(arguments); Signature *notVisibleSignature = nullptr; + if (signatures.size() > 1) { + resolveFlags |= TypeRelationFlag::OVERLOADING_CONTEXT; + } + auto collectSignatures = [&](TypeRelationFlag relationFlags) { for (auto *sig : signatures) { if (notVisibleSignature != nullptr && !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { continue; } + if (sig->HasSignatureFlag(SignatureFlags::BRIDGE)) { + // Bridges are never invoked direcly + continue; + } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto *concreteSig = ValidateSignature(std::make_tuple(sig, typeArguments, relationFlags), arguments, pos, argTypeInferenceRequired, signatures.size() == 1); @@ -760,20 +783,6 @@ ArenaVector ETSChecker::CollectSignatures(ArenaVector return compatibleSignatures; } -static void ClearUnboxingFlags(TypeRelation *relation, Signature *sig, ir::Expression *argument, size_t index) -{ - auto identical = relation->IsIdenticalTo(sig->Params()[index]->TsType(), argument->TsType()); - // NOTE(gaborarontakacs): The unboxing flag, which was added due to overloading, needs to be removed when it's - // unnecessary for the most specific signature. - // Do not remove the flag for tuples, e.g., `let a = [21 as Number] as [number]`, - // because unboxing will be executed later during the function call in this case. - // This condition may be removed after refactoring primitive types. - if (identical && argument->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG) && - !(argument->IsMemberExpression() && argument->AsMemberExpression()->Object()->TsType()->IsETSTupleType())) { - argument->RemoveBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG); - } -} - static void UpdateArrayArgsAndUnboxingFlags(ETSChecker *checker, Signature *sig, const ArenaVector &arguments) { @@ -784,7 +793,6 @@ static void UpdateArrayArgsAndUnboxingFlags(ETSChecker *checker, Signature *sig, auto flags = TypeRelationFlag::NO_THROW | TypeRelationFlag::BOXING | TypeRelationFlag::UNBOXING | TypeRelationFlag::WIDENING; ClearPreferredTypeForArray(checker, argument, paramType, flags, true); - ClearUnboxingFlags(checker->Relation(), sig, argument, index); } } @@ -863,7 +871,18 @@ Signature *ETSChecker::ValidateSignatures(ArenaVector &signatures, auto compatibleSignatures = CollectSignatures(signatures, typeArguments, arguments, pos, resolveFlags); if (!compatibleSignatures.empty()) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return GetMostSpecificSignature(compatibleSignatures, arguments, pos, resolveFlags); + auto *sig = GetMostSpecificSignature(compatibleSignatures, arguments, pos, resolveFlags); + // NOTE (DZ): skip Promise constructor/then/catch check - + // temporary solution, need to be removed after fixing OHOS code! + if (sig == nullptr || !sig->HasFunction() || + !(sig->Function()->IsConstructor() || sig->Function()->Id()->Name().Is("then") || + sig->Function()->Id()->Name().Is("catch")) || + !sig->Owner()->Name().Is("Promise")) { + // May need to re-check the arguments now that we know the particular signature to call. + ValidateSignature({sig, nullptr, TypeRelationFlag::WIDENING | TypeRelationFlag::NO_SUBSTITUTION_NEEDED}, + arguments, pos, FindTypeInferenceArguments(arguments), true); + } + return sig; } if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) { @@ -887,6 +906,8 @@ Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector return true; }; + auto isGeneric = [](const Signature *sig) { return sig->TypeParams().empty(); }; + Signature *result = nullptr; size_t currentMinLength = SIZE_MAX; @@ -914,8 +935,15 @@ Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector } else if (candidateLength < currentLength) { result = candidate; // Shorter parameter count wins currentMinLength = result->Function()->Params().size(); - } else if (candidateLength == currentLength) { - // Ambiguous resolution for same-length params + } else if (candidateLength >= currentLength) { + continue; + // NOTE (smartin): all other cases below are unreachable code + } else if (!isGeneric(candidate) && isGeneric(result)) { + result = candidate; + } else if (isGeneric(candidate) && !isGeneric(result)) { + continue; + } else { + // Ambiguous resolution for same-length params, same genericity if (result->Owner() == candidate->Owner()) { result = nullptr; } @@ -925,22 +953,50 @@ Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector return result; } -static Type *GetParatmeterTypeOrRestAtIdx(checker::ETSChecker *checker, Signature *sig, const size_t idx) +static Type *GetParameterTypeOrRestAtIdx(checker::ETSChecker *checker, Signature *sig, const size_t idx) { return idx < sig->ArgCount() ? sig->Params().at(idx)->TsType() : checker->GetElementTypeOfArray(sig->RestVar()->TsType()); } -static void InitMostSpecificType(checker::ETSChecker *checker, const ArenaVector &signatures, - [[maybe_unused]] Type *&mostSpecificType, [[maybe_unused]] Signature *&prevSig, - const size_t idx) +static void InitMostSpecificType(TypeRelation *relation, const ArenaVector &signatures, + Type *&mostSpecificType, Signature *&prevSig, const size_t idx) { + // Attempt to choose the widest type of available ones + SavedTypeRelationFlagsContext ctx {relation, TypeRelationFlag::WIDENING | TypeRelationFlag::ONLY_CHECK_WIDENING}; + auto checker = relation->GetChecker()->AsETSChecker(); for (auto *sig : signatures) { - if (Type *sigType = GetParatmeterTypeOrRestAtIdx(checker, sig, idx); - sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { + Type *sigType = GetParameterTypeOrRestAtIdx(checker, sig, idx); + relation->Result(false); + + if (sigType->IsETSObjectType()) { + if (sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { + continue; + } + if (!sigType->AsETSObjectType()->IsBoxedPrimitive()) { + // Found "non-primitive" ref type + mostSpecificType = sigType; + prevSig = sig; + return; + } + relation->SetNode(prevSig->Function()->Params()[idx]->AsETSParameterExpression()); + if (relation->IsLegalBoxedPrimitiveConversion(sigType, mostSpecificType)) { + mostSpecificType = sigType; + prevSig = sig; + continue; + } + } + if (sigType->IsETSFunctionType() && relation->IsSupertypeOf(sigType, mostSpecificType)) { mostSpecificType = sigType; prevSig = sig; - return; + continue; + } + relation->Result(false); + WideningConverter(checker, relation, sigType, mostSpecificType); + if (relation->IsTrue()) { + mostSpecificType = sigType; + prevSig = sig; + continue; } } } @@ -950,18 +1006,51 @@ void ETSChecker::SearchAmongMostSpecificTypes(Type *&mostSpecificType, Signature bool lookForClassType) { auto [pos, idx, sig] = info; - Type *sigType = GetParatmeterTypeOrRestAtIdx(this, sig, idx); + Type *sigType = GetParameterTypeOrRestAtIdx(this, sig, idx); + if (prevSig->Function()->Params()[idx]->IsETSParameterExpression()) { + Relation()->SetNode(prevSig->Function()->Params()[idx]->AsETSParameterExpression()); + } const bool isClassType = sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE); if (isClassType == lookForClassType) { if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { + Relation()->SetNode(nullptr); return; } + + if (idx >= prevSig->MinArgCount() && idx < sig->MinArgCount()) { + // NOTE (smartin): prefer non-optional parameters over optional ones + Relation()->Result(true); + mostSpecificType = sigType; + prevSig = sig; + return; + } + + if (isClassType && sigType->AsETSObjectType()->IsBoxedPrimitive() && mostSpecificType->IsETSObjectType() && + mostSpecificType->AsETSObjectType()->IsBoxedPrimitive()) { + // NOTE (smartin): when a param with type int is available, make it more specific than other primitive + // types. The making of correct rules for this is still in progress in spec, so this is a temp solution. + if (mostSpecificType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { + return; + } + + TypeRelationFlag flags = TypeRelationFlag::NO_THROW | TypeRelationFlag::UNBOXING | + TypeRelationFlag::BOXING | TypeRelationFlag::WIDENING; + Relation()->SetFlags(flags); + if (sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) || + Relation()->IsLegalBoxedPrimitiveConversion(mostSpecificType, sigType)) { + Relation()->Result(true); + mostSpecificType = sigType; + prevSig = sig; + return; + } + } if (Relation()->IsAssignableTo(sigType, mostSpecificType)) { mostSpecificType = sigType; prevSig = sig; } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() && - !Relation()->IsAssignableTo(mostSpecificType, sigType)) { + !Relation()->IsAssignableTo(mostSpecificType, sigType) && + !Relation()->IsLegalBoxedPrimitiveConversion(sigType, mostSpecificType)) { auto funcName = sig->Function()->Id()->Name(); LogError(diagnostic::AMBIGUOUS_CALL, {funcName, funcName, funcName, prevSig, funcName, sig}, pos); } @@ -1038,7 +1127,9 @@ ArenaMultiMap ETSChecker::GetSuitableSignaturesForParameter Type *mostSpecificType = signatures.front()->Params().at(i)->TsType(); Signature *prevSig = signatures.front(); - InitMostSpecificType(this, signatures, mostSpecificType, prevSig, i); + // NOTE: first we choose the some signature with possibly widest argumetns' types + // Then we search for the most specific signature + InitMostSpecificType(Relation(), signatures, mostSpecificType, prevSig, i); for (auto *sig : signatures) { SearchAmongMostSpecificTypes(mostSpecificType, prevSig, std::make_tuple(pos, i, sig), true); } @@ -1047,8 +1138,9 @@ ArenaMultiMap ETSChecker::GetSuitableSignaturesForParameter } for (auto *sig : signatures) { - Type *sigType = GetParatmeterTypeOrRestAtIdx(this, sig, i); - if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) { + Type *sigType = GetParameterTypeOrRestAtIdx(this, sig, i); + if (Relation()->IsIdenticalTo(sigType, mostSpecificType) || + (sigType->IsETSFunctionType() && Relation()->IsSupertypeOf(sigType, mostSpecificType))) { bestSignaturesForParameter.insert({i, sig}); } } @@ -1187,6 +1279,32 @@ void ETSChecker::UpdateDeclarationFromSignature(ir::CallExpression *expr, checke callIdentifier->SetVariable(newVar); } +Signature *ETSChecker::MakeSignatureInvocable(Signature *sig, ir::CallExpression *callExpr) +{ + if (sig == nullptr) { + return nullptr; + } + std::size_t const argumentCount = callExpr->Arguments().size(); + std::size_t const parameterCount = sig->Params().size(); + auto count = std::min(parameterCount, argumentCount); + for (std::size_t idx = 0; idx < count; ++idx) { + // Kludge to make promise code compile + if (callExpr->Arguments().at(idx)->IsArrowFunctionExpression()) { + continue; + } + + auto ctx = checker::AssignmentContext( + Relation(), callExpr->Arguments().at(idx), callExpr->Arguments().at(idx)->TsType(), + sig->Params().at(idx)->TsType(), callExpr->Arguments().at(idx)->Start(), + {{diagnostic::INVALID_ASSIGNMNENT, + {callExpr->Arguments().at(idx)->TsType(), sig->Params().at(idx)->TsType()}}}); + if (!ctx.IsAssignable()) { + return nullptr; + } + } + return sig; +} + Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector &signatures, ir::CallExpression *callExpr, const lexer::SourcePosition &pos, @@ -1196,6 +1314,7 @@ Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVectorTypeParams(), callExpr->Arguments(), pos, "call", reportFlag); + sig = MakeSignatureInvocable(sig, callExpr); UpdateDeclarationFromSignature(callExpr, sig); return sig; } @@ -1216,6 +1335,7 @@ Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVectorTypeParams(), callExpr->Arguments(), pos, "call", reportFlag); + sig = MakeSignatureInvocable(sig, callExpr); if (sig != nullptr) { EnsureValidCurlyBrace(callExpr); } @@ -1252,7 +1372,7 @@ void ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVectorParams()[index]->TsType()); } - arguments[index]->AsObjectExpression()->SetPreferredType(tp); + arguments[index]->SetPreferredType(tp); arguments[index]->Check(this); } } @@ -1336,7 +1456,8 @@ checker::Type *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method) } bool ETSChecker::CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload, - const ir::MethodDefinition *const currentFunc, bool omitSameAsm) + const ir::MethodDefinition *const currentFunc, bool omitSameAsm, + TypeRelationFlag relationFlags) { // Don't necessary to check overload for invalid functions if (func->Name().Is(ERROR_LITERAL)) { @@ -1344,7 +1465,7 @@ bool ETSChecker::CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType return false; } - SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK); + SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), relationFlags); Relation()->SignatureIsIdenticalTo(func->CallSignatures()[0], overload->CallSignatures()[0]); if (Relation()->IsTrue() && func->CallSignatures()[0]->GetSignatureInfo()->restVar == @@ -2326,30 +2447,23 @@ size_t &ETSChecker::ConstraintCheckScopesCount() return constraintCheckScopesCount_; } -bool ETSChecker::CmpAssemblerTypesWithRank(Signature const *const sig1, Signature const *const sig2) noexcept +bool ETSChecker::HasSameAssemblySignature(Signature const *const sig1, Signature const *const sig2) noexcept { - for (size_t ix = 0U; ix < sig1->Params().size(); ++ix) { - std::stringstream s1; - std::stringstream s2; - sig1->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s1); - sig2->Params()[ix]->TsType()->ToAssemblerTypeWithRank(s2); - if (s1.str() != s2.str()) { - return false; - break; - } + if (sig1->ReturnType()->ToAssemblerTypeWithRank() != sig2->ReturnType()->ToAssemblerTypeWithRank()) { + return false; } - return true; -} -bool ETSChecker::HasSameAssemblySignature(Signature const *const sig1, Signature const *const sig2) noexcept -{ if (sig1->ArgCount() != sig2->ArgCount()) { return false; } - if (!CmpAssemblerTypesWithRank(sig1, sig2)) { - return false; + for (size_t ix = 0U; ix < sig1->Params().size(); ++ix) { + if (sig1->Params()[ix]->TsType()->ToAssemblerTypeWithRank() != + sig2->Params()[ix]->TsType()->ToAssemblerTypeWithRank()) { + return false; + } } + auto *rv1 = sig1->RestVar(); auto *rv2 = sig2->RestVar(); if (rv1 == nullptr && rv2 == nullptr) { @@ -2358,11 +2472,8 @@ bool ETSChecker::HasSameAssemblySignature(Signature const *const sig1, Signature if (rv1 == nullptr || rv2 == nullptr) { // exactly one of them is null return false; } - std::stringstream s1; - std::stringstream s2; - rv1->TsType()->ToAssemblerTypeWithRank(s1); - rv2->TsType()->ToAssemblerTypeWithRank(s2); - return s1.str() == s2.str(); + + return (rv1->TsType()->ToAssemblerTypeWithRank() == rv2->TsType()->ToAssemblerTypeWithRank()); } bool ETSChecker::HasSameAssemblySignatures(ETSFunctionType const *const func1, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 5ae8c1dd92..13f3575f66 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -16,6 +16,8 @@ #include "checker/ETSchecker.h" #include "checker/types/globalTypesHolder.h" +#include "checker/checkerContext.h" +#include "checker/ETSAnalyzerHelpers.h" #include "checker/types/ets/etsTupleType.h" #include "checker/ets/typeRelationContext.h" #include "checker/ets/typeConverter.h" @@ -369,31 +371,48 @@ checker::Type *ETSChecker::ApplyConditionalOperatorPromotion(checker::ETSChecker ES2PANDA_UNREACHABLE(); } -Type *ETSChecker::ApplyUnaryOperatorPromotion(Type *type, const bool createConst, const bool doPromotion, - const bool isCondExpr) +Type *ETSChecker::GetUnaryOperatorPromotedType(Type *type, const bool doPromotion) +{ + auto globalTypesHolder = GetGlobalTypesHolder(); + + if (doPromotion) { + if (type == globalTypesHolder->GlobalByteBuiltinType() || type == globalTypesHolder->GlobalShortBuiltinType() || + type == globalTypesHolder->GlobalCharBuiltinType() || + type == globalTypesHolder->GlobalIntegerBuiltinType()) { + return GlobalIntBuiltinType(); + } + + if (type->IsIntType() || type->IsByteType() || type->IsShortType() || type->IsCharType()) { + return GlobalIntBuiltinType(); + } + } + + return type; +} + +Type *ETSChecker::ApplyUnaryOperatorPromotion(Type *type, const bool isCondExpr) { Type *unboxedType = isCondExpr ? MaybeUnboxConditionalInRelation(type) : MaybeUnboxInRelation(type); if (unboxedType == nullptr) { return nullptr; } - if (doPromotion) { - switch (ETSType(unboxedType)) { - case TypeFlag::BYTE: - case TypeFlag::SHORT: - case TypeFlag::CHAR: { - if (!createConst) { - return GlobalIntType(); - } - return CreateIntTypeFromType(unboxedType); - } - default: { - break; - } - } + switch (ETSType(unboxedType)) { + case TypeFlag::BYTE: + [[fallthrough]]; + case TypeFlag::SHORT: + [[fallthrough]]; + case TypeFlag::CHAR: + [[fallthrough]]; + case TypeFlag::INT: + return GlobalIntBuiltinType(); + + default: + break; } - return unboxedType; + + return type; } bool ETSChecker::IsNullLikeOrVoidExpression(const ir::Expression *expr) const @@ -405,7 +424,7 @@ bool ETSChecker::IsNullLikeOrVoidExpression(const ir::Expression *expr) const std::tuple ETSChecker::IsResolvedAndValue(const ir::Expression *expr, Type *type) const { auto [isResolve, isValue] = - IsNullLikeOrVoidExpression(expr) ? std::make_tuple(true, false) : type->ResolveConditionExpr(); + IsNullLikeOrVoidExpression(expr) ? std::make_tuple(true, false) : IsConstantTestValue(expr); const Type *tsType = expr->TsType(); if (tsType->DefinitelyNotETSNullish() && !type->IsETSPrimitiveOrEnumType()) { @@ -452,30 +471,6 @@ Type *ETSChecker::HandleBooleanLogicalOperators(Type *leftType, Type *rightType, return nullptr; } -bool ETSChecker::HandleLogicalPotentialResult(ir::Expression *left, ir::Expression *right, ir::BinaryExpression *expr, - checker::Type *leftType) -{ - if (leftType->IsConstantType() && leftType->IsETSBooleanType()) { - if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { - expr->SetResult(leftType->AsETSBooleanType()->GetValue() ? right : left); - return true; - } - expr->SetResult(leftType->AsETSBooleanType()->GetValue() ? left : right); - return true; - } - - if (!leftType->IsETSPrimitiveType() && !leftType->PossiblyETSValueTyped()) { - expr->SetResult(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND ? right : left); - return true; - } - if (leftType->IsETSNullType() || leftType->IsETSUndefinedType()) { - expr->SetResult(expr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND ? left : right); - return true; - } - - return false; -} - void ETSChecker::ResolveReturnStatement(checker::Type *funcReturnType, checker::Type *argumentType, ir::ScriptFunction *containingFunc, ir::ReturnStatement *st) { @@ -500,8 +495,6 @@ void ETSChecker::ResolveReturnStatement(checker::Type *funcReturnType, checker:: argumentType = MaybeBoxInRelation(argumentType); if (argumentType == nullptr) { LogError(diagnostic::INVALID_EXPR_IN_RETURN, {}, st->Argument()->Start()); - } else { - st->Argument()->AddBoxingUnboxingFlags(GetBoxingFlag(argumentType)); } } @@ -536,7 +529,6 @@ checker::Type *ETSChecker::CheckArrayElements(ir::ArrayExpression *init) for (auto *typeFromTuple : elementType->AsETSTupleType()->GetTupleTypesList()) { elementTypes.emplace_back(typeFromTuple); } - continue; } @@ -544,22 +536,30 @@ checker::Type *ETSChecker::CheckArrayElements(ir::ArrayExpression *init) elementType = elementType->AsETSArrayType()->ElementType(); } - elementTypes.push_back(GetNonConstantType(elementType)); + elementTypes.emplace_back(elementType); } if (elementTypes.empty()) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return ProgramAllocator()->New(GlobalETSObjectType()); } - auto const isNumeric = [](checker::Type *ct) { return ct->HasTypeFlag(TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC); }; - auto const isChar = [](checker::Type *ct) { return ct->HasTypeFlag(TypeFlag::CHAR); }; - auto *const arrayElementType = - std::all_of(elementTypes.begin(), elementTypes.end(), isNumeric) - ? std::all_of(elementTypes.begin(), elementTypes.end(), isChar) ? GlobalCharType() : GlobalDoubleType() - : CreateETSUnionType(std::move(elementTypes)); + auto const isNumericLiteral = [this](checker::Type *&ct) { + auto const rc = + ct->IsConstantType() && Relation()->IsSupertypeOf(GetGlobalTypesHolder()->GlobalNumericBuiltinType(), ct); + ct = GetNonConstantType(ct); + return rc; + }; + auto const isChar = [this](checker::Type *ct) { + return Relation()->IsSupertypeOf(GetGlobalTypesHolder()->GlobalCharBuiltinType(), ct); + }; + auto const elementType = std::all_of(elementTypes.begin(), elementTypes.end(), isNumericLiteral) + ? std::all_of(elementTypes.begin(), elementTypes.end(), isChar) + ? GlobalCharBuiltinType() + : GlobalDoubleBuiltinType() + : CreateETSUnionType(std::move(elementTypes)); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateETSResizableArrayType(arrayElementType); + return CreateETSResizableArrayType(elementType); } void ETSChecker::InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::ArrowFunctionExpression *init) @@ -594,15 +594,12 @@ void ETSChecker::InferAliasLambdaType(ir::TypeNode *localTypeAnnotation, ir::Arr } } -checker::Type *ETSChecker::FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags, - ir::Expression *init) +checker::Type *ETSChecker::FixOptionalVariableType(varbinder::Variable *const bindingVar, ir::ModifierFlags flags) { if ((flags & ir::ModifierFlags::OPTIONAL) != 0) { - if (init != nullptr && bindingVar->TsType()->IsETSPrimitiveType()) { - init->SetBoxingUnboxingFlags(GetBoxingFlag(bindingVar->TsType())); - } auto *variableType = bindingVar->TsType() != nullptr ? bindingVar->TsType() : GlobalTypeError(); - bindingVar->SetTsType(CreateETSUnionType({GlobalETSUndefinedType(), variableType})); + bindingVar->SetTsType( + !variableType->IsTypeError() ? CreateETSUnionType({GlobalETSUndefinedType(), variableType}) : variableType); } return bindingVar->TsType(); } @@ -639,8 +636,9 @@ checker::Type *PreferredObjectTypeFromAnnotation(checker::Type *annotationType) return nullptr; } -bool SetPreferredTypeForExpression(ETSChecker *checker, ir::Identifier *ident, ir::TypeNode *typeAnnotation, - ir::Expression *init, checker::Type *annotationType) +// CC-OFFNXT(huge_cyclomatic_complexity, huge_cca_cyclomatic_complexity[C++]) solid logic +static bool SetPreferredTypeForExpression(ETSChecker *checker, ir::Identifier *ident, ir::TypeNode *typeAnnotation, + ir::Expression *init, checker::Type *annotationType) { if (init->IsMemberExpression() && init->AsMemberExpression()->Object()->IsObjectExpression()) { checker->LogError(diagnostic::MEMBER_OF_OBJECT_LIT, {}, ident->Start()); @@ -664,14 +662,17 @@ bool SetPreferredTypeForExpression(ETSChecker *checker, ir::Identifier *ident, i } if (init->IsObjectExpression() && annotationType != nullptr) { - init->AsObjectExpression()->SetPreferredType(PreferredObjectTypeFromAnnotation(annotationType)); + init->SetPreferredType(PreferredObjectTypeFromAnnotation(annotationType)); } if (init->IsETSNewArrayInstanceExpression() && annotationType != nullptr) { - init->AsETSNewArrayInstanceExpression()->SetPreferredType(annotationType); + init->SetPreferredType(annotationType); } if (init->IsETSNewMultiDimArrayInstanceExpression() && annotationType != nullptr) { - init->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredType(annotationType); + init->SetPreferredType(annotationType); + } + if (init->IsNumberLiteral() && annotationType != nullptr) { + init->SetPreferredType(annotationType); } if (typeAnnotation != nullptr && init->IsArrowFunctionExpression()) { @@ -783,8 +784,8 @@ static void CheckRecordType(ir::Expression *init, checker::Type *annotationType, ES2PANDA_ASSERT(property->IsProperty()); auto p = property->AsProperty(); - ETSChecker::SetPreferredTypeIfPossible(p->Key(), typeArguments[0]); - ETSChecker::SetPreferredTypeIfPossible(p->Value(), typeArguments[1]); + p->Key()->SetPreferredType(typeArguments[0]); + p->Value()->SetPreferredType(typeArguments[1]); Type *keyType = p->Key()->Check(checker); Type *valueType = p->Value()->Check(checker); @@ -813,7 +814,7 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T } if (init == nullptr) { - return FixOptionalVariableType(bindingVar, flags, init); + return FixOptionalVariableType(bindingVar, flags); } CheckAssignForDeclare(ident, typeAnnotation, init, flags, this); } else { @@ -863,7 +864,7 @@ checker::Type *ETSChecker::CheckVariableDeclaration(ir::Identifier *ident, ir::T bindingVar->SetTsType(needWidening ? GetNonConstantType(initType) : initType); } - return FixOptionalVariableType(bindingVar, flags, init); + return FixOptionalVariableType(bindingVar, flags); } void ETSChecker::VariableTypeFromInitializer(varbinder::Variable *variable, Type *annotationType, Type *initType) @@ -1010,64 +1011,50 @@ checker::Type *ETSChecker::GetExtensionAccessorReturnType(ir::MemberExpression * // Smart cast support //==============================================================================// -checker::Type *ETSChecker::ResolveSmartType(checker::Type *sourceType, checker::Type *targetType) +static checker::Type *MaybeReadonlyType(ETSChecker *checker, checker::Type *sourceType, checker::Type *targetType) { - // For left-hand variable of primitive type leave it as is. - if (targetType->IsETSPrimitiveType()) { + // For left-hand variable of builtin type leave it as is. + if (targetType->IsBuiltinNumeric()) { return targetType; } - // For left-hand variable of tuple type leave it as is. - if (targetType->IsETSTupleType()) { - return targetType; + // Preserve 'Readonly' type flag in smart type if it exists in declared type + if (targetType->HasTypeFlag(TypeFlag::READONLY) && !sourceType->HasTypeFlag(TypeFlag::READONLY)) { + sourceType = sourceType->Clone(checker); + sourceType->AddTypeFlag(TypeFlag::READONLY); } + return sourceType; +} + +checker::Type *ETSChecker::ResolveSmartType(checker::Type *sourceType, checker::Type *targetType, + std::optional value) +{ + // For left-hand variable of primitive type leave it as is. + ES2PANDA_ASSERT(!targetType->IsETSPrimitiveType() && !sourceType->IsETSPrimitiveType()); // For left-hand invalid variable set smart type to right-hand type. if (targetType->IsTypeError()) { return sourceType; } - // For left-hand variable of builtin type leave it as is. - if (targetType->IsETSObjectType() && targetType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - return targetType; - } - - // Nothing to do with identical types: - auto *nonConstSourceType = GetNonConstantType(sourceType); - auto *nonConstTargetType = GetNonConstantType(targetType); - - if (Relation()->IsIdenticalTo(nonConstSourceType, nonConstTargetType) || - Relation()->IsIdenticalTo(GlobalBuiltinJSValueType(), nonConstTargetType)) { - return targetType; - } - // For type parameter, null or undefined source type return it as is. if (sourceType->IsETSTypeParameter() || sourceType->DefinitelyETSNullish()) { return sourceType; } - // In case of Union left-hand type we have to select the proper type from the Union - // Because now we have logging of errors we have to continue analyze incorrect program, for - // this case we change typeError to source type. - if (targetType->IsETSUnionType()) { - auto component = targetType->AsETSUnionType()->GetAssignableType(this, sourceType); - return component->IsTypeError() ? MaybeBoxType(sourceType) : component; - } - - // If source is reference type, set it as the current and use it for identifier smart cast - if (sourceType->IsETSReferenceType()) { - return sourceType; + // In case of Union left-hand type we try to select the proper type from the Union + if (targetType->IsETSUnionType() && !sourceType->IsUnionType()) { + auto *constituentType = targetType->AsETSUnionType()->GetAssignableType(this, sourceType, value); + if (constituentType != nullptr) { + return MaybeReadonlyType(this, sourceType, constituentType); + } } - // For right-hand variable of primitive type apply boxing conversion (case: 'let x: Object = 5', then x => Int). - if (sourceType->IsETSPrimitiveType() && !sourceType->IsETSVoidType() && targetType->IsETSObjectType()) { - return MaybeBoxInRelation(sourceType); + // General case - return more specific subtype + if (Relation()->IsSupertypeOf(targetType, sourceType)) { + return MaybeReadonlyType(this, sourceType, targetType); } - // NOTE - it seems that all the other possible cases are assignments like: - // 'Object = ObjectLiteral' or smth similar ??? - // thus for such cases also leave the target type as is. - // Possible errors in tests should clarify this hypothesis sooner or later :) return targetType; } @@ -1832,7 +1819,9 @@ void ETSChecker::ConcatConstantString(util::UString &target, Type *type) { switch (ETSType(type)) { case TypeFlag::ETS_OBJECT: { - ES2PANDA_ASSERT(type->IsETSStringType()); + if (!type->IsETSStringType()) { + break; + } target.Append(type->AsETSStringType()->GetValue()); break; } @@ -2017,8 +2006,8 @@ varbinder::VariableFlags ETSChecker::GetAccessFlagFromNode(const ir::AstNode *no Type *ETSChecker::CheckSwitchDiscriminant(ir::Expression *discriminant) { - discriminant->Check(this); - auto *discriminantType = GetNonConstantType(MaybeUnboxExpression(discriminant)); + Type *discriminantType = discriminant->Check(this); + discriminantType = GetNonConstantType(MaybeUnboxType(discriminantType)); if (!discriminantType->HasTypeFlag(TypeFlag::VALID_SWITCH_TYPE)) { if (!(discriminantType->IsETSObjectType() && discriminantType->AsETSObjectType()->HasObjectFlag( @@ -2030,33 +2019,12 @@ Type *ETSChecker::CheckSwitchDiscriminant(ir::Expression *discriminant) return discriminantType; } -void ETSChecker::AddBoxingUnboxingFlagsToNode(ir::AstNode *node, Type *boxingUnboxingType) -{ - if (boxingUnboxingType->IsETSObjectType()) { - node->AddBoxingUnboxingFlags(GetBoxingFlag(boxingUnboxingType)); - } else if (!boxingUnboxingType->IsETSUnionType()) { - node->AddBoxingUnboxingFlags(GetUnboxingFlag(boxingUnboxingType)); - } -} - Type *ETSChecker::MaybeBoxExpression(ir::Expression *expr) { auto *promoted = MaybeBoxType(expr->TsType()); - if (promoted != expr->TsType()) { - expr->AddBoxingUnboxingFlags(GetBoxingFlag(promoted)); - } return promoted; } -Type *ETSChecker::MaybeUnboxExpression(ir::Expression *expr) -{ - auto *primitive = MaybeUnboxType(expr->TsType()); - if (primitive != expr->TsType()) { - expr->AddBoxingUnboxingFlags(GetUnboxingFlag(primitive)); - } - return primitive; -} - void ETSChecker::CheckForSameSwitchCases(ArenaVector const &cases) { CheckItemCasesConstant(cases); @@ -2151,7 +2119,7 @@ void ETSChecker::CheckItemCasesConstant(ArenaVector c if (caseTest == nullptr) { continue; } - auto *caseType = caseTest->TsType(); + auto *caseType = MaybeUnboxType(caseTest->TsType()); if (caseType->HasTypeFlag(TypeFlag::TYPE_ERROR)) { continue; } @@ -2229,7 +2197,7 @@ void ETSChecker::CheckItemCasesDuplicate(ArenaVector } if (caseTest->IsLiteral() && compareCaseTest->IsLiteral() && - GetStringFromLiteral(caseTest) != GetStringFromLiteral(compareCaseTest)) { + caseTest->AsLiteral()->ToString() != compareCaseTest->AsLiteral()->ToString()) { continue; } @@ -2259,7 +2227,7 @@ bool ETSChecker::CompareIdentifiersValuesAreDifferent(ir::Expression *compareVal return caseValue != compareCaseValue; } - return caseValue != GetStringFromLiteral(compareValue); + return caseValue != compareValue->ToString(); } void ETSChecker::CheckIdentifierSwitchCase(ir::Expression *currentCase, ir::Expression *compareCase, @@ -2283,23 +2251,6 @@ void ETSChecker::CheckIdentifierSwitchCase(ir::Expression *currentCase, ir::Expr } } -std::string ETSChecker::GetStringFromLiteral(ir::Expression *caseTest) const -{ - switch (caseTest->Type()) { - case ir::AstNodeType::CHAR_LITERAL: { - return std::to_string(caseTest->AsCharLiteral()->Char()); - } - case ir::AstNodeType::STRING_LITERAL: - case ir::AstNodeType::NULL_LITERAL: - case ir::AstNodeType::UNDEFINED_LITERAL: - case ir::AstNodeType::NUMBER_LITERAL: { - return util::Helpers::LiteralToPropName(caseTest).Mutf8(); - } - default: - ES2PANDA_UNREACHABLE(); - } -} - bool ETSChecker::IsSameDeclarationType(varbinder::LocalVariable *target, varbinder::LocalVariable *compare) { return target->Declaration()->Type() == compare->Declaration()->Type(); @@ -2533,7 +2484,6 @@ void ETSChecker::InferTypesForLambda(ir::ScriptFunction *lambda, ir::ETSFunction } if (lambda->ReturnTypeAnnotation() == nullptr) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) Type *inferredReturnType = calleeType->ReturnType()->GetType(this); bool isPrimitive = inferredReturnType != nullptr && inferredReturnType->IsETSPrimitiveType(); if (!isPrimitive && maybeSubstitutedFunctionSig != nullptr) { @@ -2549,14 +2499,12 @@ void ETSChecker::InferTypesForLambda(ir::ScriptFunction *lambda, Signature *sign for (size_t i = 0; i < lambda->Params().size(); ++i) { auto *const lambdaParam = lambda->Params().at(i)->AsETSParameterExpression()->Ident(); if (lambdaParam->TypeAnnotation() == nullptr) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) lambdaParam->Variable()->SetTsType(signature->Params().at(i)->TsType()); lambdaParam->SetTsType(signature->Params().at(i)->TsType()); } } if (lambda->ReturnTypeAnnotation() == nullptr) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) lambda->SetPreferredReturnType(signature->ReturnType()); } } @@ -2716,6 +2664,7 @@ void ETSChecker::GenerateGetterSetterBody(ArenaVector &stmts, A // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) auto ident = ProgramAllocNode(paramExpression->Ident()->Name(), ProgramAllocator()); ident->SetVariable(paramExpression->Variable()); + ident->SetTsTypeAnnotation(nullptr); auto *assignmentExpression = // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) ProgramAllocNode(memberExpression, ident, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); @@ -2753,6 +2702,7 @@ static std::tupleBindParamScope(paramScope); paramScope->BindFunctionScope(functionScope); + auto classCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), classScope); ArenaVector params(checker->ProgramAllocator()->Adapter()); ArenaVector stmts(checker->ProgramAllocator()->Adapter()); @@ -2819,7 +2769,6 @@ ir::MethodDefinition *ETSChecker::GenerateDefaultGetterSetter(ir::ClassProperty functionScope->BindNode(func); - auto classCtx = varbinder::LexicalScope::Enter(checker->VarBinder(), classScope); checker->VarBinder()->AsETSBinder()->ResolveMethodDefinition(method); method->Function()->ClearFlag(ir::ScriptFunctionFlags::EXTERNAL); @@ -2940,6 +2889,7 @@ void ETSChecker::GenerateGetterSetterPropertyAndMethod(ir::ClassProperty *origin getter->Variable()->TsType()->AsETSFunctionType()->AddCallSignature( setter->TsType()->AsETSFunctionType()->CallSignatures()[0]); getter->AddOverload(setter); + setter->SetParent(getter); } } @@ -3144,19 +3094,6 @@ void ETSChecker::CheckTypeParameterVariance(ir::ClassDefinition *classDef) } } -void ETSChecker::SetPreferredTypeIfPossible(ir::Expression *const expr, Type *const targetType) -{ - // Object expression requires that its type be set by the context before checking. in this case, the target type - // provides that context. - if (expr->IsObjectExpression()) { - expr->AsObjectExpression()->SetPreferredType(targetType); - } - - if (expr->IsArrayExpression()) { - expr->AsArrayExpression()->SetPreferredType(targetType); - } -} - checker::ETSFunctionType *ETSChecker::IntersectSignatureSets(const checker::ETSFunctionType *left, const checker::ETSFunctionType *right) { diff --git a/ets2panda/checker/ets/narrowingConverter.h b/ets2panda/checker/ets/narrowingConverter.h deleted file mode 100644 index f42051d88b..0000000000 --- a/ets2panda/checker/ets/narrowingConverter.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2021-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ES2PANDA_COMPILER_CHECKER_ETS_NARROWING_CONVERTER_H -#define ES2PANDA_COMPILER_CHECKER_ETS_NARROWING_CONVERTER_H - -#include "checker/ETSchecker.h" -#include "checker/ets/typeConverter.h" -#include "util/helpers.h" - -namespace ark::es2panda::checker { -class NarrowingConverter : public TypeConverter { -public: - static constexpr TypeFlag NARROWABLE_TO_FLOAT = TypeFlag::DOUBLE; - static constexpr TypeFlag NARROWABLE_TO_LONG = TypeFlag::FLOAT | NARROWABLE_TO_FLOAT; - static constexpr TypeFlag NARROWABLE_TO_INT = TypeFlag::LONG | NARROWABLE_TO_LONG; - static constexpr TypeFlag NARROWABLE_TO_CHAR = TypeFlag::SHORT | TypeFlag::INT | NARROWABLE_TO_INT; - static constexpr TypeFlag NARROWABLE_TO_SHORT = TypeFlag::CHAR | TypeFlag::INT | NARROWABLE_TO_INT; - static constexpr TypeFlag NARROWABLE_TO_BYTE = TypeFlag::CHAR | NARROWABLE_TO_CHAR; - - explicit NarrowingConverter(ETSChecker *checker, TypeRelation *relation, Type *target, Type *source) - : TypeConverter(checker, relation, target, source) - { - if (!relation->ApplyNarrowing()) { - return; - } - - ES2PANDA_ASSERT(relation->GetNode()); - - switch (ETSChecker::ETSChecker::ETSType(target)) { - case TypeFlag::BYTE: { - ApplyNarrowing(NARROWABLE_TO_BYTE); - break; - } - case TypeFlag::CHAR: { - ApplyNarrowing(NARROWABLE_TO_CHAR); - break; - } - case TypeFlag::SHORT: { - ApplyNarrowing(NARROWABLE_TO_SHORT); - break; - } - case TypeFlag::INT: { - ApplyNarrowing(NARROWABLE_TO_INT); - break; - } - case TypeFlag::LONG: { - ApplyNarrowing(NARROWABLE_TO_LONG); - break; - } - case TypeFlag::FLOAT: { - ApplyNarrowing(NARROWABLE_TO_FLOAT); - break; - } - - default: { - break; - } - } - } - -private: - template - void ApplyNarrowing(TypeFlag flag) - { - if (!Source()->HasTypeFlag(flag)) { - return; - } - - switch (ETSChecker::ETSChecker::ETSType(Source())) { - case TypeFlag::CHAR: { - ApplyNarrowing(); - break; - } - case TypeFlag::SHORT: { - ApplyNarrowing(); - break; - } - case TypeFlag::INT: { - ApplyNarrowing(); - break; - } - case TypeFlag::LONG: { - ApplyNarrowing(); - break; - } - case TypeFlag::FLOAT: { - ApplyNarrowing(); - break; - } - case TypeFlag::DOUBLE: { - ApplyNarrowing(); - break; - } - default: { - break; - } - } - } - - template - To CastFloatingPointToIntOrLong(From value) - { - if (std::isinf(value)) { - if (std::signbit(value)) { - return std::numeric_limits::min(); - } - return std::numeric_limits::max(); - } - ES2PANDA_ASSERT(std::is_floating_point_v); - ES2PANDA_ASSERT(std::is_integral_v); - To minInt = std::numeric_limits::min(); - To maxInt = std::numeric_limits::max(); - auto floatMinInt = static_cast(minInt); - auto floatMaxInt = static_cast(maxInt); - - if (value > floatMinInt) { - if (value < floatMaxInt) { - return static_cast(value); - } - return maxInt; - } - if (std::isnan(value)) { - return 0; - } - return minInt; - } - - template - TType CalculateNarrowedValue(Type *target, Type *source, SType value) - { - switch (ETSChecker::ETSChecker::ETSType(target)) { - case TypeFlag::BYTE: - case TypeFlag::CHAR: - case TypeFlag::SHORT: { - if (source->HasTypeFlag(checker::TypeFlag::DOUBLE) || source->HasTypeFlag(checker::TypeFlag::FLOAT)) { - return static_cast(CastFloatingPointToIntOrLong(value)); - } - return static_cast(value); - } - case TypeFlag::INT: - case TypeFlag::LONG: { - if (source->HasTypeFlag(checker::TypeFlag::DOUBLE) || source->HasTypeFlag(checker::TypeFlag::FLOAT)) { - return CastFloatingPointToIntOrLong(value); - } - return static_cast(value); - } - case TypeFlag::FLOAT: - case TypeFlag::DOUBLE: { - return static_cast(value); - } - default: { - ES2PANDA_UNREACHABLE(); - } - } - } - - template - void ApplyNarrowing() - { - using SType = typename SourceType::UType; - using TType = typename TargetType::UType; - - if (Source()->HasTypeFlag(TypeFlag::CONSTANT)) { - SType value = reinterpret_cast(Source())->GetValue(); - if (!Relation()->InCastingContext() && Source()->HasTypeFlag(TypeFlag::ETS_FLOATING_POINT) && - Target()->HasTypeFlag(TypeFlag::ETS_INTEGRAL)) { - auto narrowedValue = CalculateNarrowedValue(Target(), Source(), value); - if (narrowedValue != value) { - Relation()->Result(RelationResult::ERROR); - return; - } - } - - if (Relation()->InCastingContext() || util::Helpers::IsTargetFitInSourceRange(value)) { - Relation()->Result(true); - return; - } - - Relation()->Result(RelationResult::ERROR); - return; - } - - Relation()->Result(true); - } -}; -} // namespace ark::es2panda::checker - -#endif diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index b656a25717..4760ea0ca1 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -1518,37 +1518,6 @@ void ETSChecker::CheckInnerClassMembers(const ETSObjectType *classType) } } -lexer::Number ETSChecker::ExtractNumericValue(Type const *const indexType) -{ - TypeFlag typeKind = ETSType(indexType); - lexer::Number resNum; - switch (typeKind) { - case TypeFlag::BYTE: { - resNum = lexer::Number(indexType->AsByteType()->GetValue()); - break; - } - case TypeFlag::SHORT: { - resNum = lexer::Number(indexType->AsShortType()->GetValue()); - break; - } - case TypeFlag::INT: { - resNum = lexer::Number(indexType->AsIntType()->GetValue()); - break; - } - case TypeFlag::FLOAT: { - resNum = lexer::Number(indexType->AsFloatType()->GetValue()); - break; - } - case TypeFlag::DOUBLE: { - resNum = lexer::Number(indexType->AsDoubleType()->GetValue()); - break; - } - default: - break; - } - return resNum; -} - bool ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed) { auto const expressionType = expr->Check(this); @@ -1556,47 +1525,58 @@ bool ETSChecker::ValidateArrayIndex(ir::Expression *const expr, bool relaxed) return false; } - Type const *const unboxedExpressionType = MaybeUnboxInRelation(expressionType); - if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) { - expr->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType)); + if (!expressionType->IsETSObjectType() || + (!expressionType->AsETSObjectType()->HasObjectFlag(relaxed ? ETSObjectFlags::BUILTIN_ARRAY_NUMERIC + : ETSObjectFlags::BUILTIN_ARRAY_INDEX))) { + LogError(diagnostic::INVALID_INDEX_TYPE, {expressionType->ToString()}, expr->Start()); + return false; } - Type const *const indexType = ApplyUnaryOperatorPromotion(expressionType); - - if (relaxed && indexType != nullptr) { - lexer::Number resNum = ExtractNumericValue(indexType); - double value = resNum.GetDouble(); - double intpart; - if (std::modf(value, &intpart) != 0.0) { - LogError(diagnostic::INDEX_NONINTEGRAL_FLOAT, {}, expr->Start()); - return false; - } - bool tildeFlag = false; - if (expr->IsUnaryExpression() && - expr->AsUnaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_TILDE) { - tildeFlag = true; - } - if ((tildeFlag && value > 0) || (!tildeFlag && value < 0)) { - LogError(diagnostic::NEGATIVE_INDEX, {}, expr->Start()); - return false; - } + if (!relaxed || !expressionType->IsConstantType()) { + return true; } - if (indexType == nullptr || - (!indexType->HasTypeFlag(relaxed ? (TypeFlag::ETS_ARRAY_INDEX | TypeFlag::ETS_FLOATING_POINT) - : TypeFlag::ETS_ARRAY_INDEX))) { - std::stringstream message(""); - expressionType->ToString(message); + ES2PANDA_ASSERT(expr->IsNumberLiteral()); + double value = expr->AsNumberLiteral()->Number().GetDouble(); + + double intPart; + if (std::modf(value, &intPart) != 0.0) { + LogError(diagnostic::INDEX_NONINTEGRAL_FLOAT, {}, expr->Start()); + return false; + } - LogError(diagnostic::INVALID_INDEX_TYPE, {message.str()}, expr->Start()); + if (intPart < 0.0) { + LogError(diagnostic::NEGATIVE_INDEX, {}, expr->Start()); return false; } return true; } -std::optional ETSChecker::GetTupleElementAccessValue(const Type *const type) +std::optional ETSChecker::GetTupleElementAccessValue(const ir::Expression *expr) { + auto checkLongValBounds = [this](int64_t val, const lexer::SourcePosition &p) -> std::optional { + if (val < 0) { + LogError(diagnostic::TUPLE_INDEX_OOB, {}, p); + return std::nullopt; + } + return static_cast(val); + }; + + if (expr->IsNumberLiteral()) { + auto num = expr->AsNumberLiteral()->Number(); + if (num.IsInt()) { + return checkLongValBounds(num.GetInt(), expr->Start()); + } + if (num.IsLong()) { + return checkLongValBounds(num.GetLong(), expr->Start()); + } + ES2PANDA_UNREACHABLE(); + } + + // Below code should be unreachable after removing primitives + auto type = expr->TsType(); + ES2PANDA_ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)); switch (ETSType(type)) { @@ -1625,14 +1605,9 @@ std::optional ETSChecker::GetTupleElementAccessValue(const Type *co bool ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, ir::MemberExpression *const expr, const bool reportError) { - auto const expressionType = expr->Property()->Check(this); - auto const *const unboxedExpressionType = MaybeUnboxInRelation(expressionType); - - if (expressionType->IsETSObjectType() && (unboxedExpressionType != nullptr)) { - expr->Property()->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxedExpressionType)); - } + auto const exprType = expr->Property()->Check(this); + auto const *const unboxedExpressionType = MaybeUnboxInRelation(exprType); - const auto *const exprType = expr->Property()->TsType(); ES2PANDA_ASSERT(exprType != nullptr); if (!exprType->HasTypeFlag(TypeFlag::CONSTANT)) { @@ -1645,14 +1620,13 @@ bool ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, ir::MemberE return false; } - if (!exprType->HasTypeFlag(TypeFlag::ETS_ARRAY_INDEX | TypeFlag::LONG)) { - if (reportError) { - LogError(diagnostic::TUPLE_INDEX_NOT_INT, {}, expr->Property()->Start()); - } + if (!Relation()->IsSupertypeOf(GlobalIntBuiltinType(), exprType) && + !Relation()->IsSupertypeOf(GlobalLongBuiltinType(), exprType)) { + LogError(diagnostic::TUPLE_INDEX_NOT_INT, {}, expr->Property()->Start()); return false; } - auto exprValue = GetTupleElementAccessValue(exprType); + auto exprValue = GetTupleElementAccessValue(expr->Property()); if (!exprValue.has_value() || (*exprValue >= tuple->GetTupleSize())) { if (reportError) { LogError(diagnostic::TUPLE_INDEX_OOB, {}, expr->Property()->Start()); @@ -1665,6 +1639,13 @@ bool ETSChecker::ValidateTupleIndex(const ETSTupleType *const tuple, ir::MemberE bool ETSChecker::ValidateTupleIndexFromEtsObject(const ETSTupleType *const tuple, ir::MemberExpression *const expr) { + if (expr->Property() == nullptr || expr->Property()->Variable() == nullptr || + expr->Property()->Variable()->Declaration() == nullptr || + expr->Property()->Variable()->Declaration()->Node() == nullptr || + expr->Property()->Variable()->Declaration()->Node()->AsClassElement() == nullptr) { + LogError(diagnostic::TUPLE_INDEX_NONCONST, {}, expr->Start()); + return false; + } auto *value = expr->Property()->Variable()->Declaration()->Node()->AsClassElement()->Value(); if (value == nullptr) { LogError(diagnostic::TUPLE_INDEX_NONCONST, {}, expr->Property()->Start()); @@ -1682,7 +1663,7 @@ bool ETSChecker::ValidateTupleIndexFromEtsObject(const ETSTupleType *const tuple return false; } - auto exprValue = GetTupleElementAccessValue(exprType); + auto exprValue = GetTupleElementAccessValue(expr); if (!exprValue.has_value() || (*exprValue >= tuple->GetTupleSize())) { LogError(diagnostic::TUPLE_INDEX_OOB, {}, expr->Property()->Start()); return false; @@ -1975,6 +1956,9 @@ static bool ShouldRemoveStaticSearchFlag(const ir::MemberExpression *const membe if (object->IsMemberExpression()) { object = object->AsMemberExpression()->Property(); } + if (object->IsTypeNode()) { + return false; + } if (!object->IsIdentifier() || (object->AsIdentifier()->Variable() == nullptr) || object->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::INITIALIZED)) { return true; @@ -2015,6 +1999,9 @@ const varbinder::Variable *ETSChecker::GetTargetRef(const ir::MemberExpression * if (memberExpr->Object()->IsMemberExpression()) { return memberExpr->Object()->AsMemberExpression()->PropVar(); } + if (memberExpr->Object()->IsTypeNode() && memberExpr->Object()->TsType()->IsETSObjectType()) { + return memberExpr->Object()->TsType()->Variable(); + } return nullptr; } @@ -2538,26 +2525,8 @@ Type *ETSChecker::GetApparentType(Type *type) Type const *ETSChecker::GetApparentType(Type const *type) const { - auto currChecker = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker(); - auto &apparentTypes = currChecker->apparentTypes_; - if (auto it = apparentTypes.find(type); LIKELY(it != apparentTypes.end())) { - return it->second; - } - // Relaxed for some types - if (type->IsETSTypeParameter()) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return GetApparentType(type->AsETSTypeParameter()->GetConstraintType()); - } - if (type->IsETSArrayType()) { - return type; - } - if (type->IsETSStringType()) { - return GlobalBuiltinETSStringType(); - } - if (type->IsETSUnionType() || type->IsETSNonNullishType() || type->IsETSPartialTypeParameter()) { - ASSERT_PRINT(false, std::string("Type ") + type->ToString() + " was not found in apparent_types_"); - } - return type; + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return const_cast(const_cast(this)->GetApparentType(const_cast(type))); } ETSObjectType *ETSChecker::GetClosestCommonAncestor(ETSObjectType *source, ETSObjectType *target) diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 7fdd86d463..39970f37d6 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -14,7 +14,7 @@ */ #include "checker/checker.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" #include "checker/types/globalTypesHolder.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/etsPartialTypeParameter.h" @@ -58,16 +58,13 @@ void ETSChecker::CheckTruthinessOfType(ir::Expression *expr) if (conditionType == nullptr) { return; } + expr->SetTsType(MaybeBoxType(conditionType)); if (conditionType->IsETSVoidType()) { LogError(diagnostic::VOID_IN_LOGIC, {}, expr->Start()); return; } - if (conditionType->IsETSPrimitiveType()) { - FlagExpressionWithUnboxing(testType, conditionType, expr); - } - // For T_S compatibility if (conditionType->IsETSEnumType()) { expr->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); @@ -394,10 +391,13 @@ Type *ETSChecker::GetNonConstantType(Type *type) } if (type->IsETSUnionType()) { - return CreateETSUnionType(ETSUnionType::GetNonConstantTypes(this, type->AsETSUnionType()->ConstituentTypes())); + return CreateETSUnionType(type->AsETSUnionType()->GetNonConstantTypes(this)); } if (!type->IsETSPrimitiveType()) { + if (type->IsETSObjectType() && type->AsETSObjectType()->IsBoxedPrimitive()) { + type->RemoveTypeFlag(TypeFlag::CONSTANT); + } return type; } @@ -949,7 +949,7 @@ void ETSChecker::CheckFunctionSignatureAnnotations(const ArenaVectorIsETSParameterExpression()) { CheckAnnotations(param->AsETSParameterExpression()->Annotations()); if (param->AsETSParameterExpression()->TypeAnnotation() != nullptr) { - param->AsETSParameterExpression()->TypeAnnotation()->Check(this); + CheckAnnotations(param->AsETSParameterExpression()->TypeAnnotation()->Annotations()); } } } @@ -1095,21 +1095,68 @@ void ETSChecker::CheckStandardAnnotation(ir::AnnotationUsage *anno) } } +static auto IsNonArrayLiteral(ir::Expression *init) +{ + if ((init == nullptr) || init->IsLiteral()) { + return true; + } + + if (init->TsType()->IsETSEnumType() && init->TsType()->AsETSEnumType()->NodeIsEnumLiteral(init)) { + return true; + } + return false; +} + +static auto IsValidAnnotationPropInitializer(ir::Expression *init) +{ + if (IsNonArrayLiteral(init)) { + return true; + } + + if (init->IsArrayExpression()) { + for (auto elem : init->AsArrayExpression()->Elements()) { + if (!IsValidAnnotationPropInitializer(elem)) { + return false; + } + } + return true; + } + return false; +} + +static bool ValidateAnnotationPropertyType(checker::Type *type, ETSChecker *checker) +{ + if (type == nullptr || type->IsTypeError()) { + ES2PANDA_ASSERT(checker->IsAnyError()); + return false; + } + + if (type->IsETSArrayType() || type->IsETSResizableArrayType()) { + return ValidateAnnotationPropertyType(checker->GetElementTypeOfArray(type), checker); + } + auto relation = checker->Relation(); + return type->IsETSEnumType() || type->IsETSStringType() || + (type->IsETSObjectType() && (relation->IsSupertypeOf(checker->GlobalETSBooleanBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalByteBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalShortBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalIntBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalLongBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalFloatBuiltinType(), type) || + relation->IsSupertypeOf(checker->GlobalDoubleBuiltinType(), type))); +} + void ETSChecker::CheckAnnotationPropertyType(ir::ClassProperty *property) { // typeAnnotation check - if (!ValidateAnnotationPropertyType(property->TsType())) { + if (!ValidateAnnotationPropertyType(property->TsType(), this)) { LogError(diagnostic::ANNOT_FIELD_INVALID_TYPE, {}, property->Start()); } - // The type of the Initializer has been check in the parser, - // except for the enumeration type, because it is a member expression, - // so here is an additional check to the enumeration type. - if (property->Value() != nullptr && - ((property->Value()->IsMemberExpression() && !property->TsType()->IsETSEnumType()) || - property->Value()->IsIdentifier())) { - LogError(diagnostic::ANNOTATION_FIELD_NONLITERAL, {}, property->Value()->Start()); + if (IsValidAnnotationPropInitializer(property->Value())) { + return; } + + LogError(diagnostic::ANNOTATION_FIELD_NONLITERAL, {}, property->Value()->Start()); } void ETSChecker::CheckSinglePropertyAnnotation(ir::AnnotationUsage *st, ir::AnnotationDeclaration *annoDecl) @@ -1124,17 +1171,6 @@ void ETSChecker::CheckSinglePropertyAnnotation(ir::AnnotationUsage *st, ir::Anno CheckAnnotationPropertyType(param); } -void ETSChecker::ProcessRequiredFields(ArenaUnorderedMap &fieldMap, - ir::AnnotationUsage *st, ETSChecker *checker) const -{ - for (const auto &entry : fieldMap) { - if (entry.second->Value() == nullptr) { - checker->LogError(diagnostic::ANNOT_FIELD_NO_VAL, {entry.first}, st->Start()); - continue; - } - } -} - void ETSChecker::CheckMultiplePropertiesAnnotation(ir::AnnotationUsage *st, util::StringView const &baseName, ArenaUnorderedMap &fieldMap) { @@ -1235,85 +1271,15 @@ Type const *ETSChecker::MaybeUnboxType(Type const *type) const return MaybeUnboxType(const_cast(type)); } -ir::BoxingUnboxingFlags ETSChecker::GetBoxingFlag(Type *const boxingType) -{ - auto typeKind = TypeKind(MaybeUnboxInRelation(boxingType)); - switch (typeKind) { - case TypeFlag::ETS_BOOLEAN: - return ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN; - case TypeFlag::BYTE: - return ir::BoxingUnboxingFlags::BOX_TO_BYTE; - case TypeFlag::CHAR: - return ir::BoxingUnboxingFlags::BOX_TO_CHAR; - case TypeFlag::SHORT: - return ir::BoxingUnboxingFlags::BOX_TO_SHORT; - case TypeFlag::INT: - return ir::BoxingUnboxingFlags::BOX_TO_INT; - case TypeFlag::LONG: - return ir::BoxingUnboxingFlags::BOX_TO_LONG; - case TypeFlag::FLOAT: - return ir::BoxingUnboxingFlags::BOX_TO_FLOAT; - case TypeFlag::DOUBLE: - return ir::BoxingUnboxingFlags::BOX_TO_DOUBLE; - default: - ES2PANDA_UNREACHABLE(); - } -} - -ir::BoxingUnboxingFlags ETSChecker::GetUnboxingFlag(Type const *const unboxingType) const -{ - auto typeKind = TypeKind(unboxingType); - switch (typeKind) { - case TypeFlag::ETS_BOOLEAN: - return ir::BoxingUnboxingFlags::UNBOX_TO_BOOLEAN; - case TypeFlag::BYTE: - return ir::BoxingUnboxingFlags::UNBOX_TO_BYTE; - case TypeFlag::CHAR: - return ir::BoxingUnboxingFlags::UNBOX_TO_CHAR; - case TypeFlag::SHORT: - return ir::BoxingUnboxingFlags::UNBOX_TO_SHORT; - case TypeFlag::INT: - return ir::BoxingUnboxingFlags::UNBOX_TO_INT; - case TypeFlag::LONG: - return ir::BoxingUnboxingFlags::UNBOX_TO_LONG; - case TypeFlag::FLOAT: - return ir::BoxingUnboxingFlags::UNBOX_TO_FLOAT; - case TypeFlag::DOUBLE: - return ir::BoxingUnboxingFlags::UNBOX_TO_DOUBLE; - default: - ES2PANDA_UNREACHABLE(); - } -} - -void ETSChecker::MaybeAddBoxingFlagInRelation(TypeRelation *relation, Type *target) -{ - auto boxingResult = MaybeBoxInRelation(target); - if ((boxingResult != nullptr) && !relation->OnlyCheckBoxingUnboxing()) { - relation->GetNode()->RemoveBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOXING_FLAG); - relation->GetNode()->AddBoxingUnboxingFlags(GetBoxingFlag(boxingResult)); - relation->Result(true); - } -} - -void ETSChecker::MaybeAddUnboxingFlagInRelation(TypeRelation *relation, Type *source, Type *self) -{ - auto unboxingResult = UnboxingConverter(this, relation, source, self).Result(); - if ((unboxingResult != nullptr) && relation->IsTrue() && !relation->OnlyCheckBoxingUnboxing()) { - relation->GetNode()->AddBoxingUnboxingFlags(GetUnboxingFlag(unboxingResult)); - } -} - void ETSChecker::CheckUnboxedTypeWidenable(TypeRelation *relation, Type *target, Type *self) { - checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx( - relation, TypeRelationFlag::ONLY_CHECK_WIDENING | - (relation->ApplyNarrowing() ? TypeRelationFlag::NARROWING : TypeRelationFlag::NONE)); + checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(relation, TypeRelationFlag::ONLY_CHECK_WIDENING); // NOTE: vpukhov. handle union type auto unboxedType = MaybeUnboxInRelation(target); if (unboxedType == nullptr) { return; } - NarrowingWideningConverter(this, relation, unboxedType, self); + WideningConverter(this, relation, unboxedType, self); if (!relation->IsTrue()) { relation->Result(relation->IsAssignableTo(self, unboxedType)); } @@ -1327,10 +1293,6 @@ void ETSChecker::CheckUnboxedTypesAssignable(TypeRelation *relation, Type *sourc return; } relation->IsAssignableTo(unboxedSourceType, unboxedTargetType); - if (relation->IsTrue()) { - relation->GetNode()->AddBoxingUnboxingFlags( - relation->GetChecker()->AsETSChecker()->GetUnboxingFlag(unboxedSourceType)); - } } void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *source, Type *target) @@ -1338,7 +1300,6 @@ void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *so ES2PANDA_ASSERT(relation != nullptr); checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx( relation, (relation->ApplyWidening() ? TypeRelationFlag::WIDENING : TypeRelationFlag::NONE) | - (relation->ApplyNarrowing() ? TypeRelationFlag::NARROWING : TypeRelationFlag::NONE) | (relation->OnlyCheckBoxingUnboxing() ? TypeRelationFlag::ONLY_CHECK_BOXING_UNBOXING : TypeRelationFlag::NONE)); @@ -1352,17 +1313,12 @@ void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *so return; } relation->IsAssignableTo(boxedSourceType, target); - if (relation->IsTrue()) { - MaybeAddBoxingFlagInRelation(relation, boxedSourceType); - } else { + if (!relation->IsTrue()) { auto unboxedTargetType = MaybeUnboxInRelation(target); if (unboxedTargetType == nullptr) { return; } - NarrowingWideningConverter(this, relation, unboxedTargetType, source); - if (relation->IsTrue()) { - MaybeAddBoxingFlagInRelation(relation, target); - } + WideningConverter(this, relation, unboxedTargetType, source); } } @@ -1376,10 +1332,6 @@ void ETSChecker::CheckUnboxedSourceTypeWithWideningAssignable(TypeRelation *rela if (!relation->IsTrue() && relation->ApplyWidening()) { relation->GetChecker()->AsETSChecker()->CheckUnboxedTypeWidenable(relation, target, unboxedSourceType); } - if (!relation->OnlyCheckBoxingUnboxing()) { - relation->GetNode()->AddBoxingUnboxingFlags( - relation->GetChecker()->AsETSChecker()->GetUnboxingFlag(unboxedSourceType)); - } } static ir::AstNode *DerefETSTypeReference(ir::AstNode *node) @@ -1451,10 +1403,11 @@ bool ETSChecker::CheckLambdaInfer(ir::AstNode *typeAnnotation, ir::ArrowFunction return true; } -bool ETSChecker::CheckLambdaTypeAnnotation(ir::AstNode *typeAnnotation, +bool ETSChecker::CheckLambdaTypeAnnotation(ir::ETSParameterExpression *param, ir::ArrowFunctionExpression *const arrowFuncExpr, Type *const parameterType, TypeRelationFlag flags) { + auto *typeAnnotation = param->Ident()->TypeAnnotation(); auto checkInvocable = [&arrowFuncExpr, ¶meterType, this](TypeRelationFlag functionFlags) { Type *const argumentType = arrowFuncExpr->Check(this); functionFlags |= TypeRelationFlag::NO_THROW; @@ -1466,10 +1419,10 @@ bool ETSChecker::CheckLambdaTypeAnnotation(ir::AstNode *typeAnnotation, // process `single` type as usual. if (!typeAnnotation->IsETSUnionType()) { - auto param = typeAnnotation->Parent()->Parent()->AsETSParameterExpression(); // #22952: infer optional parameter heuristics auto nonNullishParam = param->IsOptional() ? GetNonNullishType(parameterType) : parameterType; if (!nonNullishParam->IsETSFunctionType()) { + arrowFuncExpr->Check(this); return true; } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) @@ -1530,13 +1483,12 @@ bool ETSChecker::ResolveLambdaArgumentType(Signature *signature, ir::Expression } arrowFuncExpr->SetTsType(nullptr); - auto const *const param = + auto *const param = signature->GetSignatureInfo()->params[paramPosition]->Declaration()->Node()->AsETSParameterExpression(); - ir::AstNode *typeAnn = param->Ident()->TypeAnnotation(); Type *const parameterType = signature->Params()[paramPosition]->TsType(); // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - bool rc = CheckLambdaTypeAnnotation(typeAnn, arrowFuncExpr, parameterType, resolutionFlags); + bool rc = CheckLambdaTypeAnnotation(param, arrowFuncExpr, parameterType, resolutionFlags); if (!rc) { if ((resolutionFlags & TypeRelationFlag::NO_THROW) == 0) { Type *const argumentType = arrowFuncExpr->Check(this); diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 7ae0ec47b2..fd835f0b7a 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -52,32 +52,6 @@ IntType *ETSChecker::CreateIntType(int32_t value) return ProgramAllocator()->New(value); } -IntType *ETSChecker::CreateIntTypeFromType(Type *type) -{ - if (!type->HasTypeFlag(TypeFlag::CONSTANT)) { - return GlobalIntType()->AsIntType(); - } - - if (type->IsIntType()) { - return type->AsIntType(); - } - - switch (ETSType(type)) { - case TypeFlag::CHAR: { - return CreateIntType(static_cast(type->AsCharType()->GetValue())); - } - case TypeFlag::BYTE: { - return CreateIntType(static_cast(type->AsByteType()->GetValue())); - } - case TypeFlag::SHORT: { - return CreateIntType(static_cast(type->AsShortType()->GetValue())); - } - default: { - return nullptr; - } - } -} - LongType *ETSChecker::CreateLongType(int64_t value) { return ProgramAllocator()->New(value); diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index f8a63c3124..f2aecd19fb 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -77,19 +77,7 @@ void InstantiationContext::InstantiateType(ETSObjectType *type, ir::TSTypeParame result_ = paramType; return; } - - if (paramType->IsETSPrimitiveType()) { - checker_->Relation()->SetNode(it); - - auto *const boxedTypeArg = checker_->MaybeBoxInRelation(paramType); - if (boxedTypeArg != nullptr) { - paramType = boxedTypeArg->Instantiate(checker_->Allocator(), checker_->Relation(), - checker_->GetGlobalTypesHolder()); - } else { - ES2PANDA_UNREACHABLE(); - } - } - + ES2PANDA_ASSERT(!paramType->IsETSPrimitiveType()); typeArgTypes.push_back(paramType); } } @@ -136,10 +124,10 @@ static void CheckInstantiationConstraints(ETSChecker *checker, ArenaVectorIsETSReferenceType() || typeArg->IsETSVoidType()); + auto maybeIrrelevantTypeArg = typeArg->IsETSVoidType() ? checker->GlobalETSUndefinedType() : typeArg; auto constraint = typeParam->GetConstraintType()->Substitute(relation, substitution); - if (!relation->IsAssignableTo(typeArg, constraint)) { - // NOTE(vpukhov): refine message - checker->LogError(diagnostic::INIT_NOT_ASSIGNABLE, {typeArg, constraint}, pos); + if (!relation->IsSupertypeOf(constraint, maybeIrrelevantTypeArg)) { + checker->LogError(diagnostic::TYPEARG_TYPEPARAM_SUBTYPING, {typeArg, constraint}, pos); } } } diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index ef6c5017f9..eeb2ba008d 100644 --- a/ets2panda/checker/ets/typeRelationContext.h +++ b/ets2panda/checker/ets/typeRelationContext.h @@ -45,19 +45,11 @@ public: flags_ |= flags; relation->SetNode(node); - // NOTE (oeotvos) The narrowing flag will be applied here. It means, that the result of "let tmp: int = 1.5" - // will be 1, which could cause problems. - if (source->HasTypeFlag(TypeFlag::CONSTANT)) { - flags_ |= TypeRelationFlag::NARROWING; - } - relation->SetFlags(flags_); if (!relation->IsAssignableTo(source, target)) { if (relation->IsLegalBoxedPrimitiveConversion(target, source)) { - Type *sourceUnboxedType = etsChecker->MaybeUnboxType(source); - relation->GetNode()->AddBoxingUnboxingFlags(etsChecker->GetUnboxingFlag(sourceUnboxedType)); - relation->GetNode()->AddBoxingUnboxingFlags(etsChecker->GetBoxingFlag(target)); + relation->Result(true); } if (((flags_ & TypeRelationFlag::UNBOXING) != 0) && !relation->IsTrue() && source->IsETSObjectType() && !target->IsETSObjectType()) { @@ -107,6 +99,9 @@ public: relation->SetFlags(flags_ | initialFlags); if (!relation->IsAssignableTo(source, target)) { + if (relation->IsLegalBoxedPrimitiveConversion(target, source)) { + relation->Result(true); + } if (((flags_ & TypeRelationFlag::UNBOXING) != 0U) && !relation->IsTrue() && source->IsETSObjectType() && !target->IsETSObjectType()) { etsChecker->CheckUnboxedSourceTypeWithWideningAssignable(relation, source, target); diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index f3ad9a385b..8d28ba8fd7 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -191,21 +191,6 @@ void ETSChecker::ValidateResolvedIdentifier(ir::Identifier *const ident) } } -bool ETSChecker::ValidateAnnotationPropertyType(checker::Type *type) -{ - if (type == nullptr || type->IsTypeError()) { - ES2PANDA_ASSERT(IsAnyError()); - return false; - } - - if (type->IsETSArrayType() || type->IsETSResizableArrayType()) { - return ValidateAnnotationPropertyType(MaybeUnboxType(GetElementTypeOfArray(type))); - } - - return type->HasTypeFlag(TypeFlag::ETS_NUMERIC | TypeFlag::ETS_ENUM | TypeFlag::ETS_BOOLEAN) || - type->IsETSStringType(); -} - void ETSChecker::ValidateUnaryOperatorOperand(varbinder::Variable *variable) { if (IsVariableGetterSetter(variable)) { diff --git a/ets2panda/checker/ets/wideningConverter.h b/ets2panda/checker/ets/wideningConverter.h index 00f65deda0..163f5545e0 100644 --- a/ets2panda/checker/ets/wideningConverter.h +++ b/ets2panda/checker/ets/wideningConverter.h @@ -30,11 +30,7 @@ public: return; } - if (!Source()->HasTypeFlag(TypeFlag::CONSTANT)) { - ApplyGlobalWidening(); - } else { - ApplyConstWidening(); - } + ApplyGlobalWidening(); } private: @@ -45,39 +41,6 @@ private: static constexpr TypeFlag WIDENABLE_TO_FLOAT = TypeFlag::LONG | WIDENABLE_TO_LONG; static constexpr TypeFlag WIDENABLE_TO_DOUBLE = TypeFlag::FLOAT | WIDENABLE_TO_FLOAT; - void ApplyConstWidening() - { - switch (ETSChecker::ETSChecker::ETSType(Target())) { - case TypeFlag::SHORT: { - ApplyWidening(WIDENABLE_TO_SHORT); - break; - } - case TypeFlag::CHAR: { - ApplyWidening(WIDENABLE_TO_CHAR); - break; - } - case TypeFlag::INT: { - ApplyWidening(WIDENABLE_TO_INT); - break; - } - case TypeFlag::LONG: { - ApplyWidening(WIDENABLE_TO_LONG); - break; - } - case TypeFlag::FLOAT: { - ApplyWidening(WIDENABLE_TO_FLOAT); - break; - } - case TypeFlag::DOUBLE: { - ApplyWidening(WIDENABLE_TO_DOUBLE); - break; - } - default: { - break; - } - } - } - void ApplyGlobalWidening() { switch (ETSChecker::ETSChecker::ETSType(Target())) { @@ -121,31 +84,31 @@ private: ES2PANDA_ASSERT(Relation()->GetNode()); switch (ETSChecker::ETSChecker::ETSType(Source())) { case TypeFlag::BYTE: { - Relation()->GetNode()->SetTsType(Checker()->GlobalByteType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalByteBuiltinType()); break; } case TypeFlag::SHORT: { - Relation()->GetNode()->SetTsType(Checker()->GlobalShortType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalShortBuiltinType()); break; } case TypeFlag::CHAR: { - Relation()->GetNode()->SetTsType(Checker()->GlobalCharType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalCharBuiltinType()); break; } case TypeFlag::INT: { - Relation()->GetNode()->SetTsType(Checker()->GlobalIntType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalIntBuiltinType()); break; } case TypeFlag::LONG: { - Relation()->GetNode()->SetTsType(Checker()->GlobalLongType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalLongBuiltinType()); break; } case TypeFlag::FLOAT: { - Relation()->GetNode()->SetTsType(Checker()->GlobalFloatType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalFloatBuiltinType()); break; } case TypeFlag::DOUBLE: { - Relation()->GetNode()->SetTsType(Checker()->GlobalDoubleType()); + Relation()->GetNode()->SetTsType(Checker()->GlobalDoubleBuiltinType()); break; } default: { @@ -156,62 +119,6 @@ private: Relation()->Result(true); } - - template - void ApplyWidening(TypeFlag flag) - { - if (!Source()->HasTypeFlag(flag)) { - return; - } - - switch (ETSChecker::ETSChecker::ETSType(Source())) { - case TypeFlag::BYTE: { - ApplyWidening(); - break; - } - case TypeFlag::CHAR: { - ApplyWidening(); - break; - } - case TypeFlag::SHORT: { - ApplyWidening(); - break; - } - case TypeFlag::INT: { - ApplyWidening(); - break; - } - case TypeFlag::LONG: { - ApplyWidening(); - break; - } - case TypeFlag::FLOAT: { - ApplyWidening(); - break; - } - case TypeFlag::DOUBLE: { - ApplyWidening(); - break; - } - default: { - return; - } - } - Relation()->Result(true); - } - - template - void ApplyWidening() - { - using SType = typename SourceType::UType; - using TType = typename TargetType::UType; - SType value = reinterpret_cast(Source())->GetValue(); - - if (!Relation()->OnlyCheckWidening()) { - ES2PANDA_ASSERT(Relation()->GetNode()); - Relation()->GetNode()->SetTsType(Checker()->ProgramAllocator()->New(static_cast(value))); - } - } }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/byteType.cpp b/ets2panda/checker/types/ets/byteType.cpp index 44537a4f54..e69f7aff80 100644 --- a/ets2panda/checker/types/ets/byteType.cpp +++ b/ets2panda/checker/types/ets/byteType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,8 +15,9 @@ #include "byteType.h" +#include "checker/ETSchecker.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingConverter.h" +#include "checker/types/ets/etsObjectType.h" namespace ark::es2panda::checker { void ByteType::Identical(TypeRelation *relation, Type *other) @@ -26,13 +27,7 @@ void ByteType::Identical(TypeRelation *relation, Type *other) } } -void ByteType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) -{ - if (relation->ApplyUnboxing()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); -} +void ByteType::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) {} bool ByteType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) { @@ -57,38 +52,9 @@ void ByteType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::SHORT | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::CHAR)) { - conversion::WideningNarrowingPrimitive(relation, this, target->AsCharType()); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_BYTE)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/byteType.h b/ets2panda/checker/types/ets/byteType.h index a92f1f637d..a622ebc4e2 100644 --- a/ets2panda/checker/types/ets/byteType.h +++ b/ets2panda/checker/types/ets/byteType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,11 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_BYTE; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_ != 0}; - } - private: UType value_ {0}; }; diff --git a/ets2panda/checker/types/ets/charType.cpp b/ets2panda/checker/types/ets/charType.cpp index 62fad52d6e..43bbec66cd 100644 --- a/ets2panda/checker/types/ets/charType.cpp +++ b/ets2panda/checker/types/ets/charType.cpp @@ -16,7 +16,7 @@ #include "charType.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" namespace ark::es2panda::checker { void CharType::Identical(TypeRelation *relation, Type *other) @@ -28,10 +28,7 @@ void CharType::Identical(TypeRelation *relation, Type *other) void CharType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingWideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); + WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } bool CharType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) @@ -57,38 +54,9 @@ void CharType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/charType.h b/ets2panda/checker/types/ets/charType.h index 9ddb9054ff..793a64ea4e 100644 --- a/ets2panda/checker/types/ets/charType.h +++ b/ets2panda/checker/types/ets/charType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,11 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_CHAR; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_ != '\0'}; - } - private: UType value_ {'\0'}; }; diff --git a/ets2panda/checker/types/ets/doubleType.cpp b/ets2panda/checker/types/ets/doubleType.cpp index 91477c19e4..ad58d7bc8c 100644 --- a/ets2panda/checker/types/ets/doubleType.cpp +++ b/ets2panda/checker/types/ets/doubleType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -28,9 +28,6 @@ void DoubleType::Identical(TypeRelation *relation, Type *other) void DoubleType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing() && !relation->IsTrue()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } @@ -56,34 +53,9 @@ void DoubleType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | - TypeFlag::FLOAT)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/doubleType.h b/ets2panda/checker/types/ets/doubleType.h index e7e7dde792..fa3d5de326 100644 --- a/ets2panda/checker/types/ets/doubleType.h +++ b/ets2panda/checker/types/ets/doubleType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,12 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_DOUBLE; } - std::tuple ResolveConditionExpr() const override - { - // isNan = !(value_ == value_) - return {IsConstantType(), (value_ != 0) && (value_ == value_)}; - } - private: UType value_ {0.0}; }; diff --git a/ets2panda/checker/types/ets/etsAnyType.cpp b/ets2panda/checker/types/ets/etsAnyType.cpp index 811705455b..d9b87e49a2 100644 --- a/ets2panda/checker/types/ets/etsAnyType.cpp +++ b/ets2panda/checker/types/ets/etsAnyType.cpp @@ -33,8 +33,6 @@ void ETSAnyType::AssignmentTarget(TypeRelation *relation, Type *source) } if (relation->ApplyBoxing()) { - auto checker = relation->GetChecker()->AsETSChecker(); - relation->GetNode()->AddBoxingUnboxingFlags(checker->GetBoxingFlag(checker->MaybeBoxType(source))); relation->Result(true); } } @@ -109,4 +107,4 @@ Type *ETSAnyType::Instantiate(ArenaAllocator *allocator, [[maybe_unused]] TypeRe { return allocator->New(); } -} // namespace ark::es2panda::checker \ No newline at end of file +} // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsAnyType.h b/ets2panda/checker/types/ets/etsAnyType.h index 3dbca0c808..1a315b36d6 100644 --- a/ets2panda/checker/types/ets/etsAnyType.h +++ b/ets2panda/checker/types/ets/etsAnyType.h @@ -38,11 +38,6 @@ public: TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), false}; - } }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsArrayType.cpp b/ets2panda/checker/types/ets/etsArrayType.cpp index 2f0573d664..79d9cc3983 100644 --- a/ets2panda/checker/types/ets/etsArrayType.cpp +++ b/ets2panda/checker/types/ets/etsArrayType.cpp @@ -111,7 +111,7 @@ void ETSArrayType::AssignmentTarget(TypeRelation *relation, Type *source) source->AsETSArrayType()->ElementType()->IsETSPrimitiveOrEnumType()) { return; } - relation->IsAssignableTo(source->AsETSArrayType()->ElementType(), element_); + relation->IsSupertypeOf(element_, source->AsETSArrayType()->ElementType()); } } diff --git a/ets2panda/checker/types/ets/etsArrayType.h b/ets2panda/checker/types/ets/etsArrayType.h index 9794adb54f..c9dd00904f 100644 --- a/ets2panda/checker/types/ets/etsArrayType.h +++ b/ets2panda/checker/types/ets/etsArrayType.h @@ -38,11 +38,6 @@ public: element_ = element; } - std::tuple ResolveConditionExpr() const override - { - return {false, false}; - } - void ToString(std::stringstream &ss, bool precise) const override; void ToAssemblerType(std::stringstream &ss) const override; diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp index 46308e495d..bc2a83fca7 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.cpp @@ -39,6 +39,15 @@ void ETSAsyncFuncReturnType::Identical(TypeRelation *relation, Type *other) relation->Result(false); } +void ETSAsyncFuncReturnType::IsSupertypeOf(TypeRelation *relation, Type *source) +{ + GetPromiseTypeArg()->IsSupertypeOf(relation, source); + if (relation->IsTrue()) { + return; + } + promiseType_->IsSupertypeOf(relation, source); +} + bool ETSAsyncFuncReturnType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) { return false; @@ -47,9 +56,6 @@ bool ETSAsyncFuncReturnType::AssignmentSource([[maybe_unused]] TypeRelation *rel void ETSAsyncFuncReturnType::AssignmentTarget(TypeRelation *relation, Type *source) { relation->IsAssignableTo(source, promiseType_) || relation->IsAssignableTo(source, GetPromiseTypeArg()); - if (relation->IsTrue() && !source->IsETSObjectType() && relation->ApplyBoxing()) { - relation->GetChecker()->AsETSChecker()->MaybeAddBoxingFlagInRelation(relation, source); - } } void ETSAsyncFuncReturnType::CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h index e079ff71a6..d6b4d58b22 100644 --- a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h +++ b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h @@ -33,6 +33,7 @@ public: void ToString(std::stringstream &ss, bool precise) const override; void Identical(TypeRelation *relation, Type *other) override; + void IsSupertypeOf(TypeRelation *relation, Type *source) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; void CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) override; diff --git a/ets2panda/checker/types/ets/etsBooleanType.cpp b/ets2panda/checker/types/ets/etsBooleanType.cpp index e3d661ea8d..f19823daa2 100644 --- a/ets2panda/checker/types/ets/etsBooleanType.cpp +++ b/ets2panda/checker/types/ets/etsBooleanType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,14 +26,9 @@ void ETSBooleanType::Identical(TypeRelation *relation, Type *other) } } -void ETSBooleanType::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) -{ - if (relation->ApplyUnboxing() && !relation->IsTrue()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } -} +void ETSBooleanType::AssignmentTarget([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *source) {} -bool ETSBooleanType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) +bool ETSBooleanType::AssignmentSource(TypeRelation *relation, Type *target) { if (relation->ApplyBoxing() && target->IsETSObjectType()) { relation->GetChecker()->AsETSChecker()->CheckBoxedSourceTypeAssignable(relation, this, target); diff --git a/ets2panda/checker/types/ets/etsBooleanType.h b/ets2panda/checker/types/ets/etsBooleanType.h index 421ae63e3b..2bc7ccaddc 100644 --- a/ets2panda/checker/types/ets/etsBooleanType.h +++ b/ets2panda/checker/types/ets/etsBooleanType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -51,11 +51,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_BOOLEAN; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_}; - } - private: UType value_ {false}; }; diff --git a/ets2panda/checker/types/ets/etsDynamicType.cpp b/ets2panda/checker/types/ets/etsDynamicType.cpp index 3fb4c1392d..cd6be095d6 100644 --- a/ets2panda/checker/types/ets/etsDynamicType.cpp +++ b/ets2panda/checker/types/ets/etsDynamicType.cpp @@ -105,7 +105,7 @@ bool ETSDynamicType::IsConvertible(Type const *target) target->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC | checker::TypeFlag::ETS_BOOLEAN); } -ETSFunctionType *ETSDynamicType::CreateMethodTypeForProp(const util::StringView &name) const +ETSFunctionType *ETSDynamicType::CreateMethodTypeForProp(util::StringView name) const { auto checker = GetRelation()->GetChecker()->AsETSChecker(); return checker->CreateETSDynamicMethodType(name, {{}, Allocator()->Adapter()}, lang_); diff --git a/ets2panda/checker/types/ets/etsDynamicType.h b/ets2panda/checker/types/ets/etsDynamicType.h index 9506417407..47b99e3102 100644 --- a/ets2panda/checker/types/ets/etsDynamicType.h +++ b/ets2panda/checker/types/ets/etsDynamicType.h @@ -57,7 +57,7 @@ public: return hasDecl_; } - ETSFunctionType *CreateMethodTypeForProp(const util::StringView &name) const override; + ETSFunctionType *CreateMethodTypeForProp(util::StringView name) const override; void ToAssemblerType(std::stringstream &ss) const override; diff --git a/ets2panda/checker/types/ets/etsEnumType.cpp b/ets2panda/checker/types/ets/etsEnumType.cpp index 61d23b7cbf..bea6d5044b 100644 --- a/ets2panda/checker/types/ets/etsEnumType.cpp +++ b/ets2panda/checker/types/ets/etsEnumType.cpp @@ -77,7 +77,7 @@ bool ETSIntEnumType::AssignmentSource(TypeRelation *relation, Type *target) if (target->AsETSObjectType()->IsGlobalETSObjectType() || target->AsETSObjectType()->Name() == compiler::Signatures::NUMERIC) { result = true; - } else if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC)) { + } else if (target->IsBuiltinNumeric()) { result = true; relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); } @@ -108,8 +108,7 @@ void ETSIntEnumType::Cast(TypeRelation *const relation, Type *const target) relation->Result(true); return; } - if (target->HasTypeFlag(TypeFlag::ETS_NUMERIC) || - (target->IsETSObjectType() && target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC))) { + if (target->HasTypeFlag(TypeFlag::ETS_NUMERIC) || target->IsBuiltinNumeric()) { relation->Result(true); return; } @@ -122,11 +121,11 @@ void ETSIntEnumType::CastTarget(TypeRelation *relation, Type *source) relation->Result(true); return; } - if (source->IsETSObjectType() && source->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC)) { + if (source->IsBuiltinNumeric()) { relation->Result(true); return; } conversion::Forbidden(relation); } -} // namespace ark::es2panda::checker \ No newline at end of file +} // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsEnumType.h b/ets2panda/checker/types/ets/etsEnumType.h index 99e5b34528..79e5212669 100644 --- a/ets2panda/checker/types/ets/etsEnumType.h +++ b/ets2panda/checker/types/ets/etsEnumType.h @@ -19,16 +19,24 @@ #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/etsObjectTypeConstants.h" #include "checker/types/typeFlag.h" +#include "ir/base/classProperty.h" +#include "ir/expressions/arrayExpression.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/expressions/memberExpression.h" namespace ark::es2panda::checker { class ETSEnumType : public ETSObjectType { public: + // CC-OFFNXT(G.FUN.01-CPP) solid logic + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) explicit ETSEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, - ir::AstNode *declNode, TypeRelation *relation) + ir::AstNode *declNode, TypeRelation *relation, ETSObjectFlags const flag) : ETSObjectType(allocator, name, internalName, - std::make_tuple(declNode, ETSObjectFlags::CLASS | ETSObjectFlags::ENUM_OBJECT, relation)) + std::make_tuple(declNode, ETSObjectFlags::CLASS | flag, relation)), + memberNameToOrdinal_(allocator->Adapter()) { + InitElementsShortcuts(declNode->AsClassDefinition()); } NO_COPY_SEMANTIC(ETSEnumType); @@ -37,21 +45,85 @@ public: ETSEnumType() = delete; ~ETSEnumType() override = default; - static constexpr std::string_view const TO_STRING_METHOD_NAME {"toString"}; - static constexpr std::string_view const VALUE_OF_METHOD_NAME {"valueOf"}; - static constexpr std::string_view const GET_NAME_METHOD_NAME {"getName"}; - static constexpr std::string_view const GET_VALUE_OF_METHOD_NAME {"getValueOf"}; - static constexpr std::string_view const FROM_VALUE_METHOD_NAME {"fromValue"}; - static constexpr std::string_view const VALUES_METHOD_NAME {"values"}; - static constexpr std::string_view const GET_ORDINAL_METHOD_NAME {"getOrdinal"}; - static constexpr std::string_view const DOLLAR_GET_METHOD_NAME {"$_get"}; + static constexpr std::string_view TO_STRING_METHOD_NAME {"toString"}; + static constexpr std::string_view VALUE_OF_METHOD_NAME {"valueOf"}; + static constexpr std::string_view GET_NAME_METHOD_NAME {"getName"}; + static constexpr std::string_view GET_VALUE_OF_METHOD_NAME {"getValueOf"}; + static constexpr std::string_view FROM_VALUE_METHOD_NAME {"fromValue"}; + static constexpr std::string_view VALUES_METHOD_NAME {"values"}; + static constexpr std::string_view GET_ORDINAL_METHOD_NAME {"getOrdinal"}; + static constexpr std::string_view DOLLAR_GET_METHOD_NAME {"$_get"}; + + static constexpr std::string_view STRING_VALUES_ARRAY_NAME {"#StringValuesArray"}; + static constexpr std::string_view VALUES_ARRAY_NAME {"#ValuesArray"}; + static constexpr std::string_view NAMES_ARRAY_NAME {"#NamesArray"}; + + auto *Underlying() + { + ES2PANDA_ASSERT(membersValues_->TsType() != nullptr); + return membersValues_->TsType()->AsETSArrayType()->ElementType(); + } + + auto GetOrdinalFromMemberName(std::string_view name) const + { + return memberNameToOrdinal_.at(name); + } + + auto GetValueLiteralFromOrdinal(size_t ord) const + { + ES2PANDA_ASSERT(ord < membersValues_->Elements().size()); + return membersValues_->Elements()[ord]; + } + + bool NodeIsEnumLiteral(ir::Expression *node) const + { + ES2PANDA_ASSERT(node->TsType() == this); + if (!node->IsMemberExpression()) { + return false; + } + + auto mobj = node->AsMemberExpression()->Object(); + if (mobj->TsType() == this) { + // No need to search properties since enum-literals are the only enum-type properties + // NOTE(dkofanov): For some reason, 'enumLowering' changes 'CLASS' to 'ENUM_LITERAL', instead of 'ENUM'. + ES2PANDA_ASSERT(GetDeclNode()->AsClassDefinition()->IsEnumTransformed()); + return true; + } + return false; + } + +private: + void InitElementsShortcuts(ir::ClassDefinition *declNode) + { + Span membersNames {}; + for (auto elem : declNode->Body()) { + auto elemName = elem->AsClassElement()->Key()->AsIdentifier()->Name(); + if (elemName == NAMES_ARRAY_NAME) { + membersNames = Span(elem->AsClassProperty()->Value()->AsArrayExpression()->Elements()); + } else if (elemName == VALUES_ARRAY_NAME) { + membersValues_ = elem->AsClassProperty()->Value()->AsArrayExpression(); // int-enum + } else if ((elemName == STRING_VALUES_ARRAY_NAME) && (membersValues_ == nullptr)) { + membersValues_ = elem->AsClassProperty()->Value()->AsArrayExpression(); // string-enum + } + } + auto membersValues = Span {membersValues_->Elements()}; + ES2PANDA_ASSERT(membersValues.size() == membersNames.size()); + for (size_t i = 0; i < membersNames.size(); i++) { + memberNameToOrdinal_.insert({membersNames[i]->AsStringLiteral()->Str(), i}); + ES2PANDA_ASSERT(membersValues[i]->IsStringLiteral() || membersValues[i]->IsNumberLiteral()); + } + } + +private: + ArenaMap memberNameToOrdinal_; + ir::ArrayExpression *membersValues_; }; class ETSIntEnumType : public ETSEnumType { public: explicit ETSIntEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) - : ETSEnumType(allocator, name, internalName, declNode, relation) + : ETSEnumType(allocator, name, internalName, declNode, relation, ETSObjectFlags::INT_ENUM_OBJECT) { AddTypeFlag(checker::TypeFlag::ETS_INT_ENUM); } @@ -72,7 +144,7 @@ class ETSStringEnumType : public ETSEnumType { public: explicit ETSStringEnumType(ThreadSafeArenaAllocator *allocator, util::StringView name, util::StringView internalName, ir::AstNode *declNode, TypeRelation *relation) - : ETSEnumType(allocator, name, internalName, declNode, relation) + : ETSEnumType(allocator, name, internalName, declNode, relation, ETSObjectFlags::STRING_ENUM_OBJECT) { AddTypeFlag(checker::TypeFlag::ETS_STRING_ENUM); } @@ -91,4 +163,4 @@ public: } // namespace ark::es2panda::checker -#endif \ No newline at end of file +#endif diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index cb1fe63b87..5a9a176d9c 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -72,13 +72,23 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, bool isExtensionHack = signature->HasSignatureFlag(SignatureFlags::EXTENSION_FUNCTION); if (signature->RestVar() != nullptr) { - auto *functionN = checker->GlobalBuiltinFunctionType(arity, true)->AsETSObjectType(); + auto nPosParams = signature->Params().size(); + auto *functionN = checker->GlobalBuiltinFunctionType(nPosParams, true)->AsETSObjectType(); auto *substitution = checker->NewSubstitution(); + for (size_t i = 0; i < nPosParams; i++) { + substitution->emplace(functionN->TypeArguments()[i]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->Params()[i]->TsType())); + } auto *elementType = !signature->RestVar()->TsType()->IsETSTupleType() ? checker->GetElementTypeOfArray(signature->RestVar()->TsType()) : checker->GlobalETSAnyType(); - substitution->emplace(functionN->TypeArguments()[0]->AsETSTypeParameter(), checker->MaybeBoxType(elementType)); - return functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); + substitution->emplace(functionN->TypeArguments()[nPosParams]->AsETSTypeParameter(), + checker->MaybeBoxType(elementType)); + substitution->emplace(functionN->TypeArguments()[nPosParams + 1]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->ReturnType())); + auto result = functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); + result->AddObjectFlag(checker::ETSObjectFlags::FUNCTIONAL); + return result; } ES2PANDA_ASSERT(arity >= signature->MinArgCount() && arity <= signature->ArgCount()); @@ -102,6 +112,8 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, if (signature->HasSignatureFlag(SignatureFlags::THIS_RETURN_TYPE)) { HackThisParameterInExtensionFunctionInvoke(result, arity); } + + result->AddObjectFlag(checker::ETSObjectFlags::FUNCTIONAL); return result; } diff --git a/ets2panda/checker/types/ets/etsFunctionType.h b/ets2panda/checker/types/ets/etsFunctionType.h index 14eea128aa..ffc9e8ea59 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.h +++ b/ets2panda/checker/types/ets/etsFunctionType.h @@ -134,11 +134,6 @@ public: void Cast(TypeRelation *relation, Type *target) override; void CastTarget(TypeRelation *relation, Type *source) override; - std::tuple ResolveConditionExpr() const override - { - return {false, false}; - } - void SetHelperSignature(Signature *signature) noexcept { helperSignature_ = signature; diff --git a/ets2panda/checker/types/ets/etsNeverType.h b/ets2panda/checker/types/ets/etsNeverType.h index 06904ce058..7e998eb6b6 100644 --- a/ets2panda/checker/types/ets/etsNeverType.h +++ b/ets2panda/checker/types/ets/etsNeverType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -38,11 +38,6 @@ public: TypeFacts GetTypeFacts() const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), false}; - } }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsNullishTypes.h b/ets2panda/checker/types/ets/etsNullishTypes.h index 195332ffd2..ff11033e5d 100644 --- a/ets2panda/checker/types/ets/etsNullishTypes.h +++ b/ets2panda/checker/types/ets/etsNullishTypes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -37,11 +37,6 @@ public: void ToDebugInfoType([[maybe_unused]] std::stringstream &ss) const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), false}; - } }; class ETSUndefinedType : public Type { @@ -60,11 +55,6 @@ public: void ToDebugInfoType([[maybe_unused]] std::stringstream &ss) const override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; - - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), false}; - } }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 61a6db0141..c86dbcd510 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -20,12 +20,15 @@ #include "checker/types/globalTypesHolder.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" #include "checker/types/ets/etsEnumType.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "compiler/lowering/phase.h" #include "ir/statements/annotationDeclaration.h" namespace ark::es2panda::checker { +static std::multimap GetSignaturesForSyntheticType(ETSObjectType const *owner, + util::StringView name, + PropertySearchFlags flags); + void ETSObjectType::Iterate(const PropertyTraverser &cb) const { for (const auto *prop : GetAllProperties()) { @@ -41,8 +44,7 @@ void ETSObjectType::Iterate(const PropertyTraverser &cb) const } } -varbinder::LocalVariable *ETSObjectType::SearchFieldsDecls(const util::StringView &name, - PropertySearchFlags flags) const +varbinder::LocalVariable *ETSObjectType::SearchFieldsDecls(util::StringView name, PropertySearchFlags flags) const { varbinder::LocalVariable *res {}; if ((flags & PropertySearchFlags::SEARCH_INSTANCE_FIELD) != 0) { @@ -63,7 +65,7 @@ varbinder::LocalVariable *ETSObjectType::SearchFieldsDecls(const util::StringVie return res; } -varbinder::LocalVariable *ETSObjectType::GetProperty(const util::StringView &name, PropertySearchFlags flags) const +varbinder::LocalVariable *ETSObjectType::GetProperty(util::StringView name, PropertySearchFlags flags) const { varbinder::LocalVariable *res = SearchFieldsDecls(name, flags); if (res == nullptr && (flags & PropertySearchFlags::SEARCH_METHOD) != 0) { @@ -173,16 +175,11 @@ static void UpdateDeclarationForGetterSetter(varbinder::LocalVariable *res, cons res->Reset(decl, var->Flags()); } -varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(const util::StringView &name, +varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(util::StringView name, PropertySearchFlags flags) const { - std::vector signatures; - varbinder::LocalVariable *functionalInterface = CollectSignaturesForSyntheticType(signatures, name, flags); - // #22952: the called function *always* returns nullptr - ES2PANDA_ASSERT(functionalInterface == nullptr); - (void)functionalInterface; - - if (signatures.empty()) { + auto signatureSet = GetSignaturesForSyntheticType(this, name, flags); + if (signatureSet.empty()) { return nullptr; } @@ -190,8 +187,8 @@ varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(co varbinder::VariableFlags::METHOD); ETSFunctionType *funcType = CreateMethodTypeForProp(name); - for (auto &s : signatures) { - funcType->AddCallSignature(s); + for (auto &s : signatureSet) { + funcType->AddCallSignature(s.second); } res->SetTsType(funcType); @@ -202,77 +199,91 @@ varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(co return res; } -ETSFunctionType *ETSObjectType::CreateMethodTypeForProp(const util::StringView &name) const +ETSFunctionType *ETSObjectType::CreateMethodTypeForProp(util::StringView name) const { ES2PANDA_ASSERT(GetRelation() != nullptr); return GetRelation()->GetChecker()->AsETSChecker()->CreateETSMethodType(name, {{}, Allocator()->Adapter()}); } -static void AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, - varbinder::LocalVariable *found) +static void ReplaceArgInSig(std::multimap *signatureSet, Signature *sigToInsert, + TypeRelation *relation) { - for (auto *it : found->TsType()->AsETSFunctionType()->CallSignatures()) { - if (std::find(signatures.begin(), signatures.end(), it) != signatures.end()) { - continue; + auto range = signatureSet->equal_range(sigToInsert->ArgCount()); + for (auto it = range.first; it != range.second; ++it) { + auto sigToReplace = it->second; + + if (relation->IsSupertypeOf(sigToInsert->Owner(), sigToReplace->Owner()) && + relation->SignatureIsSupertypeOf(sigToInsert, sigToReplace)) { + // Already overridden by a subtype's signature + return; } - if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) && it->HasSignatureFlag(SignatureFlags::ABSTRACT)) { - continue; + if (relation->IsSupertypeOf(sigToReplace->Owner(), sigToInsert->Owner()) && + relation->SignatureIsSupertypeOf(sigToReplace, sigToInsert)) { + signatureSet->erase(it); + signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); + return; } - if (std::any_of(signatures.begin(), signatures.end(), [&it, &checker](auto sig) { - return checker->AreOverrideCompatible(sig, it) && - it->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) && - (checker->Relation()->IsSupertypeOf(it->Owner(), sig->Owner()) || - !sig->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE)); - })) { + } + signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); +} + +// CC-OFFNXT(huge_depth) solid logic +static void AddSignatureToSignatureSet(std::multimap *signatureSet, + varbinder::LocalVariable *found, TypeRelation *relation, + PropertySearchFlags flags) +{ + for (auto *sigToInsert : found->TsType()->AsETSFunctionType()->CallSignatures()) { + if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) && + sigToInsert->HasSignatureFlag(SignatureFlags::ABSTRACT)) { continue; } - // Issue: #18720 - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - signatures.emplace_back(it); + + if (signatureSet->count(sigToInsert->ArgCount()) != 0U) { + ReplaceArgInSig(signatureSet, sigToInsert, relation); + } else { + signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); + } } } -varbinder::LocalVariable *ETSObjectType::CollectSignaturesForSyntheticType(std::vector &signatures, - const util::StringView &name, - PropertySearchFlags flags) const +static void CollectSignaturesForSyntheticType(ETSObjectType const *owner, + std::multimap *signatureSet, util::StringView name, + PropertySearchFlags flags) { - auto *checker = GetRelation()->GetChecker()->AsETSChecker(); - if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) { - if (auto *found = GetOwnProperty(name); + if (auto *found = owner->GetOwnProperty(name); found != nullptr && !found->TsType()->IsTypeError()) { ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignature(signatures, flags, checker, found); + AddSignatureToSignatureSet(signatureSet, found, owner->GetRelation(), flags); } } if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) { - if (auto *found = GetOwnProperty(name); + if (auto *found = owner->GetOwnProperty(name); found != nullptr && !found->TsType()->IsTypeError()) { ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignature(signatures, flags, checker, found); + AddSignatureToSignatureSet(signatureSet, found, owner->GetRelation(), flags); } } - if (superType_ != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) { - superType_->CollectSignaturesForSyntheticType(signatures, name, flags); + if (owner->SuperType() != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) { + CollectSignaturesForSyntheticType(owner->SuperType(), signatureSet, name, flags); } - ArenaVector interfaces(Allocator()->Adapter()); - checker->GetInterfacesOfClass(const_cast(this), interfaces); - - for (auto *const &interface : interfaces) { - if (interface != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) && - !this->IsPartial()) { // NOTE: issue 24548 - if (auto *found = - interface->GetProperty(name, flags | PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION); - found != nullptr && !found->TsType()->IsTypeError()) { - ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignature(signatures, flags, checker, found); - } + if ((flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) { + for (auto *interface : owner->Interfaces()) { + CollectSignaturesForSyntheticType(interface, signatureSet, name, flags); } } - return nullptr; +} + +static std::multimap GetSignaturesForSyntheticType(ETSObjectType const *owner, + util::StringView name, + PropertySearchFlags flags) +{ + std::multimap signatureSet; + CollectSignaturesForSyntheticType(owner, &signatureSet, name, flags); + return signatureSet; } std::vector ETSObjectType::GetAllProperties() const @@ -545,6 +556,9 @@ bool ETSObjectType::IsBoxedPrimitive() const if (this->IsETSDynamicType()) { return false; } + if (this->IsETSEnumType()) { + return false; + } return this->IsETSUnboxableObject(); } @@ -580,8 +594,8 @@ ETSFunctionType *ETSObjectType::GetFunctionalInterfaceInvokeType() const return invoke->TsType()->AsETSFunctionType(); } -bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *const target, TypeFlag unboxFlags, - TypeFlag wideningFlags, TypeFlag narrowingFlags) +bool ETSObjectType::CastWidening(TypeRelation *const relation, Type *const target, TypeFlag unboxFlags, + TypeFlag wideningFlags) { if (target->HasTypeFlag(unboxFlags)) { conversion::Unboxing(relation, this); @@ -591,10 +605,6 @@ bool ETSObjectType::CastWideningNarrowing(TypeRelation *const relation, Type *co conversion::UnboxingWideningPrimitive(relation, this, target); return true; } - if (target->HasTypeFlag(narrowingFlags)) { - conversion::UnboxingNarrowingPrimitive(relation, this, target); - return true; - } return false; } @@ -609,7 +619,7 @@ bool ETSObjectType::TryCastByte(TypeRelation *const relation, Type *const target return true; } if (target->HasTypeFlag(TypeFlag::CHAR)) { - conversion::UnboxingWideningNarrowingPrimitive(relation, this, target); + conversion::UnboxingWideningPrimitive(relation, this, target); return true; } return false; @@ -621,25 +631,21 @@ bool ETSObjectType::TryCastIntegral(TypeRelation *const relation, Type *const ta return true; } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT) && - CastWideningNarrowing(relation, target, TypeFlag::SHORT, - TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, - TypeFlag::BYTE | TypeFlag::CHAR)) { + CastWidening(relation, target, TypeFlag::SHORT, + TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { return true; } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR) && - CastWideningNarrowing(relation, target, TypeFlag::CHAR, - TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, - TypeFlag::BYTE | TypeFlag::SHORT)) { + CastWidening(relation, target, TypeFlag::CHAR, + TypeFlag::SHORT | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { return true; } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_INT) && - CastWideningNarrowing(relation, target, TypeFlag::INT, TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE, - TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR)) { + CastWidening(relation, target, TypeFlag::INT, TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { return true; } if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG) && - CastWideningNarrowing(relation, target, TypeFlag::LONG, TypeFlag::FLOAT | TypeFlag::DOUBLE, - TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT)) { + CastWidening(relation, target, TypeFlag::LONG, TypeFlag::FLOAT | TypeFlag::DOUBLE)) { return true; } return false; @@ -648,14 +654,11 @@ bool ETSObjectType::TryCastIntegral(TypeRelation *const relation, Type *const ta bool ETSObjectType::TryCastFloating(TypeRelation *const relation, Type *const target) { if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT) && - CastWideningNarrowing(relation, target, TypeFlag::FLOAT, TypeFlag::DOUBLE, - TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG)) { + CastWidening(relation, target, TypeFlag::FLOAT, TypeFlag::DOUBLE)) { return true; } - if (auto narrowingFlags = - TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT; - this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && - CastWideningNarrowing(relation, target, TypeFlag::DOUBLE, TypeFlag::NONE, narrowingFlags)) { + if (this->HasObjectFlag(ETSObjectFlags::BUILTIN_DOUBLE) && + CastWidening(relation, target, TypeFlag::DOUBLE, TypeFlag::NONE)) { return true; } return false; @@ -677,6 +680,12 @@ bool ETSObjectType::TryCastUnboxable(TypeRelation *const relation, Type *const t conversion::WideningReference(relation, this, target->AsETSObjectType()); return true; } + + if (target->IsETSEnumType()) { + auto unboxedThis = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(this); + return relation->IsCastableTo(unboxedThis, target); + } + conversion::Forbidden(relation); return true; } @@ -702,10 +711,6 @@ bool ETSObjectType::CastNumericObject(TypeRelation *const relation, Type *const if (this->IsETSUnboxableObject()) { return TryCastUnboxable(relation, target); } - if (target->IsETSPrimitiveType()) { - conversion::NarrowingReferenceUnboxing(relation, this, target); - return true; - } return false; } @@ -1483,7 +1488,7 @@ ETSObjectType *ETSObjectType::GetInstantiatedType(util::StringView hash) return found2->second; } -void ETSObjectType::InsertInstantiationMap(const util::StringView &key, ETSObjectType *value) +void ETSObjectType::InsertInstantiationMap(util::StringView key, ETSObjectType *value) { auto &instantiationMap = compiler::GetPhaseManager()->Context()->GetChecker()->AsETSChecker()->GetObjectInstantiationMap(); diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index 20e5811f3d..4c8538f082 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -241,12 +241,12 @@ public: bool IsDescendantOf(const ETSObjectType *ascendant) const; - const util::StringView &Name() const + util::StringView Name() const { return name_; } - const util::StringView &AssemblerName() const + util::StringView AssemblerName() const { return internalName_; } @@ -294,10 +294,10 @@ public: return typeParams->Scope(); } - void InsertInstantiationMap(const util::StringView &key, ETSObjectType *value); + void InsertInstantiationMap(const util::StringView key, ETSObjectType *value); template - varbinder::LocalVariable *GetOwnProperty(const util::StringView &name) const + varbinder::LocalVariable *GetOwnProperty(const util::StringView name) const { EnsurePropertiesInstantiated(); auto found = properties_[static_cast(TYPE)].find(name); @@ -345,17 +345,14 @@ public: } std::vector ForeignProperties() const; - varbinder::LocalVariable *GetProperty(const util::StringView &name, PropertySearchFlags flags) const; + varbinder::LocalVariable *GetProperty(util::StringView name, PropertySearchFlags flags) const; std::vector GetAllProperties() const; varbinder::LocalVariable *CopyProperty(varbinder::LocalVariable *prop, ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); std::vector Methods() const; std::vector Fields() const; - varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, + varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(util::StringView name, PropertySearchFlags flags) const; - varbinder::LocalVariable *CollectSignaturesForSyntheticType(std::vector &signatures, - const util::StringView &name, - PropertySearchFlags flags) const; bool CheckIdenticalFlags(ETSObjectType *other) const; ETSObjectType *CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags); void Iterate(const PropertyTraverser &cb) const; @@ -393,11 +390,6 @@ public: return allocator_; } - std::tuple ResolveConditionExpr() const override - { - return {false, false}; - } - [[nodiscard]] static std::uint32_t GetPrecedence(checker::ETSChecker *checker, ETSObjectType const *type) noexcept; bool IsPropertiesInstantiated() const @@ -406,7 +398,7 @@ public: } protected: - virtual ETSFunctionType *CreateMethodTypeForProp(const util::StringView &name) const; + virtual ETSFunctionType *CreateMethodTypeForProp(util::StringView name) const; private: template @@ -438,15 +430,14 @@ private: propertiesInstantiated_ = true; } } - bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, - TypeFlag narrowingFlags); + bool CastWidening(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags); void IdenticalUptoTypeArguments(TypeRelation *relation, Type *other); void SubstitutePartialTypes(TypeRelation *relation, Type *other); void IsGenericSupertypeOf(TypeRelation *relation, ETSObjectType *source); void UpdateTypeProperty(varbinder::LocalVariable *const prop, PropertyType fieldType, PropertyProcesser const &func); - varbinder::LocalVariable *SearchFieldsDecls(const util::StringView &name, PropertySearchFlags flags) const; + varbinder::LocalVariable *SearchFieldsDecls(util::StringView name, PropertySearchFlags flags) const; void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector &&newTypeArgs, ETSObjectType *base); diff --git a/ets2panda/checker/types/ets/etsObjectTypeConstants.h b/ets2panda/checker/types/ets/etsObjectTypeConstants.h index 0a51f2f1d6..1b27c6e7c7 100644 --- a/ets2panda/checker/types/ets/etsObjectTypeConstants.h +++ b/ets2panda/checker/types/ets/etsObjectTypeConstants.h @@ -56,16 +56,26 @@ enum class ETSObjectFlags : std::uint64_t { BUILTIN_DOUBLE = 1U << 31U, BUILTIN_ARRAY = 1ULL << 32U, - ENUM_OBJECT = 1ULL << 33U, - EXTENSION_FUNCTION = 1ULL << 34U, + INT_ENUM_OBJECT = 1ULL << 33U, + STRING_ENUM_OBJECT = 1ULL << 34U, - FUNCTIONAL_REFERENCE = 1ULL << 35U, + EXTENSION_FUNCTION = 1ULL << 35U, + FUNCTIONAL_REFERENCE = 1ULL << 36U, - BUILTIN_NUMERIC = BUILTIN_BYTE | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | BUILTIN_FLOAT | BUILTIN_DOUBLE, + ENUM_OBJECT = INT_ENUM_OBJECT | STRING_ENUM_OBJECT, + + BUILTIN_FLOATING_POINT = BUILTIN_DOUBLE | BUILTIN_FLOAT, + BUILTIN_INTEGRAL = BUILTIN_BYTE | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG, + + BUILTIN_ARRAY_INDEX = BUILTIN_BYTE | BUILTIN_SHORT | BUILTIN_INT, + BUILTIN_ARRAY_NUMERIC = BUILTIN_ARRAY_INDEX | BUILTIN_FLOATING_POINT, + + BUILTIN_NUMERIC = BUILTIN_INTEGRAL | BUILTIN_FLOATING_POINT, // Complete set includes null|undefined|Object VALUE_TYPED = BUILTIN_BOOLEAN | BUILTIN_CHAR | BUILTIN_NUMERIC | BUILTIN_BIGINT | STRING, UNBOXABLE_TYPE = BUILTIN_BOOLEAN | BUILTIN_CHAR | BUILTIN_NUMERIC, BUILTIN_TYPE = BUILTIN_STRING | BUILTIN_BIGINT | UNBOXABLE_TYPE, + CONVERTIBLE_TO_NUMERIC = BUILTIN_NUMERIC | BUILTIN_CHAR | INT_ENUM_OBJECT, GLOBAL_CLASS = CLASS | GLOBAL, FUNCTIONAL_INTERFACE = INTERFACE | ABSTRACT | FUNCTIONAL, diff --git a/ets2panda/checker/types/ets/etsResizableArrayType.cpp b/ets2panda/checker/types/ets/etsResizableArrayType.cpp index 25fcd72aba..464207ceda 100644 --- a/ets2panda/checker/types/ets/etsResizableArrayType.cpp +++ b/ets2panda/checker/types/ets/etsResizableArrayType.cpp @@ -14,6 +14,7 @@ */ #include "etsResizableArrayType.h" +#include "etsUnionType.h" namespace ark::es2panda::checker { @@ -24,4 +25,16 @@ ETSResizableArrayType *ETSResizableArrayType::Substitute(TypeRelation *relation, return copiedType; } -} // namespace ark::es2panda::checker \ No newline at end of file +void ETSResizableArrayType::ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const +{ + if (ElementType() != nullptr) { + if (HasTypeFlag(TypeFlag::READONLY)) { + ss << "readonly "; + } + ss << "Array<"; + ElementType()->ToString(ss, precise); + ss << ">"; + } +} + +} // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsResizableArrayType.h b/ets2panda/checker/types/ets/etsResizableArrayType.h index 1301e72693..90936ceadf 100644 --- a/ets2panda/checker/types/ets/etsResizableArrayType.h +++ b/ets2panda/checker/types/ets/etsResizableArrayType.h @@ -76,10 +76,12 @@ public: ETSResizableArrayType *Substitute(TypeRelation *relation, const Substitution *substitution) override; + void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override; + private: Type *element_; }; } // namespace ark::es2panda::checker -#endif \ No newline at end of file +#endif diff --git a/ets2panda/checker/types/ets/etsStringType.cpp b/ets2panda/checker/types/ets/etsStringType.cpp index 1a3c8ba2cc..ef98c512f8 100644 --- a/ets2panda/checker/types/ets/etsStringType.cpp +++ b/ets2panda/checker/types/ets/etsStringType.cpp @@ -74,5 +74,4 @@ void ETSStringType::IsSubtypeOf(TypeRelation *relation, Type *source) auto *const checker = relation->GetChecker()->AsETSChecker(); relation->IsSupertypeOf(source, checker->GlobalBuiltinETSStringType()); } - } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsStringType.h b/ets2panda/checker/types/ets/etsStringType.h index 513f4deb52..ab6b6e0760 100644 --- a/ets2panda/checker/types/ets/etsStringType.h +++ b/ets2panda/checker/types/ets/etsStringType.h @@ -76,11 +76,6 @@ public: return value_; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), IsConstantType() ? (GetValue().Length() != 0) : false}; - } - private: util::StringView value_ {}; }; diff --git a/ets2panda/checker/types/ets/etsTupleType.cpp b/ets2panda/checker/types/ets/etsTupleType.cpp index cd7ffe68c1..d0eb6e7034 100644 --- a/ets2panda/checker/types/ets/etsTupleType.cpp +++ b/ets2panda/checker/types/ets/etsTupleType.cpp @@ -65,7 +65,9 @@ void ETSTupleType::ToDebugInfoType(std::stringstream &ss) const Type *ETSTupleType::GetTypeAtIndex(const TupleSizeType index) const { - ES2PANDA_ASSERT(index < GetTupleSize()); + if (index >= GetTupleSize()) { // happens when dealing with type errors + return nullptr; + } return GetTupleTypesList().at(index); } diff --git a/ets2panda/checker/types/ets/etsTupleType.h b/ets2panda/checker/types/ets/etsTupleType.h index 53418a226c..2a326dedf9 100644 --- a/ets2panda/checker/types/ets/etsTupleType.h +++ b/ets2panda/checker/types/ets/etsTupleType.h @@ -43,11 +43,6 @@ public: return typeList_; } - std::tuple ResolveConditionExpr() const override - { - return {false, false}; - } - [[nodiscard]] ETSObjectType *GetWrapperType() const { return wrapperType_; diff --git a/ets2panda/checker/types/ets/etsTypeAliasType.h b/ets2panda/checker/types/ets/etsTypeAliasType.h index a0811891f9..f5b249c692 100644 --- a/ets2panda/checker/types/ets/etsTypeAliasType.h +++ b/ets2panda/checker/types/ets/etsTypeAliasType.h @@ -53,11 +53,6 @@ public: targetType_ = targetType; } - std::tuple ResolveConditionExpr() const override - { - return {false, false}; - } - void SetRecursive(bool value = true) { isRecursive_ = value; diff --git a/ets2panda/checker/types/ets/etsUnionType.cpp b/ets2panda/checker/types/ets/etsUnionType.cpp index 2bbdf54442..cb112121c8 100644 --- a/ets2panda/checker/types/ets/etsUnionType.cpp +++ b/ets2panda/checker/types/ets/etsUnionType.cpp @@ -138,16 +138,7 @@ void ETSUnionType::RelationTarget(TypeRelation *relation, Type *source, RelFN co return; } - if (std::any_of(constituentTypes_.begin(), constituentTypes_.end(), - [relation, refsource, relFn](auto *t) { return relFn(relation, refsource, t); })) { - if (refsource != source) { - // Some nodes can have both boxing and unboxing flags set. When applying them, first the unboxing happens - // (then a possible primitive conversion), and boxing at last. - // NOTE (smartin): when boxing/unboxing is moved to a lowering, review this part of the code - const auto mergedBoxingFlags = - relation->GetNode()->GetBoxingUnboxingFlags() | checker->GetBoxingFlag(refsource); - relation->GetNode()->SetBoxingUnboxingFlags(mergedBoxingFlags); - } + if (AnyOfConstituentTypes([relation, refsource, relFn](auto *t) { return relFn(relation, refsource, t); })) { relation->Result(true); return; } @@ -162,8 +153,8 @@ void ETSUnionType::RelationTarget(TypeRelation *relation, Type *source, RelFN co if (relFn(relation, source, checker->MaybeUnboxType(ct))) { if (related) { AmbiguousUnionOperation(relation); + return; } - relation->GetNode()->SetBoxingUnboxingFlags(checker->GetBoxingFlag(ct)); related = true; } } @@ -173,97 +164,55 @@ void ETSUnionType::RelationTarget(TypeRelation *relation, Type *source, RelFN co bool ETSUnionType::AssignmentSource(TypeRelation *relation, Type *target) { - auto *const checker = relation->GetChecker()->AsETSChecker(); - if (target->HasTypeFlag(TypeFlag::PRIMITIVE)) { - if (!relation->ApplyUnboxing()) { - return relation->Result(false); - } - relation->GetNode()->SetBoxingUnboxingFlags( - relation->GetChecker()->AsETSChecker()->GetUnboxingFlag(checker->MaybeUnboxType(target))); - } - - return relation->Result(std::all_of(constituentTypes_.begin(), constituentTypes_.end(), - [relation, target](auto *t) { return relation->IsAssignableTo(t, target); })); + ES2PANDA_ASSERT(!target->IsETSPrimitiveType()); + return relation->Result( + AllOfConstituentTypes([relation, target](auto *t) { return relation->IsAssignableTo(t, target); })); } void ETSUnionType::AssignmentTarget(TypeRelation *relation, Type *source) { - auto const relFn = []([[maybe_unused]] TypeRelation *rel, [[maybe_unused]] Type *src, [[maybe_unused]] Type *tgt) { - return rel->IsAssignableTo(src, tgt); - }; + auto const relFn = [](TypeRelation *rel, Type *src, Type *tgt) { return rel->IsAssignableTo(src, tgt); }; RelationTarget(relation, source, relFn); } void ETSUnionType::Cast(TypeRelation *relation, Type *target) { - auto *const checker = relation->GetChecker()->AsETSChecker(); - - if (target->HasTypeFlag(TypeFlag::PRIMITIVE)) { - if (!relation->ApplyUnboxing()) { - relation->Result(false); - return; - } - - relation->GetNode()->SetBoxingUnboxingFlags( - relation->GetChecker()->AsETSChecker()->GetUnboxingFlag(checker->MaybeUnboxType(target))); - } + ES2PANDA_ASSERT(!target->IsETSPrimitiveType()); if (relation->InCastingContext()) { - relation->Result(std::any_of(constituentTypes_.begin(), constituentTypes_.end(), - [relation, target](auto *t) { return relation->IsCastableTo(t, target); })); + relation->Result( + AnyOfConstituentTypes([relation, target](auto *t) { return relation->IsCastableTo(t, target); })); return; } - relation->Result(std::all_of(constituentTypes_.begin(), constituentTypes_.end(), - [relation, target](auto *t) { return relation->IsCastableTo(t, target); })); + relation->Result(AllOfConstituentTypes([relation, target](auto *t) { return relation->IsCastableTo(t, target); })); } void ETSUnionType::CastTarget(TypeRelation *relation, Type *source) { - auto const relFn = []([[maybe_unused]] TypeRelation *rel, [[maybe_unused]] Type *src, [[maybe_unused]] Type *tgt) { - return rel->IsCastableTo(src, tgt); - }; + auto const relFn = [](TypeRelation *rel, Type *src, Type *tgt) -> bool { return rel->IsCastableTo(src, tgt); }; RelationTarget(relation, source, relFn); } -static auto constexpr ETS_NORMALIZABLE_NUMERIC = TypeFlag(TypeFlag::ETS_NUMERIC); - -static Type *LargestNumeric(Type *t1, Type *t2) -{ - static_assert(TypeFlag::DOUBLE > TypeFlag::FLOAT); - static_assert(TypeFlag::FLOAT > TypeFlag::LONG); - static_assert(TypeFlag::LONG > TypeFlag::INT); - static_assert(TypeFlag::INT > TypeFlag::SHORT); - static_assert(TypeFlag::SHORT > TypeFlag::BYTE); - - auto v1 = t1->TypeFlags() & ETS_NORMALIZABLE_NUMERIC; - auto v2 = t2->TypeFlags() & ETS_NORMALIZABLE_NUMERIC; - ES2PANDA_ASSERT(helpers::math::IsPowerOfTwo(v1)); - ES2PANDA_ASSERT(helpers::math::IsPowerOfTwo(v2)); - return v1 > v2 ? t1 : t2; -} - static std::optional TryMergeTypes(TypeRelation *relation, Type *const t1, Type *const t2) { - auto checker = relation->GetChecker()->AsETSChecker(); - auto never = checker->GetGlobalTypesHolder()->GlobalETSNeverType(); + auto *const checker = relation->GetChecker()->AsETSChecker(); + auto *const never = checker->GetGlobalTypesHolder()->GlobalETSNeverType(); + if (relation->IsSupertypeOf(t1, t2) || t2 == never) { return t1; } if (relation->IsSupertypeOf(t2, t1) || t1 == never) { return t2; } - // NOTE(vpukhov): numerics - clarification required return std::nullopt; } void ETSUnionType::LinearizeAndEraseIdentical(TypeRelation *relation, ArenaVector &types) { - auto *const checker = relation->GetChecker()->AsETSChecker(); - // Linearize - size_t const initialSz = types.size(); - for (size_t i = 0; i < initialSz; ++i) { + std::size_t const initialSz = types.size(); + for (std::size_t i = 0U; i < initialSz; ++i) { auto ct = types[i]; if (ct->IsETSUnionType()) { auto const &otherTypes = ct->AsETSUnionType()->ConstituentTypes(); @@ -273,50 +222,32 @@ void ETSUnionType::LinearizeAndEraseIdentical(TypeRelation *relation, ArenaVecto types[i] = nullptr; } } - size_t insPos = 0; - for (size_t i = 0; i < types.size(); ++i) { - auto *const ct = types[i]; - if (ct != nullptr) { - types[insPos++] = ct; - } - } - types.resize(insPos); - // Promote primitives - for (auto &ct : types) { - ct = checker->MaybeBoxType(ct); - } + // Remove nullptrs + types.erase(std::remove_if(types.begin(), types.end(), [](Type *ct) { return ct == nullptr; }), types.end()); + // Reduce subtypes for (auto cmpIt = types.begin(); cmpIt != types.end(); ++cmpIt) { - for (auto it = std::next(cmpIt); it != types.end();) { - auto merged = TryMergeTypes(relation, *cmpIt, *it); - if (!merged) { + auto it = std::next(cmpIt); + while (it != types.end()) { + if (auto merged = TryMergeTypes(relation, *cmpIt, *it); !merged) { ++it; - continue; - } - - if (merged == *cmpIt) { + } else if (*merged == *cmpIt) { it = types.erase(it); - continue; + } else { + cmpIt = types.erase(cmpIt); + it = cmpIt != types.end() ? std::next(cmpIt) : cmpIt; } - - cmpIt = types.erase(cmpIt); - it = std::next(cmpIt); } } } void ETSUnionType::NormalizeTypes(TypeRelation *relation, ArenaVector &types) { - if (types.size() == 1) { - return; - } - auto const isNumeric = [](auto *ct) { return ct->HasTypeFlag(ETS_NORMALIZABLE_NUMERIC); }; - if (std::all_of(types.begin(), types.end(), isNumeric)) { - types[0] = std::accumulate(std::next(types.begin()), types.end(), types[0], LargestNumeric); - types.resize(1); + if (types.size() == 1U) { return; } + LinearizeAndEraseIdentical(relation, types); } @@ -325,7 +256,7 @@ Type *ETSUnionType::Instantiate(ArenaAllocator *allocator, TypeRelation *relatio auto *const checker = relation->GetChecker()->AsETSChecker(); ArenaVector copiedConstituents(allocator->Adapter()); for (auto *it : constituentTypes_) { - copiedConstituents.push_back(it->Instantiate(allocator, relation, globalTypes)); + copiedConstituents.emplace_back(it->Instantiate(allocator, relation, globalTypes)); } return checker->CreateETSUnionType(std::move(copiedConstituents)); } @@ -335,14 +266,14 @@ Type *ETSUnionType::Substitute(TypeRelation *relation, const Substitution *subst auto *const checker = relation->GetChecker()->AsETSChecker(); ArenaVector substitutedConstituents(checker->Allocator()->Adapter()); for (auto *ctype : constituentTypes_) { - substitutedConstituents.push_back(ctype->Substitute(relation, substitution)); + substitutedConstituents.emplace_back(ctype->Substitute(relation, substitution)); } return checker->CreateETSUnionType(std::move(substitutedConstituents)); } void ETSUnionType::IsSupertypeOf(TypeRelation *relation, Type *source) { - for (auto const &ctype : ConstituentTypes()) { + for (auto const *ctype : ConstituentTypes()) { if (relation->IsSupertypeOf(ctype, source)) { return; } @@ -351,7 +282,7 @@ void ETSUnionType::IsSupertypeOf(TypeRelation *relation, Type *source) void ETSUnionType::IsSubtypeOf(TypeRelation *relation, Type *target) { - for (auto const &ctype : ConstituentTypes()) { + for (auto const *ctype : ConstituentTypes()) { if (!relation->IsSupertypeOf(target, ctype)) { return; } @@ -360,133 +291,70 @@ void ETSUnionType::IsSubtypeOf(TypeRelation *relation, Type *target) void ETSUnionType::CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) { - for (auto const &ctype : ConstituentTypes()) { + for (auto *ctype : ConstituentTypes()) { relation->CheckVarianceRecursively(ctype, relation->TransferVariant(varianceFlag, VarianceFlag::COVARIANT)); } } -bool ETSUnionType::IsAssignableType(checker::Type *sourceType) const noexcept -{ - if (sourceType->IsETSTypeParameter() || sourceType->IsTypeError()) { - return true; - } - - if (sourceType->IsETSUnionType() || sourceType->IsETSArrayType() || sourceType->IsETSFunctionType()) { - return true; - } - - return false; -} - -checker::Type *ETSUnionType::HandleNumericPrecedence( - checker::ETSChecker *checker, checker::ETSObjectType *objectType, checker::Type *sourceType, - std::map &numericTypes) const noexcept -{ - auto const sourceId = - (objectType != nullptr) ? ETSObjectType::GetPrecedence(checker, objectType) : Type::GetPrecedence(sourceType); - if (sourceId > 0U) { - for (auto const [id, type] : numericTypes) { - if (id >= sourceId) { - return type; - } - } - if (sourceType->IsConstantType() && !numericTypes.empty()) { - return numericTypes.begin()->second; - } - } - return nullptr; -} - -// NOTE! When calling this method we assume that 'AssignmentTarget(...)' check was passes successfully, -// thus the required assignable type always exists. -checker::Type *ETSUnionType::GetAssignableType(checker::ETSChecker *checker, checker::Type *sourceType) const noexcept +// ATTENTION! When calling this method we assume that 'AssignmentTarget(...)' check was passes successfully, +// thus the required assignable type (or corresponding supertype) always exists. +checker::Type *ETSUnionType::GetAssignableType(checker::ETSChecker *checker, checker::Type *sourceType, + [[maybe_unused]] std::optional value) const noexcept { - if (IsAssignableType(sourceType)) { - return sourceType; - } - - auto *objectType = sourceType->IsETSObjectType() ? sourceType->AsETSObjectType() - : sourceType->IsETSTupleType() ? sourceType->AsETSTupleType()->GetWrapperType() - : nullptr; - std::map numericTypes {}; - bool const isBool = objectType != nullptr ? objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN) - : sourceType->HasTypeFlag(TypeFlag::ETS_BOOLEAN); - bool const isChar = objectType != nullptr ? objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR) - : sourceType->HasTypeFlag(TypeFlag::CHAR); - - if (objectType != nullptr) { - if (objectType->IsETSResizableArrayType() || sourceType->IsETSTupleType()) { - checker::Type *assignableType = GetAssignableBuiltinType(checker, objectType, isBool, isChar, numericTypes); - // NOTE: For array and tuple types, they may be readonly, so we cannot simply use the it - if (assignableType != nullptr && assignableType->HasTypeFlag(TypeFlag::READONLY)) { - return assignableType; - } - } - if ((!objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE) || - objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_STRING))) { - // NOTE: here wo don't cast the actual type to possible base type using in the union, but use it as is! - return sourceType; + for (auto *ctype : ConstituentTypes()) { + if (checker->Relation()->IsSupertypeOf(ctype, sourceType)) { + return ctype; } } - if (checker::Type *assignableType = GetAssignableBuiltinType(checker, objectType, isBool, isChar, numericTypes); - assignableType != nullptr) { - return assignableType; + if (!sourceType->IsBuiltinNumeric()) { + return nullptr; } - if (auto *assignableType = HandleNumericPrecedence(checker, objectType, sourceType, numericTypes)) { + // NOTE (DZ): we still keep 'numericTypes` collection for possible processing cases like 'let x: short|double = 1` + // Waiting for complete clearness in spec - now return the highest type in such a case or type itself. + // Maybe 'value' will be used for this purpose + std::map numericTypes {}; + auto *objectType = sourceType->AsETSObjectType(); + if (auto *assignableType = GetAssignableBuiltinType(checker, objectType, numericTypes); assignableType != nullptr) { return assignableType; } - for (auto *constituentType : constituentTypes_) { - if (constituentType->IsETSObjectType() && constituentType->AsETSObjectType()->IsGlobalETSObjectType()) { - return constituentType; - } + if (!numericTypes.empty()) { + return (*std::prev(numericTypes.end())).second; } - - return checker->GlobalTypeError(); + return nullptr; } checker::Type *ETSUnionType::GetAssignableBuiltinType( - checker::ETSChecker *checker, checker::ETSObjectType *sourceType, bool const isBool, bool const isChar, - std::map &numericTypes) const noexcept + checker::ETSChecker *checker, checker::ETSObjectType *sourceType, + std::map &numericTypes) const noexcept { - checker::Type *assignableType = nullptr; - for (auto *constituentType : constituentTypes_) { if (!constituentType->IsETSObjectType() && !constituentType->IsETSTupleType()) { continue; } - auto *const type = constituentType->IsETSTupleType() ? constituentType->AsETSTupleType()->GetWrapperType() - : constituentType->AsETSObjectType(); - if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN)) { - if (isBool) { - assignableType = constituentType; - break; - } - } else if (type->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { - if (isChar) { - assignableType = constituentType; - break; - } - } else if (auto const id = ETSObjectType::GetPrecedence(checker, type); id > 0U) { - numericTypes.emplace(id, constituentType); - } else if (assignableType == nullptr && sourceType != nullptr && - checker->Relation()->IsSupertypeOf(type, sourceType)) { - assignableType = constituentType; + ETSObjectType *objectType = constituentType->AsETSObjectType(); + if (!objectType->IsBuiltinNumeric()) { + continue; } + + if (checker->Relation()->IsIdenticalTo(objectType, sourceType)) { + return sourceType; + } + + numericTypes.emplace(ETSObjectType::GetPrecedence(checker, objectType), objectType); } - return assignableType; + return nullptr; } -bool ETSUnionType::ExtractType(checker::ETSChecker *checker, checker::ETSObjectType *sourceType, +bool ETSUnionType::ExtractType(checker::ETSChecker *checker, checker::Type *source, ArenaVector &unionTypes) noexcept { std::map::const_iterator> numericTypes {}; - bool const isBool = sourceType->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN); - bool const isChar = sourceType->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR); + source = checker->GetNonConstantType(source); bool rc = false; auto it = unionTypes.cbegin(); @@ -502,27 +370,18 @@ bool ETSUnionType::ExtractType(checker::ETSChecker *checker, checker::ETSObjectT constituentType->RemoveTypeFlag(checker::TypeFlag::GENERIC); } - if (checker->Relation()->IsIdenticalTo(constituentType, sourceType)) { + if (checker->Relation()->IsIdenticalTo(constituentType, source)) { rc = true; - it = unionTypes.erase(it); + if (!(*it)->IsETSTypeParameter()) { + it = unionTypes.erase(it); + } continue; } - if (checker->Relation()->IsSupertypeOf(constituentType, sourceType)) { + if (checker->Relation()->IsSupertypeOf(constituentType, source)) { rc = true; - } else if (!rc && constituentType->IsETSObjectType()) { - auto *const objectType = (*it)->AsETSObjectType(); - if (isBool && objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_BOOLEAN)) { - unionTypes.erase(it); - return true; - } - - if (isChar && objectType->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { - unionTypes.erase(it); - return true; - } - - if (auto const id = ETSObjectType::GetPrecedence(checker, objectType); id > 0U) { + } else if (!rc && constituentType->IsBuiltinNumeric()) { + if (auto const id = ETSObjectType::GetPrecedence(checker, constituentType->AsETSObjectType()); id > 0U) { numericTypes.emplace(id, it); } } @@ -534,76 +393,46 @@ bool ETSUnionType::ExtractType(checker::ETSChecker *checker, checker::ETSObjectT return true; } - if (auto const sourceId = ETSObjectType::GetPrecedence(checker, sourceType); sourceId > 0U) { - for (auto const [id, it1] : numericTypes) { - if (id >= sourceId) { - unionTypes.erase(it1); - return true; - } - } + if (source->IsBuiltinNumeric() && !numericTypes.empty()) { + unionTypes.erase((*std::prev(numericTypes.end())).second); + return true; } return false; } -bool ETSUnionType::ExtractType(checker::ETSChecker *checker, checker::ETSArrayType *sourceType, - ArenaVector &unionTypes) noexcept -{ - auto it = unionTypes.cbegin(); - - bool rc = false; - while (it != unionTypes.cend()) { - auto *constituentType = *it; - - if (constituentType->IsETSTypeParameter()) { - constituentType = constituentType->AsETSTypeParameter()->GetConstraintType(); - } - - if (checker->Relation()->IsIdenticalTo(constituentType, sourceType)) { - rc = true; - unionTypes.erase(it); - continue; - } - if (checker->Relation()->IsSupertypeOf(constituentType, sourceType)) { - rc = true; - } - ++it; - } - - return rc; -} - std::pair ETSUnionType::GetComplimentaryType(ETSChecker *const checker, checker::Type *sourceType) { ArenaVector unionTypes(checker->Allocator()->Adapter()); - for (auto *it : constituentTypes_) { - unionTypes.emplace_back(it); + for (auto *ct : constituentTypes_) { + unionTypes.emplace_back(ct->Clone(checker)); } - bool ok = true; - if (sourceType->IsETSUnionType()) { - for (auto *const constituentType : sourceType->AsETSUnionType()->ConstituentTypes()) { - if (ok = ExtractType(checker, constituentType->AsETSObjectType(), unionTypes); !ok) { - break; - } + auto const extractType = [checker, &unionTypes](Type *&type) -> bool { + ES2PANDA_ASSERT(!type->IsETSPrimitiveType()); + if (type->IsETSEnumType()) { + return true; } - } else if (sourceType->IsETSArrayType()) { - ok = ExtractType(checker, sourceType->AsETSArrayType(), unionTypes); - } else { - // NOTE(vpukhov): #19701 void refactoring - if (sourceType->IsETSPrimitiveType() && !sourceType->IsETSVoidType()) { - sourceType = checker->MaybeBoxInRelation(sourceType); - } else if (sourceType->HasTypeFlag(checker::TypeFlag::GENERIC)) { + if (type->HasTypeFlag(checker::TypeFlag::GENERIC)) { // Because 'instanceof' expression does not check for type parameters, then for generic types we should // consider that expressions like 'SomeType' and 'SomeType' are identical for smart casting. - sourceType = sourceType->Clone(checker); - sourceType->RemoveTypeFlag(checker::TypeFlag::GENERIC); + type = type->Clone(checker); + type->RemoveTypeFlag(checker::TypeFlag::GENERIC); } + return ExtractType(checker, type, unionTypes); + }; - if (sourceType->IsETSObjectType()) { - ok = ExtractType(checker, sourceType->AsETSObjectType(), unionTypes); + bool ok = true; + + if (sourceType->IsETSUnionType()) { + for (auto *constituentType : sourceType->AsETSUnionType()->ConstituentTypes()) { + if (ok = extractType(constituentType); !ok) { + break; + } } + } else { + ok = extractType(sourceType); } if (!ok) { @@ -611,7 +440,9 @@ std::pair ETSUnionType::GetComplimentaryType(E } checker::Type *complimentaryType; - if (unionTypes.size() == 1U) { + if (auto const size = unionTypes.size(); size == 0U) { + complimentaryType = checker->GetGlobalTypesHolder()->GlobalETSNeverType(); + } else if (size == 1U) { complimentaryType = unionTypes.front(); } else { complimentaryType = checker->CreateETSUnionType(std::move(unionTypes)); @@ -620,142 +451,15 @@ std::pair ETSUnionType::GetComplimentaryType(E return std::make_pair(sourceType, complimentaryType); } -Type *ETSUnionType::FindTypeIsCastableToThis(ir::Expression *node, TypeRelation *relation, Type *source) const -{ - ES2PANDA_ASSERT(node); - bool nodeWasSet = false; - if (relation->GetNode() == nullptr) { - nodeWasSet = true; - relation->SetNode(node); - } - // Prioritize object to object conversion - auto it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), [relation, source](Type *target) { - relation->IsCastableTo(source, target); - return relation->IsTrue() && source->IsETSReferenceType() && target->IsETSReferenceType(); - }); - if (it != constituentTypes_.end()) { - if (nodeWasSet) { - relation->SetNode(nullptr); - } - return *it; - } - it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), [relation, source](Type *target) { - relation->IsCastableTo(source, target); - return relation->IsTrue(); - }); - if (nodeWasSet) { - relation->SetNode(nullptr); - } - if (it != constituentTypes_.end()) { - return *it; - } - return nullptr; -} - -Type *ETSUnionType::FindTypeIsCastableToSomeType(ir::Expression *node, TypeRelation *relation, Type *target) const -{ - ES2PANDA_ASSERT(node); - bool nodeWasSet = false; - if (relation->GetNode() == nullptr) { - nodeWasSet = true; - relation->SetNode(node); - relation->SetFlags(TypeRelationFlag::CASTING_CONTEXT); - } - auto isCastablePred = [](TypeRelation *r, Type *sourceType, Type *targetType) { - if (targetType->IsETSUnionType()) { - auto *foundTargetType = targetType->AsETSUnionType()->FindTypeIsCastableToThis(r->GetNode(), r, sourceType); - r->Result(foundTargetType != nullptr); - } else { - r->IsCastableTo(sourceType, targetType); - } - return r->IsTrue(); - }; - // Prioritize object to object conversion - auto it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), - [relation, target, &isCastablePred](Type *source) { - return isCastablePred(relation, source, target) && source->IsETSReferenceType() && - target->IsETSReferenceType(); - }); // CC-OFF(G.FMT.02) project code style - if (it != constituentTypes_.end()) { - if (nodeWasSet) { - relation->SetNode(nullptr); - relation->RemoveFlags(TypeRelationFlag::CASTING_CONTEXT); - } - return *it; - } - it = std::find_if( - constituentTypes_.begin(), constituentTypes_.end(), - [relation, target, &isCastablePred](Type *source) { return isCastablePred(relation, source, target); }); - if (nodeWasSet) { - relation->SetNode(nullptr); - relation->RemoveFlags(TypeRelationFlag::CASTING_CONTEXT); - } - if (it != constituentTypes_.end()) { - return *it; - } - return nullptr; -} - -Type *ETSUnionType::FindUnboxableType() const +Type *ETSUnionType::FindUnboxableType() const noexcept { - auto it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), - [](Type *t) { return t->IsETSUnboxableObject(); }); - if (it != constituentTypes_.end()) { - return *it; - } - return nullptr; -} - -bool ETSUnionType::HasObjectType(ETSObjectFlags flag) const -{ - auto it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), [flag](Type *t) { - return t->IsETSObjectType() && t->AsETSObjectType()->HasObjectFlag(flag); - }); - return it != constituentTypes_.end(); -} - -Type *ETSUnionType::FindExactOrBoxedType(ETSChecker *checker, Type *const type) const -{ - auto it = std::find_if(constituentTypes_.begin(), constituentTypes_.end(), [checker, type](Type *ct) { - if (ct->IsETSUnboxableObject()) { - auto *const unboxedCt = checker->MaybeUnboxInRelation(ct); - return unboxedCt == type; - } - return ct == type; - }); - if (it != constituentTypes_.end()) { - return *it; - } - return nullptr; -} - -std::tuple ETSUnionType::ResolveConditionExpr() const -{ - if (PossiblyETSString()) { - return {false, false}; - } - if (std::all_of(ConstituentTypes().begin(), ConstituentTypes().end(), - [](checker::Type const *ct) { return ct->DefinitelyETSNullish(); })) { - return {true, false}; - } - // We have to test if union can contain builtin numerics or string types to infer "true" - return {false, false}; -} - -bool ETSUnionType::HasType(Type *type) const -{ - for (const auto &cType : constituentTypes_) { - if (cType == type) { - return true; - } - } - return false; + return FindSpecificType([](Type *t) { return t->IsETSUnboxableObject(); }); } -bool ETSUnionType::IsOverlapWith(TypeRelation *relation, Type *type) +bool ETSUnionType::IsOverlapWith(TypeRelation *relation, Type const *type) const noexcept { // NOTE(aakmaev): replace this func with intersection type when it will be implemented - for (auto const &ct : ConstituentTypes()) { + for (auto *ct : constituentTypes_) { if (type->IsETSUnionType() && type->AsETSUnionType()->IsOverlapWith(relation, ct)) { return true; } @@ -766,11 +470,11 @@ bool ETSUnionType::IsOverlapWith(TypeRelation *relation, Type *type) return false; } -ArenaVector ETSUnionType::GetNonConstantTypes(ETSChecker *checker, const ArenaVector &types) +ArenaVector ETSUnionType::GetNonConstantTypes(ETSChecker *checker) const noexcept { ArenaVector nonConstTypes(checker->Allocator()->Adapter()); - for (const auto &ct : types) { - nonConstTypes.push_back(checker->GetNonConstantType(ct)); + for (auto *ct : constituentTypes_) { + nonConstTypes.emplace_back(checker->GetNonConstantType(ct)); } return nonConstTypes; } diff --git a/ets2panda/checker/types/ets/etsUnionType.h b/ets2panda/checker/types/ets/etsUnionType.h index 12ae980aec..54c15370d8 100644 --- a/ets2panda/checker/types/ets/etsUnionType.h +++ b/ets2panda/checker/types/ets/etsUnionType.h @@ -45,39 +45,48 @@ public: void IsSupertypeOf(TypeRelation *relation, Type *source) override; void IsSubtypeOf(TypeRelation *relation, Type *target) override; void CheckVarianceRecursively(TypeRelation *relation, VarianceFlag varianceFlag) override; - Type *FindTypeIsCastableToThis(ir::Expression *node, TypeRelation *relation, Type *source) const; - Type *FindTypeIsCastableToSomeType(ir::Expression *node, TypeRelation *relation, Type *target) const; - Type *FindUnboxableType() const; - bool HasObjectType(ETSObjectFlags flag) const; - bool HasType(Type *type) const; + [[nodiscard]] Type *FindUnboxableType() const noexcept; - bool IsOverlapWith(TypeRelation *relation, Type *type); - - Type *FindExactOrBoxedType(ETSChecker *checker, Type *type) const; + [[nodiscard]] bool IsOverlapWith(TypeRelation *relation, Type const *type) const noexcept; static void NormalizeTypes(TypeRelation *relation, ArenaVector &types); - static ArenaVector GetNonConstantTypes(ETSChecker *checker, const ArenaVector &types); - - std::tuple ResolveConditionExpr() const override; + [[nodiscard]] ArenaVector GetNonConstantTypes(ETSChecker *checker) const noexcept; // Do not use it anywhere except codegen - Type *GetAssemblerLUB() const + Type *GetAssemblerLUB() const noexcept { return assemblerLub_; } template - bool AllOfConstituentTypes(UnaryPredicate p) const + [[nodiscard]] bool AllOfConstituentTypes(UnaryPredicate p) const noexcept { return std::all_of(constituentTypes_.cbegin(), constituentTypes_.cend(), p); } - checker::Type *HandleNumericPrecedence(checker::ETSChecker *checker, checker::ETSObjectType *objectType, - checker::Type *sourceType, - std::map &numericTypes) const noexcept; - [[nodiscard]] checker::Type *GetAssignableType(ETSChecker *checker, checker::Type *sourceType) const noexcept; + template + [[nodiscard]] bool AnyOfConstituentTypes(UnaryPredicate p) const noexcept + { + return std::any_of(constituentTypes_.cbegin(), constituentTypes_.cend(), p); + } + + template + [[nodiscard]] Type *FindSpecificType(UnaryPredicate p) const noexcept + { + auto const it = std::find_if(constituentTypes_.cbegin(), constituentTypes_.cend(), p); + return it != constituentTypes_.cend() ? *it : nullptr; + } + + template + [[nodiscard]] bool HasSpecificType(UnaryPredicate p) const noexcept + { + return FindSpecificType(p) != nullptr; + } + + [[nodiscard]] checker::Type *GetAssignableType(ETSChecker *checker, checker::Type *sourceType, + std::optional value) const noexcept; [[nodiscard]] std::pair GetComplimentaryType(ETSChecker *checker, checker::Type *sourceType); @@ -89,16 +98,12 @@ private: void RelationTarget(TypeRelation *relation, Type *source, RelFN const &relFn); static void LinearizeAndEraseIdentical(TypeRelation *relation, ArenaVector &types); - [[nodiscard]] static bool ExtractType(ETSChecker *checker, checker::ETSObjectType *sourceType, - ArenaVector &unionTypes) noexcept; - [[nodiscard]] static bool ExtractType(ETSChecker *checker, checker::ETSArrayType *sourceType, + [[nodiscard]] static bool ExtractType(ETSChecker *checker, checker::Type *source, ArenaVector &unionTypes) noexcept; [[nodiscard]] checker::Type *GetAssignableBuiltinType( - checker::ETSChecker *checker, checker::ETSObjectType *sourceType, bool isBool, bool isChar, - std::map &numericTypes) const noexcept; - - bool IsAssignableType(checker::Type *sourceType) const noexcept; + checker::ETSChecker *checker, checker::ETSObjectType *sourceType, + std::map &numericTypes) const noexcept; static Type *ComputeAssemblerLUB(ETSChecker *checker, ETSUnionType *un); diff --git a/ets2panda/checker/types/ets/etsVoidType.cpp b/ets2panda/checker/types/ets/etsVoidType.cpp index bb3e90fb25..0fe7ede620 100644 --- a/ets2panda/checker/types/ets/etsVoidType.cpp +++ b/ets2panda/checker/types/ets/etsVoidType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -23,6 +23,11 @@ void ETSVoidType::Identical(TypeRelation *relation, Type *other) } } +void ETSVoidType::IsSupertypeOf(TypeRelation *const relation, Type *source) +{ + relation->Result(source->IsETSUndefinedType()); +} + bool ETSVoidType::AssignmentSource(TypeRelation *relation, Type *target) { // NOTE(vpukhov): #19701 void refactoring diff --git a/ets2panda/checker/types/ets/etsVoidType.h b/ets2panda/checker/types/ets/etsVoidType.h index bf6f9fcf7f..845d638d89 100644 --- a/ets2panda/checker/types/ets/etsVoidType.h +++ b/ets2panda/checker/types/ets/etsVoidType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -26,6 +26,7 @@ public: void Identical(TypeRelation *relation, Type *other) override; void AssignmentTarget(TypeRelation *relation, Type *source) override; bool AssignmentSource(TypeRelation *relation, Type *target) override; + void IsSupertypeOf(TypeRelation *relation, Type *source) override; Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; void ToString(std::stringstream &ss, [[maybe_unused]] bool precise) const override diff --git a/ets2panda/checker/types/ets/floatType.cpp b/ets2panda/checker/types/ets/floatType.cpp index 7f69458b18..958f338480 100644 --- a/ets2panda/checker/types/ets/floatType.cpp +++ b/ets2panda/checker/types/ets/floatType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,7 +16,7 @@ #include "floatType.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" namespace ark::es2panda::checker { void FloatType::Identical(TypeRelation *relation, Type *other) @@ -28,10 +28,7 @@ void FloatType::Identical(TypeRelation *relation, Type *other) void FloatType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingWideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); + WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } bool FloatType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) @@ -57,38 +54,9 @@ void FloatType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_FLOAT)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/floatType.h b/ets2panda/checker/types/ets/floatType.h index 61f04f8e0b..936effb4b0 100644 --- a/ets2panda/checker/types/ets/floatType.h +++ b/ets2panda/checker/types/ets/floatType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,12 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_FLOAT; } - std::tuple ResolveConditionExpr() const override - { - // isNan = !(value_ == value_) - return {IsConstantType(), (value_ != 0) && (value_ == value_)}; - } - private: UType value_ {0.0}; }; diff --git a/ets2panda/checker/types/ets/intType.cpp b/ets2panda/checker/types/ets/intType.cpp index c21e904b08..3587ee1bc0 100644 --- a/ets2panda/checker/types/ets/intType.cpp +++ b/ets2panda/checker/types/ets/intType.cpp @@ -16,7 +16,7 @@ #include "intType.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" namespace ark::es2panda::checker { void IntType::Identical(TypeRelation *relation, Type *other) @@ -28,10 +28,7 @@ void IntType::Identical(TypeRelation *relation, Type *other) void IntType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing() && !relation->IsTrue()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingWideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); + WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } bool IntType::AssignmentSource(TypeRelation *relation, Type *target) @@ -57,38 +54,9 @@ void IntType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_INT)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/intType.h b/ets2panda/checker/types/ets/intType.h index b1583a8695..835cc47d61 100644 --- a/ets2panda/checker/types/ets/intType.h +++ b/ets2panda/checker/types/ets/intType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,11 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_INT; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_ != 0}; - } - private: UType value_ {0}; }; diff --git a/ets2panda/checker/types/ets/longType.cpp b/ets2panda/checker/types/ets/longType.cpp index 7f4d080115..7b8c5b34fa 100644 --- a/ets2panda/checker/types/ets/longType.cpp +++ b/ets2panda/checker/types/ets/longType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,7 +16,7 @@ #include "longType.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" namespace ark::es2panda::checker { void LongType::Identical(TypeRelation *relation, Type *other) @@ -28,10 +28,7 @@ void LongType::Identical(TypeRelation *relation, Type *other) void LongType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing() && !relation->IsTrue()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingWideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); + WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } bool LongType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) @@ -57,38 +54,9 @@ void LongType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::SHORT | TypeFlag::CHAR | TypeFlag::INT)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::FLOAT | TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_LONG)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/longType.h b/ets2panda/checker/types/ets/longType.h index 898b692072..0823bc7608 100644 --- a/ets2panda/checker/types/ets/longType.h +++ b/ets2panda/checker/types/ets/longType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,11 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_LONG; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_ != 0}; - } - private: UType value_ {0}; }; diff --git a/ets2panda/checker/types/ets/shortType.cpp b/ets2panda/checker/types/ets/shortType.cpp index bc2011294b..c7f79a229e 100644 --- a/ets2panda/checker/types/ets/shortType.cpp +++ b/ets2panda/checker/types/ets/shortType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,7 +16,7 @@ #include "shortType.h" #include "checker/ets/conversion.h" -#include "checker/ets/narrowingWideningConverter.h" +#include "checker/ets/wideningConverter.h" namespace ark::es2panda::checker { void ShortType::Identical(TypeRelation *relation, Type *other) @@ -28,10 +28,7 @@ void ShortType::Identical(TypeRelation *relation, Type *other) void ShortType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *source) { - if (relation->ApplyUnboxing() && !relation->IsTrue()) { - relation->GetChecker()->AsETSChecker()->MaybeAddUnboxingFlagInRelation(relation, source, this); - } - NarrowingWideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); + WideningConverter(relation->GetChecker()->AsETSChecker(), relation, this, source); } bool ShortType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) @@ -57,38 +54,9 @@ void ShortType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->HasTypeFlag(TypeFlag::BYTE | TypeFlag::CHAR)) { - conversion::NarrowingPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { - conversion::WideningPrimitive(relation, this, target); - return; - } - - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) { - conversion::Boxing(relation, this); - return; - } - - if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_TYPE)) { - auto unboxedTarget = relation->GetChecker()->AsETSChecker()->MaybeUnboxInRelation(target); - if (unboxedTarget == nullptr) { - conversion::Forbidden(relation); - return; - } - Cast(relation, unboxedTarget); - if (relation->IsTrue()) { - conversion::Boxing(relation, unboxedTarget); - return; - } - conversion::Forbidden(relation); - return; - } - - conversion::BoxingWideningReference(relation, this, target->AsETSObjectType()); + if (target->HasTypeFlag(TypeFlag::ETS_OBJECT) && + target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_SHORT)) { + conversion::Boxing(relation, this); return; } diff --git a/ets2panda/checker/types/ets/shortType.h b/ets2panda/checker/types/ets/shortType.h index 0cbd73ab16..4b226806a3 100644 --- a/ets2panda/checker/types/ets/shortType.h +++ b/ets2panda/checker/types/ets/shortType.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -52,11 +52,6 @@ public: ss << compiler::Signatures::TYPE_DESCRIPTOR_SHORT; } - std::tuple ResolveConditionExpr() const override - { - return {IsConstantType(), value_ != 0}; - } - private: UType value_ {0}; }; diff --git a/ets2panda/checker/types/ets/types.h b/ets2panda/checker/types/ets/types.h index 68b9f0079e..ce05b8b154 100644 --- a/ets2panda/checker/types/ets/types.h +++ b/ets2panda/checker/types/ets/types.h @@ -42,5 +42,6 @@ #include "etsReadonlyType.h" #include "etsAnyType.h" #include "etsNeverType.h" +#include "etsEnumType.h" #endif /* TYPES_H */ diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 300e9b3fbf..8aa8a44cb7 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -168,6 +168,7 @@ void GlobalTypesHolder::AddEtsSpecificBuiltinTypes() builtinNameMappings_.emplace("Int", GlobalTypeId::ETS_INT_BUILTIN); builtinNameMappings_.emplace("Integral", GlobalTypeId::ETS_INTEGRAL_BUILTIN); builtinNameMappings_.emplace("Long", GlobalTypeId::ETS_LONG_BUILTIN); + builtinNameMappings_.emplace("Numeric", GlobalTypeId::ETS_NUMERIC_BUILTIN); builtinNameMappings_.emplace("Object", GlobalTypeId::ETS_OBJECT_BUILTIN); builtinNameMappings_.emplace("Runtime", GlobalTypeId::ETS_RUNTIME_BUILTIN); builtinNameMappings_.emplace("RuntimeLinker", GlobalTypeId::ETS_RUNTIME_LINKER_BUILTIN); @@ -491,6 +492,11 @@ Type *GlobalTypesHolder::GlobalLongBuiltinType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_LONG_BUILTIN)); } +Type *GlobalTypesHolder::GlobalNumericBuiltinType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_NUMERIC_BUILTIN)); +} + Type *GlobalTypesHolder::GlobalMapBuiltinType() { return globalTypes_.at(static_cast(GlobalTypeId::ETS_MAP_BUILTIN)); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index 635c8b080e..9374659544 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -75,6 +75,7 @@ enum class GlobalTypeId : std::size_t { ETS_INT_BUILTIN, ETS_INTEGRAL_BUILTIN, ETS_LONG_BUILTIN, + ETS_NUMERIC_BUILTIN, ETS_MAP_BUILTIN, ETS_RECORD_BUILTIN, ETS_ERROR_BUILTIN, @@ -99,7 +100,6 @@ enum class GlobalTypeId : std::size_t { ETS_FUNCTION_BUILTIN, ETS_REGEXP_BUILTIN, ETS_ARRAY_BUILTIN, - ETS_ARRAY, ETS_INTEROP_JSRUNTIME_BUILTIN, ETS_INTEROP_JSVALUE_BUILTIN, ETS_BOX_BUILTIN, @@ -113,6 +113,7 @@ enum class GlobalTypeId : std::size_t { ETS_DOUBLE_BOX_BUILTIN, ETS_BIG_INT_BUILTIN, ETS_BIG_INT, + ETS_ARRAY, ETS_FUNCTION0_CLASS, ETS_FUNCTION1_CLASS, @@ -285,6 +286,7 @@ public: Type *GlobalIntegerBuiltinType(); Type *GlobalIntegralBuiltinType(); Type *GlobalLongBuiltinType(); + Type *GlobalNumericBuiltinType(); Type *GlobalErrorBuiltinType(); Type *GlobalRuntimeBuiltinType(); Type *GlobalShortBuiltinType(); diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index 2a4f8ec06d..d94e607e8b 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -90,6 +90,7 @@ enum class SignatureFlags : uint32_t { RETHROWS = 1U << 17U, EXTENSION_FUNCTION = 1U << 18U, DUPLICATE_ASM = 1U << 19U, + BRIDGE = 1U << 20U, INTERNAL_PROTECTED = INTERNAL | PROTECTED, GETTER_OR_SETTER = GETTER | SETTER, @@ -223,6 +224,11 @@ public: return signatureInfo_->restVar; } + [[nodiscard]] varbinder::LocalVariable *RestVar() noexcept + { + return signatureInfo_->restVar; + } + [[nodiscard]] uint8_t ProtectionFlag() const noexcept { if ((flags_ & SignatureFlags::PRIVATE) != 0) { diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index e03343c7f1..090981812f 100644 --- a/ets2panda/checker/types/type.cpp +++ b/ets2panda/checker/types/type.cpp @@ -49,6 +49,11 @@ bool Type::IsETSAsyncFuncReturnType() const return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::ASYNC_FUNC_RETURN_TYPE); } +bool Type::IsBuiltinNumeric() const noexcept +{ + return IsETSObjectType() && AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_NUMERIC); +} + bool Type::IsLambdaObject() const { if (IsETSObjectType() && (AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::FUNCTIONAL_INTERFACE) || @@ -151,36 +156,6 @@ Type *Type::Substitute([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] return this; } -std::uint32_t Type::GetPrecedence(Type const *type) noexcept -{ - ES2PANDA_ASSERT(type != nullptr); - if (type->HasTypeFlag(TypeFlag::BYTE)) { - return 1U; - } - if (type->HasTypeFlag(TypeFlag::CHAR)) { - return 2U; - } - if (type->HasTypeFlag(TypeFlag::SHORT)) { - return 3U; - } - if (type->HasTypeFlag(TypeFlag::INT)) { - return 4U; - } - if (type->HasTypeFlag(TypeFlag::LONG)) { - return 5U; - } - if (type->HasTypeFlag(TypeFlag::FLOAT)) { - return 6U; - } - if (type->HasTypeFlag(TypeFlag::DOUBLE)) { - return 7U; - } - if (type->HasTypeFlag(TypeFlag::BIGINT)) { - return 8U; - } - return 0U; -} - bool IsTypeError(Type const *tp) { return tp != nullptr && tp->IsTypeError(); diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index 12a433f569..c3d06181de 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -143,11 +143,13 @@ public: return reinterpret_cast(this); } - bool IsETSDynamicType() const + [[nodiscard]] bool IsETSDynamicType() const noexcept { return IsETSObjectType() && HasTypeFlag(TypeFlag::ETS_DYNAMIC_FLAG); } + [[nodiscard]] bool IsBuiltinNumeric() const noexcept; + ETSDynamicType *AsETSDynamicType() { ES2PANDA_ASSERT(IsETSDynamicType()); @@ -265,15 +267,24 @@ public: ToAssemblerType(ss); } - virtual uint32_t Rank() const + std::string ToAssemblerType() const { - return 0; + std::stringstream ss; + ToAssemblerType(ss); + return ss.str(); + } + + std::string ToAssemblerTypeWithRank() const + { + std::stringstream ss; + ToAssemblerTypeWithRank(ss); + return ss.str(); } - virtual std::tuple ResolveConditionExpr() const + virtual uint32_t Rank() const { - ES2PANDA_UNREACHABLE(); - }; + return 0; + } virtual void Identical(TypeRelation *relation, Type *other); virtual void AssignmentTarget(TypeRelation *relation, Type *source) = 0; @@ -288,7 +299,6 @@ public: [[maybe_unused]] VarianceFlag varianceFlag) { } - [[nodiscard]] static std::uint32_t GetPrecedence(Type const *type) noexcept; virtual Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); [[nodiscard]] virtual Type *Clone(Checker *checker); diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index 965d2172bb..80a8ad001a 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -114,7 +114,6 @@ bool TypeRelation::IsIdenticalTo(IndexInfo *source, IndexInfo *target) return result_ == RelationResult::TRUE; } -// NOTE: applyNarrowing -> flag bool TypeRelation::IsAssignableTo(Type *source, Type *target) { if (source == target) { @@ -193,10 +192,7 @@ bool TypeRelation::IsCastableTo(Type *const source, Type *const target) return false; } - // NOTE: Can't cache if the node has BoxingUnboxingFlags. These flags should be stored and restored on the node - // on cache hit. - if (UncheckedCast() && node_->GetBoxingUnboxingFlags() == ir::BoxingUnboxingFlags::NONE && - !node_->HasAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF)) { + if (UncheckedCast() && !node_->HasAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF)) { checker_->UncheckedCastableResult().cached.insert( {{source->Id(), target->Id()}, {result_, RelationType::UNCHECKED_CASTABLE}}); } @@ -209,21 +205,44 @@ bool TypeRelation::IsCastableTo(Type *const source, Type *const target) bool TypeRelation::IsLegalBoxedPrimitiveConversion(Type *target, Type *source) { - if (!target->IsETSReferenceType() || !source->IsETSReferenceType()) { + ETSChecker *checker = this->GetChecker()->AsETSChecker(); + + if (target == nullptr || source == nullptr) { return false; } + + if (target->IsETSUnionType() && source->IsETSObjectType()) { + Type *sourceUnboxedType = checker->MaybeUnboxType(source); + if (sourceUnboxedType == nullptr || !sourceUnboxedType->IsETSPrimitiveType()) { + return false; + } + Type *boxedUnionTarget = target->AsETSUnionType()->FindUnboxableType(); + if (boxedUnionTarget == nullptr) { + return false; + } + Type *targetUnboxedType = checker->MaybeUnboxType(boxedUnionTarget); + if (targetUnboxedType == nullptr || !targetUnboxedType->IsETSPrimitiveType()) { + return false; + } + bool res = this->Result(this->IsAssignableTo(sourceUnboxedType, target)); + return res; + } + if (!target->IsETSObjectType() || !source->IsETSObjectType()) { return false; } - if (!target->AsETSObjectType()->IsBoxedPrimitive() || !source->AsETSObjectType()->IsBoxedPrimitive()) { + + if (!target->AsETSObjectType()->IsBoxedPrimitive() && !source->AsETSObjectType()->IsBoxedPrimitive()) { return false; } - ETSChecker *checker = this->GetChecker()->AsETSChecker(); - Type *targetUnboxedType = checker->MaybeUnboxType(target); Type *sourceUnboxedType = checker->MaybeUnboxType(source); + if (source->IsETSIntEnumType()) { + targetUnboxedType = checker->GlobalIntType(); + } + if (targetUnboxedType == nullptr || sourceUnboxedType == nullptr) { return false; } @@ -231,7 +250,8 @@ bool TypeRelation::IsLegalBoxedPrimitiveConversion(Type *target, Type *source) return false; } - return this->Result(this->IsAssignableTo(sourceUnboxedType, targetUnboxedType)); + bool res = this->Result(this->IsAssignableTo(sourceUnboxedType, targetUnboxedType)); + return res; } bool TypeRelation::IsSupertypeOf(Type *super, Type *sub) diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index 6e1ad8cb6d..c5abfa2e85 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -37,7 +37,6 @@ using ENUMBITOPS_OPERATORS; enum class TypeRelationFlag : uint32_t { NONE = 0U, - NARROWING = 1U << 0U, WIDENING = 1U << 1U, BOXING = 1U << 2U, UNBOXING = 1U << 3U, @@ -63,10 +62,13 @@ enum class TypeRelationFlag : uint32_t { NO_THROW_GENERIC_TYPEALIAS = 1U << 24U, OVERRIDING_CONTEXT = 1U << 25U, IGNORE_REST_PARAM = 1U << 26U, + STRING_TO_CHAR = 1U << 27U, + OVERLOADING_CONTEXT = 1U << 28U, + NO_SUBSTITUTION_NEEDED = 1U << 29U, ASSIGNMENT_CONTEXT = WIDENING | BOXING | UNBOXING, - BRIDGE_CHECK = OVERRIDING_CONTEXT | IGNORE_TYPE_PARAMETERS | NO_RETURN_TYPE_CHECK, - CASTING_CONTEXT = NARROWING | WIDENING | BOXING | UNBOXING | UNCHECKED_CAST, + BRIDGE_CHECK = OVERRIDING_CONTEXT | IGNORE_TYPE_PARAMETERS, + CASTING_CONTEXT = WIDENING | BOXING | UNBOXING | UNCHECKED_CAST, }; enum class RelationResult { TRUE, FALSE, UNKNOWN, MAYBE, CACHE_MISS, ERROR }; @@ -143,11 +145,6 @@ public: return result_ == RelationResult::ERROR; } - bool ApplyNarrowing() const - { - return (flags_ & TypeRelationFlag::NARROWING) != 0; - } - bool ApplyWidening() const { return (flags_ & TypeRelationFlag::WIDENING) != 0; diff --git a/ets2panda/compiler/base/condition.cpp b/ets2panda/compiler/base/condition.cpp index dc0b40e8dc..e0ebfb209d 100644 --- a/ets2panda/compiler/base/condition.cpp +++ b/ets2panda/compiler/base/condition.cpp @@ -15,6 +15,7 @@ #include "condition.h" +#include "checker/ETSAnalyzerHelpers.h" #include "compiler/core/pandagen.h" #include "compiler/core/ETSGen.h" #include "ir/expressions/assignmentExpression.h" diff --git a/ets2panda/compiler/base/lreference.cpp b/ets2panda/compiler/base/lreference.cpp index 240aa09bd3..9f9a3c45c0 100644 --- a/ets2panda/compiler/base/lreference.cpp +++ b/ets2panda/compiler/base/lreference.cpp @@ -295,11 +295,15 @@ void ETSLReference::SetValueComputed(const ir::MemberExpression *memberExpr) con return; } - ES2PANDA_ASSERT(objectType->IsETSArrayType() || objectType->IsETSResizableArrayType()); - auto vRegtype = etsg_->GetVRegType(baseReg_); - auto *elementType = vRegtype->IsETSArrayType() ? vRegtype->AsETSArrayType()->ElementType() - : vRegtype->AsETSResizableArrayType()->ElementType(); - etsg_->StoreArrayElement(Node(), baseReg_, propReg_, elementType); + if (objectType->IsETSArrayType() || objectType->IsETSResizableArrayType()) { + auto vRegtype = etsg_->GetVRegType(baseReg_); + auto *elementType = vRegtype->IsETSArrayType() ? vRegtype->AsETSArrayType()->ElementType() + : vRegtype->AsETSResizableArrayType()->ElementType(); + etsg_->StoreArrayElement(Node(), baseReg_, propReg_, elementType); + return; + } + + ES2PANDA_ASSERT(objectType->IsETSNeverType()); // nothing to do, we're in dead code anyway } void ETSLReference::SetValueGetterSetter(const ir::MemberExpression *memberExpr) const diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index 0d3494b72f..bae951abe4 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -18,13 +18,12 @@ #include "compiler/base/catchTable.h" #include "checker/ets/dynamic/dynamicCall.h" #include "compiler/base/condition.h" -#include "compiler/core/ETSGen-inl.h" #include "compiler/base/lreference.h" #include "compiler/core/switchBuilder.h" -#include "compiler/function/functionBuilder.h" #include "checker/ETSchecker.h" #include "checker/types/ets/etsDynamicFunctionType.h" #include "checker/types/ets/etsTupleType.h" +#include "ETSGen-inl.h" namespace ark::es2panda::compiler { @@ -53,15 +52,11 @@ void ETSCompiler::Compile(const ir::ClassProperty *st) const auto ttctx = compiler::TargetTypeContext(etsg, st->TsType()); compiler::RegScope rs(etsg); - ir::BoxingUnboxingFlags flags = - (st->Value() != nullptr) ? st->Value()->GetBoxingUnboxingFlags() : ir::BoxingUnboxingFlags::NONE; - if (st->Value() == nullptr) { etsg->LoadDefaultValue(st, st->TsType()); } else { st->Value()->Compile(etsg); etsg->ApplyConversion(st->Value(), st->TsType()); - st->Value()->SetBoxingUnboxingFlags(flags); } if (st->IsStatic()) { @@ -138,8 +133,8 @@ void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const if (expr->Signature() != nullptr) { const compiler::TargetTypeContext ttctx2(etsg, elementType); - ArenaVector arguments(GetCodeGen()->Allocator()->Adapter()); - etsg->InitObject(expr, expr->Signature(), arguments); + static const ArenaVector ARGUMENTS(GetCodeGen()->Allocator()->Adapter()); + etsg->InitObject(expr, expr->Signature(), ARGUMENTS); } else { etsg->LoadAccumulatorPoison(expr, elementType); } @@ -257,11 +252,7 @@ static void HandleUnionTypeInForOf(compiler::ETSGen *etsg, checker::Type const * } else if (currentType->IsETSResizableArrayType()) { etsg->LoadResizableArrayElement(st, unionReg, *countReg); } else { - etsg->LoadStringChar(st, unionReg, *countReg); - // NOTE(vpukhov): #20510 use a single unboxing convertor - etsg->ApplyCastToBoxingFlags(st, ir::BoxingUnboxingFlags::BOX_TO_CHAR); - etsg->EmitBoxingConversion(ir::BoxingUnboxingFlags::BOX_TO_CHAR, st); - etsg->CastToChar(st); + etsg->LoadStringChar(st, unionReg, *countReg, true); } } @@ -334,6 +325,11 @@ void ETSCompiler::Compile(const ir::ETSTypeReferencePart *node) const ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), node->TsType())); } +void ETSCompiler::Compile(const ir::OpaqueTypeNode *node) const +{ + GetETSGen()->SetAccumulatorType(node->TsType()); +} + void ETSCompiler::Compile([[maybe_unused]] const ir::ETSWildcardType *node) const { ES2PANDA_UNREACHABLE(); @@ -732,14 +728,37 @@ void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg } } +bool IsCastCallName(util::StringView name) +{ + return name == Signatures::BYTE_CAST || name == Signatures::SHORT_CAST || name == Signatures::INT_CAST || + name == Signatures::LONG_CAST || name == Signatures::FLOAT_CAST || name == Signatures::DOUBLE_CAST || + name == Signatures::CHAR_CAST; +} + +bool IsCastCall(checker::Signature *signature) +{ + ES2PANDA_ASSERT(signature->HasSignatureFlag(checker::SignatureFlags::STATIC)); + auto *func = signature->Function(); + return (func->Parent()->Parent()->IsMethodDefinition() && IsCastCallName(func->Id()->Name()) && + util::Helpers::ContainingClass(func)->AsETSObjectType()->IsBoxedPrimitive() && + (signature->Params().size() == 1) && signature->Params()[0]->TsType()->IsETSPrimitiveType()); +} + void ETSCompiler::EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, checker::Signature *signature) const { ETSGen *etsg = GetETSGen(); - if (expr->Callee()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { - etsg->ApplyConversionAndStoreAccumulator(expr->Callee(), calleeReg, nullptr); - } if (signature->HasSignatureFlag(checker::SignatureFlags::STATIC)) { + if (IsCastCall(signature)) { + ES2PANDA_ASSERT(expr->Arguments().size() == 1); + auto *param = expr->Arguments()[0]; + param->Compile(etsg); + + const auto *const targetType = etsg->Checker()->GetApparentType(expr->TsType()); + auto ttctx = compiler::TargetTypeContext(etsg, nullptr); + CompileCastPrimitives(param, targetType); + return; + } etsg->CallExact(expr, expr->Signature(), expr->Arguments()); } else if (expr->Callee()->IsMemberExpression()) { auto me = expr->Callee()->AsMemberExpression(); @@ -798,10 +817,6 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const } else { ES2PANDA_UNREACHABLE(); } - - if (expr->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG | ir::BoxingUnboxingFlags::BOXING_FLAG)) { - etsg->ApplyConversion(expr, expr->TsType()); - } } void ETSCompiler::Compile(const ir::ConditionalExpression *expr) const @@ -1414,9 +1429,9 @@ void ETSCompiler::Compile(const ir::ReturnStatement *st) const return; } - auto ttctx = compiler::TargetTypeContext(etsg, etsg->ReturnType()); + auto ttctx = compiler::TargetTypeContext(etsg, st->ReturnType()); argument->Compile(etsg); - etsg->ApplyConversion(argument, etsg->ReturnType()); + etsg->ApplyConversion(argument, st->ReturnType()); if (etsg->ExtendWithFinalizer(st->Parent(), st)) { return; @@ -1528,6 +1543,7 @@ void ETSCompiler::Compile(const ir::VariableDeclarator *st) const etsg->LoadDefaultValue(st, st->Id()->AsIdentifier()->Variable()->TsType()); } + // ????????????????????????????????????? is this meaningfull???? etsg->ApplyConversion(st, st->TsType()); lref.SetValue(); } @@ -1570,46 +1586,9 @@ void ETSCompiler::Compile(const ir::TSArrayType *node) const etsg->LoadAccumulatorPoison(node, node->TsType()); } -void ETSCompiler::CompileCastUnboxable(const ir::TSAsExpression *expr) const +void ETSCompiler::CompileCastPrimitives(const ir::Expression *expr, checker::Type const *targetType) const { ETSGen *etsg = GetETSGen(); - auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); - ES2PANDA_ASSERT(targetType->IsETSObjectType()); - - switch (targetType->AsETSObjectType()->UnboxableKind()) { - case checker::ETSObjectFlags::BUILTIN_BOOLEAN: - etsg->CastToBoolean(expr); - break; - case checker::ETSObjectFlags::BUILTIN_BYTE: - etsg->CastToByte(expr); - break; - case checker::ETSObjectFlags::BUILTIN_CHAR: - etsg->CastToChar(expr); - break; - case checker::ETSObjectFlags::BUILTIN_SHORT: - etsg->CastToShort(expr); - break; - case checker::ETSObjectFlags::BUILTIN_INT: - etsg->CastToInt(expr); - break; - case checker::ETSObjectFlags::BUILTIN_LONG: - etsg->CastToLong(expr); - break; - case checker::ETSObjectFlags::BUILTIN_FLOAT: - etsg->CastToFloat(expr); - break; - case checker::ETSObjectFlags::BUILTIN_DOUBLE: - etsg->CastToDouble(expr); - break; - default: - ES2PANDA_UNREACHABLE(); - } -} - -void ETSCompiler::CompileCastPrimitives(const ir::TSAsExpression *expr) const -{ - ETSGen *etsg = GetETSGen(); - auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); switch (checker::ETSChecker::TypeKind(targetType)) { case checker::TypeFlag::ETS_BOOLEAN: { @@ -1648,12 +1627,25 @@ void ETSCompiler::CompileCastPrimitives(const ir::TSAsExpression *expr) const ES2PANDA_UNREACHABLE(); } } + etsg->SetAccumulatorType(targetType); } -void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const +// NOTE(gogabr): will be needed once we forbid as conversions +/* +static void CastIfDynamic(ETSGen *etsg, ir::Expression const *expr, checker::TypeFlag typeFlag) +{ + // CC-OFFNXT(redundant_code[C++]) tmp code + if (checker::ETSChecker::TypeKind(expr->TsType()) == checker::TypeFlag::ETS_DYNAMIC_TYPE) { + etsg->CastDynamicToe(expr, typeFlag); + return; + } + ES2PANDA_UNREACHABLE(); +} +*/ + +void ETSCompiler::CompileCast(const ir::TSAsExpression *expr, checker::Type const *targetType) const { ETSGen *etsg = GetETSGen(); - auto *targetType = etsg->Checker()->GetApparentType(expr->TsType()); switch (checker::ETSChecker::TypeKind(targetType)) { case checker::TypeFlag::ETS_ARRAY: @@ -1674,8 +1666,29 @@ void ETSCompiler::CompileCast(const ir::TSAsExpression *expr) const etsg->CastToDynamic(expr, targetType->AsETSDynamicType()); break; } + // NOTE(gogabr): will be needed once we forbid as conversion + /* + // CC-OFFNXT(redundant_code[C++]) tmp code + case checker::TypeFlag::DOUBLE: + case checker::TypeFlag::STRING: + case checker::TypeFlag::ETS_BOOLEAN: { + CastIfDynamic(etsg, expr->Expr(), targetType->TypeFlags()); + break; // no further conversion + } + case checker::TypeFlag::BYTE: + case checker::TypeFlag::SHORT: + case checker::TypeFlag::INT: + case checker::TypeFlag::LONG: + case checker::TypeFlag::FLOAT: + case checker::TypeFlag::CHAR: { + CastIfDynamic(etsg, expr->Expr(), targetType->TypeFlags()); + CompileCastPrimitives(expr, targetType); + break; + } + */ default: { - CompileCastPrimitives(expr); + CompileCastPrimitives(expr, targetType); + break; } } } @@ -1687,26 +1700,11 @@ void ETSCompiler::Compile(const ir::TSAsExpression *expr) const const auto *const targetType = etsg->Checker()->GetApparentType(expr->TsType()); - auto ttctx = compiler::TargetTypeContext(etsg, nullptr); - if ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U) { - etsg->ApplyUnboxingConversion(expr->Expr()); - } - - if (targetType->IsETSObjectType() && - ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U || - (expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U) && - checker::ETSChecker::TypeKind(etsg->GetAccumulatorType()) != checker::TypeFlag::ETS_OBJECT) { - if (targetType->IsETSUnboxableObject()) { - CompileCastUnboxable(expr); - } + if (!etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), targetType)) { + auto ttctx = compiler::TargetTypeContext(etsg, nullptr); + CompileCast(expr, targetType); + ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), targetType)); } - - if ((expr->Expr()->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U) { - etsg->ApplyBoxingConversion(expr->Expr()); - } - - CompileCast(expr); - ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), targetType)); } void ETSCompiler::Compile([[maybe_unused]] const ir::TSInterfaceDeclaration *st) const {} diff --git a/ets2panda/compiler/core/ETSCompiler.h b/ets2panda/compiler/core/ETSCompiler.h index 94cd1e8f35..42f81ca50a 100644 --- a/ets2panda/compiler/core/ETSCompiler.h +++ b/ets2panda/compiler/core/ETSCompiler.h @@ -36,9 +36,8 @@ public: private: void GetDynamicNameParts(const ir::CallExpression *expr, ArenaVector &parts) const; void CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const; - void CompileCastUnboxable(const ir::TSAsExpression *expr) const; - void CompileCastPrimitives(const ir::TSAsExpression *expr) const; - void CompileCast(const ir::TSAsExpression *expr) const; + void CompileCastPrimitives(const ir::Expression *expr, checker::Type const *targetType) const; + void CompileCast(const ir::TSAsExpression *expr, checker::Type const *targetType) const; void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, checker::Signature *signature) const; bool HandleArrayTypeLengthProperty(const ir::MemberExpression *expr, ETSGen *etsg) const; bool HandleStaticProperties(const ir::MemberExpression *expr, ETSGen *etsg) const; diff --git a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp index edcf0a2205..44669b1241 100644 --- a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp +++ b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp @@ -193,11 +193,6 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::OmittedExpression *expr) co ES2PANDA_UNREACHABLE(); } -void ETSCompiler::Compile([[maybe_unused]] const ir::OpaqueTypeNode *node) const -{ - ES2PANDA_UNREACHABLE(); -} - void ETSCompiler::Compile([[maybe_unused]] const ir::BrokenTypeNode *node) const { ES2PANDA_UNREACHABLE(); diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index e1e8635c3c..fde13df423 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -13,7 +13,6 @@ * limitations under the License. */ -#include "ETSGen.h" #include "ETSGen-inl.h" #include "generated/signatures.h" @@ -30,14 +29,13 @@ #include "ir/statements/continueStatement.h" #include "ir/statements/tryStatement.h" #include "ir/ts/tsInterfaceDeclaration.h" -#include "varbinder/variableFlags.h" #include "compiler/base/lreference.h" #include "compiler/base/catchTable.h" #include "compiler/core/dynamicContext.h" #include "varbinder/ETSBinder.h" #include "varbinder/variable.h" #include "checker/types/type.h" -#include "checker/types/typeFlag.h" +#include "checker/types/signature.h" #include "checker/checker.h" #include "checker/ETSchecker.h" #include "checker/types/ets/etsObjectType.h" @@ -402,9 +400,6 @@ static bool StaticAccessRequiresReferenceSafetyCheck(const ir::AstNode *const no if (parent->IsCallExpression() && parent->AsCallExpression()->Callee() == node) { return false; } - if (node->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { - return false; - } return true; } @@ -680,6 +675,18 @@ const checker::Type *ETSGen::LoadDefaultValue(const ir::AstNode *node, const che if (type->IsETSReferenceType()) { if (checker->Relation()->IsSupertypeOf(type, checker->GlobalETSUndefinedType())) { LoadAccumulatorUndefined(node); + } else if (type->IsETSObjectType() && type->AsETSObjectType()->IsBoxedPrimitive()) { + // Call default constructor for boxed primitive types. + static auto const DUMMY_ARGS = ArenaVector(checker->Allocator()->Adapter()); + auto const &signatures = type->AsETSObjectType()->ConstructSignatures(); + auto const it = std::find_if(signatures.cbegin(), signatures.cend(), [](checker::Signature *signature) { + return signature->ArgCount() == 0U && !signature->HasRestParameter(); + }); + if (it != signatures.cend()) { + InitObject(node, *it, DUMMY_ARGS); + } else { + LoadAccumulatorPoison(node, type); + } } else { LoadAccumulatorPoison(node, type); } @@ -992,6 +999,11 @@ void ETSGen::GuardUncheckedType(const ir::AstNode *node, const checker::Type *un SetAccumulatorType(unchecked); // this check guards possible type violations, **do not relax it** CheckedReferenceNarrowing(node, Checker()->MaybeBoxType(target)); + // Because on previous step accumulator type may be set in CheckerReferenceNarrowing to boxed counterpart of + // target We need to apply unbox conversion if needed to avoid RTE + if (target->IsETSPrimitiveType() && GetAccumulatorType()->IsETSUnboxableObject()) { + ApplyConversion(node, target); + } } SetAccumulatorType(target); } @@ -1010,14 +1022,16 @@ void ETSGen::EmitFailedTypeCastException(const ir::AstNode *node, const VReg src void ETSGen::LoadConstantObject(const ir::Expression *node, const checker::Type *type) { - if (type->HasTypeFlag(checker::TypeFlag::BIGINT_LITERAL)) { + if (type->IsETSBigIntType()) { LoadAccumulatorBigInt(node, type->AsETSObjectType()->AsETSBigIntType()->GetValue()); const VReg value = AllocReg(); StoreAccumulator(node, value); CreateBigIntObject(node, value); - } else { + } else if (type->IsETSStringType()) { LoadAccumulatorString(node, type->AsETSObjectType()->AsETSStringType()->GetValue()); SetAccumulatorType(node->TsType()); + } else { + ES2PANDA_UNREACHABLE(); } } @@ -1070,78 +1084,15 @@ void ETSGen::ApplyConversionCast(const ir::AstNode *node, const checker::Type *t } } -void ETSGen::ApplyBoxingConversion(const ir::AstNode *node) -{ - EmitBoxingConversion(node); - node->SetBoxingUnboxingFlags( - static_cast(node->GetBoxingUnboxingFlags() & ~(ir::BoxingUnboxingFlags::BOXING_FLAG))); -} - -void ETSGen::ApplyUnboxingConversion(const ir::AstNode *node) -{ - auto const callUnbox = [this, node](std::string_view sig, checker::Type const *unboxedType) { - auto boxedType = Checker()->MaybeBoxType(unboxedType)->AsETSObjectType(); - EmitUnboxedCall(node, sig, unboxedType, boxedType); - }; - - auto const unboxFlags = - ir::BoxingUnboxingFlags(node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG); - node->RemoveBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG); - - switch (unboxFlags) { - case ir::BoxingUnboxingFlags::UNBOX_TO_BOOLEAN: - callUnbox(Signatures::BUILTIN_BOOLEAN_UNBOXED, Checker()->GlobalETSBooleanType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_BYTE: - callUnbox(Signatures::BUILTIN_BYTE_UNBOXED, Checker()->GlobalByteType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_CHAR: - callUnbox(Signatures::BUILTIN_CHAR_UNBOXED, Checker()->GlobalCharType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_SHORT: - callUnbox(Signatures::BUILTIN_SHORT_UNBOXED, Checker()->GlobalShortType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_INT: - callUnbox(Signatures::BUILTIN_INT_UNBOXED, Checker()->GlobalIntType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_LONG: - callUnbox(Signatures::BUILTIN_LONG_UNBOXED, Checker()->GlobalLongType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_FLOAT: - callUnbox(Signatures::BUILTIN_FLOAT_UNBOXED, Checker()->GlobalFloatType()); - return; - case ir::BoxingUnboxingFlags::UNBOX_TO_DOUBLE: - callUnbox(Signatures::BUILTIN_DOUBLE_UNBOXED, Checker()->GlobalDoubleType()); - return; - default: - ES2PANDA_UNREACHABLE(); - } -} - void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targetType) { - auto ttctx = TargetTypeContext(this, targetType); - - const bool hasBoxingflags = (node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG) != 0U; - const bool hasUnboxingflags = (node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U; - if (hasBoxingflags && !hasUnboxingflags) { - ApplyBoxingConversion(node); - return; - } - - if (hasUnboxingflags) { - ApplyUnboxingConversion(node); - } - if (targetType == nullptr) { return; } - ApplyConversionCast(node, targetType); + auto ttctx = TargetTypeContext(this, targetType); - if (hasBoxingflags) { - ApplyBoxingConversion(node); - } + ApplyConversionCast(node, targetType); } void ETSGen::ApplyCast(const ir::AstNode *node, const checker::Type *targetType) @@ -1187,116 +1138,6 @@ void ETSGen::ApplyCast(const ir::AstNode *node, const checker::Type *targetType) } } -void ETSGen::ApplyCastToBoxingFlags(const ir::AstNode *node, const ir::BoxingUnboxingFlags targetType) -{ - switch (targetType) { - case ir::BoxingUnboxingFlags::BOX_TO_DOUBLE: { - CastToDouble(node); - break; - } - case ir::BoxingUnboxingFlags::BOX_TO_FLOAT: { - CastToFloat(node); - break; - } - case ir::BoxingUnboxingFlags::BOX_TO_LONG: { - CastToLong(node); - break; - } - case ir::BoxingUnboxingFlags::BOX_TO_INT: { - CastToInt(node); - break; - } - case ir::BoxingUnboxingFlags::BOX_TO_BYTE: { - CastToByte(node); - break; - } - default: { - break; - } - } -} - -void ETSGen::EmitUnboxedCall(const ir::AstNode *node, std::string_view signatureFlag, - const checker::Type *const targetType, const checker::Type *const boxedType) -{ - RegScope rs(this); - // NOTE(vpukhov): #20510 lowering - if (node->HasAstNodeFlags(ir::AstNodeFlags::CHECKCAST)) { - CheckedReferenceNarrowing(node, boxedType); - } - - // to cast to primitive types we probably have to cast to corresponding boxed built-in types first. - auto *const checker = Checker()->AsETSChecker(); - auto const *accumulatorType = GetAccumulatorType(); - if (accumulatorType->IsETSObjectType() && //! accumulatorType->DefinitelyNotETSNullish() && - !checker->Relation()->IsIdenticalTo(const_cast(accumulatorType), - const_cast(boxedType))) { - CastToReftype(node, boxedType, false); - } - - Ra().Emit(node, signatureFlag, dummyReg_, 0); - SetAccumulatorType(targetType); - if (node->IsExpression()) { - const_cast(node->AsExpression())->SetTsType(const_cast(targetType)); - } -} - -// NOTE(vpukhov): #20510 should be available only as a part of ApplyBoxingConversion -void ETSGen::EmitBoxingConversion(ir::BoxingUnboxingFlags boxingFlag, const ir::AstNode *node) -{ - auto const callBox = [this, node](std::string_view sig, checker::Type const *unboxedType) { - Ra().Emit(node, sig, dummyReg_, 0); - SetAccumulatorType(Checker()->MaybeBoxType(unboxedType)->AsETSObjectType()); - }; - - switch (boxingFlag) { - case ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN: - callBox(Signatures::BUILTIN_BOOLEAN_VALUE_OF, Checker()->GlobalETSBooleanType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_BYTE: - callBox(Signatures::BUILTIN_BYTE_VALUE_OF, Checker()->GlobalByteType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_CHAR: - callBox(Signatures::BUILTIN_CHAR_VALUE_OF, Checker()->GlobalCharType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_SHORT: - callBox(Signatures::BUILTIN_SHORT_VALUE_OF, Checker()->GlobalShortType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_INT: - callBox(Signatures::BUILTIN_INT_VALUE_OF, Checker()->GlobalIntType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_LONG: - callBox(Signatures::BUILTIN_LONG_VALUE_OF, Checker()->GlobalLongType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_FLOAT: - callBox(Signatures::BUILTIN_FLOAT_VALUE_OF, Checker()->GlobalFloatType()); - return; - case ir::BoxingUnboxingFlags::BOX_TO_DOUBLE: - callBox(Signatures::BUILTIN_DOUBLE_VALUE_OF, Checker()->GlobalDoubleType()); - return; - default: - ES2PANDA_UNREACHABLE(); - } -} - -// NOTE(vpukhov): #20510 should be available only as a part of ApplyBoxingConversion -void ETSGen::EmitBoxingConversion(const ir::AstNode *node) -{ - auto boxingFlag = - static_cast(ir::BoxingUnboxingFlags::BOXING_FLAG & node->GetBoxingUnboxingFlags()); - - RegScope rs(this); - - ApplyCastToBoxingFlags(node, boxingFlag); - - EmitBoxingConversion(boxingFlag, node); - - if (node->IsExpression()) { - auto boxedType = const_cast(GetAccumulatorType()); - const_cast(node->AsExpression())->SetTsType(boxedType); - } -} - void ETSGen::SwapBinaryOpArgs(const ir::AstNode *const node, const VReg lhs) { const RegScope rs(this); @@ -1680,9 +1521,8 @@ void ETSGen::CastToInt(const ir::AstNode *node) void ETSGen::CastToReftype(const ir::AstNode *const node, const checker::Type *const targetType, const bool unchecked) { - ES2PANDA_ASSERT(GetAccumulatorType()->IsETSReferenceType()); - const auto *const sourceType = GetAccumulatorType(); + ES2PANDA_ASSERT(sourceType->IsETSReferenceType()); if (sourceType->IsETSDynamicType()) { CastDynamicToObject(node, targetType); @@ -1772,14 +1612,13 @@ void ETSGen::CastToString(const ir::AstNode *const node) if (sourceType->IsETSStringType()) { return; } - ES2PANDA_ASSERT(sourceType->IsETSReferenceType()); - // caller must ensure parameter is not null Ra().Emit(node, Signatures::BUILTIN_OBJECT_TO_STRING, dummyReg_, 0); SetAccumulatorType(Checker()->GetGlobalTypesHolder()->GlobalETSStringBuiltinType()); } +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP) solid logic, big switch case void ETSGen::CastToDynamic(const ir::AstNode *node, const checker::ETSDynamicType *type) { std::string_view methodName {}; @@ -1816,6 +1655,13 @@ void ETSGen::CastToDynamic(const ir::AstNode *node, const checker::ETSDynamicTyp case checker::TypeFlag::ETS_TUPLE: methodName = compiler::Signatures::Dynamic::NewObjectBuiltin(type->Language()); break; + case checker::TypeFlag::ETS_UNDEFINED: + case checker::TypeFlag::ETS_VOID: + methodName = compiler::Signatures::Dynamic::GetUndefinedBuiltin(type->Language()); + break; + case checker::TypeFlag::ETS_NULL: + methodName = compiler::Signatures::Dynamic::GetNullBuiltin(type->Language()); + break; case checker::TypeFlag::ETS_DYNAMIC_TYPE: SetAccumulatorType(type); return; @@ -2620,15 +2466,6 @@ void ETSGen::RefEqualityLoose(const ir::AstNode *node, VReg lhs, VReg rhs, Label if (ltype->DefinitelyETSNullish() || rtype->DefinitelyETSNullish()) { HandleDefinitelyNullishEquality(node, lhs, rhs, ifFalse); - } else if (!ltype->PossiblyETSValueTypedExceptNullish() || !rtype->PossiblyETSValueTypedExceptNullish()) { - auto ifTrue = AllocLabel(); - if ((ltype->PossiblyETSUndefined() && rtype->PossiblyETSNull()) || - (rtype->PossiblyETSUndefined() && ltype->PossiblyETSNull())) { - HandlePossiblyNullishEquality(node, lhs, rhs, ifFalse, ifTrue); - } - LoadAccumulator(node, lhs); - Ra().Emit(node, rhs, ifFalse); - SetLabel(node, ifTrue); } else if (auto spec = SelectLooseObjComparator( // try to select specific type // CC-OFFNXT(G.FMT.06-CPP) project code style const_cast(Checker()), const_cast(ltype), @@ -3244,10 +3081,14 @@ void ETSGen::DoubleIsNaN(const ir::AstNode *node) SetAccumulatorType(Checker()->GlobalETSBooleanType()); } -void ETSGen::LoadStringChar(const ir::AstNode *node, const VReg stringObj, const VReg charIndex) +void ETSGen::LoadStringChar(const ir::AstNode *node, const VReg stringObj, const VReg charIndex, bool needBox) { Ra().Emit(node, Signatures::BUILTIN_STRING_CHAR_AT, stringObj, charIndex); SetAccumulatorType(Checker()->GlobalCharType()); + if (needBox) { + Ra().Emit(node, Signatures::BUILTIN_CHAR_VALUE_OF, dummyReg_, 0); + SetAccumulatorType(Checker()->GlobalCharBuiltinType()); + } } void ETSGen::ThrowException(const ir::Expression *expr) diff --git a/ets2panda/compiler/core/ETSGen.h b/ets2panda/compiler/core/ETSGen.h index bdfe9e92fa..9ebeb8790f 100644 --- a/ets2panda/compiler/core/ETSGen.h +++ b/ets2panda/compiler/core/ETSGen.h @@ -222,8 +222,6 @@ public: void LoadAccumulatorDynamicModule(const ir::AstNode *node, const ir::ETSImportDeclaration *import); - void ApplyBoxingConversion(const ir::AstNode *node); - void ApplyUnboxingConversion(const ir::AstNode *node); void ApplyConversion(const ir::AstNode *node) { if (targetType_ != nullptr) { @@ -233,9 +231,6 @@ public: void ApplyConversionCast(const ir::AstNode *node, const checker::Type *targetType); void ApplyConversion(const ir::AstNode *node, const checker::Type *targetType); void ApplyCast(const ir::AstNode *node, const checker::Type *targetType); - void ApplyCastToBoxingFlags(const ir::AstNode *node, const ir::BoxingUnboxingFlags targetType); - void EmitBoxingConversion(ir::BoxingUnboxingFlags boxingFlag, const ir::AstNode *node); - void EmitBoxingConversion(const ir::AstNode *node); void SwapBinaryOpArgs(const ir::AstNode *node, VReg lhs); VReg MoveAccToReg(const ir::AstNode *node); @@ -264,7 +259,7 @@ public: } void LoadStringLength(const ir::AstNode *node); - void LoadStringChar(const ir::AstNode *node, VReg stringObj, VReg charIndex); + void LoadStringChar(const ir::AstNode *node, VReg stringObj, VReg charIndex, bool needBox = false); void FloatIsNaN(const ir::AstNode *node); void DoubleIsNaN(const ir::AstNode *node); @@ -456,9 +451,6 @@ public: private: const VReg dummyReg_ = VReg::RegStart(); - void EmitUnboxedCall(const ir::AstNode *node, std::string_view signatureFlag, const checker::Type *targetType, - const checker::Type *boxedType); - void LoadConstantObject(const ir::Expression *node, const checker::Type *type); void StringBuilderAppend(const ir::AstNode *node, VReg builder); void AppendString(const ir::Expression *binExpr, VReg builder); diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 8f0b822ef9..d3dd8aa926 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -26,8 +26,6 @@ #include "ir/base/scriptFunction.h" #include "ir/base/classProperty.h" #include "ir/statements/annotationDeclaration.h" -#include "ir/ts/tsEnumDeclaration.h" -#include "ir/ts/tsEnumMember.h" #include "ir/ts/tsInterfaceDeclaration.h" #include "ir/ts/tsInterfaceBody.h" #include "ir/ts/tsTypeParameterDeclaration.h" @@ -358,37 +356,64 @@ void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const pa } // Helper function to reduce EmitDefaultFieldValue size and pass code check -static pandasm::ScalarValue CreateScalarValue(const checker::Type *type, checker::TypeFlag typeKind) +// We assume that all the checks have been passes successfully and the value in number literal is valid. +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic, big switch case +static pandasm::ScalarValue CreateScalarValue(ir::Literal const *literal, checker::TypeFlag typeKind) { switch (typeKind) { case checker::TypeFlag::ETS_BOOLEAN: { + ES2PANDA_ASSERT(literal->IsBooleanLiteral()); return pandasm::ScalarValue::Create( - static_cast(type->AsETSBooleanType()->GetValue())); + static_cast(literal->AsBooleanLiteral()->Value())); } case checker::TypeFlag::BYTE: { - return pandasm::ScalarValue::Create(type->AsByteType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral() + ->Number() + .GetValueAndCastTo>()); } case checker::TypeFlag::SHORT: { - return pandasm::ScalarValue::Create(type->AsShortType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral() + ->Number() + .GetValueAndCastTo>()); } case checker::TypeFlag::INT: { - return pandasm::ScalarValue::Create(type->AsIntType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral() + ->Number() + .GetValueAndCastTo>()); } case checker::TypeFlag::LONG: { - return pandasm::ScalarValue::Create(type->AsLongType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral() + ->Number() + .GetValueAndCastTo>()); } case checker::TypeFlag::FLOAT: { - return pandasm::ScalarValue::Create(type->AsFloatType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral() + ->Number() + .GetValueAndCastTo>()); } case checker::TypeFlag::DOUBLE: { - return pandasm::ScalarValue::Create(type->AsDoubleType()->GetValue()); + ES2PANDA_ASSERT(literal->IsNumberLiteral()); + return pandasm::ScalarValue::Create( + literal->AsNumberLiteral()->Number().GetDouble()); } case checker::TypeFlag::CHAR: { - return pandasm::ScalarValue::Create(type->AsCharType()->GetValue()); + ES2PANDA_ASSERT(literal->IsCharLiteral()); + return pandasm::ScalarValue::Create(literal->AsCharLiteral()->Char()); } case checker::TypeFlag::ETS_OBJECT: { + ES2PANDA_ASSERT(literal->IsStringLiteral()); return pandasm::ScalarValue::Create( - type->AsETSObjectType()->AsETSStringType()->GetValue().Mutf8()); + literal->AsStringLiteral()->Str().Mutf8()); } default: { ES2PANDA_UNREACHABLE(); @@ -398,19 +423,14 @@ static pandasm::ScalarValue CreateScalarValue(const checker::Type *type, checker void ETSEmitter::EmitDefaultFieldValue(pandasm::Field &classField, const ir::Expression *init) { - if (init == nullptr) { + if (init == nullptr || !init->IsLiteral()) { return; } const auto *type = init->TsType(); - - if (!type->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - return; - } - auto typeKind = checker::ETSChecker::TypeKind(type); classField.metadata->SetFieldType(classField.type); - classField.metadata->SetValue(CreateScalarValue(type, typeKind)); + classField.metadata->SetValue(CreateScalarValue(init->AsLiteral(), typeKind)); } void ETSEmitter::GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external) @@ -631,14 +651,23 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern Program()->recordTable.emplace(classRecord.name, std::move(classRecord)); } -// Helper function to check if the unary expression is a numeric literal with negation. -// This expression should be handled during lowering with the associated issue number. -static bool IsNegativeLiteralNode(const ir::UnaryExpression *expr) +void ETSEmitter::ProcessArrayExpression( + std::string &baseName, std::vector>> &result, + std::vector &literals, const ir::Expression *elem) { - return expr->OperatorType() == lexer::TokenType::PUNCTUATOR_MINUS && expr->Argument()->IsNumberLiteral(); + auto litArrays = CreateLiteralArray(baseName, elem); + auto emplaceLiteral = [&literals](panda_file::LiteralTag tag, const auto &value) { + literals.emplace_back(pandasm::LiteralArray::Literal {tag, value}); + }; + + emplaceLiteral(panda_file::LiteralTag::TAGVALUE, static_cast(panda_file::LiteralTag::LITERALARRAY)); + emplaceLiteral(panda_file::LiteralTag::LITERALARRAY, litArrays.back().first); + for (const auto &item : litArrays) { + result.push_back(item); + } } -void ETSEmitter::CreateEnumProp(const ir::ClassProperty *prop, pandasm::Field &field) +static void CreateEnumProp(const ir::ClassProperty *prop, pandasm::Field &field) { if (prop->Value() == nullptr) { return; @@ -657,22 +686,6 @@ void ETSEmitter::CreateEnumProp(const ir::ClassProperty *prop, pandasm::Field &f } } -void ETSEmitter::ProcessArrayExpression( - std::string &baseName, std::vector>> &result, - std::vector &literals, const ir::Expression *elem) -{ - auto litArrays = CreateLiteralArray(baseName, elem); - auto emplaceLiteral = [&literals](panda_file::LiteralTag tag, const auto &value) { - literals.emplace_back(pandasm::LiteralArray::Literal {tag, value}); - }; - - emplaceLiteral(panda_file::LiteralTag::TAGVALUE, static_cast(panda_file::LiteralTag::LITERALARRAY)); - emplaceLiteral(panda_file::LiteralTag::LITERALARRAY, litArrays.back().first); - for (const auto &item : litArrays) { - result.push_back(item); - } -} - static void ProcessEnumExpression(std::vector &literals, const ir::Expression *elem) { auto *memberExpr = elem->IsCallExpression() ? elem->AsCallExpression()->Arguments()[0]->AsMemberExpression() @@ -694,47 +707,54 @@ static void ProcessEnumExpression(std::vector &l void ETSEmitter::ProcessArrayElement(const ir::Expression *elem, std::vector &literals, std::string &baseName, LiteralArrayVector &result) { - switch (elem->Type()) { - case ir::AstNodeType::NUMBER_LITERAL: { - auto doubleValue = elem->AsNumberLiteral()->Number().GetDouble(); - literals.emplace_back(pandasm::LiteralArray::Literal { - panda_file::LiteralTag::TAGVALUE, static_cast(panda_file::LiteralTag::DOUBLE)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::DOUBLE, doubleValue}); + ES2PANDA_ASSERT(elem->IsLiteral() || elem->IsArrayExpression() || elem->IsMemberExpression()); + if (elem->IsMemberExpression()) { + ProcessEnumExpression(literals, elem); + return; + } + auto emplaceLiteral = [&literals](panda_file::LiteralTag tag, auto value) { + literals.emplace_back( + pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE, static_cast(tag)}); + literals.emplace_back(pandasm::LiteralArray::Literal {tag, value}); + }; + // NOTE(dkofanov): Why 'LiteralTag::ARRAY_*'-types isn't used? + switch (checker::ETSChecker::TypeKind(elem->TsType())) { + case checker::TypeFlag::ETS_BOOLEAN: { + emplaceLiteral(panda_file::LiteralTag::BOOL, elem->AsBooleanLiteral()->Value()); break; } - case ir::AstNodeType::BOOLEAN_LITERAL: { - bool boolValue = elem->AsBooleanLiteral()->Value(); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::TAGVALUE, - static_cast(panda_file::LiteralTag::BOOL)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::BOOL, boolValue}); + case checker::TypeFlag::CHAR: + case checker::TypeFlag::BYTE: + case checker::TypeFlag::SHORT: + case checker::TypeFlag::INT: { + emplaceLiteral(panda_file::LiteralTag::INTEGER, + static_cast(elem->AsNumberLiteral()->Number().GetInt())); break; } - case ir::AstNodeType::STRING_LITERAL: { - std::string stringValue {elem->AsStringLiteral()->Str().Utf8()}; - literals.emplace_back(pandasm::LiteralArray::Literal { - panda_file::LiteralTag::TAGVALUE, static_cast(panda_file::LiteralTag::STRING)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::STRING, stringValue}); + case checker::TypeFlag::LONG: { + emplaceLiteral(panda_file::LiteralTag::BIGINT, + static_cast(elem->AsNumberLiteral()->Number().GetInt())); break; } - case ir::AstNodeType::ARRAY_EXPRESSION: { - ProcessArrayExpression(baseName, result, literals, elem); + case checker::TypeFlag::FLOAT: { + emplaceLiteral(panda_file::LiteralTag::FLOAT, elem->AsNumberLiteral()->Number().GetFloat()); break; } - case ir::AstNodeType::MEMBER_EXPRESSION: - case ir::AstNodeType::CALL_EXPRESSION: { - ProcessEnumExpression(literals, elem); + case checker::TypeFlag::DOUBLE: { + emplaceLiteral(panda_file::LiteralTag::DOUBLE, elem->AsNumberLiteral()->Number().GetDouble()); break; } - case ir::AstNodeType::UNARY_EXPRESSION: { - double doubleValue = (-1) * elem->AsUnaryExpression()->Argument()->AsNumberLiteral()->Number().GetDouble(); - literals.emplace_back(pandasm::LiteralArray::Literal { - panda_file::LiteralTag::TAGVALUE, static_cast(panda_file::LiteralTag::DOUBLE)}); - literals.emplace_back(pandasm::LiteralArray::Literal {panda_file::LiteralTag::DOUBLE, doubleValue}); + case checker::TypeFlag::ETS_OBJECT: { + emplaceLiteral(panda_file::LiteralTag::STRING, elem->AsStringLiteral()->ToString()); break; } - default: - ES2PANDA_UNREACHABLE(); + case checker::TypeFlag::ETS_ARRAY: { + ProcessArrayExpression(baseName, result, literals, elem); break; + } + default: { + ES2PANDA_UNREACHABLE(); + } } } @@ -763,13 +783,9 @@ void ETSEmitter::CreateLiteralArrayProp(const ir::ClassProperty *prop, std::stri ++rank; elemType = checker->GetElementTypeOfArray(elemType); } - if (elemType->IsETSEnumType()) { - field.type = PandasmTypeWithRank(elemType, rank); - } else { - std::stringstream ss; - elemType->ToAssemblerType(ss); - field.type = pandasm::Type(ss.str(), rank); - } + std::stringstream ss; + elemType->ToAssemblerType(ss); + field.type = pandasm::Type(ss.str(), rank); auto value = prop->Value(); if (value != nullptr) { @@ -844,8 +860,8 @@ pandasm::AnnotationElement ETSEmitter::ProcessArrayType(const ir::ClassProperty std::string_view {litArrays.back().first}))}; } -pandasm::AnnotationElement ETSEmitter::ProcessETSEnumType(std::string &baseName, const ir::Expression *init, - const checker::Type *type) +static pandasm::AnnotationElement ProcessETSEnumType(std::string &baseName, const ir::Expression *init, + const checker::Type *type) { auto declNode = init->AsMemberExpression()->PropVar()->Declaration()->Node(); auto *initValue = declNode->AsClassProperty()->OriginEnumMember()->Init(); @@ -864,38 +880,19 @@ pandasm::AnnotationElement ETSEmitter::GenCustomAnnotationElement(const ir::Clas { const auto *init = prop->Value(); const auto *type = init->TsType(); - auto typeKind = checker::ETSChecker::TypeKind(type); - auto propName = prop->Id()->Name().Mutf8(); if (type->IsETSArrayType() || type->IsETSResizableArrayType()) { return ProcessArrayType(prop, baseName, init); } - if (type->IsETSEnumType()) { return ProcessETSEnumType(baseName, init, type); } - switch (checker::ETSChecker::TypeKind( - Context()->GetChecker()->AsETSChecker()->MaybeUnboxType(const_cast(type)))) { - case checker::TypeFlag::BYTE: - case checker::TypeFlag::SHORT: - case checker::TypeFlag::INT: - case checker::TypeFlag::LONG: - case checker::TypeFlag::FLOAT: - case checker::TypeFlag::DOUBLE: - case checker::TypeFlag::ETS_BOOLEAN: - case checker::TypeFlag::ETS_OBJECT: { - if (init->IsUnaryExpression() && IsNegativeLiteralNode(init->AsUnaryExpression())) { - double negNumberValue = - (-1) * init->AsUnaryExpression()->Argument()->AsNumberLiteral()->Number().GetDouble(); - return pandasm::AnnotationElement { - propName, std::make_unique( - pandasm::ScalarValue::Create(negNumberValue))}; - } - return pandasm::AnnotationElement { - propName, std::make_unique(CreateScalarValue(init->TsType(), typeKind))}; - } - default: - ES2PANDA_UNREACHABLE(); + if (init->IsLiteral()) { + auto typeKind = checker::ETSChecker::TypeKind(type); + auto propName = prop->Id()->Name().Mutf8(); + return pandasm::AnnotationElement { + propName, std::make_unique(CreateScalarValue(init->AsLiteral(), typeKind))}; } + ES2PANDA_UNREACHABLE(); } pandasm::AnnotationData ETSEmitter::GenCustomAnnotation(ir::AnnotationUsage *anno, std::string &baseName) @@ -1003,8 +1000,13 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationFunctionalReference(const ir::C pandasm::AnnotationData functionalReference(Signatures::ETS_ANNOTATION_FUNCTIONAL_REFERENCE); pandasm::AnnotationElement value( Signatures::ANNOTATION_KEY_VALUE, - std::make_unique(pandasm::ScalarValue::Create( - const_cast(classDef)->FunctionalReferenceReferencedMethod().Mutf8()))); + std::make_unique( + pandasm::ScalarValue::Create(const_cast(classDef) + ->FunctionalReferenceReferencedMethod() + ->Function() + ->Scope() + ->InternalName() + .Mutf8()))); functionalReference.AddElement(std::move(value)); return functionalReference; } @@ -1051,32 +1053,37 @@ ir::MethodDefinition *ETSEmitter::FindAsyncImpl(ir::ScriptFunction *asyncFunc) const ir::ClassDefinition *classDef = ownerNode->AsClassDefinition(); ES2PANDA_ASSERT(classDef != nullptr); - auto it = - std::find_if(classDef->Body().rbegin(), classDef->Body().rend(), [&implName, &asyncFunc](ir::AstNode *node) { - if (!node->IsMethodDefinition()) { - return false; - } - bool isSameName = node->AsMethodDefinition()->Id()->Name().Utf8() == implName; - bool isBothStaticOrInstance = - (node->Modifiers() & ir::ModifierFlags::STATIC) == (asyncFunc->Modifiers() & ir::ModifierFlags::STATIC); - return isSameName && isBothStaticOrInstance; - }); - if (it == classDef->Body().rend()) { + ir::MethodDefinition *method = nullptr; + for (auto node : classDef->Body()) { + if (!node->IsMethodDefinition()) { + continue; + } + bool isSameName = node->AsMethodDefinition()->Id()->Name().Utf8() == implName; + bool isBothStaticOrInstance = + (node->Modifiers() & ir::ModifierFlags::STATIC) == (asyncFunc->Modifiers() & ir::ModifierFlags::STATIC); + if (isSameName && isBothStaticOrInstance) { + method = node->AsMethodDefinition(); + break; + } + } + if (method == nullptr) { return nullptr; } - ir::MethodDefinition *method = (*it)->AsMethodDefinition(); auto *checker = static_cast(Context()->GetChecker()); checker::TypeRelation *typeRel = checker->Relation(); checker::SavedTypeRelationFlagsContext savedFlagsCtx(typeRel, checker::TypeRelationFlag::NO_RETURN_TYPE_CHECK); method->Function()->Signature()->IsSubtypeOf(typeRel, asyncFunc->Signature()); - auto overloadIt = method->Overloads().begin(); - while (overloadIt != method->Overloads().end() && !typeRel->IsTrue()) { - method = *overloadIt; - method->Function()->Signature()->IsSubtypeOf(typeRel, asyncFunc->Signature()); - ++overloadIt; + if (typeRel->IsTrue()) { + return method; + } + for (auto overload : method->Overloads()) { + overload->Function()->Signature()->IsSubtypeOf(typeRel, asyncFunc->Signature()); + if (typeRel->IsTrue()) { + return overload; + } } - return typeRel->IsTrue() ? method : nullptr; + return nullptr; } pandasm::AnnotationData ETSEmitter::GenAnnotationAsync(ir::ScriptFunction *scriptFunc) diff --git a/ets2panda/compiler/core/ETSemitter.h b/ets2panda/compiler/core/ETSemitter.h index b3a8942026..db06f5bd5d 100644 --- a/ets2panda/compiler/core/ETSemitter.h +++ b/ets2panda/compiler/core/ETSemitter.h @@ -91,11 +91,8 @@ private: void GenClassRecord(const ir::ClassDefinition *classDef, bool external); pandasm::AnnotationElement ProcessArrayType(const ir::ClassProperty *prop, std::string &baseName, const ir::Expression *init); - pandasm::AnnotationElement ProcessETSEnumType(std::string &baseName, const ir::Expression *init, - const checker::Type *type); pandasm::AnnotationElement GenCustomAnnotationElement(const ir::ClassProperty *prop, std::string &baseName); pandasm::AnnotationData GenCustomAnnotation(ir::AnnotationUsage *anno, std::string &baseName); - void CreateEnumProp(const ir::ClassProperty *prop, pandasm::Field &field); void ProcessArrayElement(const ir::Expression *elem, std::vector &literals, std::string &baseName, LiteralArrayVector &result); LiteralArrayVector CreateLiteralArray(std::string &baseName, const ir::Expression *array); diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 1e5e752ae7..7086b2707d 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -173,6 +173,13 @@ static bool DoIsolatedDeclgenCheck(const util::Options &options, const std::stri return true; } +static bool CheckIfPhaseToSkip(util::Options &options, const std::string &name) +{ + return options.GetSkipPhases().count(name) > 0 || + (options.IsGenerateDeclEnableIsolated() && name == compiler::InsertOptionalParametersAnnotation::NAME); +} + +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program &program) { auto &options = const_cast(*context.config->options); @@ -184,13 +191,14 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & options.SetGenerateDeclEnabled(true); } - bool skipPhase = false; + bool afterCheckerPhase = false; while (auto phase = context.phaseManager->NextPhase()) { const auto name = std::string {phase->Name()}; - skipPhase = options.GetSkipPhases().count(name) > 0 || - (options.IsGenerateDeclEnableIsolated() && - phase->Name() == compiler::InsertOptionalParametersAnnotation::NAME); - if (skipPhase) { + if (name == compiler::CheckerPhase::NAME) { + afterCheckerPhase = true; + } + + if (CheckIfPhaseToSkip(options, name)) { continue; } @@ -210,12 +218,13 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & if (!options.IsGenerateDeclEnableIsolated()) { verifier.IntroduceNewInvariants(phase->Name()); } + if (verifierEachPhase || options.HasVerifierPhase(phase->Name())) { verifier.Verify(phase->Name()); } // Stop lowerings processing after Checker phase if any error happened. - if (phase->Name() == compiler::CheckerPhase::NAME && context.diagnosticEngine->IsAnyError()) { + if (afterCheckerPhase && context.diagnosticEngine->IsAnyError()) { return false; } diff --git a/ets2panda/compiler/lowering/checkerPhase.h b/ets2panda/compiler/lowering/checkerPhase.h index f9a915da10..ecc59837ba 100644 --- a/ets2panda/compiler/lowering/checkerPhase.h +++ b/ets2panda/compiler/lowering/checkerPhase.h @@ -21,7 +21,7 @@ namespace ark::es2panda::compiler { class CheckerPhase : public Phase { public: - static constexpr std::string_view NAME = "CheckerPhase"; + static constexpr std::string_view const NAME = "CheckerPhase"; std::string_view Name() const override { return NAME; diff --git a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp index f9dd8d0d64..42a8564a0f 100644 --- a/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/arrayLiteralLowering.cpp @@ -44,7 +44,7 @@ ArenaVector ArrayLiteralLowering::GenerateDefaultCallToConstruc auto *indexSymbol = Gensym(Allocator()); auto *lengthSymbol = Gensym(Allocator()); auto *typeNode = checker_->AllocNode(eleType, Allocator()); - ss << "let @@I1 : int = @@I2.length as int;"; + ss << "let @@I1 : int = @@I2.length.toInt();"; newStmts.emplace_back(lengthSymbol); newStmts.emplace_back(arraySymbol->Clone(Allocator(), nullptr)); ss << "for (let @@I3 = 0; @@I4 < @@E5; @@I6 = @@I7 + 1) {"; @@ -78,8 +78,7 @@ static bool IsInAnnotationContext(ir::AstNode *node) ir::AstNode *ArrayLiteralLowering::TryTransformLiteralArrayToRefArray(ir::ArrayExpression *literalArray) { - auto literalArrayType = - literalArray->TsType() != nullptr ? literalArray->TsType() : literalArray->GetPreferredType(); + auto literalArrayType = literalArray->TsType() != nullptr ? literalArray->TsType() : literalArray->PreferredType(); if (literalArrayType->IsETSArrayType() || literalArrayType->IsETSTupleType() || !literalArrayType->IsETSResizableArrayType() || IsInAnnotationContext(literalArray)) { return literalArray; @@ -88,15 +87,26 @@ ir::AstNode *ArrayLiteralLowering::TryTransformLiteralArrayToRefArray(ir::ArrayE std::vector newStmts; std::stringstream ss; auto *genSymIdent = Gensym(Allocator()); + auto *genSymIdent2 = Gensym(Allocator()); auto *type = checker_->AllocNode(arrayType, Allocator()); + // ss << "let @@I1 : FixedArray<@@T2> = @@E3;"; + // ss << "Array.from<@@T4>(@@I5);"; ss << "let @@I1 : FixedArray<@@T2> = @@E3;"; - ss << "Array.from<@@T4>(@@I5);"; + ss << "let @@I4 : Array<@@T5> = new Array<@@T6>(@@I7.length);"; + ss << "for (let i = 0; i < @@I8.length; ++i) { @@I9[i] = @@I10[i]}"; + ss << "@@I11;"; newStmts.emplace_back(genSymIdent); newStmts.emplace_back(type); - literalArray->SetTsType(nullptr); newStmts.emplace_back(literalArray); + literalArray->SetTsType(nullptr); + newStmts.emplace_back(genSymIdent2); + newStmts.emplace_back(type->Clone(Allocator(), nullptr)); newStmts.emplace_back(type->Clone(Allocator(), nullptr)); newStmts.emplace_back(genSymIdent->Clone(Allocator(), nullptr)); + newStmts.emplace_back(genSymIdent->Clone(Allocator(), nullptr)); + newStmts.emplace_back(genSymIdent2->Clone(Allocator(), nullptr)); + newStmts.emplace_back(genSymIdent->Clone(Allocator(), nullptr)); + newStmts.emplace_back(genSymIdent2->Clone(Allocator(), nullptr)); auto *parent = literalArray->Parent(); auto *loweringResult = parser_->CreateFormattedExpression(ss.str(), newStmts); @@ -121,7 +131,7 @@ ir::AstNode *ArrayLiteralLowering::TryTransformNewArrayExprToRefArray(ir::ETSNew auto *genSymIdent = Gensym(Allocator()); std::stringstream ss; - ss << "let @@I1 = new Array<@@T2>(@@E3 as number);"; + ss << "let @@I1 = new Array<@@T2>(@@E3.toDouble());"; auto *type = checker_->AllocNode(arrayType, Allocator()); auto *dimension = newExpr->Dimension()->Clone(Allocator(), nullptr); newStmts.emplace_back(genSymIdent); @@ -159,7 +169,7 @@ ir::Statement *ArrayLiteralLowering::CreateNestedArrayCreationStatement(ArenaVec ir::MemberExpressionKind::ELEMENT_ACCESS, true, false); std::string creationTemplate = - "for (let @@I1 = 0; @@I2 < @@I3; @@I4 = @@I5 + 1) { let @@I6 = new Array<@@T7>(@@E8 as number); @@E9 = @@I10}"; + "for (let @@I1 = 0; @@I2 < @@I3; @@I4 = @@I5 + 1) { let @@I6 = new Array<@@T7>(@@E8.toDouble()); @@E9 = @@I10}"; ir::Statement *forUpdateStmt = parser_->CreateFormattedStatement( creationTemplate, genSymIdent, genSymIdent->Clone(Allocator(), nullptr), lastDimIdent->Clone(Allocator(), nullptr), genSymIdent->Clone(Allocator(), nullptr), @@ -209,7 +219,7 @@ ir::AstNode *ArrayLiteralLowering::TryTransformNewMultiDimArrayToRefArray( auto arrayType = newExpr->TsType()->AsETSResizableArrayType()->ElementType(); auto *type = checker_->AllocNode(arrayType, Allocator()); auto *genSymIdent = Gensym(Allocator()); - std::string newArray = "let @@I1 = new Array<@@T2>(@@I3 as number)"; + std::string newArray = "let @@I1 = new Array<@@T2>(@@I3.toDouble())"; auto idents = TransformDimVectorToIdentVector(newExpr->Dimensions(), statements); auto newArraystatement = parser_->CreateFormattedStatements(newArray, genSymIdent, type, idents[0]->Clone(Allocator(), nullptr)); @@ -255,4 +265,4 @@ ArenaAllocator *ArrayLiteralLowering::Allocator() return checker_->Allocator(); } -} // namespace ark::es2panda::compiler \ No newline at end of file +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp index 9645a5ff5d..2440c30134 100644 --- a/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp +++ b/ets2panda/compiler/lowering/ets/asyncMethodLowering.cpp @@ -169,6 +169,7 @@ void ComposeAsyncImplMethod(checker::ETSChecker *checker, ir::MethodDefinition * auto *baseOverloadImplMethod = node->BaseOverloadMethod()->AsyncPairMethod(); implMethod->Function()->Id()->SetVariable(baseOverloadImplMethod->Function()->Id()->Variable()); baseOverloadImplMethod->AddOverload(implMethod); + implMethod->SetParent(baseOverloadImplMethod); } else { classDef->EmplaceBody(implMethod); } diff --git a/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp b/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp deleted file mode 100644 index 5ad356570b..0000000000 --- a/ets2panda/compiler/lowering/ets/boxedTypeLowering.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2024-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "boxedTypeLowering.h" - -#include "checker/ETSchecker.h" -#include "compiler/lowering/util.h" -#include "generated/signatures.h" - -namespace ark::es2panda::compiler { - -std::string_view BoxedTypeLowering::Name() const -{ - return "BoxedTypeLowering"; -} - -void BoxNumberLiteralArguments(ir::CallExpression *callExpr, PhaseManager *phaseManager, checker::ETSChecker *checker, - parser::ETSParser *parser) -{ - const static std::unordered_map BOXTO({ - {ir::BoxingUnboxingFlags::BOX_TO_BOOLEAN, compiler::Signatures::BUILTIN_BOOLEAN_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_BYTE, compiler::Signatures::BUILTIN_BYTE_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_SHORT, compiler::Signatures::BUILTIN_SHORT_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_CHAR, compiler::Signatures::BUILTIN_CHAR_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_INT, compiler::Signatures::BUILTIN_INT_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_LONG, compiler::Signatures::BUILTIN_LONG_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_FLOAT, compiler::Signatures::BUILTIN_FLOAT_CLASS}, - {ir::BoxingUnboxingFlags::BOX_TO_DOUBLE, compiler::Signatures::BUILTIN_DOUBLE_CLASS}, - }); - - for (size_t i = 0; i < callExpr->Arguments().size(); ++i) { - auto arg = callExpr->Arguments()[i]; - if (arg->IsNumberLiteral()) { - const auto boxingFlag = arg->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::BOXING_FLAG; - auto it = BOXTO.find(static_cast(boxingFlag)); - if (it == BOXTO.end()) { - continue; - } - - auto res = parser->CreateFormattedExpression("@@I1.valueOf(@@E2)", it->second, arg); - res->SetParent(callExpr); - res->SetRange(arg->Range()); - arg->RemoveBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOXING_FLAG); - callExpr->Arguments()[i] = res; - - Recheck(phaseManager, checker->VarBinder()->AsETSBinder(), checker, res); - } - } -} - -bool BoxedTypeLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) -{ - auto checker = ctx->GetChecker()->AsETSChecker(); - auto parser = ctx->parser->AsETSParser(); - auto phaseManager = ctx->phaseManager; - program->Ast()->TransformChildrenRecursively( - // CC-OFFNXT(G.FMT.14-CPP) project code style - [phaseManager, checker, parser](checker::AstNodePtr ast) -> checker::AstNodePtr { - if (!ast->IsCallExpression()) { - return ast; - } - - auto callExpr = ast->AsCallExpression(); - if (callExpr->Signature() == nullptr || - // Skip lambda expressions because lambda parameters are treated a special way as ETSObjectType. - callExpr->Callee()->TsType()->IsETSObjectType()) { - return ast; - } - - BoxNumberLiteralArguments(callExpr, phaseManager, checker, parser); - - return ast; - }, - Name()); - return true; -} - -} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp index a0a8c9534c..ce8e088aa6 100644 --- a/ets2panda/compiler/lowering/ets/boxingForLocals.cpp +++ b/ets2panda/compiler/lowering/ets/boxingForLocals.cpp @@ -134,6 +134,7 @@ static void HandleFunctionParam(public_lib::Context *ctx, ir::ETSParameterExpres auto *initId = allocator->New(id->Name(), allocator); initId->SetVariable(id->Variable()); initId->SetTsType(oldType); + initId->SetRange(id->Range()); // The new variable will have the same name as the parameter. This is not representable in source code. auto *boxedType = checker->GlobalBuiltinBoxType(oldType); @@ -146,6 +147,7 @@ static void HandleFunctionParam(public_lib::Context *ctx, ir::ETSParameterExpres auto *newDeclarator = util::NodeAllocator::ForceSetParent( allocator, ir::VariableDeclaratorFlag::CONST, allocator->New(newVarName.View(), allocator), newInit); + newDeclarator->SetRange(param->Range()); ArenaVector declVec {allocator->Adapter()}; declVec.emplace_back(newDeclarator); @@ -162,6 +164,7 @@ static void HandleFunctionParam(public_lib::Context *ctx, ir::ETSParameterExpres auto *newDeclaration = util::NodeAllocator::ForceSetParent( allocator, ir::VariableDeclaration::VariableDeclarationKind::CONST, allocator, std::move(declVec)); newDeclaration->SetParent(body); + newDeclaration->SetRange(param->Range()); bodyStmts.insert(bodyStmts.begin(), newDeclaration); auto lexScope = varbinder::LexicalScope::Enter(varBinder, scope); @@ -189,9 +192,11 @@ static ir::AstNode *HandleVariableDeclarator(public_lib::Context *ctx, ir::Varia auto initArgs = ArenaVector(allocator->Adapter()); if (declarator->Init() != nullptr) { auto *arg = declarator->Init(); - if (arg->TsType() != type) { + if (!checker->IsTypeIdenticalTo(arg->TsType(), type)) { arg = util::NodeAllocator::ForceSetParent( allocator, arg, allocator->New(type, allocator), false); + arg->AsTSAsExpression()->TypeAnnotation()->SetRange(declarator->Init()->Range()); + arg->SetRange(declarator->Init()->Range()); } initArgs.push_back(arg); } @@ -201,6 +206,11 @@ static ir::AstNode *HandleVariableDeclarator(public_lib::Context *ctx, ir::Varia allocator, declarator->Flag(), allocator->New(id->Name(), allocator), newInit); newDeclarator->SetParent(declarator->Parent()); + newInit->GetTypeRef()->SetRange(declarator->Range()); + newInit->SetRange(declarator->Range()); + newDeclarator->Id()->SetRange(declarator->Range()); + newDeclarator->SetRange(declarator->Range()); + auto *newDecl = allocator->New(oldVar->Name(), newDeclarator); auto *newVar = allocator->New(newDecl, oldVar->Flags()); newDeclarator->Id()->AsIdentifier()->SetVariable(newVar); @@ -251,7 +261,7 @@ static ir::AstNode *HandleReference(public_lib::Context *ctx, ir::Identifier *id auto *checker = ctx->GetChecker()->AsETSChecker(); // `as` is needed to account for smart types - auto *res = parser->CreateFormattedExpression("@@I1.get() as @@T2", var->Name(), id->TsType()); + auto *res = parser->CreateFormattedExpression("@@I1.get() as @@T2", var->Name(), id->Variable()->TsType()); res->SetParent(id->Parent()); res->AsTSAsExpression() ->Expr() @@ -266,8 +276,7 @@ static ir::AstNode *HandleReference(public_lib::Context *ctx, ir::Identifier *id // adjustment later. res->Check(checker); - ES2PANDA_ASSERT(res->TsType() == id->TsType()); - res->SetBoxingUnboxingFlags(id->GetBoxingUnboxingFlags()); + ES2PANDA_ASSERT(res->TsType() == id->Variable()->TsType()); return res; } @@ -301,7 +310,6 @@ static ir::AstNode *HandleAssignment(public_lib::Context *ctx, ir::AssignmentExp res->Check(checker); ES2PANDA_ASSERT(res->TsType() == ass->TsType()); - res->SetBoxingUnboxingFlags(ass->GetBoxingUnboxingFlags()); return res; } @@ -352,6 +360,7 @@ bool BoxingForLocals::PerformForModule(public_lib::Context *ctx, parser::Program std::function searchForFunctions = [&](ir::AstNode *ast) { if (ast->IsScriptFunction()) { HandleScriptFunction(ctx, ast->AsScriptFunction()); // no recursion + RefineSourceRanges(ast); } else { ast->Iterate(searchForFunctions); } diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp index de86a2313a..57b3ae2698 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.cpp @@ -14,23 +14,207 @@ */ #include "constantExpressionLowering.h" +#include +#include #include "checker/ETSchecker.h" #include "compiler/lowering/util.h" -#include "lexer/token/token.h" +#include "ir/expressions/literals/undefinedLiteral.h" +#include "compiler/lowering/scopesInit/scopesInitPhase.h" +#include "util/helpers.h" namespace ark::es2panda::compiler { -void ConstantExpressionLowering::LogError(const diagnostic::DiagnosticKind &diagnostic, - const util::DiagnosticMessageParams &diagnosticParams, - const lexer::SourcePosition &pos) const +constexpr static char32_t MAX_CHAR = 0xFFFF; + +static ir::BooleanLiteral *CreateBooleanLiteral(bool val, ir::AstNode *parent, const lexer::SourceRange &loc, + ArenaAllocator *allocator) +{ + auto resNode = util::NodeAllocator::Alloc(allocator, val); + resNode->SetParent(parent); + resNode->SetRange(loc); + resNode->SetFolded(); + return resNode; +} + +template +static ir::NumberLiteral *CreateNumberLiteral(T val, ir::AstNode *parent, const lexer::SourceRange &loc, + ArenaAllocator *allocator) +{ + auto resNum = lexer::Number(val); + + auto *resNode = util::NodeAllocator::Alloc(allocator, resNum); + + // Some hack to set string representation of lexer::Number + resNode->Number().SetStr(util::UString(resNode->ToString(), allocator).View()); + + resNode->SetParent(parent); + resNode->SetRange(loc); + resNode->SetFolded(); + return resNode; +} + +static ir::Identifier *CreateErrorIdentifier(const ir::AstNode *node, ArenaAllocator *allocator) +{ + // Creating Identifier without passing any arguments leads to creating Error Identifier with *ERROR_LITERAL* + auto res = util::NodeAllocator::Alloc(allocator, allocator); + + res->SetParent(const_cast(node)->Parent()); + res->SetRange(node->Range()); + return res; +} + +static ir::CharLiteral *CreateCharLiteral(char16_t val, ir::AstNode *parent, const lexer::SourceRange &loc, + ArenaAllocator *allocator) +{ + auto *result = util::NodeAllocator::Alloc(allocator, val); + result->SetParent(parent); + result->SetRange(loc); + result->SetFolded(); + return result; +} + +static ir::PrimitiveType TypeRankToPrimitiveType(TypeRank tr) +{ + switch (tr) { + case TypeRank::CHAR: + return ir::PrimitiveType::CHAR; + case TypeRank::INT8: + return ir::PrimitiveType::BYTE; + case TypeRank::INT16: + return ir::PrimitiveType::SHORT; + case TypeRank::INT32: + return ir::PrimitiveType::INT; + case TypeRank::INT64: + return ir::PrimitiveType::LONG; + case TypeRank::FLOAT: + return ir::PrimitiveType::FLOAT; + case TypeRank::DOUBLE: + return ir::PrimitiveType::DOUBLE; + } + ES2PANDA_UNREACHABLE(); +} + +static TypeRank GetTypeRank(const ir::Literal *literal) +{ + if (literal->IsCharLiteral()) { + return TypeRank::CHAR; + } + if (literal->IsNumberLiteral()) { + auto number = literal->AsNumberLiteral()->Number(); + if (number.IsByte()) { + return TypeRank::INT8; + } + if (number.IsShort()) { + return TypeRank::INT16; + } + if (number.IsInt()) { + return TypeRank::INT32; + } + if (number.IsLong()) { + return TypeRank::INT64; + } + if (number.IsFloat()) { + return TypeRank::FLOAT; + } + if (number.IsDouble()) { + return TypeRank::DOUBLE; + } + } + ES2PANDA_UNREACHABLE(); +} + +template +static TargetType GetVal(const ir::Literal *node) +{ + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(node->IsBooleanLiteral()); + return node->AsBooleanLiteral()->Value(); + } + + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(node->IsCharLiteral()); + return node->AsCharLiteral()->Char(); + } + + ES2PANDA_ASSERT(node->IsNumberLiteral()); + + auto numNode = node->AsNumberLiteral(); + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsByte()); + return numNode->Number().GetByte(); + } + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsShort()); + return numNode->Number().GetShort(); + } + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsInt()); + return numNode->Number().GetInt(); + } + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsLong()); + return numNode->Number().GetLong(); + } + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsFloat()); + return numNode->Number().GetFloat(); + } + if constexpr (std::is_same_v) { + ES2PANDA_ASSERT(numNode->Number().IsDouble()); + return numNode->Number().GetDouble(); + } + ES2PANDA_UNREACHABLE(); +} + +template +static To CastValTo(const ir::Literal *lit) +{ + if (lit->IsBooleanLiteral()) { + return static_cast(GetVal(lit)); + } + + ES2PANDA_ASSERT(lit->IsNumberLiteral() || lit->IsCharLiteral()); + + auto rank = GetTypeRank(lit); + switch (rank) { + case TypeRank::DOUBLE: + return static_cast(GetVal(lit)); + case TypeRank::FLOAT: + return static_cast(GetVal(lit)); + case TypeRank::INT64: + return static_cast(GetVal(lit)); + case TypeRank::INT32: + return static_cast(GetVal(lit)); + case TypeRank::INT16: + return static_cast(GetVal(lit)); + case TypeRank::INT8: + return static_cast(GetVal(lit)); + case TypeRank::CHAR: + return static_cast(GetVal(lit)); + } + + ES2PANDA_UNREACHABLE(); +} + +static bool IsConvertibleToNumericType(const ir::Literal *lit) +{ + return lit->IsCharLiteral() || lit->IsNumberLiteral(); +} + +static void LogError(public_lib::Context *context, const diagnostic::DiagnosticKind &diagnostic, + const util::DiagnosticMessageParams &diagnosticParams, const lexer::SourcePosition &pos) { - context_->diagnosticEngine->LogDiagnostic(diagnostic, diagnosticParams, pos); + context->diagnosticEngine->LogDiagnostic(diagnostic, diagnosticParams, pos); } -static bool IsSupportedLiteralForNumeric(ir::Literal *const node) +static bool IsCorrectNumberLiteral(const ir::AstNode *lit) { - return node->IsNumberLiteral() || node->IsCharLiteral() || node->IsBooleanLiteral(); + if (!lit->IsNumberLiteral()) { + return false; + } + + return !lit->AsNumberLiteral()->Number().ConversionError(); } static bool IsSupportedLiteral(ir::Expression *const node) @@ -40,146 +224,227 @@ static bool IsSupportedLiteral(ir::Expression *const node) } auto literal = node->AsLiteral(); - return literal->IsNumberLiteral() || literal->IsCharLiteral() || literal->IsBooleanLiteral() || - literal->IsStringLiteral() || literal->IsUndefinedLiteral() || literal->IsNullLiteral(); + return IsCorrectNumberLiteral(literal) || literal->IsCharLiteral() || literal->IsBooleanLiteral() || + literal->IsStringLiteral(); } -static bool IsStringTypeReference(ir::ETSTypeReference *type) +template +static ir::AstNode *CommonCastNumberLiteralTo(const ir::Literal *num, ArenaAllocator *allocator) { - auto name = type->Part()->GetIdent()->Name(); - return name == "string" || name == "String"; + auto parent = const_cast(num)->Parent(); + + if constexpr (std::is_same_v) { + return CreateCharLiteral(CastValTo(num), parent, num->Range(), allocator); + } + + return CreateNumberLiteral(CastValTo(num), parent, num->Range(), allocator); } -static bool CheckIsBooleanConstantForUnary(ir::Literal *const unaryLiteral, lexer::TokenType opType) +template +static ir::AstNode *FloatingPointNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) { - if (unaryLiteral->IsBooleanLiteral()) { - return true; + if (sizeof(From) > sizeof(To)) { + // Constant narrowing floating point conversion is not permitted + LogError(context, diagnostic::CONSTANT_FLOATING_POINT_COVERSION, {}, num->Start()); + return const_cast(num); } - return opType == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK; + + // float -> double + return CommonCastNumberLiteralTo(num, context->allocator); } -static bool CheckIsBooleanConstantForBinary(ir::Literal *lhs, ir::Literal *rhs, lexer::TokenType opType) +template +static ir::AstNode *NarrowingNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) { - if (lhs->IsBooleanLiteral() && rhs->IsBooleanLiteral()) { - return true; + auto maxTo = std::numeric_limits::max(); + auto minTo = std::numeric_limits::min(); + auto val = GetVal(num); + if (val < minTo || val > maxTo) { + LogError(context, diagnostic::CONSTANT_VALUE_OUT_OF_RANGE, {}, num->Start()); + return const_cast(num); } - return opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN || - opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_LESS_THAN || opType == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_EQUAL || opType == lexer::TokenType::PUNCTUATOR_NOT_EQUAL || - opType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || opType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR; + + return CommonCastNumberLiteralTo(num, context->allocator); } -static bool CheckIsNumericConstant(ir::Literal *const left, ir::Literal *const right) +template +static ir::AstNode *IntegralNumberLiteralCast(const ir::Literal *num, public_lib::Context *context) { - return (left->IsNumberLiteral() || left->IsCharLiteral()) && (right->IsNumberLiteral() || right->IsCharLiteral()); + if (sizeof(From) > sizeof(To)) { + return NarrowingNumberLiteralCast(num, context); + } + + // Widening + return CommonCastNumberLiteralTo(num, context->allocator); } -template -static TargetType GetOperand(ir::Literal *const node) +template +static ir::AstNode *CastNumberOrCharLiteralFromTo(const ir::Literal *num, public_lib::Context *context) { - if (node->IsBooleanLiteral()) { - return node->AsBooleanLiteral()->Value(); + if constexpr (std::is_same_v) { + return const_cast(num); } - if (node->IsNumberLiteral()) { - auto numNode = node->AsNumberLiteral(); - if (numNode->Number().IsInt()) { - return numNode->Number().GetInt(); - } - if (numNode->Number().IsLong()) { - return numNode->Number().GetLong(); - } - if (numNode->Number().IsFloat()) { - return numNode->Number().GetFloat(); - } - if (numNode->Number().IsDouble()) { - return numNode->Number().GetDouble(); - } - ES2PANDA_UNREACHABLE(); + if constexpr (std::is_floating_point_v && std::is_floating_point_v) { + return FloatingPointNumberLiteralCast(num, context); } - if (node->IsCharLiteral()) { - return node->AsCharLiteral()->Char(); + if constexpr (std::is_integral_v && std::is_integral_v) { + return IntegralNumberLiteralCast(num, context); + } + + if constexpr (std::is_integral_v && std::is_floating_point_v) { + // integral -> floating point (widening) + return CommonCastNumberLiteralTo(num, context->allocator); + } + + if constexpr (std::is_floating_point_v && std::is_integral_v) { + // Constant narrowing floating point conversion is not permitted + LogError(context, diagnostic::CONSTANT_FLOATING_POINT_COVERSION, {}, num->Start()); + return const_cast(num); } ES2PANDA_UNREACHABLE(); } -static TypeRank GetTypeRank(ir::Literal *const literal) +template +static ir::AstNode *CastNumberOrCharLiteralFrom(const ir::Literal *lit, ir::PrimitiveType type, + public_lib::Context *context) { - if (literal->IsCharLiteral()) { - return TypeRank::CHAR; - } - if (literal->IsNumberLiteral()) { - auto number = literal->AsNumberLiteral()->Number(); - if (number.IsInt()) { - return TypeRank::INT32; - } - if (number.IsLong()) { - return TypeRank::INT64; - } - if (number.IsDouble()) { - return TypeRank::DOUBLE; - } - return TypeRank::FLOAT; + switch (type) { + case ir::PrimitiveType::CHAR: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::BYTE: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::SHORT: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::INT: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::LONG: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::FLOAT: + return CastNumberOrCharLiteralFromTo(lit, context); + case ir::PrimitiveType::DOUBLE: + return CastNumberOrCharLiteralFromTo(lit, context); + default: + ES2PANDA_UNREACHABLE(); } - ES2PANDA_UNREACHABLE(); } -static bool TestLiteralIsNotZero(ir::Literal *literal) +static ir::AstNode *CorrectNumberOrCharLiteral(const ir::Literal *lit, ir::PrimitiveType type, + public_lib::Context *context) { - ES2PANDA_ASSERT(literal->IsCharLiteral() || literal->IsNumberLiteral()); - if (literal->IsCharLiteral()) { - return literal->AsCharLiteral()->Char() != 0; + if (TypeRankToPrimitiveType(GetTypeRank(lit)) == type) { + return const_cast(lit); } - auto number = literal->AsNumberLiteral()->Number(); - if (number.IsInt()) { - return number.GetInt() != 0; - } - if (number.IsLong()) { - return number.GetLong() != 0; + switch (GetTypeRank(lit)) { + case TypeRank::CHAR: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::INT8: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::INT16: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::INT32: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::INT64: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::FLOAT: + return CastNumberOrCharLiteralFrom(lit, type, context); + case TypeRank::DOUBLE: + return CastNumberOrCharLiteralFrom(lit, type, context); + default: + ES2PANDA_UNREACHABLE(); } - if (number.IsDouble()) { - return number.GetDouble() != 0; +} + +ir::TypeNode *GetTypeAnnotationFromVarDecl(const ir::Literal *lit) +{ + auto *parent = lit->Parent(); + if (!parent->IsVariableDeclarator()) { + return nullptr; } - if (number.IsFloat()) { - return number.GetFloat() != 0; + auto vd = parent->AsVariableDeclarator(); + if (!vd->Id()->IsIdentifier()) { + return nullptr; } - ES2PANDA_UNREACHABLE(); + return vd->Id()->AsIdentifier()->TypeAnnotation(); } -ir::AstNode *ConstantExpressionLowering::FoldTernaryConstant(ir::ConditionalExpression *cond) +static ir::PrimitiveType GetRightTypeOfNumberOrCharLiteral(const ir::Literal *lit) { - ir::AstNode *resNode {}; + auto *parent = lit->Parent(); + if (parent->IsVariableDeclarator()) { + auto vb = parent->AsVariableDeclarator(); + if (!vb->Id()->IsIdentifier()) { + return TypeRankToPrimitiveType(GetTypeRank(lit)); + } + + if (vb->Id()->AsIdentifier()->TypeAnnotation() == nullptr) { + return TypeRankToPrimitiveType(GetTypeRank(lit)); + } + + if (vb->Id()->AsIdentifier()->TypeAnnotation()->IsETSPrimitiveType()) { + return vb->Id()->AsIdentifier()->TypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType(); + } + } else if (parent->IsClassProperty()) { + auto cp = parent->AsClassProperty(); + if (cp->TypeAnnotation() == nullptr) { + return TypeRankToPrimitiveType(GetTypeRank(lit)); + } + + if (cp->TypeAnnotation()->IsETSPrimitiveType()) { + return cp->TypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType(); + } + } + + return TypeRankToPrimitiveType(GetTypeRank(lit)); +} - auto const testCond = cond->Test()->AsLiteral(); - if (testCond->IsBooleanLiteral()) { - resNode = testCond->AsBooleanLiteral()->Value() ? cond->Consequent() : cond->Alternate(); +static ir::AstNode *TryToCorrectNumberOrCharLiteral(ir::AstNode *node, public_lib::Context *context) +{ + if (IsCorrectNumberLiteral(node) || node->IsCharLiteral()) { + auto lit = node->AsExpression()->AsLiteral(); + return CorrectNumberOrCharLiteral(lit, GetRightTypeOfNumberOrCharLiteral(lit), context); } + + return node; +} + +// NOLINTBEGIN(readability-else-after-return) +static bool TestLiteral(const ir::Literal *lit) +{ // 15.10.1 Extended Conditional Expression - if (testCond->IsStringLiteral()) { - resNode = !testCond->AsStringLiteral()->Str().Empty() ? cond->Consequent() : cond->Alternate(); + if (lit->IsBooleanLiteral()) { + return lit->AsBooleanLiteral()->Value(); } - if (testCond->IsNullLiteral() || testCond->IsUndefinedLiteral()) { - resNode = cond->Alternate(); + if (lit->IsStringLiteral()) { + return !lit->AsStringLiteral()->Str().Empty(); } - if (testCond->IsCharLiteral() || testCond->IsNumberLiteral()) { - resNode = TestLiteralIsNotZero(testCond) ? cond->Consequent() : cond->Alternate(); + if (lit->IsCharLiteral()) { + return lit->AsCharLiteral()->Char() != 0; } - - if (resNode == nullptr) { - return cond; + if (lit->IsNumberLiteral()) { + return !lit->AsNumberLiteral()->Number().IsZero(); } + ES2PANDA_UNREACHABLE(); +} +// NOLINTEND(readability-else-after-return) - resNode->SetParent(cond->Parent()); +ir::AstNode *ConstantExpressionLowering::FoldTernaryConstant(ir::ConditionalExpression *cond) +{ + auto const test = cond->Test()->AsLiteral(); + auto res = TestLiteral(test) ? cond->Consequent() : cond->Alternate(); + auto resNode = res->Clone(context_->allocator, cond->Parent()); + auto *scope = NearestScope(resNode->Parent()); + auto localCtx = varbinder::LexicalScope::Enter(varbinder_, scope); + InitScopesPhaseETS::RunExternalNode(resNode, varbinder_); resNode->SetRange(cond->Range()); return resNode; } template -bool ConstantExpressionLowering::PerformRelationOperator(InputType left, InputType right, lexer::TokenType opType) +static bool PerformRelationOperation(InputType left, InputType right, lexer::TokenType opType) { switch (opType) { case lexer::TokenType::PUNCTUATOR_GREATER_THAN: { @@ -194,9 +459,11 @@ bool ConstantExpressionLowering::PerformRelationOperator(InputType left, InputTy case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: { return left <= right; } + case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_EQUAL: { return left == right; } + case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { return left != right; } @@ -206,367 +473,528 @@ bool ConstantExpressionLowering::PerformRelationOperator(InputType left, InputTy } } -bool ConstantExpressionLowering::HandleRelationOperator(ir::Literal *left, ir::Literal *right, lexer::TokenType opType) +static ir::AstNode *HandleNumericalRelationalExpression(const ir::BinaryExpression *expr, ArenaAllocator *allocator) { - if (left->IsBooleanLiteral()) { - return PerformRelationOperator(GetOperand(left), GetOperand(right), opType); - } - if (left->IsStringLiteral()) { - return PerformRelationOperator(left->AsStringLiteral()->Str(), right->AsStringLiteral()->Str(), opType); - } + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + + ES2PANDA_ASSERT(left->IsNumberLiteral() || left->IsCharLiteral()); + ES2PANDA_ASSERT(right->IsNumberLiteral() || right->IsCharLiteral()); + + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); - TypeRank leftRank = GetTypeRank(left); - TypeRank rightRank = GetTypeRank(right); - TypeRank targetRank = std::max(leftRank, rightRank); + bool res = false; switch (targetRank) { case TypeRank::DOUBLE: { - return PerformRelationOperator(GetOperand(left), GetOperand(right), opType); + res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); + break; } case TypeRank::FLOAT: { - return PerformRelationOperator(GetOperand(left), GetOperand(right), opType); + res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); + break; } case TypeRank::INT64: { - return PerformRelationOperator(GetOperand(left), GetOperand(right), opType); + res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); + break; } case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: case TypeRank::CHAR: { - return PerformRelationOperator(GetOperand(left), GetOperand(right), opType); + res = PerformRelationOperation(CastValTo(left), CastValTo(right), opType); + break; } default: { ES2PANDA_UNREACHABLE(); } } + + return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), allocator); +} + +static ir::AstNode *HandleRelationalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) +{ + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + + if (IsConvertibleToNumericType(left) && IsConvertibleToNumericType(right)) { + return HandleNumericalRelationalExpression(expr, context->allocator); + } + + if (left->IsStringLiteral() && right->IsStringLiteral()) { + auto res = PerformRelationOperation(left->AsStringLiteral()->Str(), right->AsStringLiteral()->Str(), opType); + return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), + context->allocator); + } + + if (left->IsBooleanLiteral() && right->IsBooleanLiteral()) { + auto res = PerformRelationOperation(GetVal(left), GetVal(right), opType); + return CreateBooleanLiteral(res, const_cast(expr)->Parent(), expr->Range(), + context->allocator); + } + + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return CreateErrorIdentifier(expr, context->allocator); +} + +static bool IsMultiplicativeExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_MULTIPLY || opType == lexer::TokenType::PUNCTUATOR_DIVIDE || + opType == lexer::TokenType::PUNCTUATOR_MOD; +} + +static bool IsRelationalExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN || + opType == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_LESS_THAN || opType == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_EQUAL || opType == lexer::TokenType::PUNCTUATOR_NOT_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL || + opType == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL; +} + +static bool IsAdditiveExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + + return opType == lexer::TokenType::PUNCTUATOR_PLUS || opType == lexer::TokenType::PUNCTUATOR_MINUS; +} + +static double CalculateFloatZeroDevision(double leftNum) +{ + if (leftNum == 0.0) { + return std::numeric_limits::quiet_NaN(); + } + if (leftNum > 0) { + return std::numeric_limits::infinity(); + } + return -std::numeric_limits::infinity(); } -bool ConstantExpressionLowering::HandleBitwiseLogicalOperator(ir::Literal *left, ir::Literal *right, - lexer::TokenType opType) +template +static TargetType PerformMultiplicativeOperation(TargetType leftNum, TargetType rightNum, + const ir::BinaryExpression *expr, public_lib::Context *context) { - bool leftValue = left->AsBooleanLiteral()->Value(); - bool rightValue = right->AsBooleanLiteral()->Value(); + auto isForbiddenZeroDivision = [&rightNum]() { return std::is_integral_v && rightNum == 0; }; + auto isFloatZeroDevision = [&rightNum]() { return std::is_floating_point_v && rightNum == 0; }; + auto opType = expr->OperatorType(); switch (opType) { - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - return (static_cast(leftValue) ^ static_cast(rightValue)) != 0U; + case lexer::TokenType::PUNCTUATOR_MULTIPLY: { + return leftNum * rightNum; } - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { - return (static_cast(leftValue) & static_cast(rightValue)) != 0U; + case lexer::TokenType::PUNCTUATOR_DIVIDE: { + if (isForbiddenZeroDivision()) { + LogError(context, diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); + // Max integral value + return std::numeric_limits::max(); + } + if (isFloatZeroDevision()) { + return CalculateFloatZeroDevision(leftNum); + } + + ES2PANDA_ASSERT(rightNum != 0); + // CC-OFFNXT(G.EXP.22-CPP) false positive + return leftNum / rightNum; } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - return (static_cast(leftValue) | static_cast(rightValue)) != 0U; + case lexer::TokenType::PUNCTUATOR_MOD: { + if (isForbiddenZeroDivision()) { + LogError(context, diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); + // Max integral value + return std::numeric_limits::max(); + } + if constexpr (std::is_integral_v) { + return leftNum % rightNum; + } else { + return std::fmod(leftNum, rightNum); + } } - default: { + default: ES2PANDA_UNREACHABLE(); - } } } -ir::AstNode *ConstantExpressionLowering::HandleLogicalOperator(ir::BinaryExpression *expr, lexer::TokenType opType) +static ir::AstNode *HandleMultiplicativeExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { - auto left = expr->Left(); - auto right = expr->Right(); + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return CreateErrorIdentifier(expr, context->allocator); + } - bool leftBoolValue = false; - ir::AstNode *resultValueNode = nullptr; + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); - if (left->IsBooleanLiteral()) { - leftBoolValue = left->AsBooleanLiteral()->Value(); - } else if (left->IsNumberLiteral() || left->IsCharLiteral()) { - leftBoolValue = GetOperand(left->AsLiteral()) != 0; - } else if (left->IsStringLiteral()) { - leftBoolValue = left->AsStringLiteral()->Str().Length() != 0; - } else if (left->IsNullLiteral() || left->IsUndefinedLiteral()) { - leftBoolValue = false; - } else { - ES2PANDA_UNREACHABLE(); + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: { + double res = + PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); + return CreateNumberLiteral(res, parent, loc, allocator); + } + case TypeRank::FLOAT: { + float res = PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); + return CreateNumberLiteral(res, parent, loc, allocator); + } + case TypeRank::INT64: { + int64_t res = + PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); + return CreateNumberLiteral(res, parent, loc, allocator); + } + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: + case TypeRank::CHAR: { + int32_t res = + PerformMultiplicativeOperation(CastValTo(left), CastValTo(right), expr, context); + return CreateNumberLiteral(res, parent, loc, allocator); + } + default: + ES2PANDA_UNREACHABLE(); } +} - switch (opType) { - case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { - if (!leftBoolValue) { - resultValueNode = left; - break; - } - resultValueNode = right; - break; +template +static TargetType PerformAdditiveOperation(TargetType left, TargetType right, lexer::TokenType opType) +{ + if constexpr (std::is_floating_point_v) { + switch (opType) { + case lexer::TokenType::PUNCTUATOR_PLUS: + return left + right; + case lexer::TokenType::PUNCTUATOR_MINUS: + return left - right; + default: + ES2PANDA_UNREACHABLE(); } - case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - if (leftBoolValue) { - resultValueNode = left; - } else { - resultValueNode = right; + } else { + // Integral types + // try bit cast to unsigned counterpart to avoid signed integer overflow + auto uLeft = bit_cast, TargetType>(left); + auto uRight = bit_cast, TargetType>(right); + + switch (opType) { + case lexer::TokenType::PUNCTUATOR_PLUS: { + return bit_cast>(uLeft + uRight); } - break; + case lexer::TokenType::PUNCTUATOR_MINUS: { + return bit_cast>(uLeft - uRight); + } + default: + ES2PANDA_UNREACHABLE(); } - default: { - ES2PANDA_UNREACHABLE(); + } +} + +static ir::AstNode *PerformStringAdditiveOperation(const ir::BinaryExpression *expr, public_lib::Context *context) +{ + auto const lhs = expr->Left()->AsLiteral(); + auto const rhs = expr->Right()->AsLiteral(); + auto resStr = util::UString(context->allocator); + + auto appendLiteral = [&resStr, allocator = context->allocator](const ir::Literal *lit) { + if (lit->IsCharLiteral()) { + resStr.Append(static_cast(lit->AsCharLiteral()->Char()) & MAX_CHAR); + return; + } + if (lit->IsStringLiteral()) { + // No need to create new temporary string (util::UString) for string literal + resStr.Append(lit->AsStringLiteral()->Str()); + return; } - } + resStr.Append(util::UString(lit->ToString(), allocator).View()); + }; - resultValueNode->SetParent(expr->Parent()); - resultValueNode->SetRange({left->Range().start, right->Range().end}); - return resultValueNode; + appendLiteral(lhs); + appendLiteral(rhs); + + auto resNode = util::NodeAllocator::Alloc(context->allocator, resStr.View()); + resNode->SetParent(const_cast(expr)->Parent()); + resNode->SetRange(expr->Range()); + return resNode; } -ir::AstNode *ConstantExpressionLowering::FoldBinaryBooleanConstant(ir::BinaryExpression *expr) +static ir::AstNode *HandleAdditiveExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { auto left = expr->Left()->AsLiteral(); auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + if ((opType == lexer::TokenType::PUNCTUATOR_PLUS) && (left->IsStringLiteral() || right->IsStringLiteral())) { + return PerformStringAdditiveOperation(expr, context); + } - bool result {}; - switch (expr->OperatorType()) { - case lexer::TokenType::PUNCTUATOR_GREATER_THAN: - case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: - case lexer::TokenType::PUNCTUATOR_LESS_THAN: - case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: - case lexer::TokenType::PUNCTUATOR_EQUAL: - case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: { - if ((left->IsBooleanLiteral() && right->IsBooleanLiteral()) || CheckIsNumericConstant(left, right) || - (left->IsStringLiteral() && right->IsStringLiteral())) { - result = HandleRelationOperator(left, right, expr->OperatorType()); - break; - } - return expr; + if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return CreateErrorIdentifier(expr, context->allocator); + } + + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); + + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: { + auto res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - if (left->IsBooleanLiteral() && right->IsBooleanLiteral()) { - result = HandleBitwiseLogicalOperator(left, right, expr->OperatorType()); - break; - } - return expr; + case TypeRank::FLOAT: { + auto res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } - case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: - case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { - // Special because of extended conditional expression - return HandleLogicalOperator(expr, expr->OperatorType()); + case TypeRank::INT64: { + int64_t res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } - default: { - return expr; + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: + case TypeRank::CHAR: { + int32_t res = PerformAdditiveOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } + default: + ES2PANDA_UNREACHABLE(); } +} - auto resNode = util::NodeAllocator::Alloc(context_->allocator, result); - resNode->SetParent(expr->Parent()); - resNode->SetRange(expr->Range()); - return resNode; +static bool IsShiftExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || opType == lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT || + opType == lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT; } -template -IntegerType ConstantExpressionLowering::PerformBitwiseArithmetic(IntegerType left, IntegerType right, - lexer::TokenType operationType) +template +static SignedType PerformShiftOperation(SignedType left, SignedType right, lexer::TokenType opType) { - using UnsignedType = std::make_unsigned_t; + using UnsignedType = std::make_unsigned_t; - UnsignedType result = 0; - UnsignedType unsignedLeftValue = left; - UnsignedType unsignedRightValue = right; + SignedType result = 0; + auto uLeft = bit_cast(left); + auto uRight = bit_cast(right); auto mask = std::numeric_limits::digits - 1U; - auto shift = unsignedRightValue & mask; + UnsignedType shift = uRight & mask; - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { - result = unsignedLeftValue & unsignedRightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { - result = unsignedLeftValue | unsignedRightValue; - break; - } - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - result = unsignedLeftValue ^ unsignedRightValue; - break; - } + switch (opType) { case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: { static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); - result = unsignedLeftValue << shift; - break; + return bit_cast(uLeft << shift); } case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: { - static_assert(sizeof(IntegerType) == 4 || sizeof(IntegerType) == 8); - result = static_cast(unsignedLeftValue) >> shift; // NOLINT(hicpp-signed-bitwise) - break; + static_assert(sizeof(SignedType) == 4 || sizeof(SignedType) == 8); + return bit_cast(left >> shift); // NOLINT(hicpp-signed-bitwise) } case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: { static_assert(sizeof(UnsignedType) == 4 || sizeof(UnsignedType) == 8); - result = unsignedLeftValue >> shift; - break; + return bit_cast(uLeft >> shift); } - default: { + default: ES2PANDA_UNREACHABLE(); - } } - return result; } -template -lexer::Number ConstantExpressionLowering::HandleBitwiseOperator(TargetType leftNum, TargetType rightNum, - lexer::TokenType operationType, TypeRank targetRank) +static ir::AstNode *HandleShiftExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + + if (!IsConvertibleToNumericType(left) || !IsConvertibleToNumericType(right)) { + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return CreateErrorIdentifier(expr, context->allocator); + } + + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); + + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); switch (targetRank) { - case TypeRank::DOUBLE: { - return lexer::Number(PerformBitwiseArithmetic(leftNum, rightNum, operationType)); - } - case TypeRank::FLOAT: { - return lexer::Number(PerformBitwiseArithmetic(leftNum, rightNum, operationType)); - } + case TypeRank::DOUBLE: case TypeRank::INT64: { - return lexer::Number(PerformBitwiseArithmetic(leftNum, rightNum, operationType)); + int64_t res = PerformShiftOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } + case TypeRank::FLOAT: case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: case TypeRank::CHAR: { - return lexer::Number(PerformBitwiseArithmetic(leftNum, rightNum, operationType)); + int32_t res = PerformShiftOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } - default: { + default: ES2PANDA_UNREACHABLE(); - } } } -template -TargetType ConstantExpressionLowering::HandleArithmeticOperation(TargetType leftNum, TargetType rightNum, - ir::BinaryExpression *expr) +static bool IsBitwiseLogicalExpression(const ir::BinaryExpression *expr) { - auto isForbiddenZeroDivision = [&rightNum]() { return std::is_integral::value && rightNum == 0; }; - auto operationType = expr->OperatorType(); - switch (operationType) { - case lexer::TokenType::PUNCTUATOR_PLUS: { - return leftNum + rightNum; + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_BITWISE_XOR || opType == lexer::TokenType::PUNCTUATOR_BITWISE_AND || + opType == lexer::TokenType::PUNCTUATOR_BITWISE_OR; +} + +template +static SignedType PerformBitwiseLogicalOperation(SignedType left, SignedType right, lexer::TokenType opType) +{ + using UnsignedType = std::make_unsigned_t; + + auto uLeft = bit_cast(left); + auto uRight = bit_cast(right); + + switch (opType) { + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { + return uLeft & uRight; } - case lexer::TokenType::PUNCTUATOR_MINUS: { - return leftNum - rightNum; + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { + return uLeft | uRight; } - case lexer::TokenType::PUNCTUATOR_DIVIDE: { - if (isForbiddenZeroDivision()) { - LogError(diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); - return rightNum; - } - return leftNum / rightNum; + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { + return uLeft ^ uRight; } - case lexer::TokenType::PUNCTUATOR_MULTIPLY: { - return leftNum * rightNum; + default: + ES2PANDA_UNREACHABLE(); + } +} + +static ir::AstNode *HandleNumericBitwiseLogicalExpression(const ir::BinaryExpression *expr, + public_lib::Context *context) +{ + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); + + TypeRank targetRank = std::max(GetTypeRank(left), GetTypeRank(right)); + switch (targetRank) { + case TypeRank::DOUBLE: + case TypeRank::INT64: { + int64_t res = PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } - case lexer::TokenType::PUNCTUATOR_MOD: { - if (isForbiddenZeroDivision()) { - LogError(diagnostic::DIVISION_BY_ZERO, {}, expr->Start()); - return rightNum; - } - if constexpr (std::is_integral_v) { - return leftNum % rightNum; - } else { - return std::fmod(leftNum, rightNum); - } + case TypeRank::FLOAT: + case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: + case TypeRank::CHAR: { + int32_t res = PerformBitwiseLogicalOperation(CastValTo(left), CastValTo(right), opType); + return CreateNumberLiteral(res, parent, loc, allocator); } default: ES2PANDA_UNREACHABLE(); } } -template -ir::AstNode *ConstantExpressionLowering::FoldBinaryNumericConstantHelper(ir::BinaryExpression *expr, - TypeRank targetRank) +static ir::AstNode *HandleBitwiseLogicalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { - auto const lhs = expr->Left()->AsLiteral(); - auto const rhs = expr->Right()->AsLiteral(); - lexer::Number resNum {}; - auto lhsNumber = GetOperand(lhs); - auto rhsNumber = GetOperand(rhs); - switch (expr->OperatorType()) { - case lexer::TokenType::PUNCTUATOR_DIVIDE: - case lexer::TokenType::PUNCTUATOR_MOD: - case lexer::TokenType::PUNCTUATOR_PLUS: - case lexer::TokenType::PUNCTUATOR_MINUS: - case lexer::TokenType::PUNCTUATOR_MULTIPLY: { - auto num = HandleArithmeticOperation(lhsNumber, rhsNumber, expr); - resNum = lexer::Number(num); + auto left = expr->Left()->AsLiteral(); + auto right = expr->Right()->AsLiteral(); + auto opType = expr->OperatorType(); + + if (IsConvertibleToNumericType(left) && IsConvertibleToNumericType(right)) { + return HandleNumericBitwiseLogicalExpression(expr, context); + } + + if (!left->IsBooleanLiteral() && !right->IsBooleanLiteral()) { + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION, {}, expr->Start()); + return CreateErrorIdentifier(expr, context->allocator); + } + + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); + bool res = false; + + auto leftVal = left->AsBooleanLiteral()->Value(); + auto rightVal = right->AsBooleanLiteral()->Value(); + switch (opType) { + case lexer::TokenType::PUNCTUATOR_BITWISE_AND: { + res = ((static_cast(leftVal) & static_cast(rightVal)) != 0); break; } - case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: - case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: - case lexer::TokenType::PUNCTUATOR_BITWISE_OR: - case lexer::TokenType::PUNCTUATOR_BITWISE_AND: - case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { - resNum = HandleBitwiseOperator(lhsNumber, rhsNumber, expr->OperatorType(), targetRank); + case lexer::TokenType::PUNCTUATOR_BITWISE_OR: { + res = ((static_cast(leftVal) | static_cast(rightVal)) != 0); break; } - default: { - // Operation might not support. - return expr; + case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: { + res = leftVal ^ rightVal; + break; } + default: + ES2PANDA_UNREACHABLE(); } + return CreateBooleanLiteral(res, parent, loc, allocator); +} - ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(context_->allocator, resNum); - resNode->SetParent(expr->Parent()); - resNode->SetRange(expr->Range()); - return resNode; +static bool IsConditionalExpression(const ir::BinaryExpression *expr) +{ + auto opType = expr->OperatorType(); + return opType == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || opType == lexer::TokenType::PUNCTUATOR_LOGICAL_OR; } -ir::AstNode *ConstantExpressionLowering::FoldBinaryNumericConstant(ir::BinaryExpression *expr) +static ir::AstNode *HandleConditionalExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { - auto left = expr->Left()->AsLiteral(); - auto right = expr->Right()->AsLiteral(); - if (!IsSupportedLiteralForNumeric(left) && !IsSupportedLiteralForNumeric(right)) { - return expr; - } + auto left = const_cast(expr)->Left()->AsLiteral(); + auto right = const_cast(expr)->Right()->AsLiteral(); - TypeRank leftRank = GetTypeRank(left); - TypeRank rightRank = GetTypeRank(right); - TypeRank targetRank = std::max(leftRank, rightRank); - switch (targetRank) { - case TypeRank::DOUBLE: { - return FoldBinaryNumericConstantHelper(expr, targetRank); - } - case TypeRank::FLOAT: { - return FoldBinaryNumericConstantHelper(expr, targetRank); - } - case TypeRank::INT64: { - return FoldBinaryNumericConstantHelper(expr, targetRank); + auto allocator = context->allocator; + auto parent = const_cast(expr)->Parent(); + auto loc = expr->Range(); + + bool lhs = TestLiteral(left); + bool rhs = TestLiteral(right); + + auto opType = expr->OperatorType(); + switch (opType) { + case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { + return CreateBooleanLiteral(lhs && rhs, parent, loc, allocator); } - case TypeRank::INT32: - case TypeRank::CHAR: { - return FoldBinaryNumericConstantHelper(expr, targetRank); + case lexer::TokenType::PUNCTUATOR_LOGICAL_OR: { + return CreateBooleanLiteral(lhs || rhs, parent, loc, allocator); } default: { ES2PANDA_UNREACHABLE(); } } + ES2PANDA_UNREACHABLE(); } -ir::AstNode *ConstantExpressionLowering::FoldBinaryStringConstant(ir::BinaryExpression *const expr) +static ir::AstNode *FoldBinaryExpression(const ir::BinaryExpression *expr, public_lib::Context *context) { - if (expr->OperatorType() != lexer::TokenType::PUNCTUATOR_PLUS) { - LogError(diagnostic::UNSUPPORTED_OPERATOR_FOR_STRING, {}, expr->Left()->Start()); - return expr; + if (IsMultiplicativeExpression(expr)) { + return HandleMultiplicativeExpression(expr, context); } - - auto const lhs = expr->Left()->AsLiteral(); - auto const rhs = expr->Right()->AsLiteral(); - auto const resStr = util::UString(lhs->ToString() + rhs->ToString(), context_->allocator).View(); - auto resNode = util::NodeAllocator::Alloc(context_->allocator, resStr); - resNode->SetParent(expr->Parent()); - resNode->SetRange(expr->Range()); - return resNode; -} - -ir::AstNode *ConstantExpressionLowering::FoldBinaryConstant(ir::BinaryExpression *const expr) -{ - auto const lhs = expr->Left()->AsLiteral(); - auto const rhs = expr->Right()->AsLiteral(); - - auto isBooleanConstant = CheckIsBooleanConstantForBinary(lhs, rhs, expr->OperatorType()); - if (isBooleanConstant) { - return FoldBinaryBooleanConstant(expr); + if (IsAdditiveExpression(expr)) { + return HandleAdditiveExpression(expr, context); } - if (lhs->IsStringLiteral() || rhs->IsStringLiteral()) { - return FoldBinaryStringConstant(expr); + if (IsShiftExpression(expr)) { + return HandleShiftExpression(expr, context); } - return FoldBinaryNumericConstant(expr); + if (IsRelationalExpression(expr)) { + return HandleRelationalExpression(expr, context); + } + if (IsBitwiseLogicalExpression(expr)) { + return HandleBitwiseLogicalExpression(expr, context); + } + if (IsConditionalExpression(expr)) { + return HandleConditionalExpression(expr, context); + } + ES2PANDA_UNREACHABLE(); } template -lexer::Number ConstantExpressionLowering::HandleBitwiseNegate(InputType value, TypeRank rank) +static lexer::Number HandleBitwiseNegate(InputType value, TypeRank rank) { switch (rank) { case TypeRank::DOUBLE: @@ -575,6 +1003,8 @@ lexer::Number ConstantExpressionLowering::HandleBitwiseNegate(InputType value, T } case TypeRank::FLOAT: case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: case TypeRank::CHAR: { return lexer::Number(static_cast(~static_cast(value))); } @@ -585,10 +1015,10 @@ lexer::Number ConstantExpressionLowering::HandleBitwiseNegate(InputType value, T } template -ir::AstNode *ConstantExpressionLowering::FoldUnaryNumericConstantHelper(ir::UnaryExpression *unary, ir::Literal *node, - TypeRank rank) +static ir::AstNode *FoldUnaryNumericConstantHelper(const ir::UnaryExpression *unary, const ir::Literal *node, + TypeRank rank, ArenaAllocator *allocator) { - auto value = GetOperand(node); + auto value = CastValTo(node); lexer::Number resNum {}; switch (unary->OperatorType()) { @@ -609,30 +1039,32 @@ ir::AstNode *ConstantExpressionLowering::FoldUnaryNumericConstantHelper(ir::Unar } } - ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(context_->allocator, resNum); - resNode->SetParent(unary->Parent()); + ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(allocator, resNum); + resNode->SetParent(const_cast(unary)->Parent()); resNode->SetRange(unary->Range()); return resNode; } -ir::AstNode *ConstantExpressionLowering::FoldUnaryNumericConstant(ir::UnaryExpression *unary) +static ir::AstNode *FoldUnaryNumericConstant(const ir::UnaryExpression *unary, ArenaAllocator *allocator) { auto literal = unary->Argument()->AsLiteral(); TypeRank rank = GetTypeRank(literal); switch (rank) { case TypeRank::DOUBLE: { - return FoldUnaryNumericConstantHelper(unary, literal, rank); + return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); } case TypeRank::FLOAT: { - return FoldUnaryNumericConstantHelper(unary, literal, rank); + return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); } case TypeRank::INT64: { - return FoldUnaryNumericConstantHelper(unary, literal, rank); + return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); } case TypeRank::INT32: + case TypeRank::INT16: + case TypeRank::INT8: case TypeRank::CHAR: { - return FoldUnaryNumericConstantHelper(unary, literal, rank); + return FoldUnaryNumericConstantHelper(unary, literal, rank, allocator); } default: { ES2PANDA_UNREACHABLE(); @@ -640,256 +1072,245 @@ ir::AstNode *ConstantExpressionLowering::FoldUnaryNumericConstant(ir::UnaryExpre } } -ir::AstNode *ConstantExpressionLowering::FoldUnaryBooleanConstant(ir::UnaryExpression *unary) +static ir::AstNode *FoldLogicalUnaryExpression(const ir::UnaryExpression *unary, ArenaAllocator *allocator) { - bool result {}; - auto *unaryLiteral = unary->Argument()->AsLiteral(); - - if (unary->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { - // 15.10.1 Extended Conditional Expression - if (unaryLiteral->IsUndefinedLiteral() || unaryLiteral->IsNullLiteral()) { - result = true; - } else { - bool value = GetOperand(unaryLiteral); - result = !value; - } - } else { - ES2PANDA_UNREACHABLE(); - } - - auto resNode = util::NodeAllocator::Alloc(context_->allocator, result); - resNode->SetParent(unary->Parent()); + auto resNode = + util::NodeAllocator::Alloc(allocator, !TestLiteral(unary->Argument()->AsLiteral())); + resNode->SetParent(const_cast(unary)->Parent()); resNode->SetRange(unary->Range()); return resNode; } -ir::AstNode *ConstantExpressionLowering::FoldUnaryConstant(ir::UnaryExpression *const unary) +static ir::AstNode *FoldUnaryExpression(const ir::UnaryExpression *unary, public_lib::Context *context) { - auto unaryLiteral = unary->Argument()->AsLiteral(); + if (unary->OperatorType() == lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK) { + return FoldLogicalUnaryExpression(unary, context->allocator); + } - auto isBooleanConstant = CheckIsBooleanConstantForUnary(unaryLiteral, unary->OperatorType()); - if (isBooleanConstant) { - return FoldUnaryBooleanConstant(unary); + auto lit = unary->Argument()->AsLiteral(); + if (lit->IsNumberLiteral() || lit->IsCharLiteral() || lit->IsBooleanLiteral()) { + return FoldUnaryNumericConstant(unary, context->allocator); } - return FoldUnaryNumericConstant(unary); + LogError(context, diagnostic::WRONG_OPERAND_TYPE_FOR_UNARY_EXPRESSION, {}, unary->Start()); + return CreateErrorIdentifier(unary, context->allocator); } -ir::AstNode *ConstantExpressionLowering::TryFoldTSAsExpressionForString(ir::TSAsExpression *expr) +static ir::AstNode *FoldTemplateLiteral(ir::TemplateLiteral *expr, ArenaAllocator *allocator) { - if (expr->Expr()->IsStringLiteral() && expr->TypeAnnotation()->IsETSTypeReference() && - IsStringTypeReference(expr->TypeAnnotation()->AsETSTypeReference())) { - auto res = expr->Expr()->AsStringLiteral(); - res->SetParent(expr->Parent()); - res->SetRange(expr->Range()); - return res; - } - return expr; -} + auto litToString = [allocator](const ir::Literal *lit) { + if (lit->IsNumberLiteral()) { + return util::UString(lit->AsNumberLiteral()->ToString(), allocator).View(); + } + if (lit->IsCharLiteral()) { + return util::UString(lit->AsCharLiteral()->ToString(), allocator).View(); + } + if (lit->IsBooleanLiteral()) { + return util::UString(lit->AsBooleanLiteral()->ToString(), allocator).View(); + } + if (lit->IsStringLiteral()) { + return lit->AsStringLiteral()->Str(); + } + ES2PANDA_UNREACHABLE(); + }; -ir::AstNode *ConstantExpressionLowering::FoldTSAsExpressionToChar(ir::TSAsExpression *expr) -{ - auto *sourceLiteral = expr->Expr()->AsLiteral(); - auto resChar = GetOperand(sourceLiteral); - ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(context_->allocator, resChar); - resNode->SetParent(expr->Parent()); - resNode->SetRange(expr->Range()); - return resNode; -} + util::UString result(allocator); + auto quasis = expr->Quasis(); + auto expressions = expr->Expressions(); -ir::AstNode *ConstantExpressionLowering::FoldTSAsExpressionToBoolean(ir::TSAsExpression *expr) -{ - auto *sourceLiteral = expr->Expr()->AsLiteral(); - auto resBool = GetOperand(sourceLiteral); - ir::TypedAstNode *resNode = util::NodeAllocator::Alloc(context_->allocator, resBool); - resNode->SetParent(expr->Parent()); - resNode->SetRange(expr->Range()); - return resNode; -} + if (!quasis[0]->Raw().Empty()) { + result.Append(quasis[0]->Cooked()); + } -ir::AstNode *ConstantExpressionLowering::FoldTSAsExpression(ir::TSAsExpression *const expr) -{ - if (expr->TypeAnnotation()->IsETSPrimitiveType()) { - auto *sourceLiteral = expr->Expr()->AsLiteral(); - lexer::Number resNum; - switch (expr->TypeAnnotation()->AsETSPrimitiveType()->GetPrimitiveType()) { - case ir::PrimitiveType::CHAR: { - return FoldTSAsExpressionToChar(expr); - } - case ir::PrimitiveType::BOOLEAN: { - return FoldTSAsExpressionToBoolean(expr); - } - case ir::PrimitiveType::BYTE: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - case ir::PrimitiveType::SHORT: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - case ir::PrimitiveType::INT: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - case ir::PrimitiveType::LONG: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - case ir::PrimitiveType::FLOAT: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - case ir::PrimitiveType::DOUBLE: { - resNum = lexer::Number(GetOperand(sourceLiteral)); - break; - } - default: { - return expr; - } + auto const num = expressions.size(); + std::size_t i = 0U; + while (i < num) { + result.Append(litToString(expressions[i]->AsLiteral())); + if (!quasis[++i]->Raw().Empty()) { + result.Append(quasis[i]->Cooked()); } - ir::TypedAstNode *result = util::NodeAllocator::Alloc(context_->allocator, resNum); - result->SetParent(expr->Parent()); - result->SetRange(expr->Range()); - return result; } - return TryFoldTSAsExpressionForString(expr); + + auto *strLit = util::NodeAllocator::Alloc(allocator, result.View()); + strLit->SetParent(expr->Parent()); + strLit->SetRange(expr->Range()); + return strLit; } -ir::AstNode *ConstantExpressionLowering::FoldMultilineString(ir::TemplateLiteral *expr) +static varbinder::Variable *ResolveIdentifier(const ir::Identifier *ident) { - auto *result = util::NodeAllocator::Alloc(context_->allocator, expr->GetMultilineString()); - result->SetParent(expr->Parent()); - result->SetRange(expr->Range()); - return result; + if (ident->Variable() != nullptr) { + return ident->Variable(); + } + + varbinder::ResolveBindingOptions option = + varbinder::ResolveBindingOptions::ALL_DECLARATION | varbinder::ResolveBindingOptions::ALL_VARIABLES; + + varbinder::Scope *scope = NearestScope(ident); + auto *resolved = scope->Find(ident->Name(), option).variable; + return resolved; } -static bool IsEnumMemberInit(ir::AstNode *node) +static varbinder::Variable *ResolveMemberExpressionProperty(ir::MemberExpression *me) { - auto parent = node->Parent(); - if (node->IsMemberExpression()) { - return node->AsMemberExpression()->Object()->IsIdentifier(); + varbinder::Variable *var = nullptr; + auto meObject = me->Object(); + if (meObject->IsMemberExpression()) { + var = ResolveMemberExpressionProperty(meObject->AsMemberExpression()); + } else if (meObject->IsIdentifier()) { + var = ResolveIdentifier(meObject->AsIdentifier()); } - if (node->IsIdentifier()) { - if (parent->IsTSEnumMember()) { - return parent->AsTSEnumMember()->Init() == node; - } - return !parent->IsMemberExpression() && !parent->IsTSEnumDeclaration() && !parent->IsETSTypeReferencePart(); + if (var == nullptr) { + return nullptr; + } + + auto decl = var->Declaration(); + varbinder::LocalScope *scope = nullptr; + if (decl->IsClassDecl()) { + // NOTE(gogabr) : for some reason, ETSGLOBAL points to class declaration instead of definition. + auto *declNode = decl->AsClassDecl()->Node(); + auto *classDef = declNode->IsClassDefinition() ? declNode->AsClassDefinition() + : declNode->IsClassDeclaration() ? declNode->AsClassDeclaration()->Definition() + : nullptr; + ES2PANDA_ASSERT(classDef != nullptr); + + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) + scope = classDef->Scope(); + } else if (decl->IsEnumDecl()) { + scope = decl->AsEnumDecl()->Node()->AsTSEnumDeclaration()->Scope(); + } else { + return nullptr; } - return false; + auto option = + varbinder::ResolveBindingOptions::STATIC_DECLARATION | varbinder::ResolveBindingOptions::STATIC_VARIABLES; + return scope->FindLocal(me->Property()->AsIdentifier()->Name(), option); } -ir::AstNode *ConstantExpressionLowering::UnFoldEnumMemberExpression(ir::AstNode *constantNode) +static bool IsConstantExpression(ir::AstNode *expr) { - ir::NodeTransformer handleUnfoldEnumMember = [this, constantNode](ir::AstNode *const node) { - if (IsEnumMemberInit(node) && constantNode->IsTSEnumDeclaration()) { - return FindAndReplaceEnumMember(node, constantNode); + if (!expr->IsExpression()) { + if (expr->IsETSTypeReference()) { + return false; } + } - return node; - }; - constantNode->TransformChildrenRecursivelyPostorder(handleUnfoldEnumMember, Name()); - return constantNode; -} + if (expr->IsETSPrimitiveType()) { + return true; + } -ir::AstNode *ConstantExpressionLowering::FindNameInEnumMember(ArenaVector *members, - util::StringView targetName) -{ - auto it = std::find_if(members->begin(), members->end(), [&targetName](ir::AstNode *member) { - return member->AsTSEnumMember()->Key()->AsIdentifier()->Name() == targetName; - }); - return (it != members->end()) ? *it : nullptr; -} + if (expr->IsIdentifier()) { + auto var = ResolveIdentifier(expr->AsIdentifier()); + return var != nullptr && var->Declaration()->IsConstDecl(); + } -ir::AstNode *ConstantExpressionLowering::FindAndReplaceEnumMember(ir::AstNode *const expr, ir::AstNode *constantNode) -{ - auto objectName = expr->IsMemberExpression() ? expr->AsMemberExpression()->Object()->AsIdentifier()->Name() - : constantNode->AsTSEnumDeclaration()->Key()->AsIdentifier()->Name(); - auto propertyName = expr->IsMemberExpression() ? expr->AsMemberExpression()->Property()->AsIdentifier()->Name() - : expr->AsIdentifier()->Name(); - for (auto curScope = constantNode->Scope(); curScope != nullptr; curScope = curScope->Parent()) { - auto *foundDecl = curScope->FindDecl(objectName); - if (foundDecl == nullptr || !foundDecl->Node()->IsTSEnumDeclaration()) { - continue; + if (expr->IsMemberExpression()) { + auto me = expr->AsMemberExpression(); + if (me->Kind() != ir::MemberExpressionKind::PROPERTY_ACCESS) { + return false; } - auto members = foundDecl->Node()->AsTSEnumDeclaration()->Members(); - auto member = FindNameInEnumMember(&members, propertyName); - if (member != nullptr) { - auto *transformedInit = member->AsTSEnumMember()->Init(); - if (transformedInit == nullptr) { - return expr; - } + auto var = ResolveMemberExpressionProperty(me); + return var != nullptr && var->Declaration()->IsReadonlyDecl(); + } - auto clonedInit = transformedInit->Clone(context_->allocator, expr->Parent()); - clonedInit->SetRange(expr->Range()); - return UnFoldEnumMemberExpression(clonedInit); - } + if (IsSupportedLiteral(expr->AsExpression())) { + return true; } - return expr; + + auto isNotConstantExpression = [](ir::AstNode *node) { return !IsConstantExpression(node); }; + + return (expr->IsBinaryExpression() || expr->IsUnaryExpression() || expr->IsTSAsExpression() || + expr->IsConditionalExpression() || expr->IsTemplateLiteral()) && + !expr->IsAnyChild(isNotConstantExpression); } -varbinder::Variable *ConstantExpressionLowering::FindIdentifier(ir::Identifier *ident) +static bool IsInTSEnumMemberInit(const ir::AstNode *n) { - auto localCtx = varbinder::LexicalScope::Enter(varbinder_, NearestScope(ident)); - auto option = varbinder::ResolveBindingOptions::ALL_VARIABLES; - auto localScope = localCtx.GetScope(); - ES2PANDA_ASSERT(localScope != nullptr); - auto *resolved = localScope->FindInFunctionScope(ident->Name(), option).variable; - if (resolved == nullptr) { - resolved = localScope->FindInGlobal(ident->Name(), option).variable; + auto enumMember = util::Helpers::FindAncestorGivenByType(n, ir::AstNodeType::TS_ENUM_MEMBER); + if (enumMember == nullptr) { + return false; } - return resolved; + + auto init = enumMember->AsTSEnumMember()->Init(); + return (init == n) || (init->FindChild([n](auto *child) { return child == n; }) != nullptr); } -ir::AstNode *ConstantExpressionLowering::UnfoldConstIdentifier(ir::AstNode *node, ir::AstNode *originNode) +ir::AstNode *ConstantExpressionLowering::UnfoldResolvedReference(ir::AstNode *resolved, ir::AstNode *node) { ir::AstNode *resNode = nullptr; - if (node->IsClassProperty()) { - auto prop = node->AsClassElement(); - resNode = prop->Value()->Clone(context_->allocator, originNode->Parent()); - resNode->SetRange(originNode->Range()); + if (resolved->IsClassProperty()) { + auto propVal = resolved->AsClassElement()->Value(); + if (propVal != nullptr && IsConstantExpression(propVal)) { + resNode = propVal->Clone(context_->allocator, node->Parent()); + resNode->SetRange(node->Range()); + } + } else if (resolved->Parent()->IsVariableDeclarator()) { + auto init = resolved->Parent()->AsVariableDeclarator()->Init(); + if (init != nullptr && IsConstantExpression(init)) { + resNode = init->Clone(context_->allocator, node->Parent()); + resNode->SetRange(node->Range()); + } + } else if (resolved->IsTSEnumMember() && IsInTSEnumMemberInit(node)) { + auto init = resolved->AsTSEnumMember()->Init(); + if (init != nullptr && IsConstantExpression(init)) { + resNode = init->Clone(context_->allocator, node->Parent()); + resNode->SetRange(node->Range()); + } } - if (node->Parent()->IsVariableDeclarator()) { - resNode = node->Parent()->AsVariableDeclarator()->Init()->Clone(context_->allocator, originNode->Parent()); - resNode->SetRange(originNode->Range()); + + if (resNode != nullptr) { + return MaybeUnfold(resNode); } - if (resNode == nullptr) { + + // failed to unfold + return node; +} + +ir::AstNode *ConstantExpressionLowering::MaybeUnfoldIdentifier(ir::Identifier *node) +{ + if (!node->IsReference(varbinder_->Extension())) { return node; } - if (!resNode->IsIdentifier()) { - return UnfoldConstIdentifiers(resNode); + + auto *resolved = ResolveIdentifier(node); + if (resolved == nullptr || !(resolved->Declaration()->IsConstDecl() || resolved->Declaration()->IsReadonlyDecl())) { + return node; } - auto *ident = resNode->AsIdentifier(); - auto *resolved = FindIdentifier(ident); - if (resolved == nullptr) { - return resNode; + return UnfoldResolvedReference(resolved->Declaration()->Node(), node); +} + +ir::AstNode *ConstantExpressionLowering::MaybeUnfoldMemberExpression(ir::MemberExpression *node) +{ + if (node->Kind() != ir::MemberExpressionKind::PROPERTY_ACCESS) { + return node; } - if (!resolved->Declaration()->IsConstDecl()) { - return resNode; + + auto resolved = ResolveMemberExpressionProperty(node); + if (resolved == nullptr || !resolved->Declaration()->IsReadonlyDecl()) { + return node; } - return UnfoldConstIdentifier(resolved->Declaration()->Node(), resNode); + return UnfoldResolvedReference(resolved->Declaration()->Node(), node); } -ir::AstNode *ConstantExpressionLowering::UnfoldConstIdentifiers(ir::AstNode *constantNode) +ir::AstNode *ConstantExpressionLowering::MaybeUnfold(ir::AstNode *node) { - ir::NodeTransformer handleUnfoldIdentifiers = [this](ir::AstNode *const node) { - if (node->IsIdentifier()) { - auto *ident = node->AsIdentifier(); - auto *resolved = FindIdentifier(ident); - if (resolved == nullptr) { - return node; - } - if (!resolved->Declaration()->IsConstDecl()) { - return node; - } - return UnfoldConstIdentifier(resolved->Declaration()->Node(), node); + ir::NodeTransformer handleMaybeUnfold = [this](ir::AstNode *const n) { + if (n->IsIdentifier() && (!n->Parent()->IsMemberExpression() || n->Parent()->AsMemberExpression()->Kind() == + ir::MemberExpressionKind::ELEMENT_ACCESS)) { + return MaybeUnfoldIdentifier(n->AsIdentifier()); } - return node; + + if (n->IsMemberExpression()) { + return MaybeUnfoldMemberExpression(n->AsMemberExpression()); + } + + return n; }; - constantNode->TransformChildrenRecursivelyPostorder(handleUnfoldIdentifiers, Name()); - return constantNode; + + node->TransformChildrenRecursivelyPostorder(handleMaybeUnfold, Name()); + return handleMaybeUnfold(node); } static bool IsPotentialConstant(const ir::AstNodeType type) @@ -899,48 +1320,42 @@ static bool IsPotentialConstant(const ir::AstNodeType type) type == ir::AstNodeType::CONDITIONAL_EXPRESSION || type == ir::AstNodeType::IDENTIFIER; } -ir::AstNode *ConstantExpressionLowering::FoldConstant(ir::AstNode *constantNode) +ir::AstNode *ConstantExpressionLowering::Fold(ir::AstNode *constantNode) { ir::NodeTransformer handleFoldConstant = [this](ir::AstNode *const node) { if (node->IsTemplateLiteral()) { auto tmpLiteral = node->AsTemplateLiteral(); - if (tmpLiteral->Expressions().empty()) { - return FoldMultilineString(tmpLiteral); - } - LogError(diagnostic::STRING_INTERPOLATION_NOT_CONSTANT, {}, node->Start()); - } - if (node->IsTSAsExpression()) { - auto tsAsExpr = node->AsTSAsExpression(); - if (IsSupportedLiteral(tsAsExpr->Expr())) { - return FoldTSAsExpression(tsAsExpr); + auto exprs = tmpLiteral->Expressions(); + auto notSupportedLit = std::find_if(exprs.begin(), exprs.end(), + [](ir::Expression *maybeLit) { return !IsSupportedLiteral(maybeLit); }); + // Cannot fold TemplateLiteral containing unsupported literal + if (notSupportedLit != exprs.end()) { + return node; } - LogError(diagnostic::ONLY_CONSTANT_EXPRESSION, {}, node->Start()); + return FoldTemplateLiteral(tmpLiteral, context_->allocator); } if (node->IsUnaryExpression()) { auto unaryOp = node->AsUnaryExpression(); if (IsSupportedLiteral(unaryOp->Argument())) { - return FoldUnaryConstant(unaryOp); + return FoldUnaryExpression(unaryOp, context_); } - LogError(diagnostic::ONLY_CONSTANT_EXPRESSION, {}, node->Start()); } if (node->IsBinaryExpression()) { auto binop = node->AsBinaryExpression(); if (IsSupportedLiteral(binop->Left()) && IsSupportedLiteral(binop->Right())) { - return FoldBinaryConstant(binop); + return FoldBinaryExpression(binop, context_); } - LogError(diagnostic::ONLY_CONSTANT_EXPRESSION, {}, node->Start()); } if (node->IsConditionalExpression()) { auto condExp = node->AsConditionalExpression(); if (IsSupportedLiteral(condExp->Test())) { return FoldTernaryConstant(condExp); } - LogError(diagnostic::ONLY_CONSTANT_EXPRESSION, {}, node->Start()); } return node; }; constantNode->TransformChildrenRecursivelyPostorder(handleFoldConstant, Name()); - return constantNode; + return TryToCorrectNumberOrCharLiteral(handleFoldConstant(constantNode), context_); } // Note: memberExpression can be constant when it is enum property access, this check will be enabled after Issue23082. @@ -956,10 +1371,10 @@ void ConstantExpressionLowering::IsInitByConstant(ir::AstNode *node) } if (!IsPotentialConstant(initTobeChecked->Type())) { - LogError(diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); + LogError(context_, diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); return; } - assignExpr->SetRight(FoldConstant(UnfoldConstIdentifiers(initTobeChecked))->AsExpression()); + assignExpr->SetRight(Fold(MaybeUnfold(initTobeChecked))->AsExpression()); } if (node->IsClassProperty()) { @@ -974,10 +1389,10 @@ void ConstantExpressionLowering::IsInitByConstant(ir::AstNode *node) } if (!IsPotentialConstant(initTobeChecked->Type())) { - LogError(diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); + LogError(context_, diagnostic::INVALID_INIT_IN_PACKAGE, {}, initTobeChecked->Start()); return; } - classProp->SetValue(FoldConstant(UnfoldConstIdentifiers(initTobeChecked))->AsExpression()); + classProp->SetValue(Fold(MaybeUnfold(initTobeChecked))->AsExpression()); } } @@ -1016,20 +1431,14 @@ bool ConstantExpressionLowering::PerformForModule(public_lib::Context *ctx, pars context_ = ctx; program_ = program; varbinder_ = ctx->parserProgram->VarBinder()->AsETSBinder(); - program->Ast()->TransformChildrenRecursively( - [this](checker::AstNodePtr const node) -> checker::AstNodePtr { - if (node->IsAnnotationDeclaration() || node->IsAnnotationUsage()) { - return FoldConstant(UnfoldConstIdentifiers(node)); - } - if (node->IsTSEnumDeclaration()) { - return FoldConstant(UnFoldEnumMemberExpression(UnfoldConstIdentifiers(node))); - } + program->Ast()->TransformChildrenRecursively( + [this](ir::AstNode *const node) -> checker::AstNodePtr { // Note: Package need to check whether its immediate initializer is const expression. if (this->program_->IsPackage() && node->IsClassDefinition() && node->AsClassDefinition()->IsGlobal()) { TryFoldInitializerOfPackage(node->AsClassDefinition()); } - return node; + return Fold(MaybeUnfold(node)); }, Name()); diff --git a/ets2panda/compiler/lowering/ets/constantExpressionLowering.h b/ets2panda/compiler/lowering/ets/constantExpressionLowering.h index 7806efd3bd..0bf1aead0f 100644 --- a/ets2panda/compiler/lowering/ets/constantExpressionLowering.h +++ b/ets2panda/compiler/lowering/ets/constantExpressionLowering.h @@ -22,7 +22,9 @@ namespace ark::es2panda::compiler { enum class TypeRank { // Keep this order + INT8, CHAR, + INT16, INT32, INT64, FLOAT, @@ -39,77 +41,14 @@ public: bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; private: - void LogError(const diagnostic::DiagnosticKind &diagnostic, const util::DiagnosticMessageParams &diagnosticParams, - const lexer::SourcePosition &pos) const; + ir::AstNode *MaybeUnfold(ir::AstNode *node); + ir::AstNode *MaybeUnfoldIdentifier(ir::Identifier *node); + ir::AstNode *MaybeUnfoldMemberExpression(ir::MemberExpression *node); + ir::AstNode *UnfoldResolvedReference(ir::AstNode *resolved, ir::AstNode *node); + ir::AstNode *Fold(ir::AstNode *constantNode); ir::AstNode *FoldTernaryConstant(ir::ConditionalExpression *cond); - template - bool PerformRelationOperator(InputType left, InputType right, lexer::TokenType opType); - - bool HandleRelationOperator(ir::Literal *left, ir::Literal *right, lexer::TokenType opType); - - bool HandleBitwiseLogicalOperator(ir::Literal *left, ir::Literal *right, lexer::TokenType opType); - - ir::AstNode *HandleLogicalOperator(ir::BinaryExpression *expr, lexer::TokenType opType); - - ir::AstNode *FoldBinaryBooleanConstant(ir::BinaryExpression *expr); - - template - IntegerType PerformBitwiseArithmetic(IntegerType left, IntegerType right, lexer::TokenType operationType); - - template - lexer::Number HandleBitwiseOperator(TargetType leftNum, TargetType rightNum, lexer::TokenType operationType, - TypeRank targetRank); - - template - TargetType HandleArithmeticOperation(TargetType leftNum, TargetType rightNum, ir::BinaryExpression *expr); - - template - ir::AstNode *FoldBinaryNumericConstantHelper(ir::BinaryExpression *expr, TypeRank targetRank); - - ir::AstNode *FoldBinaryNumericConstant(ir::BinaryExpression *expr); - - ir::AstNode *FoldBinaryStringConstant(ir::BinaryExpression *expr); - - ir::AstNode *FoldBinaryConstant(ir::BinaryExpression *expr); - - template - lexer::Number HandleBitwiseNegate(InputType value, TypeRank rank); - - template - ir::AstNode *FoldUnaryNumericConstantHelper(ir::UnaryExpression *unary, ir::Literal *node, TypeRank rank); - - ir::AstNode *FoldUnaryNumericConstant(ir::UnaryExpression *unary); - - ir::AstNode *FoldUnaryBooleanConstant(ir::UnaryExpression *unary); - - ir::AstNode *FoldUnaryConstant(ir::UnaryExpression *unary); - - ir::AstNode *TryFoldTSAsExpressionForString(ir::TSAsExpression *expr); - - ir::AstNode *FoldTSAsExpressionToChar(ir::TSAsExpression *expr); - - ir::AstNode *FoldTSAsExpressionToBoolean(ir::TSAsExpression *expr); - - ir::AstNode *FoldTSAsExpression(ir::TSAsExpression *expr); - - ir::AstNode *FoldMultilineString(ir::TemplateLiteral *expr); - - ir::AstNode *FoldConstant(ir::AstNode *constantNode); - - varbinder::Variable *FindIdentifier(ir::Identifier *ident); - - ir::AstNode *UnfoldConstIdentifier(ir::AstNode *node, ir::AstNode *originNode); - - ir::AstNode *UnFoldEnumMemberExpression(ir::AstNode *constantNode); - - ir::AstNode *FindNameInEnumMember(ArenaVector *members, util::StringView targetName); - - ir::AstNode *FindAndReplaceEnumMember(ir::AstNode *expr, ir::AstNode *constantNode); - - ir::AstNode *UnfoldConstIdentifiers(ir::AstNode *constantNode); - void IsInitByConstant(ir::AstNode *node); void TryFoldInitializerOfPackage(ir::ClassDefinition *globalClass); diff --git a/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp b/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp index 3f5c3219af..0009d6ef8f 100644 --- a/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp +++ b/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp @@ -36,7 +36,6 @@ static ir::AstNode *ConvertMemberExpressionToAsExpression(ir::CallExpression *ca allocator, me->Object()->Clone(allocator, nullptr)->AsExpression(), checker->AllocNode(toType, allocator), false); res->SetParent(call->Parent()); - res->SetBoxingUnboxingFlags(call->GetBoxingUnboxingFlags()); { auto scope = varbinder::LexicalScope::Enter(checker->VarBinder(), NearestScope(me)); diff --git a/ets2panda/compiler/lowering/ets/enumLowering.cpp b/ets2panda/compiler/lowering/ets/enumLowering.cpp index 8a503952b4..ffe2201556 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumLowering.cpp @@ -160,6 +160,7 @@ template void EnumLoweringPhase::CreateEnumItemFields(const ir::TSEnumDeclaration *const enumDecl, ir::ClassDefinition *const enumClass, EnumType enumType) { + static_assert(ORDINAL_TYPE == ir::PrimitiveType::INT); int32_t ordinal = 0; auto createEnumItemField = [this, enumClass, enumType, &ordinal](ir::TSEnumMember *const member) { auto *const enumMemberIdent = @@ -322,7 +323,7 @@ void EnumLoweringPhase::CreateCCtorForEnumClass(ir::ClassDefinition *const enumC ir::ClassProperty *EnumLoweringPhase::CreateOrdinalField(ir::ClassDefinition *const enumClass) { auto *const fieldIdent = Allocator()->New(ORDINAL_NAME, Allocator()); - auto *const intTypeAnnotation = Allocator()->New(ir::PrimitiveType::INT, Allocator()); + auto *const intTypeAnnotation = Allocator()->New(ORDINAL_TYPE, Allocator()); auto *field = AllocNode(fieldIdent, nullptr, intTypeAnnotation, ir::ModifierFlags::PRIVATE | ir::ModifierFlags::READONLY, Allocator(), false); @@ -337,7 +338,7 @@ ir::ScriptFunction *EnumLoweringPhase::CreateFunctionForCtorOfEnumClass(ir::Clas { ArenaVector params(Allocator()->Adapter()); - auto *const intTypeAnnotation = AllocNode(ir::PrimitiveType::INT, Allocator()); + auto *const intTypeAnnotation = AllocNode(ORDINAL_TYPE, Allocator()); auto *const inputOrdinalParam = MakeFunctionParam(context_, PARAM_ORDINAL, intTypeAnnotation); params.push_back(inputOrdinalParam); @@ -358,8 +359,8 @@ ir::ScriptFunction *EnumLoweringPhase::CreateFunctionForCtorOfEnumClass(ir::Clas ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr), scriptFlags, // CC-OFF(G.FMT.02) project code style ir::ModifierFlags::CONSTRUCTOR | - ir::ModifierFlags::PRIVATE, // CC-OFF(G.FMT.02) project code style - Language(Language::Id::ETS)}); // CC-OFF(G.FMT.02) project code style + ir::ModifierFlags::PUBLIC, // CC-OFF(G.FMT.02) project code style + Language(Language::Id::ETS)}); // CC-OFF(G.FMT.02) project code style func->SetIdent(id); @@ -385,11 +386,13 @@ ir::ScriptFunction *EnumLoweringPhase::CreateFunctionForCtorOfEnumClass(ir::Clas ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); auto *rightHandSide = AllocNode(PARAM_ORDINAL, Allocator()); rightHandSide->SetVariable(inputOrdinalParam->Ident()->Variable()); - auto *initializer = - AllocNode(leftHandSide, rightHandSide, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - auto initStatement = AllocNode(initializer); - initStatement->SetParent(body); - body->AddStatement(initStatement); + if (!enumClass->IsDeclare()) { + auto *initializer = + AllocNode(leftHandSide, rightHandSide, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + auto initStatement = AllocNode(initializer); + initStatement->SetParent(body); + body->AddStatement(initStatement); + } return func; } @@ -400,6 +403,7 @@ void EnumLoweringPhase::CreateCtorForEnumClass(ir::ClassDefinition *const enumCl auto *funcExpr = AllocNode(func); auto *const identClone = func->Id()->Clone(Allocator(), nullptr); + // NOTE(gogabr): constructor should be private, but interop_js complains, see test_js_use_ets_enum.ts auto *const methodDef = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, identClone, funcExpr, ir::ModifierFlags::PUBLIC, Allocator(), false); methodDef->SetParent(enumClass); @@ -599,8 +603,7 @@ ir::Identifier *EnumLoweringPhase::CreateEnumValuesArray(const ir::TSEnumDeclara lexer::Number(member->AsTSEnumMember() ->Init() ->AsNumberLiteral() - ->Number() - .GetValue())); + ->Number())); return enumValueLiteral; }); // clang-format on @@ -789,7 +792,8 @@ namespace { ir::VariableDeclaration *CreateForLoopInitVariableDeclaration(public_lib::Context *ctx, ir::Identifier *const loopIdentifier) { - auto *const init = ctx->AllocNode("0"); + static_assert(EnumLoweringPhase::ORDINAL_TYPE == ir::PrimitiveType::INT); + auto *const init = ctx->AllocNode(lexer::Number((int32_t)0)); auto *const decl = ctx->AllocNode(ir::VariableDeclaratorFlag::LET, loopIdentifier, init); loopIdentifier->SetParent(decl); ArenaVector decls(ctx->Allocator()->Adapter()); @@ -959,7 +963,7 @@ void EnumLoweringPhase::CreateEnumGetOrdinalMethod(const ir::TSEnumDeclaration * body.push_back(returnStmt); ArenaVector params(Allocator()->Adapter()); - auto *const intTypeAnnotation = Allocator()->New(ir::PrimitiveType::INT, Allocator()); + auto *const intTypeAnnotation = Allocator()->New(ORDINAL_TYPE, Allocator()); auto *const function = MakeFunction({std::move(params), std::move(body), intTypeAnnotation, enumDecl, ir::ModifierFlags::PUBLIC}); diff --git a/ets2panda/compiler/lowering/ets/enumLowering.h b/ets2panda/compiler/lowering/ets/enumLowering.h index ef9863fdc0..3f9f804534 100644 --- a/ets2panda/compiler/lowering/ets/enumLowering.h +++ b/ets2panda/compiler/lowering/ets/enumLowering.h @@ -24,17 +24,18 @@ namespace ark::es2panda::compiler { class EnumLoweringPhase : public PhaseForDeclarations { public: - static constexpr std::string_view const STRING_REFERENCE_TYPE {"String"}; - static constexpr std::string_view const IDENTIFIER_I {"i"}; - static constexpr std::string_view const PARAM_NAME {"name"}; - static constexpr std::string_view const PARAM_VALUE {"value"}; - static constexpr std::string_view const PARAM_ORDINAL {"ordinal"}; - static constexpr std::string_view const STRING_VALUES_ARRAY_NAME {"#StringValuesArray"}; - static constexpr std::string_view const ITEMS_ARRAY_NAME {"#ItemsArray"}; - static constexpr std::string_view const NAMES_ARRAY_NAME {"#NamesArray"}; - static constexpr std::string_view const VALUES_ARRAY_NAME {"#ValuesArray"}; - static constexpr std::string_view const ORDINAL_NAME {"#ordinal"}; - static constexpr std::string_view const BASE_CLASS_NAME {"BaseEnum"}; + static constexpr std::string_view STRING_REFERENCE_TYPE {"String"}; + static constexpr std::string_view IDENTIFIER_I {"i"}; + static constexpr std::string_view PARAM_NAME {"name"}; + static constexpr std::string_view PARAM_VALUE {"value"}; + static constexpr std::string_view PARAM_ORDINAL {"ordinal"}; + static constexpr std::string_view ITEMS_ARRAY_NAME {"#ItemsArray"}; + static constexpr std::string_view STRING_VALUES_ARRAY_NAME {checker::ETSEnumType::STRING_VALUES_ARRAY_NAME}; + static constexpr std::string_view NAMES_ARRAY_NAME {checker::ETSEnumType::NAMES_ARRAY_NAME}; + static constexpr std::string_view VALUES_ARRAY_NAME {checker::ETSEnumType::VALUES_ARRAY_NAME}; + static constexpr std::string_view BASE_CLASS_NAME {"BaseEnum"}; + static constexpr std::string_view ORDINAL_NAME {"#ordinal"}; + static constexpr auto ORDINAL_TYPE {ir::PrimitiveType::INT}; enum EnumType { INT = 0, LONG = 1, STRING = 2 }; diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index 1eb861ff8a..abd8401d58 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp @@ -91,11 +91,12 @@ static EnumCastType NeedHandleEnumCasting(ir::TSAsExpression *node) { auto type = node->TsType(); EnumCastType castType = EnumCastType::NONE; + if (type == nullptr) { + return castType; + } if (type->IsETSStringType()) { castType = EnumCastType::CAST_TO_STRING; - } else if (type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC) || - (type->IsETSObjectType() && - type->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_NUMERIC))) { + } else if (type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC) || type->IsBuiltinNumeric()) { castType = EnumCastType::CAST_TO_INT; } else if (type->IsETSEnumType()) { castType = type->IsETSIntEnumType() ? EnumCastType::CAST_TO_INT_ENUM : EnumCastType::CAST_TO_STRING_ENUM; @@ -323,15 +324,34 @@ ir::AstNode *EnumPostCheckLoweringPhase::GenerateEnumCasting(ir::TSAsExpression return node; } +static auto *InlineValueOf(ir::MemberExpression *enumMemberRef, ArenaAllocator *allocator) +{ + auto key = enumMemberRef->Property()->AsIdentifier()->Name().Utf8(); + auto enumType = enumMemberRef->TsType()->AsETSEnumType(); + auto ord = enumType->GetOrdinalFromMemberName(key); + auto origLiteral = enumType->GetValueLiteralFromOrdinal(ord); + auto literal = origLiteral->Clone(allocator, enumMemberRef->Parent())->AsExpression(); + literal->SetTsType(origLiteral->TsType()); + return literal; +} + ir::AstNode *EnumPostCheckLoweringPhase::GenerateValueOfCall(ir::AstNode *const node) { - node->Parent()->AddAstNodeFlags(ir::AstNodeFlags::RECHECK); + node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); if (!node->IsExpression()) { - node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); return node; } + // NOTE: temporary workaround + // Need to find out why ETSParameterExpression has GENERATE_VALUE_OF flag + // Need to be refactored after complete rework on overload resolution + if (node->IsETSParameterExpression()) { + return node; + } + node->Parent()->AddAstNodeFlags(ir::AstNodeFlags::RECHECK); + if (node->AsExpression()->TsType()->AsETSEnumType()->NodeIsEnumLiteral(node->AsExpression())) { + return InlineValueOf(node->AsMemberExpression(), context_->Allocator()); + } auto *callExpr = CreateCallInstanceEnumExpression(context_, node, checker::ETSEnumType::VALUE_OF_METHOD_NAME); - node->RemoveAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF); return callExpr; } @@ -380,11 +400,9 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars if (node->IsExpression()) { node->AsExpression()->SetTsType(nullptr); // force recheck } - if (checker_->Context().ContainingClass() == nullptr) { - auto *parentClass = util::Helpers::FindAncestorGivenByType(node, ir::AstNodeType::CLASS_DEFINITION); - checker_->Context().SetContainingClass( - parentClass->AsClassDefinition()->TsType()->AsETSObjectType()); - } + auto *parentClass = util::Helpers::FindAncestorGivenByType(node, ir::AstNodeType::CLASS_DEFINITION); + checker::SavedCheckerContext savedContext(checker_, checker_->Context().Status(), + parentClass->AsClassDefinition()->TsType()->AsETSObjectType()); node->RemoveAstNodeFlags(ir::AstNodeFlags::RECHECK); node->Check(checker_); if (node->IsExpression() && node->AsExpression()->TsType() != nullptr && @@ -402,7 +420,8 @@ bool EnumPostCheckLoweringPhase::PerformForModule(public_lib::Context *ctx, pars } return GenerateEnumCasting(node->AsTSAsExpression(), castFlag); } - if (node->IsSwitchStatement() && node->AsSwitchStatement()->Discriminant()->TsType()->IsETSEnumType()) { + if (node->IsSwitchStatement() && (node->AsSwitchStatement()->Discriminant()->TsType() != nullptr) && + node->AsSwitchStatement()->Discriminant()->TsType()->IsETSEnumType()) { return GenerateGetOrdinalCallForSwitch(node->AsSwitchStatement()); } return node; diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.h b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.h index 35fbb2c8b9..1ce716fe85 100644 --- a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.h +++ b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.h @@ -29,7 +29,7 @@ enum class EnumCastType { CAST_TO_STRING_ENUM, }; -class EnumPostCheckLoweringPhase : public PhaseForBodies { +class EnumPostCheckLoweringPhase : public PhaseForDeclarations { public: EnumPostCheckLoweringPhase() noexcept = default; std::string_view Name() const override diff --git a/ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp b/ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp new file mode 100644 index 0000000000..0e97ab93fb --- /dev/null +++ b/ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "enumPropertiesInAnnotationsLowering.h" +#include "checker/types/ets/etsArrayType.h" +#include "checker/types/ets/etsEnumType.h" +#include "ir/base/classProperty.h" + +namespace ark::es2panda::compiler { + +static void TransformEnumArrayRecursively(checker::ETSArrayType *propType) +{ + if (propType->ElementType()->IsETSEnumType()) { + auto newElemType = propType->ElementType()->AsETSEnumType()->Underlying(); + propType->SetElementType(newElemType); + return; + } + if (propType->ElementType()->IsETSArrayType()) { + TransformEnumArrayRecursively(propType->ElementType()->AsETSArrayType()); + } +} + +static void SetValueType(ir::Expression *value, checker::Type *newType) +{ + if (value->Variable() != nullptr) { + value->Variable()->SetTsType(newType); + } + value->SetTsType(newType); + if (newType->IsETSArrayType() && newType->AsETSArrayType()->ElementType()->IsETSArrayType()) { + for (auto elem : value->AsArrayExpression()->Elements()) { + SetValueType(elem, newType->AsETSArrayType()->ElementType()); + } + } +} + +static void TransformEnumToUnderlying(ir::ClassProperty *prop, checker::Checker *checker) +{ + checker::Type *propType = prop->TsType(); + checker::Type *newPropType {}; + if (propType->IsETSEnumType()) { + prop->SetTypeAnnotation(nullptr); + newPropType = propType->AsETSEnumType()->Underlying(); + } else if (propType->IsETSArrayType()) { + prop->SetTypeAnnotation(nullptr); + newPropType = propType->Clone(checker); + TransformEnumArrayRecursively(newPropType->AsETSArrayType()); + } else { + return; + } + prop->SetTsType(newPropType); + prop->Key()->SetTsType(newPropType); + prop->Key()->Variable()->SetTsType(newPropType); + if (prop->Value() != nullptr) { + SetValueType(prop->Value(), newPropType); + } +} + +bool EnumPropertiesInAnnotationsLoweringPhase::PerformForModule([[maybe_unused]] public_lib::Context *ctx, + parser::Program *program) +{ + auto *checker = ctx->GetChecker(); + program->Ast()->IterateRecursively([checker](auto *node) { + if (node->IsAnnotationDeclaration() || node->IsAnnotationUsage()) { + node->Iterate([checker](auto *child) { + child->IsClassProperty() ? TransformEnumToUnderlying(child->AsClassProperty(), checker) : void(); + }); + } + }); + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/checker/ets/narrowingWideningConverter.h b/ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.h similarity index 43% rename from ets2panda/checker/ets/narrowingWideningConverter.h rename to ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.h index 8aa21fea56..c5869ede39 100644 --- a/ets2panda/checker/ets/narrowingWideningConverter.h +++ b/ets2panda/compiler/lowering/ets/enumPropertiesInAnnotationsLowering.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,25 +13,23 @@ * limitations under the License. */ -#ifndef ES2PANDA_COMPILER_CHECKER_ETS_NARROWING_WIDENING_CONVERTER_H -#define ES2PANDA_COMPILER_CHECKER_ETS_NARROWING_WIDENING_CONVERTER_H +#ifndef ES2PANDA_COMPILER_ENUM_PROPERTIES_IN_ANNOTATIONS_LOWERING_H +#define ES2PANDA_COMPILER_ENUM_PROPERTIES_IN_ANNOTATIONS_LOWERING_H -#include "checker/ets/narrowingConverter.h" -#include "checker/ets/wideningConverter.h" +#include "compiler/lowering/phase.h" -namespace ark::es2panda::checker { -class NarrowingWideningConverter : public NarrowingConverter { +namespace ark::es2panda::compiler { + +class EnumPropertiesInAnnotationsLoweringPhase : public PhaseForDeclarations { public: - explicit NarrowingWideningConverter(ETSChecker *checker, TypeRelation *relation, Type *target, Type *source) - : NarrowingConverter(checker, relation, target, source) + EnumPropertiesInAnnotationsLoweringPhase() noexcept = default; + std::string_view Name() const override { - if (Relation()->IsTrue() || Relation()->IsError()) { - return; - } - - WideningConverter(checker, relation, target, source); + return "EnumPropertiesInAnnotationsLoweringPhase"; } + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; }; -} // namespace ark::es2panda::checker -#endif +} // namespace ark::es2panda::compiler + +#endif // ES2PANDA_COMPILER_ENUM_PROPERTIES_IN_ANNOTATIONS_LOWERING_H diff --git a/ets2panda/compiler/lowering/ets/expandBrackets.cpp b/ets2panda/compiler/lowering/ets/expandBrackets.cpp index 1dccd5d05d..2f865dca1e 100644 --- a/ets2panda/compiler/lowering/ets/expandBrackets.cpp +++ b/ets2panda/compiler/lowering/ets/expandBrackets.cpp @@ -33,8 +33,8 @@ static constexpr char const FORMAT_NEW_ARRAY_EXPRESSION[] = " throw new TypeError(\"Fractional part of index expression should be zero.\");" "};" "(@@E5);"; -static constexpr char const CAST_NEW_DIMENSION_EXPRESSION[] = "@@I1 as int"; -static constexpr char const CAST_OLD_DIMENSION_EXPRESSION[] = "(@@E1) as int"; +static constexpr char const CAST_NEW_DIMENSION_EXPRESSION[] = "(@@I1).toInt()"; +static constexpr char const CAST_OLD_DIMENSION_EXPRESSION[] = "(@@E1).toInt()"; // NOLINTEND(modernize-avoid-c-arrays) ir::Expression *ExpandBracketsPhase::ProcessNewArrayInstanceExpression( @@ -46,10 +46,9 @@ ir::Expression *ExpandBracketsPhase::ProcessNewArrayInstanceExpression( ES2PANDA_ASSERT(checker != nullptr); auto *dimension = newInstanceExpression->Dimension(); auto *dimType = dimension->TsType(); - if (auto *unboxed = checker->MaybeUnboxInRelation(dimType); unboxed != nullptr) { - dimType = unboxed; - } - if (dimType == nullptr || !dimType->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) { + ES2PANDA_ASSERT(dimType->IsETSObjectType()); + + if (!dimType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_FLOATING_POINT)) { return newInstanceExpression; } @@ -98,10 +97,8 @@ ir::Expression *ExpandBracketsPhase::ProcessNewMultiDimArrayInstanceExpression( for (std::size_t i = 0U; i < newInstanceExpression->Dimensions().size(); ++i) { auto *dimension = newInstanceExpression->Dimensions()[i]; auto *dimType = dimension->TsType(); - if (auto *unboxed = checker->MaybeUnboxInRelation(dimType); unboxed != nullptr) { - dimType = unboxed; - } - if (dimType == nullptr || !dimType->HasTypeFlag(checker::TypeFlag::ETS_FLOATING_POINT)) { + ES2PANDA_ASSERT(dimType->IsETSObjectType()); + if (!dimType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::BUILTIN_FLOATING_POINT)) { continue; } diff --git a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp index bb3fcbff99..0ec34677b1 100644 --- a/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/extensionAccessorLowering.cpp @@ -71,7 +71,6 @@ static void TryHandleExtensionAccessor(checker::ETSChecker *checker, ir::MemberE checker, expr, ArenaVector(checker->ProgramAllocator()->Adapter())); auto *rightExpr = assignExpr->AsAssignmentExpression()->Right(); - rightExpr->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); if (IsMemberExprExtensionAccessor(rightExpr)) { SwitchType(rightExpr->AsMemberExpression()); checker::Type *tsType = rightExpr->AsMemberExpression()->TsType(); @@ -96,7 +95,6 @@ static void TryHandleExtensionAccessor(checker::ETSChecker *checker, ir::MemberE checker, expr, ArenaVector(checker->ProgramAllocator()->Adapter())); callExpr->SetParent(oldParent); CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, callExpr); - callExpr->AddBoxingUnboxingFlags(expr->GetBoxingUnboxingFlags()); } static ir::AstNode *CheckAndReturnNode(checker::ETSChecker *checker, ir::AstNode *node) diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp index 1aa0c072ea..d147a29ab9 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp @@ -62,7 +62,7 @@ std::string GenericBridgesPhase::CreateMethodDefinitionString(ir::ClassDefinitio } typeNodes.emplace_back(context_->AllocNode( - const_cast(derivedFunction->Signature()->ReturnType()), context_->Allocator())); + const_cast(baseSignature->ReturnType()), context_->Allocator())); str1 += "): @@T" + std::to_string(typeNodes.size()) + ' '; typeNodes.emplace_back(context_->AllocNode( @@ -76,7 +76,7 @@ std::string GenericBridgesPhase::CreateMethodDefinitionString(ir::ClassDefinitio void GenericBridgesPhase::AddGenericBridge(ir::ClassDefinition const *const classDefinition, ir::MethodDefinition *const methodDefinition, checker::Signature const *baseSignature, - ir::ScriptFunction const *const derivedFunction) const + ir::ScriptFunction *const derivedFunction) const { auto *parser = context_->parser->AsETSParser(); std::vector typeNodes {}; @@ -114,13 +114,17 @@ void GenericBridgesPhase::AddGenericBridge(ir::ClassDefinition const *const clas auto *methodType = methodDefinition->Id()->Variable()->TsType()->AsETSFunctionType(); checker->BuildFunctionSignature(bridgeMethod->Function()); + bridgeMethod->Function()->Signature()->AddSignatureFlag(checker::SignatureFlags::BRIDGE); + auto *const bridgeMethodType = checker->BuildMethodType(bridgeMethod->Function()); - checker->CheckIdenticalOverloads(methodType, bridgeMethodType, bridgeMethod); + checker->CheckIdenticalOverloads(methodType, bridgeMethodType, bridgeMethod, false, + checker::TypeRelationFlag::NONE); bridgeMethod->SetTsType(bridgeMethodType); methodType->AddCallSignature(bridgeMethod->Function()->Signature()); methodDefinition->Id()->Variable()->SetTsType(methodType); - bridgeMethod->Check(checker); + bridgeMethod->Function()->Body()->Check( + checker); // avoid checking overriding, this may fail if only return type is different. } void GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const classDefinition, @@ -154,11 +158,13 @@ void GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const } baseSignature2 = baseSignature2->Substitute(relation, substitutions.derivedConstraints); - ir::ScriptFunction const *derivedFunction = nullptr; + ir::ScriptFunction *derivedFunction = nullptr; checker::ETSFunctionType const *methodType = derivedMethod->Id()->Variable()->TsType()->AsETSFunctionType(); for (auto *signature : methodType->CallSignatures()) { signature = signature->Substitute(relation, substitutions.derivedConstraints); - if (overrides(baseSignature1, signature) || checker->HasSameAssemblySignature(baseSignature1, signature)) { + // A special case is when the overriding function's return type is going to be unboxed. + if ((overrides(baseSignature1, signature) || checker->HasSameAssemblySignature(baseSignature1, signature)) && + baseSignature1->ReturnType()->IsETSUnboxableObject() == signature->ReturnType()->IsETSUnboxableObject()) { // NOTE: we already have custom-implemented method with the required bridge signature. // Probably sometimes we will issue warning notification here... return; diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.h b/ets2panda/compiler/lowering/ets/genericBridgesLowering.h index 508c4160ff..4fafc089c6 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.h +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.h @@ -54,7 +54,7 @@ private: ir::MethodDefinition *derivedMethod, Substitutions const &substitutions) const; void AddGenericBridge(ir::ClassDefinition const *classDefinition, ir::MethodDefinition *methodDefinition, - checker::Signature const *baseSignature, ir::ScriptFunction const *derivedFunction) const; + checker::Signature const *baseSignature, ir::ScriptFunction *derivedFunction) const; std::string CreateMethodDefinitionString(ir::ClassDefinition const *classDefinition, checker::Signature const *baseSignature, diff --git a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp index c997421bf4..18ea80f943 100644 --- a/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp +++ b/ets2panda/compiler/lowering/ets/interfacePropertyDeclarations.cpp @@ -60,6 +60,7 @@ void InterfacePropertyDeclarationsPhase::TransformOptionalFieldTypeAnnotation(pu types.push_back(ctx->AllocNode(ctx->Allocator())); auto *const unionType = ctx->AllocNode(std::move(types), ctx->Allocator()); field->SetTypeAnnotation(unionType); + unionType->SetParent(field); } field->ClearModifier(ir::ModifierFlags::OPTIONAL); diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index d3ad50c52a..f57901e6b1 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -513,8 +513,12 @@ static ArenaVector CreateRestArgumentsArrayReall auto *checker = ctx->GetChecker()->AsETSChecker(); auto *restParameterType = lciInfo->lambdaSignature->RestVar()->TsType(); + auto *restParameterSubstituteType = restParameterType->Substitute(checker->Relation(), lciInfo->substitution); auto *elementType = checker->GetElementTypeOfArray(restParameterSubstituteType); + auto *elementTypeWithDefault = checker->TypeHasDefaultValue(elementType) + ? elementType + : checker->CreateETSUnionType({elementType, checker->GlobalETSUndefinedType()}); std::stringstream statements; auto restParameterIndex = GenName(allocator).View(); auto spreadArrIterator = GenName(allocator).View(); @@ -524,7 +528,7 @@ static ArenaVector CreateRestArgumentsArrayReall statements << "let @@I1: int = 0;"; if (elementType->IsETSReferenceType()) { // NOTE(vpukhov): this is a clear null-safety violation that should be rewitten with a runtime intrinsic - statements << "let @@I2: FixedArray<@@T3 | undefined> = new (@@T4 | undefined)[@@I5.length];"; + statements << "let @@I2: FixedArray<@@T3> = new (@@T4)[@@I5.length];"; } else { statements << "let @@I2: FixedArray<@@T3> = new (@@T4)[@@I5.length];"; } @@ -532,15 +536,15 @@ static ArenaVector CreateRestArgumentsArrayReall // CC-OFFNXT(G.FMT.06) false positive << "for (let @@I9: @@T10 of @@I11){" // CC-OFFNXT(G.FMT.06) false positive - << " @@I12[@@I13] = @@I14 as @@T15 as @@T16;" - // CC-OFFNXT(G.FMT.06) false positive - << " @@I17 = @@I18 + 1;" + << " @@I12[@@I13] = @@I14 as @@T15;" + // CC-OFFNXT(G.FMT.06, G.FMT.06-CPP) false positive + << " @@I16 = @@I17 + 1;" << "}"; args = parser->CreateFormattedStatement( - statements.str(), restParameterIndex, tmpArray, elementType, elementType, lciInfo->restParameterIdentifier, - lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, checker->GlobalETSAnyType(), - lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, restParameterIndex, spreadArrIterator, - checker->MaybeBoxType(elementType), elementType, restParameterIndex, restParameterIndex); + statements.str(), restParameterIndex, tmpArray, elementTypeWithDefault, elementTypeWithDefault, + lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, tmpArray, elementType, spreadArrIterator, + checker->GlobalETSAnyType(), lciInfo->restParameterIdentifier, lciInfo->restArgumentIdentifier, + restParameterIndex, spreadArrIterator, elementType, restParameterIndex, restParameterIndex); } else { ES2PANDA_ASSERT(restParameterSubstituteType->IsETSResizableArrayType()); auto *typeNode = allocator->New( @@ -613,8 +617,7 @@ static ArenaVector CreateCallArgumentsForLambdaClassInvoke(pub } auto argName = lambdaParam->Name(); auto *type = lambdaParam->TsType()->Substitute(checker->Relation(), lciInfo->substitution); - auto *arg = wrapToObject ? parser->CreateFormattedExpression("@@I1 as @@T2 as @@T3", argName, - checker->MaybeBoxType(type), type) + auto *arg = wrapToObject ? parser->CreateFormattedExpression("@@I1 as @@T2", argName, type) : allocator->New(argName, allocator); callArguments.push_back(arg); } @@ -864,7 +867,7 @@ static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker CreateEmptyLambdaClassDeclaration(ctx, info, newTypeParams, fnInterface, lambdaProviderClass); auto classDefinition = classDeclaration->Definition(); if (info->isFunctionReference) { - classDefinition->SetFunctionalReferenceReferencedMethod(callee->Function()->Scope()->InternalName()); + classDefinition->SetFunctionalReferenceReferencedMethod(callee); classDefinition->SetModifiers(classDefinition->Modifiers() | ir::ClassDefinitionModifiers::FUNCTIONAL_REFERENCE); } @@ -1171,8 +1174,14 @@ static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpressio newCallee->SetTsType(prop->TsType()); newCallee->SetObjectType(ifaceType); + /* Pull out substituted call signature */ + auto *funcIface = + ifaceType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE) ? ifaceType : ifaceType->Interfaces()[0]; + checker::Signature *callSig = funcIface->GetFunctionalInterfaceInvokeType()->CallSignatures()[0]; + ES2PANDA_ASSERT(callSig != nullptr); + call->SetCallee(newCallee); - call->SetSignature(prop->TsType()->AsETSFunctionType()->CallSignatures()[0]); + call->SetSignature(callSig); /* NOTE(gogabr): argument types may have been spoiled by widening/narrowing conversions. Repair them here. @@ -1182,9 +1191,7 @@ static ir::AstNode *InsertInvokeCall(public_lib::Context *ctx, ir::CallExpressio if (arg->IsSpreadElement()) { continue; } - auto boxingFlags = arg->GetBoxingUnboxingFlags(); Recheck(ctx->phaseManager, varBinder, checker, arg); - arg->SetBoxingUnboxingFlags(boxingFlags); } return call; diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp index 1f35c823d6..7aa1057970 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp @@ -36,7 +36,6 @@ ir::Expression *ObjectIndexLowering::ProcessIndexSetAccess(parser::ETSParser *pa // required accessible index method[s] and all the types are properly resolved. auto indexSymbol = Gensym(checker->Allocator()); - assignmentExpression->Right()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); auto *const memberExpression = assignmentExpression->Left()->AsMemberExpression(); ir::Expression *loweringResult = nullptr; ir::AstNode *setter = nullptr; @@ -73,7 +72,6 @@ ir::Expression *ObjectIndexLowering::ProcessIndexSetAccess(parser::ETSParser *pa } loweringResult->SetParent(assignmentExpression->Parent()); loweringResult->SetRange(assignmentExpression->Range()); - loweringResult->SetBoxingUnboxingFlags(assignmentExpression->GetBoxingUnboxingFlags()); setter->AddModifier(ir::ModifierFlags::ARRAY_SETTER); auto scope = varbinder::LexicalScope::Enter(checker->VarBinder(), NearestScope(assignmentExpression->Parent())); @@ -99,7 +97,6 @@ ir::Expression *ObjectIndexLowering::ProcessIndexGetAccess(parser::ETSParser *pa loweringResult->SetRange(memberExpression->Range()); CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, loweringResult); - loweringResult->SetBoxingUnboxingFlags(memberExpression->GetBoxingUnboxingFlags()); return loweringResult; } diff --git a/ets2panda/compiler/lowering/ets/opAssignment.cpp b/ets2panda/compiler/lowering/ets/opAssignment.cpp index 2f6c22e715..d323d0006f 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.cpp +++ b/ets2panda/compiler/lowering/ets/opAssignment.cpp @@ -74,46 +74,14 @@ static lexer::TokenType CombinedOpToOp(const lexer::TokenType combinedOp) ES2PANDA_UNREACHABLE(); } -void AdjustBoxingUnboxingFlags(ir::Expression *loweringResult, const ir::Expression *oldExpr) -{ - ir::Expression *exprToProcess = nullptr; - if (loweringResult->IsAssignmentExpression()) { - exprToProcess = loweringResult->AsAssignmentExpression(); - } else if (loweringResult->IsBlockExpression() && !loweringResult->AsBlockExpression()->Statements().empty()) { - auto *statement = loweringResult->AsBlockExpression()->Statements().back(); - if (statement->IsExpressionStatement()) { - exprToProcess = statement->AsExpressionStatement()->GetExpression(); - } - } else { - ES2PANDA_UNREACHABLE(); - } - - // NOTE: gogabr. make sure that the checker never puts both a boxing and an unboxing flag on the same node. - // Then this function will become unnecessary. - const ir::BoxingUnboxingFlags oldBoxingFlag {oldExpr->GetBoxingUnboxingFlags() & - ir::BoxingUnboxingFlags::BOXING_FLAG}; - const ir::BoxingUnboxingFlags oldUnboxingFlag {oldExpr->GetBoxingUnboxingFlags() & - ir::BoxingUnboxingFlags::UNBOXING_FLAG}; - - if (exprToProcess->TsType()->IsETSPrimitiveType()) { - loweringResult->SetBoxingUnboxingFlags(oldBoxingFlag); - } else if (exprToProcess->TsType()->IsETSObjectType()) { - loweringResult->SetBoxingUnboxingFlags(oldUnboxingFlag); - } -} - -static ir::OpaqueTypeNode *CreateProxyTypeNode(public_lib::Context *ctx, ir::Expression *expr) +static ir::OpaqueTypeNode *CreateProxyTypeNode(checker::ETSChecker *checker, ir::Expression *expr) { auto *lcType = expr->TsType(); - auto *checker = ctx->GetChecker()->AsETSChecker(); if (checker->IsExtensionETSFunctionType(lcType) && expr->IsMemberExpression() && expr->AsMemberExpression()->HasMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR)) { lcType = expr->AsMemberExpression()->ExtensionAccessorType(); } - if (auto *lcTypeAsPrimitive = checker->MaybeUnboxInRelation(lcType); lcTypeAsPrimitive != nullptr) { - lcType = lcTypeAsPrimitive; - } - return ctx->AllocNode(lcType, ctx->Allocator()); + return checker->AllocNode(lcType, checker->Allocator()); } static std::string GenFormatForExpression(ir::Expression *expr, size_t ix1, size_t ix2) @@ -129,15 +97,15 @@ static std::string GenFormatForExpression(ir::Expression *expr, size_t ix1, size if ((kind & ir::MemberExpressionKind::PROPERTY_ACCESS) != 0) { res += ".@@I" + std::to_string(ix2); } else if (kind == ir::MemberExpressionKind::ELEMENT_ACCESS) { - res += "[@@I" + std::to_string(ix2) + "]"; + res += "[@@E" + std::to_string(ix2) + "]"; } } return res; } -static ir::Identifier *GetClone(ArenaAllocator *allocator, ir::Identifier *node) +static ir::Expression *GetClone(ArenaAllocator *allocator, ir::Expression *node) { - return node == nullptr ? nullptr : node->Clone(allocator, nullptr); + return node == nullptr ? nullptr : node->Clone(allocator, nullptr)->AsExpression(); } static std::string GetFormatPlaceholder(const ir::Expression *expr, const size_t counter) @@ -208,15 +176,30 @@ static std::tuple> GenerateStringForA auto result = GenerateNestedMemberAccess(expr, allocator, counter); counter += std::get<1>(result).size(); retStr += " = ( " + std::get<0>(result) + ' ' + std::string {lexer::TokenToString(CombinedOpToOp(opEqual))} + - " (@@E" + std::to_string(counter) + ")) as @@T" + std::to_string(counter + 1); + " (@@E" + std::to_string(counter) + "))"; retVec.insert(retVec.end(), std::get<1>(result).begin(), std::get<1>(result).end()); return {retStr, retVec}; } -static ir::Expression *GenerateLoweredResultForLoweredAssignment( - const lexer::TokenType opEqual, ir::MemberExpression *expr, ArenaAllocator *const allocator, - parser::ETSParser *parser, const std::array additionalAssignmentExpressions) +static std::string GetCastString(checker::ETSChecker *checker, ir::Expression *expr, ArenaVector &vec) { + auto type = expr->TsType(); + if (type->IsETSObjectType() && type->AsETSObjectType()->IsBoxedPrimitive()) { + return ".to" + type->ToString() + "()"; + } + + vec.push_back(CreateProxyTypeNode(checker, expr)); + + return " as @@T" + std::to_string(vec.size()); +} + +static ir::Expression *GenerateLoweredResultForLoweredAssignment(const lexer::TokenType opEqual, + ir::MemberExpression *expr, + checker::ETSChecker *const checker, + parser::ETSParser *parser, + ir::Expression *additionalAssignmentExpression) +{ + auto *allocator = checker->Allocator(); // Generated a formatString for the new lowered assignment expression // The formatString will look like this: "A = (A `operation` B) as T" // Where A is a member access @@ -238,16 +221,16 @@ static ir::Expression *GenerateLoweredResultForLoweredAssignment( expr->SetProperty(dummyIndex->Clone(allocator, expr)); auto [retStr, retVec] = GenerateStringForAssignment(opEqual, expr, allocator, dummyIndexDeclExpression.size() + 1); - retVec.push_back(additionalAssignmentExpressions[0]); - retVec.push_back(additionalAssignmentExpressions[1]); + retVec.push_back(additionalAssignmentExpression); + retStr += GetCastString(checker, expr, retVec); retVec.insert(retVec.begin(), dummyIndexDeclExpression.begin(), dummyIndexDeclExpression.end()); retStr = dummyIndexDeclStr + retStr; return parser->CreateFormattedExpression(retStr, retVec); } auto [retStr, retVec] = GenerateStringForAssignment(opEqual, expr, allocator, 1); - retVec.push_back(additionalAssignmentExpressions[0]); - retVec.push_back(additionalAssignmentExpressions[1]); + retVec.push_back(additionalAssignmentExpression); + retStr += GetCastString(checker, expr, retVec); return parser->CreateFormattedExpression(retStr, retVec); } @@ -255,27 +238,29 @@ static ir::Expression *ConstructOpAssignmentResult(public_lib::Context *ctx, ir: { auto *allocator = ctx->allocator; auto *parser = ctx->parser->AsETSParser(); + auto *checker = ctx->GetChecker()->AsETSChecker(); const auto opEqual = assignment->OperatorType(); ES2PANDA_ASSERT(opEqual != lexer::TokenType::PUNCTUATOR_SUBSTITUTION); auto *const left = assignment->Left(); auto *const right = assignment->Right(); - right->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); - auto *exprType = CreateProxyTypeNode(ctx, left); ir::Expression *retVal = nullptr; // Create temporary variable(s) if left hand of assignment is not defined by simple identifier[s] if (left->IsIdentifier()) { - const std::string formatString = - "@@I1 = (@@I2 " + std::string(lexer::TokenToString(CombinedOpToOp(opEqual))) + " (@@E3)) as @@T4"; - retVal = parser->CreateFormattedExpression(formatString, GetClone(allocator, left->AsIdentifier()), - GetClone(allocator, left->AsIdentifier()), right, exprType); + std::string formatString = + "@@I1 = (@@I2 " + std::string(lexer::TokenToString(CombinedOpToOp(opEqual))) + " (@@E3))"; + ArenaVector retVec(allocator->Adapter()); + retVec.push_back(GetClone(allocator, left->AsIdentifier())); + retVec.push_back(GetClone(allocator, left->AsIdentifier())); + retVec.push_back(right); + formatString += GetCastString(checker, left, retVec); + retVal = parser->CreateFormattedExpression(formatString, retVec); } else if (left->IsMemberExpression()) { // Generate ArkTS code string for new lowered assignment expression: - retVal = GenerateLoweredResultForLoweredAssignment(opEqual, left->AsMemberExpression(), allocator, parser, - {right, exprType}); + retVal = GenerateLoweredResultForLoweredAssignment(opEqual, left->AsMemberExpression(), checker, parser, right); } else { ES2PANDA_UNREACHABLE(); } @@ -314,16 +299,13 @@ ir::AstNode *HandleOpAssignment(public_lib::Context *ctx, ir::AssignmentExpressi checker::ScopeContext sc {checker, scope}; loweringResult->Check(checker); - - AdjustBoxingUnboxingFlags(loweringResult, assignment); - return loweringResult; } struct ArgumentInfo { std::string newAssignmentStatements {}; ir::Identifier *id1 = nullptr; - ir::Identifier *id2 = nullptr; + ir::Expression *id2 = nullptr; ir::Identifier *id3 = nullptr; ir::Expression *object = nullptr; ir::Expression *property = nullptr; @@ -340,12 +322,12 @@ static void ParseArgument(public_lib::Context *ctx, ir::Expression *argument, Ar } if (argument->IsIdentifier()) { - info.id1 = GetClone(allocator, argument->AsIdentifier()); + info.id1 = GetClone(allocator, argument->AsIdentifier())->AsIdentifier(); } else if (argument->IsMemberExpression()) { auto *memberExpression = argument->AsMemberExpression(); if (info.object = memberExpression->Object(); info.object != nullptr && info.object->IsIdentifier()) { - info.id1 = GetClone(allocator, info.object->AsIdentifier()); + info.id1 = GetClone(allocator, info.object->AsIdentifier())->AsIdentifier(); } else if (info.object != nullptr) { info.id1 = Gensym(allocator); info.newAssignmentStatements = "const @@I1 = (@@E2) as @@T3; "; @@ -354,9 +336,13 @@ static void ParseArgument(public_lib::Context *ctx, ir::Expression *argument, Ar if (info.property = memberExpression->Property(); info.property != nullptr && info.property->IsIdentifier()) { info.id2 = GetClone(allocator, info.property->AsIdentifier()); + } else if (info.property != nullptr && info.property->IsLiteral()) { + // Be careful not to disturb tuple element access + info.id2 = GetClone(allocator, info.property); } else if (info.property != nullptr) { info.id2 = Gensym(allocator); - info.newAssignmentStatements += "const @@I4 = (@@E5) as @@T6; "; + info.newAssignmentStatements += "const @@I4 = (@@E5) as @@T6;"; + info.newAssignmentStatements += ";"; info.propType = info.property->TsType(); } } @@ -384,25 +370,27 @@ static ir::Expression *ConstructUpdateResult(public_lib::Context *ctx, ir::Updat // NOLINTBEGIN(readability-magic-numbers) if (upd->IsPrefix()) { - argInfo.newAssignmentStatements += - "const @@I7 = (" + GenFormatForExpression(argument, 8U, 9U) + opSign + " 1" + suffix + ") as @@T10;"; - argInfo.newAssignmentStatements += GenFormatForExpression(argument, 11U, 12U) + " = @@I13; @@I14"; + argInfo.newAssignmentStatements += "const @@I7 = (" + GenFormatForExpression(argument, 8U, 9U) + + (argument->IsTSNonNullExpression() ? "!" : "") + opSign + " 1" + suffix + + ").to" + argument->TsType()->ToString() + "();"; + argInfo.newAssignmentStatements += GenFormatForExpression(argument, 10U, 11U) + " = @@I12; @@I13"; return parser->CreateFormattedExpression( argInfo.newAssignmentStatements, argInfo.id1, argInfo.object, argInfo.objType, argInfo.id2, argInfo.property, argInfo.propType, argInfo.id3, GetClone(allocator, argInfo.id1), - GetClone(allocator, argInfo.id2), argument->TsType(), GetClone(allocator, argInfo.id1), - GetClone(allocator, argInfo.id2), GetClone(allocator, argInfo.id3), GetClone(allocator, argInfo.id3)); + GetClone(allocator, argInfo.id2), GetClone(allocator, argInfo.id1), GetClone(allocator, argInfo.id2), + GetClone(allocator, argInfo.id3), GetClone(allocator, argInfo.id3)); } // upd is postfix - argInfo.newAssignmentStatements += "const @@I7 = " + GenFormatForExpression(argument, 8, 9) + " as @@T10;" + - GenFormatForExpression(argument, 11U, 12U) + " = (@@I13 " + opSign + " 1" + - suffix + ") as @@T14; @@I15;"; + argInfo.newAssignmentStatements += + "const @@I7 = " + GenFormatForExpression(argument, 8, 9) + (argument->IsTSNonNullExpression() ? "!" : "") + + ".to" + argument->TsType()->ToString() + "();" + GenFormatForExpression(argument, 10U, 11U) + " = (@@I12 " + + opSign + " 1" + suffix + ").to" + argument->TsType()->ToString() + "(); @@I13;"; return parser->CreateFormattedExpression( argInfo.newAssignmentStatements, argInfo.id1, argInfo.object, argInfo.objType, argInfo.id2, argInfo.property, argInfo.propType, argInfo.id3, GetClone(allocator, argInfo.id1), GetClone(allocator, argInfo.id2), - argument->TsType(), GetClone(allocator, argInfo.id1), GetClone(allocator, argInfo.id2), - GetClone(allocator, argInfo.id3), argument->TsType(), GetClone(allocator, argInfo.id3)); + GetClone(allocator, argInfo.id1), GetClone(allocator, argInfo.id2), GetClone(allocator, argInfo.id3), + GetClone(allocator, argInfo.id3)); // NOLINTEND(readability-magic-numbers) } @@ -434,9 +422,6 @@ static ir::AstNode *HandleUpdate(public_lib::Context *ctx, ir::UpdateExpression checker->VarBinder()->AsETSBinder()->ResolveReferencesForScopeWithContext(loweringResult, NearestScope(loweringResult)); loweringResult->Check(checker); - - AdjustBoxingUnboxingFlags(loweringResult, upd); - return loweringResult; } diff --git a/ets2panda/compiler/lowering/ets/opAssignment.h b/ets2panda/compiler/lowering/ets/opAssignment.h index 6a45b47b29..adbc88070f 100644 --- a/ets2panda/compiler/lowering/ets/opAssignment.h +++ b/ets2panda/compiler/lowering/ets/opAssignment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -22,9 +22,10 @@ namespace ark::es2panda::compiler { class OpAssignmentLowering : public PhaseForBodies { public: + static constexpr std::string_view const NAME = "OpAssignmentLowering"; std::string_view Name() const override { - return "OpAssignmentLowering"; + return NAME; } bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; diff --git a/ets2panda/compiler/lowering/ets/primitiveConversionPhase.cpp b/ets2panda/compiler/lowering/ets/primitiveConversionPhase.cpp new file mode 100644 index 0000000000..7a27a2001b --- /dev/null +++ b/ets2panda/compiler/lowering/ets/primitiveConversionPhase.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compiler/lowering/util.h" +#include "primitiveConversionPhase.h" + +namespace ark::es2panda::compiler { + +// Transform calls of the form `x.toY()`, where `x: X` and X and Y are (boxed) primitive types, +// into static calls of the form `X.toY(x)`, which will then be represented in the bytecode as single +// instructions. +// The code relies on the fact that there are no other pairs of methods in the boxed primitive classes, +// such that one is virtual and takes no arguments, the other one has the same name, is static and takes +// an object of the containing type as parameter. + +static bool CheckCalleeConversionNeed(ir::Expression *callee) +{ + return !(!callee->IsMemberExpression() || + callee->AsMemberExpression()->Kind() != ir::MemberExpressionKind::PROPERTY_ACCESS || + !callee->AsMemberExpression()->Property()->IsIdentifier()); +} + +static ir::Expression *ConvertCallIfNeeded(public_lib::Context *ctx, ir::CallExpression *call) +{ + if (!call->Arguments().empty()) { + return call; + } + + auto *callee = call->Callee(); + if (!CheckCalleeConversionNeed(callee)) { + return call; + } + + auto *calleeObj = callee->AsMemberExpression()->Object(); + auto *calleePropId = callee->AsMemberExpression()->Property()->AsIdentifier(); + + if (calleePropId->Variable()->HasFlag(varbinder::VariableFlags::STATIC)) { + return call; + } + + auto *calleeObjType = calleeObj->TsType(); + if (!calleeObjType->IsETSObjectType() || !calleeObjType->AsETSObjectType()->IsBoxedPrimitive()) { + return call; + } + + auto *staticMethodVar = calleeObjType->AsETSObjectType()->GetProperty( + calleePropId->Name(), checker::PropertySearchFlags::SEARCH_STATIC_METHOD); + if (staticMethodVar == nullptr) { + return call; + } + + auto *checker = ctx->GetChecker()->AsETSChecker(); + auto *staticSig = staticMethodVar->TsType()->AsETSFunctionType()->CallSignatures()[0]; + if (staticSig->Params().size() != 1 || + !checker->Relation()->IsIdenticalTo(staticSig->Params()[0]->TsType(), calleeObjType) || + !checker->Relation()->IsIdenticalTo(staticSig->ReturnType(), call->TsType())) { + return call; + } + + /* Now that we know that we deal with a conversion call, replace it with a static call, + except that when the call is `x.toX()`, we can just return `x`. + */ + + auto *allocator = ctx->Allocator(); + + if (checker->Relation()->IsIdenticalTo(calleeObjType, call->TsType())) { + calleeObj->SetParent(call->Parent()); + return calleeObj; + } + + auto args = ArenaVector {allocator->Adapter()}; + args.push_back(calleeObj); + + calleePropId->SetVariable(staticMethodVar); + calleePropId->SetTsType(staticMethodVar->TsType()); + auto *newCallee = util::NodeAllocator::ForceSetParent( + allocator, allocator->New(calleeObjType, allocator), calleePropId, + ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + newCallee->SetTsType(staticMethodVar->TsType()); + newCallee->SetObjectType(calleeObjType->AsETSObjectType()); + auto *newCall = + util::NodeAllocator::ForceSetParent(allocator, newCallee, std::move(args), nullptr, false); + newCall->SetParent(call->Parent()); + + CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, newCall); + + return newCall; +} + +bool PrimitiveConversionPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) +{ + program->Ast()->TransformChildrenRecursively( + // clang-format off + [&](ir::AstNode *ast) -> ir::AstNode* { + if (ast->IsCallExpression()) { + return ConvertCallIfNeeded(ctx, ast->AsCallExpression()); + } + return ast; + }, + // clang-format on + "PrimitiveConversion"); + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/primitiveConversionPhase.h b/ets2panda/compiler/lowering/ets/primitiveConversionPhase.h new file mode 100644 index 0000000000..2fdd77510e --- /dev/null +++ b/ets2panda/compiler/lowering/ets/primitiveConversionPhase.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_PRIMITIVE_CONVERSION_PHASE_H +#define ES2PANDA_COMPILER_LOWERING_PRIMITIVE_CONVERSION_PHASE_H + +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::compiler { + +class PrimitiveConversionPhase : public PhaseForBodies { +public: + std::string_view Name() const override + { + return "PrimitiveConversion"; + } + + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; + // bool PostconditionForModule(public_lib::Context *ctx, const parser::Program *program) override; +}; + +} // namespace ark::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/ets/recordLowering.cpp b/ets2panda/compiler/lowering/ets/recordLowering.cpp index 870a9c2aed..ae3026ab95 100644 --- a/ets2panda/compiler/lowering/ets/recordLowering.cpp +++ b/ets2panda/compiler/lowering/ets/recordLowering.cpp @@ -152,6 +152,20 @@ ir::Statement *RecordLowering::CreateStatement(const std::string &src, ir::Expre return nullptr; } +void RecordLowering::CheckKeyType(checker::ETSChecker *checker, checker::Type const *const keyType, + ir::ObjectExpression const *const expr, public_lib::Context *ctx) const noexcept +{ + if (keyType->IsETSObjectType()) { + if (keyType->IsETSStringType() || keyType->IsBuiltinNumeric() || + checker->Relation()->IsIdenticalTo(keyType, checker->GetGlobalTypesHolder()->GlobalNumericBuiltinType()) || + checker->Relation()->IsIdenticalTo(keyType, checker->GetGlobalTypesHolder()->GlobalIntegralBuiltinType()) || + keyType->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::ENUM_OBJECT)) { + return; + } + } + ctx->GetChecker()->AsETSChecker()->LogError(diagnostic::OBJ_LIT_UNKNOWN_PROP, {}, expr->Start()); +} + ir::Expression *RecordLowering::UpdateObjectExpression(ir::ObjectExpression *expr, public_lib::Context *ctx) { auto checker = ctx->GetChecker()->AsETSChecker(); @@ -171,10 +185,23 @@ ir::Expression *RecordLowering::UpdateObjectExpression(ir::ObjectExpression *exp // Access type arguments [[maybe_unused]] size_t constexpr NUM_ARGUMENTS = 2; - auto typeArguments = expr->PreferredType()->AsETSObjectType()->TypeArguments(); + auto const &typeArguments = expr->PreferredType()->AsETSObjectType()->TypeArguments(); ES2PANDA_ASSERT(typeArguments.size() == NUM_ARGUMENTS); + auto const *keyType = typeArguments[0]; + if (keyType->IsETSTypeParameter()) { + keyType = keyType->AsETSTypeParameter()->GetConstraintType(); + } + // check keys correctness + if (keyType->IsETSUnionType()) { + for (auto const *const ct : keyType->AsETSUnionType()->ConstituentTypes()) { + CheckKeyType(checker, ct, expr, ctx); + } + } else { + CheckKeyType(checker, keyType, expr, ctx); + } + KeySetType keySet; CheckDuplicateKey(keySet, expr, ctx); CheckLiteralsCompleteness(keySet, expr, ctx); diff --git a/ets2panda/compiler/lowering/ets/recordLowering.h b/ets2panda/compiler/lowering/ets/recordLowering.h index a422dc6083..ffdf7f795e 100644 --- a/ets2panda/compiler/lowering/ets/recordLowering.h +++ b/ets2panda/compiler/lowering/ets/recordLowering.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023 - 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -39,6 +39,8 @@ private: void CheckLiteralsCompleteness(KeySetType &keySet, ir::ObjectExpression *expr, public_lib::Context *ctx); ir::Statement *CreateStatement(const std::string &src, ir::Expression *ident, ir::Expression *key, ir::Expression *value, public_lib::Context *ctx); + void CheckKeyType(checker::ETSChecker *checker, checker::Type const *keyType, ir::ObjectExpression const *expr, + public_lib::Context *ctx) const noexcept; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp b/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp index 804519f911..2ba3489fe4 100644 --- a/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp +++ b/ets2panda/compiler/lowering/ets/resizableArrayLowering.cpp @@ -22,11 +22,11 @@ namespace ark::es2panda::compiler { using AstNodePtr = ir::AstNode *; -static ir::AstNode *ConvertToResizableArrayType(ir::TSArrayType *node, public_lib::Context *ctx) +static ir::AstNode *ConvertToResizableArrayType(ir::TSArrayType *node, public_lib::Context *ctx, bool insideAnnotdecl) { auto *parser = ctx->parser->AsETSParser(); - ir::TypeNode *typeAnnotation = - parser->CreateFormattedTypeAnnotation("Array<" + node->ElementType()->DumpEtsSrc() + ">"); + ir::TypeNode *typeAnnotation = parser->CreateFormattedTypeAnnotation((insideAnnotdecl ? "FixedArray<" : "Array<") + + node->ElementType()->DumpEtsSrc() + ">"); typeAnnotation->SetAnnotations(node->Annotations()); typeAnnotation->SetParent(node->Parent()); typeAnnotation->SetRange(node->Range()); @@ -37,13 +37,24 @@ static ir::AstNode *ConvertToResizableArrayType(ir::TSArrayType *node, public_li bool ResizableArrayConvert::PerformForModule(public_lib::Context *ctx, parser::Program *program) { - program->Ast()->TransformChildrenRecursivelyPreorder( - [ctx](ir::AstNode *node) -> AstNodePtr { + bool insideAnnotdecl = false; + program->Ast()->TransformChildrenRecursively( + [&insideAnnotdecl, ctx](ir::AstNode *node) -> AstNodePtr { + if (node->IsAnnotationDeclaration()) { + ES2PANDA_ASSERT(!insideAnnotdecl); + insideAnnotdecl = true; + } if (node->IsTSArrayType()) { - return ConvertToResizableArrayType(node->AsTSArrayType(), ctx); + return ConvertToResizableArrayType(node->AsTSArrayType(), ctx, insideAnnotdecl); } return node; }, + [&insideAnnotdecl](ir::AstNode *node) { + if (node->IsAnnotationDeclaration()) { + ES2PANDA_ASSERT(insideAnnotdecl); + insideAnnotdecl = false; + } + }, Name()); return true; diff --git a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp index a34c623cf9..34bfb2525a 100644 --- a/ets2panda/compiler/lowering/ets/restArgsLowering.cpp +++ b/ets2panda/compiler/lowering/ets/restArgsLowering.cpp @@ -108,12 +108,22 @@ static ir::Expression *CreateRestArgsArray(public_lib::Context *context, ArenaVe std::stringstream ss; auto *genSymIdent = Gensym(allocator); + auto *genSymIdent2 = Gensym(allocator); + // Was: + // ss << "let @@I1 : FixedArray<@@T2> = @@E3;"; + // ss << "Array.from<@@T4>(@@I5);"; + // Now: + // NOTE: refactor me! ss << "let @@I1 : FixedArray<@@T2> = @@E3;"; - ss << "Array.from<@@T4>(@@I5);"; + ss << "let @@I4 : Array<@@T5> = new Array<@@T6>(@@I7.length);"; + ss << "for (let i = 0; i < @@I8.length; ++i) { @@I9[i] = @@I10[i]}"; + ss << "@@I11;"; auto *arrayExpr = checker->AllocNode(std::move(copiedArguments), allocator); - auto *loweringResult = - parser->CreateFormattedExpression(ss.str(), genSymIdent, type, arrayExpr, type->Clone(allocator, nullptr), - genSymIdent->Clone(allocator, nullptr)); + auto *loweringResult = parser->CreateFormattedExpression( + ss.str(), genSymIdent, type->Clone(allocator, nullptr), arrayExpr, genSymIdent2, type, + type->Clone(allocator, nullptr), genSymIdent->Clone(allocator, nullptr), genSymIdent->Clone(allocator, nullptr), + genSymIdent2->Clone(allocator, nullptr), genSymIdent->Clone(allocator, nullptr), + genSymIdent2->Clone(allocator, nullptr)); return loweringResult; } @@ -126,7 +136,6 @@ static ir::CallExpression *RebuildCallExpression(public_lib::Context *context, i for (size_t i = 0; i < signature->Params().size(); ++i) { newArgs.push_back(originalCall->Arguments()[i]); - newArgs[i]->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); } newArgs.push_back(restArgsArray); @@ -137,7 +146,6 @@ static ir::CallExpression *RebuildCallExpression(public_lib::Context *context, i restArgsArray->SetParent(newCall); newCall->SetParent(originalCall->Parent()); newCall->AddModifier(originalCall->Modifiers()); - newCall->AddBoxingUnboxingFlags(originalCall->GetBoxingUnboxingFlags()); newCall->SetTypeParams(originalCall->TypeParams()); newCall->AddAstNodeFlags(ir::AstNodeFlags::RESIZABLE_REST); @@ -167,7 +175,6 @@ static ir::ETSNewClassInstanceExpression *RebuildNewClassInstanceExpression( restArgsArray->SetParent(newCall); newCall->SetParent(originalCall->Parent()); newCall->AddModifier(originalCall->Modifiers()); - newCall->AddBoxingUnboxingFlags(originalCall->GetBoxingUnboxingFlags()); auto *scope = NearestScope(newCall->Parent()); auto bscope = varbinder::LexicalScope::Enter(context->GetChecker()->VarBinder()->AsETSBinder(), scope); @@ -223,4 +230,4 @@ bool RestArgsLowering::PerformForModule(public_lib::Context *ctx, parser::Progra Name()); return true; } -} // namespace ark::es2panda::compiler \ No newline at end of file +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/spreadLowering.cpp b/ets2panda/compiler/lowering/ets/spreadLowering.cpp index 8c0c488a32..bf6b4e6c2e 100644 --- a/ets2panda/compiler/lowering/ets/spreadLowering.cpp +++ b/ets2panda/compiler/lowering/ets/spreadLowering.cpp @@ -67,7 +67,7 @@ ir::Identifier *CreateNewArrayLengthStatement(public_lib::Context *ctx, ir::Arra if (spaId->TsType() != nullptr && spaId->TsType()->IsETSTupleType()) { lengthString << "(" << spaId->TsType()->AsETSTupleType()->GetTupleSize() << ") + "; } else { - lengthString << "(@@I" << (argumentCount++) << ".length as int) + "; + lengthString << "(@@I" << (argumentCount++) << ".length.toInt()) + "; nodesWaitingInsert.emplace_back(spaId->Clone(allocator, nullptr)); } } @@ -96,7 +96,8 @@ static ir::Identifier *CreateNewArrayDeclareStatement(public_lib::Context *ctx, // But now cast Expression doesn't support built-in array (cast fatherType[] to sonType[]), so "newArrayName // as arrayType" should be added after cast Expression is implemented completely. // Related issue: #issue20162 - if (checker::ETSChecker::IsReferenceType(arrayElementType)) { + if (checker->IsReferenceType(arrayElementType) && + !(arrayElementType->IsETSObjectType() && arrayElementType->AsETSObjectType()->IsBoxedPrimitive())) { arrayElementType = checker->CreateETSUnionType({arrayElementType, checker->GlobalETSUndefinedType()}); } diff --git a/ets2panda/compiler/lowering/ets/stringComparison.cpp b/ets2panda/compiler/lowering/ets/stringComparison.cpp index d10fdb7b50..056f7b216c 100644 --- a/ets2panda/compiler/lowering/ets/stringComparison.cpp +++ b/ets2panda/compiler/lowering/ets/stringComparison.cpp @@ -81,7 +81,7 @@ void StringComparisonLowering::ProcessBinaryExpression(ir::BinaryExpression *exp checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); ArenaVector callArgs(checker->Allocator()->Adapter()); ir::Expression *accessor = nullptr; - auto *zeroExpr = checker->AllocNode(util::StringView("0")); + auto *zeroExpr = checker->AllocNode(lexer::Number(int32_t(0))); auto *const callee = checker->AllocNode("compareTo", checker->Allocator()); auto *var = checker->GlobalBuiltinETSStringType()->GetProperty(callee->AsIdentifier()->Name(), checker::PropertySearchFlags::SEARCH_METHOD); diff --git a/ets2panda/compiler/lowering/ets/stringConstructorLowering.h b/ets2panda/compiler/lowering/ets/stringConstructorLowering.h index e7f1c07c45..584b9ccb48 100644 --- a/ets2panda/compiler/lowering/ets/stringConstructorLowering.h +++ b/ets2panda/compiler/lowering/ets/stringConstructorLowering.h @@ -1,5 +1,5 @@ -/** - * Copyright (c) 2024 Huawei Device Co., Ltd. +/* + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp index c30b85b05f..80d07a9441 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.cpp @@ -107,11 +107,10 @@ static void InsertInGlobal(ir::ClassDefinition *globalClass, ir::AstNode *node) node->SetParent(globalClass); } -void GlobalClassHandler::SetupInitializerBlock(parser::Program *program, - ArenaVector> &&initializerBlock, +void GlobalClassHandler::SetupInitializerBlock(ArenaVector> &&initializerBlock, ir::ClassDefinition *globalClass) { - if (program->IsDeclarationModule() || initializerBlock.empty()) { + if (globalProgram_->IsDeclarationModule() || initializerBlock.empty()) { return; } @@ -125,25 +124,24 @@ void GlobalClassHandler::SetupInitializerBlock(parser::Program *program, } // Note: cannot use the all same name for every stdlib package. - std::string moduleName = std::string(program->ModuleName()); + std::string moduleName = std::string(globalProgram_->ModuleName()); std::replace(moduleName.begin(), moduleName.end(), '.', '_'); util::UString initializerBlockName = util::UString {std::string(compiler::Signatures::INITIALIZER_BLOCK_INIT) + moduleName, allocator_}; ir::MethodDefinition *initializerBlockInit = - CreateGlobalMethod(initializerBlockName.View().Utf8(), std::move(blockStmts), program); + CreateGlobalMethod(initializerBlockName.View().Utf8(), std::move(blockStmts)); InsertInGlobal(globalClass, initializerBlockInit); AddInitCallToStaticBlock(globalClass, initializerBlockInit); } -void GlobalClassHandler::SetupGlobalMethods(parser::Program *program, ArenaVector &&initStatements, +void GlobalClassHandler::SetupGlobalMethods(ArenaVector &&initStatements, ir::ClassDefinition *globalClass, bool isDeclare) { if (isDeclare) { return; } - ir::MethodDefinition *initMethod = - CreateGlobalMethod(compiler::Signatures::INIT_METHOD, std::move(initStatements), program); + ir::MethodDefinition *initMethod = CreateGlobalMethod(compiler::Signatures::INIT_METHOD, std::move(initStatements)); InsertInGlobal(globalClass, initMethod); if (!initMethod->Function()->Body()->AsBlockStatement()->Statements().empty()) { AddInitCallToStaticBlock(globalClass, initMethod); @@ -176,18 +174,34 @@ void GlobalClassHandler::MergeNamespace(ArenaVector &namespaces } } -ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector &namespaces, - parser::Program *program) +ArenaVector GlobalClassHandler::TransformNamespaces(ArenaVector &namespaces) { ArenaVector classDecls {allocator_->Adapter()}; - MergeNamespace(namespaces, program); + MergeNamespace(namespaces, globalProgram_); for (auto ns : namespaces) { - classDecls.emplace_back(TransformNamespace(ns, program)); + classDecls.emplace_back(TransformNamespace(ns)); } return classDecls; } -ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, parser::Program *program) +void GlobalClassHandler::TransformBrokenNamespace() +{ + globalProgram_->Ast()->TransformChildrenRecursively( + // clang-format off + // CC-OFFNXT(G.FMT.14-CPP) project code style + [this](ir::AstNode *node) -> ir::AstNode* { + if (node->IsETSModule() && node->AsETSModule()->IsNamespace()) { + auto res = TransformNamespace(node->AsETSModule()); + res->SetParent(node->Parent()); + return res; + } + return node; + }, + // clang-format on + "TransformBrokenNamespace"); +} + +ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns) { ir::ClassDeclaration *const globalDecl = CreateTransformedClass(ns); ir::ClassDefinition *const globalClass = globalDecl->Definition(); @@ -200,16 +214,16 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, statement->Iterate([this](ir::AstNode *node) { AddStaticBlockToClass(node); }); } auto stmts = CollectProgramGlobalStatements(body, globalClass, ns); - immediateInitializers.emplace_back(GlobalStmts {program, std::move(stmts.immediateInit)}); + immediateInitializers.emplace_back(GlobalStmts {globalProgram_, std::move(stmts.immediateInit)}); for (auto &initBlock : stmts.initializerBlocks) { - initializerBlock.emplace_back(GlobalStmts {program, std::move(initBlock)}); + initializerBlock.emplace_back(GlobalStmts {globalProgram_, std::move(initBlock)}); } AddStaticBlockToClass(globalClass); const ModuleDependencies md {allocator_->Adapter()}; - auto immediateInitStatements = FormInitMethodStatements(program, &md, std::move(immediateInitializers)); - auto initializerBlockStatements = FormInitStaticBlockMethodStatements(program, &md, std::move(initializerBlock)); - SetupGlobalMethods(program, std::move(immediateInitStatements), globalClass, ns->IsDeclare()); - SetupInitializerBlock(program, std::move(initializerBlockStatements), globalClass); + auto immediateInitStatements = FormInitMethodStatements(&md, std::move(immediateInitializers)); + auto initializerBlockStatements = FormInitStaticBlockMethodStatements(&md, std::move(initializerBlock)); + SetupGlobalMethods(std::move(immediateInitStatements), globalClass, ns->IsDeclare()); + SetupInitializerBlock(std::move(initializerBlockStatements), globalClass); // remove namespaceDecl from orginal node auto end = std::remove_if(body.begin(), body.end(), [&namespaces](ir::AstNode *node) { @@ -220,7 +234,7 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, return false; }); body.erase(end, body.end()); - auto globalClasses = TransformNamespaces(namespaces, program); + auto globalClasses = TransformNamespaces(namespaces); for (auto *cls : globalClasses) { globalClass->EmplaceBody(cls); cls->SetParent(globalClass); @@ -236,12 +250,12 @@ ir::ClassDeclaration *GlobalClassHandler::TransformNamespace(ir::ETSModule *ns, return globalDecl; } -void GlobalClassHandler::CollectProgramGlobalClasses(parser::Program *program, ArenaVector namespaces) +void GlobalClassHandler::CollectProgramGlobalClasses(ArenaVector namespaces) { - auto classDecls = TransformNamespaces(namespaces, program); - program->Ast()->AddStatements(classDecls); + auto classDecls = TransformNamespaces(namespaces); + globalProgram_->Ast()->AddStatements(classDecls); for (auto cls : classDecls) { - cls->SetParent(program->Ast()); + cls->SetParent(globalProgram_->Ast()); CollectNamespaceExportedClasses(cls->AsClassDeclaration()->Definition()); } } @@ -267,18 +281,16 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & if (programs.empty()) { return; } - - parser::Program *const globalProgram = programs.front(); - if (globalProgram->GlobalClass() != nullptr) { + if (globalProgram_->GlobalClass() != nullptr) { return; } ArenaUnorderedSet packageInitializerBlockCount(allocator_->Adapter()); - ir::ClassDeclaration *const globalDecl = CreateGlobalClass(globalProgram); + ir::ClassDeclaration *const globalDecl = CreateGlobalClass(globalProgram_); ir::ClassDefinition *const globalClass = globalDecl->Definition(); // NOTE(vpukhov): a clash inside program list is possible - ES2PANDA_ASSERT(globalProgram->IsPackage() || programs.size() == 1); + ES2PANDA_ASSERT(globalProgram_->IsPackage() || programs.size() == 1); ArenaVector immediateInitializers(allocator_->Adapter()); ArenaVector initializerBlock(allocator_->Adapter()); @@ -304,30 +316,29 @@ void GlobalClassHandler::SetupGlobalClass(const ArenaVector & program->SetGlobalClass(globalClass); } - globalProgram->Ast()->AddStatement(globalDecl); - globalDecl->SetParent(globalProgram->Ast()); + globalProgram_->Ast()->AddStatement(globalDecl); + globalDecl->SetParent(globalProgram_->Ast()); globalClass->SetGlobalInitialized(); - CollectProgramGlobalClasses(globalProgram, namespaces); - auto initializerBlockStmts = - FormInitStaticBlockMethodStatements(globalProgram, moduleDependencies, std::move(initializerBlock)); - CollectExportedClasses(globalClass, globalProgram->Ast()->Statements()); + CollectProgramGlobalClasses(namespaces); + TransformBrokenNamespace(); + auto initializerBlockStmts = FormInitStaticBlockMethodStatements(moduleDependencies, std::move(initializerBlock)); + + CollectExportedClasses(globalClass, globalProgram_->Ast()->Statements()); // NOTE(vpukhov): stdlib checks are to be removed - do not extend the existing logic - if (globalProgram->Kind() != parser::ScriptKind::STDLIB) { + if (globalProgram_->Kind() != parser::ScriptKind::STDLIB) { AddStaticBlockToClass(globalClass); - if (!util::Helpers::IsStdLib(globalProgram)) { - auto immInitStmts = - FormInitMethodStatements(globalProgram, moduleDependencies, std::move(immediateInitializers)); - SetupGlobalMethods(globalProgram, std::move(immInitStmts)); + if (!util::Helpers::IsStdLib(globalProgram_)) { + auto initStatements = FormInitMethodStatements(moduleDependencies, std::move(immediateInitializers)); + SetupGlobalMethods(std::move(initStatements)); } } - SetupInitializerBlock(globalProgram, std::move(initializerBlockStmts), globalClass); + SetupInitializerBlock(std::move(initializerBlockStmts), globalClass); } -ir::MethodDefinition *GlobalClassHandler::CreateGlobalMethod(std::string_view name, - ArenaVector &&statements, - const parser::Program *program) +ir::MethodDefinition *GlobalClassHandler::CreateGlobalMethod(const std::string_view name, + ArenaVector &&statements) { const auto functionFlags = ir::ScriptFunctionFlags::NONE; auto functionModifiers = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC; @@ -347,7 +358,7 @@ ir::MethodDefinition *GlobalClassHandler::CreateGlobalMethod(std::string_view na auto *methodDef = NodeAllocator::Alloc(allocator_, ir::MethodDefinitionKind::METHOD, ident->Clone(allocator_, nullptr)->AsExpression(), funcExpr, functionModifiers, allocator_, false); - methodDef->SetRange({lexer::SourcePosition(program), lexer::SourcePosition(program)}); + methodDef->SetRange({lexer::SourcePosition(globalProgram_), lexer::SourcePosition(globalProgram_)}); return methodDef; } @@ -396,13 +407,13 @@ ir::Identifier *GlobalClassHandler::RefIdent(const util::StringView &name) } ArenaVector> GlobalClassHandler::FormInitStaticBlockMethodStatements( - parser::Program *program, const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements) + const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements) { // Note: will create method body for initializer block one by one, don't merge them. ArenaVector> staticBlocks(allocator_->Adapter()); for (const auto &[p, ps] : initStatements) { ArenaVector statements(allocator_->Adapter()); - if (!util::Helpers::IsStdLib(program) && moduleDependencies != nullptr) { + if (!util::Helpers::IsStdLib(globalProgram_) && moduleDependencies != nullptr) { FormDependentInitTriggers(statements, moduleDependencies); } statements.insert(statements.end(), ps.begin(), ps.end()); @@ -412,12 +423,11 @@ ArenaVector> GlobalClassHandler::FormInitStaticBloc return staticBlocks; } -ArenaVector GlobalClassHandler::FormInitMethodStatements(parser::Program *program, - const ModuleDependencies *moduleDependencies, +ArenaVector GlobalClassHandler::FormInitMethodStatements(const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements) { ArenaVector statements(allocator_->Adapter()); - if (!util::Helpers::IsStdLib(program) && moduleDependencies != nullptr) { + if (!util::Helpers::IsStdLib(globalProgram_) && moduleDependencies != nullptr) { FormDependentInitTriggers(statements, moduleDependencies); } for (const auto &[p, ps] : initStatements) { @@ -552,14 +562,14 @@ static bool HasMethod(ir::ClassDefinition const *cls, const std::string_view nam }); } -void GlobalClassHandler::SetupGlobalMethods(parser::Program *program, ArenaVector &&initStatements) +void GlobalClassHandler::SetupGlobalMethods(ArenaVector &&initStatements) { - ir::ClassDefinition *const globalClass = program->GlobalClass(); - SetupGlobalMethods(program, std::move(initStatements), globalClass, program->IsDeclarationModule()); + ir::ClassDefinition *const globalClass = globalProgram_->GlobalClass(); + SetupGlobalMethods(std::move(initStatements), globalClass, globalProgram_->IsDeclarationModule()); - if (program->IsSeparateModule() && !HasMethod(globalClass, compiler::Signatures::MAIN)) { - ir::MethodDefinition *mainMethod = CreateGlobalMethod( - compiler::Signatures::MAIN, ArenaVector(allocator_->Adapter()), program); + if (globalProgram_->IsSeparateModule() && !HasMethod(globalClass, compiler::Signatures::MAIN)) { + ir::MethodDefinition *mainMethod = + CreateGlobalMethod(compiler::Signatures::MAIN, ArenaVector(allocator_->Adapter())); InsertInGlobal(globalClass, mainMethod); } } diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h index 18d7fbbbc4..0a861be7a7 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalClassHandler.h @@ -31,8 +31,13 @@ public: parser::Program *program; ArenaVector statements; }; - explicit GlobalClassHandler(parser::ETSParser *parser, ArenaAllocator *allocator) - : parser_(parser), allocator_(allocator), packageInitializerBlockCount_(allocator->Adapter()) {}; + explicit GlobalClassHandler(parser::ETSParser *parser, ArenaAllocator *allocator, parser::Program *program) + : parser_(parser), + allocator_(allocator), + globalProgram_(program), + packageInitializerBlockCount_(allocator->Adapter()) {}; + + static void MergeNamespace(ArenaVector &namespaces, parser::Program *program); /** * Each "Module" has it's own global class, which contains all top level statements across "module" @@ -40,9 +45,13 @@ public: * @param programs - vector of files in module */ void SetupGlobalClass(const ArenaVector &programs, const ModuleDependencies *moduleDependencies); - void static MergeNamespace(ArenaVector &namespaces, parser::Program *program); + void CheckPackageMultiInitializerBlock(util::StringView packageName, const ArenaVector> &initializerBlocks); + void SetGlobalProgram(parser::Program *program) + { + globalProgram_ = program; + } private: /** @@ -50,35 +59,32 @@ private: * @param program program of module * @param init_statements statements which should be executed */ - void SetupGlobalMethods(parser::Program *program, ArenaVector &&statements); + void SetupGlobalMethods(ArenaVector &&statements); void AddStaticBlockToClass(ir::AstNode *node); - void CollectProgramGlobalClasses(parser::Program *program, ArenaVector namespaces); - ir::ClassDeclaration *TransformNamespace(ir::ETSModule *ns, parser::Program *program); + void CollectProgramGlobalClasses(ArenaVector namespaces); + ir::ClassDeclaration *TransformNamespace(ir::ETSModule *ns); ir::ClassDeclaration *CreateTransformedClass(ir::ETSModule *ns); template void CollectExportedClasses(ir::ClassDefinition *classDef, const ArenaVector &statements); void CollectNamespaceExportedClasses(ir::ClassDefinition *classDef); - void SetupGlobalMethods(parser::Program *program, ArenaVector &&initStatements, - ir::ClassDefinition *globalClass, bool isDeclare); - void SetupInitializerBlock(parser::Program *program, ArenaVector> &&initializerBlock, + void SetupGlobalMethods(ArenaVector &&initStatements, ir::ClassDefinition *globalClass, + bool isDeclare); + void SetupInitializerBlock(ArenaVector> &&initializerBlock, ir::ClassDefinition *globalClass); - ArenaVector TransformNamespaces(ArenaVector &namespaces, - parser::Program *program); + ArenaVector TransformNamespaces(ArenaVector &namespaces); ir::ClassDeclaration *CreateGlobalClass(const parser::Program *globalProgram); ir::ClassStaticBlock *CreateStaticBlock(ir::ClassDefinition *classDef); - ir::MethodDefinition *CreateGlobalMethod(std::string_view name, ArenaVector &&statements, - const parser::Program *program); + ir::MethodDefinition *CreateGlobalMethod(std::string_view name, ArenaVector &&statements); void AddInitCallToStaticBlock(ir::ClassDefinition *globalClass, ir::MethodDefinition *initMethod); void AddInitializerBlockToStaticBlock(ir::ClassDefinition *globalClass, ArenaVector &&initializerBlocks); ArenaVector> FormInitStaticBlockMethodStatements( - parser::Program *program, const ModuleDependencies *moduleDependencies, - ArenaVector &&initStatements); + const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); + void TransformBrokenNamespace(); - ArenaVector FormInitMethodStatements(parser::Program *program, - const ModuleDependencies *moduleDependencies, + ArenaVector FormInitMethodStatements(const ModuleDependencies *moduleDependencies, ArenaVector &&initStatements); void FormDependentInitTriggers(ArenaVector &statements, @@ -92,6 +98,7 @@ private: parser::ETSParser *const parser_; ArenaAllocator *const allocator_; + parser::Program *globalProgram_; ArenaUnorderedSet packageInitializerBlockCount_; }; } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp index 80439e2eff..474b8f705e 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/topLevelStmts.cpp @@ -101,10 +101,11 @@ bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *prog // NOTE(vpukhov): enforce compilation failure } - GlobalClassHandler globalClass(ctx->parser->AsETSParser(), ctx->Allocator()); + GlobalClassHandler globalClass(ctx->parser->AsETSParser(), program->Allocator(), program); for (auto &[package, extPrograms] : program->ExternalSources()) { if (!extPrograms.front()->IsASTLowered()) { auto moduleDependencies = imports.HandleGlobalStmts(extPrograms); + globalClass.SetGlobalProgram(extPrograms.front()); globalClass.SetupGlobalClass(extPrograms, &moduleDependencies); for (auto extProg : extPrograms) { DeclareNamespaceExportAdjust(extProg, Name()); @@ -115,6 +116,7 @@ bool TopLevelStatements::Perform(public_lib::Context *ctx, parser::Program *prog ArenaVector mainModule(ctx->Allocator()->Adapter()); mainModule.emplace_back(program); auto moduleDependencies = imports.HandleGlobalStmts(mainModule); + globalClass.SetGlobalProgram(program); globalClass.SetupGlobalClass(mainModule, &moduleDependencies); DeclareNamespaceExportAdjust(program, Name()); diff --git a/ets2panda/compiler/lowering/ets/unboxLowering.cpp b/ets2panda/compiler/lowering/ets/unboxLowering.cpp new file mode 100644 index 0000000000..0c611f590c --- /dev/null +++ b/ets2panda/compiler/lowering/ets/unboxLowering.cpp @@ -0,0 +1,1559 @@ +/* + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "generated/tokenType.h" +#include "ir/visitor/IterateAstVisitor.h" +#include "checker/ETSchecker.h" +#include "checker/ets/dynamic/dynamicCall.h" +#include "checker/types/ets/etsTupleType.h" +#include "checker/types/globalTypesHolder.h" +#include "compiler/lowering/util.h" + +#include "compiler/lowering/ets/unboxLowering.h" + +namespace ark::es2panda::compiler { + +namespace { +struct UnboxContext { + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes,readability-identifier-naming) + explicit UnboxContext(public_lib::Context *ctx) + : parser(ctx->parser->AsETSParser()), + varbinder(ctx->GetChecker()->VarBinder()->AsETSBinder()), + checker(ctx->GetChecker()->AsETSChecker()), + allocator(ctx->Allocator()), + handled(ctx->Allocator()->Adapter()) + { + } + + // NOLINTBEGIN(misc-non-private-member-variables-in-classes) + parser::ETSParser *parser; + varbinder::ETSBinder *varbinder; + checker::ETSChecker *checker; + ArenaAllocator *allocator; + ArenaSet handled; + // NOLINTEND(misc-non-private-member-variables-in-classes) +}; +} // namespace + +static bool IsRecursivelyUnboxedReference(checker::Type *t); + +static bool IsRecursivelyUnboxed(checker::Type *t) +{ + return t->IsETSPrimitiveType() || IsRecursivelyUnboxedReference(t); +} + +static checker::Type *GetArrayElementType(checker::Type *arrType) +{ + if (arrType->IsETSResizableArrayType()) { + return arrType->AsETSResizableArrayType()->ElementType(); + } + + if (arrType->IsETSArrayType()) { + return arrType->AsETSArrayType()->ElementType(); + } + return nullptr; +} + +static bool IsRecursivelyUnboxedReference(checker::Type *t) +{ + return (t->IsETSTupleType() && + std::any_of(t->AsETSTupleType()->GetTupleTypesList().begin(), + t->AsETSTupleType()->GetTupleTypesList().end(), IsRecursivelyUnboxedReference)) || + (t->IsETSArrayType() && IsRecursivelyUnboxed(GetArrayElementType(t))) || + (t->IsETSUnionType() && + std::any_of(t->AsETSUnionType()->ConstituentTypes().begin(), t->AsETSUnionType()->ConstituentTypes().end(), + IsRecursivelyUnboxedReference)) || + (t->IsETSObjectType() && + std::any_of(t->AsETSObjectType()->TypeArguments().begin(), t->AsETSObjectType()->TypeArguments().end(), + IsRecursivelyUnboxedReference)); +} + +static bool TypeIsBoxedPrimitive(checker::Type *tp) +{ + return tp->IsETSObjectType() && tp->AsETSObjectType()->IsBoxedPrimitive(); +} + +static bool IsUnboxingApplicableReference(checker::Type *t); + +static bool IsUnboxingApplicable(checker::Type *t) +{ + return TypeIsBoxedPrimitive(t) || IsUnboxingApplicableReference(t); +} + +static bool IsUnboxingApplicableReference(checker::Type *t) +{ + return (t->IsETSTupleType() && + std::any_of(t->AsETSTupleType()->GetTupleTypesList().begin(), + t->AsETSTupleType()->GetTupleTypesList().end(), IsUnboxingApplicableReference)) || + (t->IsETSArrayType() && IsUnboxingApplicable(GetArrayElementType(t))) || + (t->IsETSUnionType() && + std::any_of(t->AsETSUnionType()->ConstituentTypes().begin(), t->AsETSUnionType()->ConstituentTypes().end(), + IsUnboxingApplicableReference)) || + (t->IsETSObjectType() && + std::any_of(t->AsETSObjectType()->TypeArguments().begin(), t->AsETSObjectType()->TypeArguments().end(), + IsUnboxingApplicableReference)); +} + +using TypeIdStorage = std::vector; // Long recursion chains are unlikely, use vector +static checker::Type *NormalizeType(UnboxContext *uctx, checker::Type *t, TypeIdStorage *alreadySeen = nullptr); +static checker::Type *MaybeRecursivelyUnboxReferenceType(UnboxContext *uctx, checker::Type *t, + TypeIdStorage *alreadySeen); + +static checker::Type *MaybeRecursivelyUnboxType(UnboxContext *uctx, checker::Type *t, + TypeIdStorage *alreadySeen = nullptr) +{ + if (TypeIsBoxedPrimitive(t)) { + return uctx->checker->MaybeUnboxType(t); + } + return NormalizeType(uctx, t, alreadySeen); +} + +static checker::Type *MaybeRecursivelyUnboxTypeParameter(UnboxContext *uctx, checker::Type *t, + TypeIdStorage *alreadySeen) +{ + /* Any recursion involves type parameters */ + if (std::find(alreadySeen->begin(), alreadySeen->end(), t->Id()) != alreadySeen->end()) { + return t; + } + alreadySeen->push_back(t->Id()); + + auto typeParameter = t->AsETSTypeParameter(); + auto constraintType = typeParameter->GetConstraintType(); + typeParameter->SetConstraintType(MaybeRecursivelyUnboxReferenceType(uctx, constraintType, alreadySeen)); + return t; +} + +static checker::Type *MaybeRecursivelyUnboxTupleType(UnboxContext *uctx, checker::Type *t, TypeIdStorage *alreadySeen) +{ + bool anyChange = false; + auto *srcTup = t->AsETSTupleType(); + + ArenaVector newTps {uctx->allocator->Adapter()}; + for (auto *e : srcTup->GetTupleTypesList()) { + auto *newE = MaybeRecursivelyUnboxReferenceType(uctx, e, alreadySeen); + newTps.push_back(newE); + anyChange |= (newE != e); + } + + return anyChange ? uctx->allocator->New(uctx->checker, newTps) : t; +} + +static checker::Type *MaybeRecursivelyUnboxUnionType(UnboxContext *uctx, checker::Type *t, TypeIdStorage *alreadySeen) +{ + bool anyChange = false; + auto *srcUnion = t->AsETSUnionType(); + ArenaVector newTps {uctx->allocator->Adapter()}; + for (auto *e : srcUnion->ConstituentTypes()) { + auto *newE = MaybeRecursivelyUnboxReferenceType(uctx, e, alreadySeen); + newTps.push_back(newE); + anyChange |= (newE != e); + } + return anyChange ? uctx->checker->CreateETSUnionType(std::move(newTps)) : t; +} + +static checker::Type *MaybeRecursivelyUnboxObjectType(UnboxContext *uctx, checker::Type *t, TypeIdStorage *alreadySeen) +{ + bool anyChange = false; + + auto *objTp = t->AsETSObjectType(); + ArenaVector newTps {uctx->allocator->Adapter()}; + for (auto *e : objTp->TypeArguments()) { + auto *newE = MaybeRecursivelyUnboxReferenceType(uctx, e, alreadySeen); + newTps.push_back(newE); + anyChange |= (newE != e); + } + return anyChange ? objTp->GetOriginalBaseType()->SubstituteArguments(uctx->checker->Relation(), newTps) : t; +} + +static checker::Type *MaybeRecursivelyUnboxReferenceType(UnboxContext *uctx, checker::Type *t, + TypeIdStorage *alreadySeen) +{ + if (t == nullptr) { + return t; + } + + if (t->IsETSTypeParameter()) { + return MaybeRecursivelyUnboxTypeParameter(uctx, t, alreadySeen); + } + + if (t->IsETSTupleType()) { + return MaybeRecursivelyUnboxTupleType(uctx, t, alreadySeen); + } + + if (t->IsETSArrayType()) { + auto *srcArr = t->AsETSArrayType(); + auto *newE = MaybeRecursivelyUnboxType(uctx, srcArr->ElementType(), alreadySeen); + return (newE == srcArr->ElementType()) ? t : uctx->checker->CreateETSArrayType(newE); + } + + if (t->IsETSResizableArrayType()) { + auto *srcArr = t->AsETSResizableArrayType(); + auto *newE = MaybeRecursivelyUnboxReferenceType(uctx, srcArr->ElementType(), alreadySeen); + return (newE == srcArr->ElementType()) ? t : uctx->checker->CreateETSResizableArrayType(newE); + } + + if (t->IsETSUnionType()) { + return MaybeRecursivelyUnboxUnionType(uctx, t, alreadySeen); + } + + if (t->IsETSObjectType()) { + return MaybeRecursivelyUnboxObjectType(uctx, t, alreadySeen); + } + + return t; +} + +// We should never see an array of boxed primitives, even as a component of some bigger type construction +static checker::Type *NormalizeType(UnboxContext *uctx, checker::Type *tp, TypeIdStorage *alreadySeen) +{ + if (alreadySeen == nullptr) { + TypeIdStorage newAlreadySeen {}; + return MaybeRecursivelyUnboxReferenceType(uctx, tp, &newAlreadySeen); + } + + return MaybeRecursivelyUnboxReferenceType(uctx, tp, alreadySeen); +} + +static void NormalizeAllTypes(UnboxContext *uctx, ir::AstNode *ast) +{ + // Use preorder to avoid dealing with inner structure of type nodes: they are quickly replaced + // by opaque nodes that have no children. + ast->TransformChildrenRecursivelyPreorder( + // clang-format off + // CC-OFFNXT(G.FMT.14-CPP) project code style + [uctx](ir::AstNode *child) -> ir::AstNode* { + if (child->IsExpression() && child->AsExpression()->IsTypeNode()) { + // Avoid dealing with annotation usages. + // ETSTypeReferenceParts only appear within ETSTypeReference, so the only way to get one is + // again through AnnotationUsage. + if (child->Parent()->IsAnnotationUsage() || child->IsETSTypeReferencePart()) { + return child; + } + auto typeNodeType = child->AsExpression()->AsTypeNode()->GetType(uctx->checker); + if (typeNodeType == nullptr || typeNodeType->IsETSDynamicType()) { + return child; + } + auto r = uctx->allocator->New(NormalizeType(uctx, typeNodeType), + uctx->allocator); + r->SetRange(child->Range()); + r->SetParent(child->Parent()); + return r; + } + if (child->IsTyped()) { + child->AsTyped()->SetTsType(NormalizeType(uctx, child->AsTyped()->TsType())); + if (child->Variable() != nullptr && child->Variable()->TsType() != nullptr) { + child->Variable()->SetTsType(NormalizeType(uctx, child->Variable()->TsType())); + } + } + return child; + }, + // clang-format on + "unbox-normalize-types"); +} + +static void HandleScriptFunctionHeader(UnboxContext *uctx, ir::ScriptFunction *func) +{ + auto *sig = func->Signature(); + if (sig == nullptr) { + return; + } + + // Special case for primitive `valueOf` functions -- should still return boxed values (used in codegen) + if (func->Parent()->Parent()->IsMethodDefinition() && + func->Parent()->Parent()->AsMethodDefinition()->Id()->Name() == "valueOf" && + ContainingClass(func)->AsETSObjectType()->IsBoxedPrimitive() && sig->Params().size() == 1 && + !sig->Params()[0]->TsType()->IsETSEnumType()) { + auto *boxed = func->Parent()->Parent()->Parent()->AsTyped()->TsType(); + auto *unboxed = MaybeRecursivelyUnboxType(uctx, boxed); + + ES2PANDA_ASSERT(sig->ReturnType() == boxed); + + sig->Params()[0]->SetTsType(unboxed); + uctx->varbinder->BuildFunctionName(func); + return; + } + + // Special case for enum boxing function -- this should still return a boxed value + if (func->Parent()->Parent()->IsMethodDefinition() && + func->Parent()->Parent()->AsMethodDefinition()->Id()->Name() == "boxedFromInt") { + return; + } + + for (size_t i = 0; i < func->Signature()->Params().size(); i++) { + auto *sigParam = func->Signature()->Params()[i]; + auto *funcParam = func->Params()[i]->AsETSParameterExpression(); + if (IsUnboxingApplicable(sigParam->TsType())) { + auto *unboxedType = MaybeRecursivelyUnboxType(uctx, sigParam->TsType()); + sigParam->SetTsType(unboxedType); + funcParam->SetTsType(unboxedType); + funcParam->Ident()->SetTsType(unboxedType); + funcParam->Variable()->SetTsType(unboxedType); + } + } + if (sig->RestVar() != nullptr) { + auto *funcRestParam = func->Params()[func->Params().size() - 1]->AsETSParameterExpression(); + ES2PANDA_ASSERT(funcRestParam != nullptr && funcRestParam->IsRestParameter()); + + auto *unboxedType = MaybeRecursivelyUnboxType(uctx, sig->RestVar()->TsType()); + sig->RestVar()->SetTsType(unboxedType); + funcRestParam->Ident()->SetTsType(unboxedType); + funcRestParam->Ident()->Variable()->SetTsType(unboxedType); + } + if (IsUnboxingApplicable(sig->ReturnType())) { + sig->SetReturnType(MaybeRecursivelyUnboxType(uctx, sig->ReturnType())); + } + + // Signature may have changed, so need to change internal name. + uctx->varbinder->BuildFunctionName(func); +} + +static void HandleClassProperty(UnboxContext *uctx, ir::ClassProperty *prop) +{ + auto *propType = prop->TsType(); + if (propType == nullptr) { + propType = prop->Key()->Variable()->TsType(); + } + ES2PANDA_ASSERT(propType != nullptr); + if (IsUnboxingApplicable(propType) && prop->Key()->IsIdentifier()) { + auto *unboxedType = MaybeRecursivelyUnboxType(uctx, propType); + prop->SetTsType(unboxedType); + prop->Key()->Variable()->SetTsType(unboxedType); + } +} + +static void HandleVariableDeclarator(UnboxContext *uctx, ir::VariableDeclarator *vdecl) +{ + if (IsUnboxingApplicable(vdecl->Id()->Variable()->TsType())) { + auto *unboxedType = MaybeRecursivelyUnboxType(uctx, vdecl->Id()->Variable()->TsType()); + vdecl->SetTsType(unboxedType); + vdecl->Id()->SetTsType(unboxedType); + vdecl->Id()->Variable()->SetTsType(unboxedType); + } +} + +static void HandleDeclarationNode(UnboxContext *uctx, ir::AstNode *ast) /// +{ + if (uctx->handled.count(ast) > 0) { + return; + } + if (ast->IsScriptFunction()) { + HandleScriptFunctionHeader(uctx, ast->AsScriptFunction()); + } else if (ast->IsMethodDefinition()) { + HandleScriptFunctionHeader(uctx, ast->AsMethodDefinition()->Function()); + } else if (ast->IsClassProperty()) { + HandleClassProperty(uctx, ast->AsClassProperty()); + } else if (ast->IsVariableDeclarator()) { + HandleVariableDeclarator(uctx, ast->AsVariableDeclarator()); + } + uctx->handled.insert(ast); +} + +static util::StringView UnboxerMethodName(checker::Type *unboxedType) +{ + if (unboxedType->IsETSIntEnumType() || unboxedType->IsETSStringEnumType()) { + return "unbox"; + } + return "unboxed"; +} + +static ir::Expression *InsertUnboxing(UnboxContext *uctx, ir::Expression *expr) +{ + auto *boxedType = expr->TsType(); + if (boxedType->IsETSTypeParameter()) { + boxedType = boxedType->AsETSTypeParameter()->GetConstraintType(); + } + auto *unboxedType = MaybeRecursivelyUnboxType(uctx, boxedType); + auto *parent = expr->Parent(); + + auto *allocator = uctx->allocator; + + // Avoid unboxing application right on top of boxing. + if (expr->IsETSNewClassInstanceExpression() && + expr->AsETSNewClassInstanceExpression()->GetArguments().size() == 1 && + uctx->checker->Relation()->IsIdenticalTo(expr->AsETSNewClassInstanceExpression()->GetArguments()[0]->TsType(), + unboxedType)) { + auto *ret = expr->AsETSNewClassInstanceExpression()->GetArguments()[0]; + ret->SetParent(parent); + return ret; + } + + auto *methodId = allocator->New(UnboxerMethodName(unboxedType), allocator); + auto *mexpr = util::NodeAllocator::ForceSetParent( + allocator, expr, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto *call = util::NodeAllocator::ForceSetParent( + allocator, mexpr, ArenaVector(allocator->Adapter()), nullptr, false); + call->SetParent(parent); + + BindLoweredNode(uctx->varbinder, call); + + auto *methodVar = boxedType->AsETSObjectType()->InstanceMethods()[methodId->Name()]; + methodId->SetVariable(methodVar); + + /* Ensure that calleeMethod's signature is updated to return an unboxed value */ + auto *calleeMethod = methodVar->Declaration()->Node(); + HandleDeclarationNode(uctx, calleeMethod); + + mexpr->SetTsType(methodVar->TsType()); + mexpr->SetObjectType(boxedType->AsETSObjectType()); + call->SetTsType(unboxedType); + call->SetSignature(methodVar->TsType()->AsETSFunctionType()->CallSignatures()[0]); + + return call; +} + +static ir::Expression *CreateToIntrinsicCallExpression(UnboxContext *uctx, checker::Type *toType, + checker::Type *exprType, ir::Expression *expr) +{ + auto *allocator = uctx->allocator; + + auto *parent = expr->Parent(); + auto *boxedToType = uctx->checker->MaybeBoxType(toType)->AsETSObjectType(); + auto *boxedExprType = uctx->checker->MaybeBoxType(exprType)->AsETSObjectType(); + auto args = ArenaVector(allocator->Adapter()); + auto name = util::UString("to" + boxedToType->ToStringAsSrc(), allocator).View(); + + auto *memberExpr = util::NodeAllocator::ForceSetParent( + allocator, allocator->New(boxedExprType, allocator), + allocator->New(name, allocator), ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + args.push_back(expr); + + auto *call = + util::NodeAllocator::ForceSetParent(allocator, memberExpr, std::move(args), nullptr, false); + call->SetParent(parent); + + BindLoweredNode(uctx->varbinder, call); + + auto *methodVar = boxedExprType->StaticMethods()[name]; + memberExpr->Property()->SetVariable(methodVar); + + /* Ensure that calleeMethod's signature is updated to accept an unboxed value */ + auto *calleeMethod = methodVar->Declaration()->Node(); + HandleDeclarationNode(uctx, calleeMethod); + + memberExpr->SetTsType(methodVar->TsType()); + memberExpr->SetObjectType(boxedExprType); + call->SetTsType(toType); + call->SetSignature(methodVar->TsType()->AsETSFunctionType()->CallSignatures()[0]); + return call; +} + +static bool CheckIfOnTopOfUnboxing(UnboxContext *uctx, ir::Expression *expr, checker::Type *unboxedType, + checker::Type *boxedType) +{ + return expr->IsCallExpression() && expr->AsCallExpression()->Arguments().empty() && + expr->AsCallExpression()->Callee()->IsMemberExpression() && + expr->AsCallExpression()->Callee()->AsMemberExpression()->Property()->IsIdentifier() && + expr->AsCallExpression()->Callee()->AsMemberExpression()->Property()->AsIdentifier()->Name() == + // CC-OFFNXT(G.FMT.02) project code style + UnboxerMethodName(unboxedType) && + uctx->checker->Relation()->IsIdenticalTo( + expr->AsCallExpression()->Callee()->AsMemberExpression()->Object()->TsType(), boxedType); +} + +static ir::Expression *LinkUnboxingExpr(ir::Expression *expr, ir::AstNode *parent) +{ + auto *ret = expr->AsCallExpression()->Callee()->AsMemberExpression()->Object(); + ret->SetParent(parent); + return ret; +} + +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic +static ir::Expression *InsertBoxing(UnboxContext *uctx, ir::Expression *expr) +{ + auto *unboxedType = expr->TsType(); + auto *boxedType = uctx->checker->MaybeBoxType(unboxedType); + auto *parent = expr->Parent(); + + // Avoid boxing application right on top of unboxing. + if (CheckIfOnTopOfUnboxing(uctx, expr, unboxedType, boxedType)) { + return LinkUnboxingExpr(expr, parent); + } + + auto *allocator = uctx->allocator; + + auto args = ArenaVector(allocator->Adapter()); + + if (unboxedType->IsETSIntEnumType() || unboxedType->IsETSStringEnumType()) { + auto *memberExpr = util::NodeAllocator::ForceSetParent( + allocator, allocator->New(boxedType, allocator), + allocator->New("boxedFromInt", allocator), ir::MemberExpressionKind::PROPERTY_ACCESS, false, + false); + auto *asExpr = CreateToIntrinsicCallExpression(uctx, uctx->checker->GlobalIntType(), unboxedType, expr); + args.push_back(asExpr); + auto *call = util::NodeAllocator::ForceSetParent(allocator, memberExpr, std::move(args), + nullptr, false); + call->SetParent(parent); + + BindLoweredNode(uctx->varbinder, call); + + auto *methodVar = boxedType->AsETSObjectType()->StaticMethods()["boxedFromInt"]; + memberExpr->Property()->SetVariable(methodVar); + + /* Ensure that calleeMethod's signature is updated to accept an unboxed value */ + auto *calleeMethod = methodVar->Declaration()->Node(); + HandleDeclarationNode(uctx, calleeMethod); + + memberExpr->SetTsType(methodVar->TsType()); + memberExpr->SetObjectType(boxedType->AsETSObjectType()); + call->SetTsType(boxedType); + call->SetSignature(methodVar->TsType()->AsETSFunctionType()->CallSignatures()[0]); + + return call; + } + + args.push_back(expr); + auto *constrCall = util::NodeAllocator::ForceSetParent( + allocator, allocator->New(boxedType, allocator), std::move(args)); + constrCall->SetParent(parent); + + auto &constructSignatures = boxedType->AsETSObjectType()->ConstructSignatures(); + checker::Signature *signature = nullptr; + for (auto *sig : constructSignatures) { + if (sig->Params().size() == 1 && sig->Params()[0]->TsType() == unboxedType) { + signature = sig; + break; + } + } + ES2PANDA_ASSERT(signature != nullptr); + + /* Ensure that the constructor signature is updated to accept an unboxed value */ + auto *constructor = signature->Function(); + HandleDeclarationNode(uctx, constructor); + constrCall->SetTsType(boxedType); + constrCall->SetSignature(signature); + + return constrCall; +} + +static checker::Type *SelectTypeToConvert( + std::tuple ctx, checker::Type *toConvert, + checker::Type *expectedType, checker::Type *actualType) +{ + auto [uctx, relation, checker] = ctx; + if (toConvert == nullptr && actualType->IsCharType() && + relation->IsSupertypeOf(expectedType, checker->GlobalBuiltinETSStringType())) { + return uctx->checker->GlobalBuiltinETSStringType(); + } + if (toConvert == nullptr && actualType->IsByteType() && + relation->IsSupertypeOf(expectedType, checker->GlobalCharBuiltinType())) { + return uctx->checker->GlobalCharBuiltinType(); + } + + // Appears in "~b" if "b" is of type Float + if (toConvert == nullptr && actualType->IsFloatType() && + relation->IsSupertypeOf(expectedType, checker->GlobalIntBuiltinType())) { + return checker->GlobalIntBuiltinType(); + } + + // Appears in "~b" if "b" is of type Double + if (toConvert == nullptr && actualType->IsDoubleType() && + relation->IsSupertypeOf(expectedType, checker->GlobalLongBuiltinType())) { + return checker->GlobalLongBuiltinType(); + } + return toConvert; +} + +/* NOTE(gogabr): conversions should be inserted at the checker stage. This function is temporary. */ +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, huge_cyclomatic_complexity) solid logic +static ir::Expression *InsertPrimitiveConversionIfNeeded(UnboxContext *uctx, ir::Expression *expr, + checker::Type *expectedType) +{ + auto *checker = uctx->checker; + auto *relation = checker->Relation(); + auto *actualType = expr->TsType(); + + ES2PANDA_ASSERT(IsRecursivelyUnboxed(actualType)); + + if (relation->IsSupertypeOf(expectedType, uctx->checker->MaybeBoxType(actualType))) { + return expr; + } + + checker::Type *toConvert = nullptr; + auto checkSubtyping = [expectedType, checker, &toConvert](checker::Type *tp) { + if (toConvert != nullptr) { + return; + } + if (checker->Relation()->IsSupertypeOf(expectedType, checker->MaybeBoxType(tp))) { + toConvert = tp; + } + }; + + switch (checker->ETSType(MaybeRecursivelyUnboxType(uctx, actualType))) { + case checker::TypeFlag::BYTE: + checkSubtyping(checker->GlobalByteBuiltinType()); + [[fallthrough]]; + case checker::TypeFlag::SHORT: + checkSubtyping(checker->GlobalShortBuiltinType()); + [[fallthrough]]; + case checker::TypeFlag::CHAR: + case checker::TypeFlag::INT: + checkSubtyping(checker->GlobalIntBuiltinType()); + [[fallthrough]]; + case checker::TypeFlag::LONG: + checkSubtyping(checker->GlobalLongBuiltinType()); + [[fallthrough]]; + case checker::TypeFlag::FLOAT: + checkSubtyping(checker->GlobalFloatBuiltinType()); + [[fallthrough]]; + case checker::TypeFlag::DOUBLE: + checkSubtyping(checker->GlobalDoubleBuiltinType()); + [[fallthrough]]; + default: + break; + } + + toConvert = SelectTypeToConvert(std::make_tuple(uctx, relation, checker), toConvert, expectedType, actualType); + ES2PANDA_ASSERT(toConvert != nullptr); + auto *toConvertUnboxed = checker->MaybeUnboxType(toConvert); + + auto *res = CreateToIntrinsicCallExpression(uctx, toConvertUnboxed, actualType, expr); + auto range = expr->Range(); + SetSourceRangesRecursively(res, range); + res->SetRange(range); + + return res; +} + +// CC-OFFNXT(huge_cyclomatic_complexity, huge_cca_cyclomatic_complexity[C++], G.FUN.01-CPP) solid logic +static ir::Expression *PerformLiteralConversion(UnboxContext *uctx, lexer::Number const &n, checker::Type *expectedType) +{ + auto *allocator = uctx->allocator; + bool isInt = false; + int64_t longValue = 0; + double doubleValue = 0.0; + if (n.IsByte()) { + longValue = n.GetByte(); + isInt = true; + } else if (n.IsShort()) { + longValue = n.GetShort(); + isInt = true; + } else if (n.IsInt()) { + longValue = n.GetInt(); + isInt = true; + } else if (n.IsLong()) { + longValue = n.GetLong(); + isInt = true; + } else if (n.IsFloat()) { + doubleValue = n.GetFloat(); + isInt = false; + } else if (n.IsDouble()) { + doubleValue = n.GetDouble(); + isInt = false; + } else { + ES2PANDA_UNREACHABLE(); + } + + lexer::Number num {}; + if (expectedType->IsByteType()) { + num = lexer::Number {isInt ? (int8_t)longValue : (int8_t)doubleValue}; + } else if (expectedType->IsShortType()) { + num = lexer::Number {isInt ? (int16_t)longValue : (int16_t)doubleValue}; + } else if (expectedType->IsIntType()) { + num = lexer::Number {isInt ? (int32_t)longValue : (int32_t)doubleValue}; + } else if (expectedType->IsLongType()) { + num = lexer::Number {isInt ? longValue : (int64_t)doubleValue}; + } else if (expectedType->IsFloatType()) { + num = lexer::Number {isInt ? (float)longValue : (float)doubleValue}; + } else if (expectedType->IsDoubleType()) { + num = lexer::Number {isInt ? (double)longValue : doubleValue}; + } else { + ES2PANDA_UNREACHABLE(); + } + + auto *res = allocator->New(num); + res->SetTsType(expectedType); + return res; +} + +static ir::Expression *InsertConversionBetweenPrimitivesIfNeeded(UnboxContext *uctx, ir::Expression *expr, + checker::Type *expectedType) +{ + auto *oldType = expr->TsType(); + if (uctx->checker->Relation()->IsIdenticalTo(oldType, expectedType)) { + return expr; + } + + auto *parent = expr->Parent(); + ir::Expression *res; + + auto range = expr->Range(); + + if (expr->IsNumberLiteral() && expectedType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + /* Some contexts (namely, annotations) expect literals, so provide them if possible */ + res = PerformLiteralConversion(uctx, expr->AsNumberLiteral()->Number(), expectedType); + res->SetRange(range); + } else if (expr->IsCharLiteral() && expectedType->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + res = PerformLiteralConversion(uctx, lexer::Number {expr->AsCharLiteral()->Char()}, expectedType); + res->SetRange(range); + } else { + res = CreateToIntrinsicCallExpression(uctx, expectedType, oldType, expr); + SetSourceRangesRecursively(res, range); + } + + res->SetParent(parent); + res->SetTsType(expectedType); + return res; +} + +static ir::Expression *AdjustType(UnboxContext *uctx, ir::Expression *expr, checker::Type *expectedType) +{ + if (expr == nullptr) { + return nullptr; + } + expectedType = uctx->checker->GetApparentType(expectedType); + checker::Type *actualType = expr->Check(uctx->checker); + + if (expectedType->IsETSDynamicType()) { + return expr; + } + if (actualType->IsETSDynamicType()) { + auto *parent = expr->Parent(); + auto *allocator = uctx->allocator; + auto *res = util::NodeAllocator::ForceSetParent( + allocator, expr, allocator->New(expectedType, allocator), false); + res->SetParent(parent); + res->SetTsType(expectedType); + res->SetRange(expr->Range()); + return res; + } + + if (actualType->IsETSPrimitiveType() && checker::ETSChecker::IsReferenceType(expectedType)) { + expr = InsertPrimitiveConversionIfNeeded(uctx, expr, expectedType); + ES2PANDA_ASSERT( + uctx->checker->Relation()->IsSupertypeOf(expectedType, uctx->checker->MaybeBoxType(expr->TsType())) || + (expr->TsType()->IsCharType() && expectedType->IsETSStringType())); + return InsertBoxing(uctx, expr); + } + if ((TypeIsBoxedPrimitive(actualType) || + (actualType->IsETSTypeParameter() && + TypeIsBoxedPrimitive(actualType->AsETSTypeParameter()->GetConstraintType()))) && + expectedType->IsETSPrimitiveType()) { + return InsertConversionBetweenPrimitivesIfNeeded(uctx, InsertUnboxing(uctx, expr), expectedType); + } + if (TypeIsBoxedPrimitive(actualType) && checker::ETSChecker::IsReferenceType(expectedType) && + !uctx->checker->Relation()->IsSupertypeOf(expectedType, actualType)) { + return AdjustType(uctx, InsertUnboxing(uctx, expr), expectedType); + } + if (actualType->IsETSPrimitiveType() && expectedType->IsETSPrimitiveType()) { + return InsertConversionBetweenPrimitivesIfNeeded(uctx, expr, expectedType); + } + return expr; +} + +static void HandleForOfStatement(UnboxContext *uctx, ir::ForOfStatement *forOf) +{ + auto *left = forOf->Left(); + + ir::Identifier *id = nullptr; + if (left->IsIdentifier()) { + id = left->AsIdentifier(); + } else if (left->IsVariableDeclaration()) { + ES2PANDA_ASSERT(left->AsVariableDeclaration()->Declarators().size() == 1); + id = left->AsVariableDeclaration()->Declarators()[0]->Id()->AsIdentifier(); + } + ES2PANDA_ASSERT(id != nullptr); + + // NOTE(gogabr): we need to recompute the right side type instead of just unboxing; + // this may be, for example, a generic call that returns a boxed array. + auto *tp = MaybeRecursivelyUnboxType(uctx, forOf->Right()->TsType()); + + checker::Type *elemTp = nullptr; + if (tp->IsETSArrayType()) { + elemTp = GetArrayElementType(tp); + } else if (tp->IsETSStringType()) { + elemTp = uctx->checker->GlobalCharType(); + } else { + ES2PANDA_ASSERT(tp->IsETSUnionType()); + ES2PANDA_ASSERT(id->Variable()->TsType()->IsETSUnionType()); + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) + elemTp = id->Variable()->TsType(); // always a union type, no need to change + } + + /* This type assignment beats other assignment that could be produced during normal handling of id's declaration + */ + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) + id->SetTsType(elemTp); + id->Variable()->SetTsType(elemTp); + id->Variable()->Declaration()->Node()->AsTyped()->SetTsType(elemTp); +} + +// Borrowed from arithmetic.cpp, didn't want to make it public -- gogabr +static checker::Type *EffectiveTypeOfNumericOrEqualsOp(checker::ETSChecker *checker, checker::Type *left, + checker::Type *right) +{ + if (left->IsDoubleType() || right->IsDoubleType()) { + return checker->GlobalDoubleType(); + } + if (left->IsFloatType() || right->IsFloatType()) { + return checker->GlobalFloatType(); + } + if (left->IsLongType() || right->IsLongType()) { + return checker->GlobalLongType(); + } + if (left->IsCharType() && right->IsCharType()) { + return checker->GlobalCharType(); + } + if (left->IsETSBooleanType() && right->IsETSBooleanType()) { + return checker->GlobalETSBooleanType(); + } + return checker->GlobalIntType(); +} + +static void ReplaceInParent(ir::AstNode *from, ir::AstNode *to) +{ + // clang-format off + // CC-OFFNXT(G.FMT.14-CPP) project code style + auto const replaceNode = [=](ir::AstNode *child) -> ir::AstNode* { + if (child == from) { + to->SetParent(from->Parent()); + return to; + } + return child; + }; + // clang-format on + from->Parent()->TransformChildren(replaceNode, "UnboxLoweringReplaceInParent"); +} + +namespace { +struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { + explicit UnboxVisitor(UnboxContext *uctx) : uctx_(uctx) {} + + void VisitReturnStatement(ir::ReturnStatement *retStmt) override + { + ir::ScriptFunction *nearestScriptFunction = nullptr; + for (ir::AstNode *curr = retStmt; curr != nullptr; curr = curr->Parent()) { + if (curr->IsScriptFunction()) { + nearestScriptFunction = curr->AsScriptFunction(); + break; + } + } + + if (nearestScriptFunction != nullptr && retStmt != nullptr) { + retStmt->SetArgument( + AdjustType(uctx_, retStmt->Argument(), nearestScriptFunction->Signature()->ReturnType())); + } + } + + void VisitIfStatement(ir::IfStatement *ifStmt) override + { + if (TypeIsBoxedPrimitive(ifStmt->Test()->TsType())) { + ifStmt->SetTest(InsertUnboxing(uctx_, ifStmt->Test())); + } + } + + void VisitWhileStatement(ir::WhileStatement *whStmt) override + { + if (TypeIsBoxedPrimitive(whStmt->Test()->TsType())) { + whStmt->SetTest(InsertUnboxing(uctx_, whStmt->Test())); + } + } + + void VisitSwitchStatement(ir::SwitchStatement *swtch) override + { + auto *discType = uctx_->checker->MaybeUnboxType(swtch->Discriminant()->TsType()); + if (!discType->IsETSPrimitiveType()) { // should be string + return; + } + swtch->SetDiscriminant(AdjustType(uctx_, swtch->Discriminant(), discType)); + for (auto *scase : swtch->Cases()) { + scase->SetTest(AdjustType(uctx_, scase->Test(), discType)); + } + } + + void HandleDynamicCall(ir::CallExpression *call) + { + auto *sig = call->Signature(); + auto numSysParams = checker::DynamicCall::IsByValue(uctx_->varbinder, call->Callee()) ? 2 : 3; + for (size_t ix = 0; ix < call->Arguments().size(); ix++) { + auto *expectedType = sig->Params()[numSysParams + ix]->TsType(); + call->Arguments()[ix] = AdjustType(uctx_, call->Arguments()[ix], expectedType); + } + } + + // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic + void VisitCallExpression(ir::CallExpression *call) override + { + if (call->Callee()->TsType()->IsETSDynamicType()) { + HandleDynamicCall(call); + return; + } + + auto *func = call->Signature()->Function(); + if (func == nullptr) { + // some lambda call, all arguments and return type need to be boxed + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < call->Arguments().size(); i++) { + auto *arg = call->Arguments()[i]; + call->Arguments()[i] = AdjustType(uctx_, arg, uctx_->checker->MaybeBoxType(arg->TsType())); + } + return; + } + + HandleDeclarationNode(uctx_, func); + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < call->Arguments().size(); i++) { + auto *arg = call->Arguments()[i]; + + if (i >= func->Signature()->Params().size()) { + auto *restVar = call->Signature()->RestVar(); + if (restVar != nullptr && + !arg->IsSpreadElement()) { // NOTE(gogabr) should we try to unbox spread elements? + auto *restElemType = GetArrayElementType(restVar->TsType()); + call->Arguments()[i] = AdjustType(uctx_, arg, restElemType); + } + } else { + auto *origSigType = func->Signature()->Params()[i]->TsType(); + if (origSigType->IsETSPrimitiveType()) { + call->Signature()->Params()[i]->SetTsType(origSigType); + call->Arguments()[i] = AdjustType(uctx_, arg, origSigType); + } else { + call->Arguments()[i] = AdjustType(uctx_, arg, call->Signature()->Params()[i]->TsType()); + } + } + } + + if (func->Signature()->ReturnType()->IsETSPrimitiveType()) { + call->Signature()->SetReturnType(func->Signature()->ReturnType()); + } else { + call->Signature()->SetReturnType(NormalizeType(uctx_, call->Signature()->ReturnType())); + } + + if (call->Signature()->HasSignatureFlag(checker::SignatureFlags::THIS_RETURN_TYPE)) { + auto *callee = call->Callee(); + auto isFuncRefCall = [&callee]() { + if (!callee->IsMemberExpression()) { + return false; + }; + auto *calleeObject = callee->AsMemberExpression()->Object(); + return (calleeObject) + ->TsType() + ->IsETSFunctionType() || // NOTE(gogabr): How can this happen after lambdaLowering? + (calleeObject->TsType()->IsETSObjectType() && + calleeObject->TsType()->AsETSObjectType()->HasObjectFlag(checker::ETSObjectFlags::FUNCTIONAL)); + }(); + if (callee->IsMemberExpression() && !isFuncRefCall) { + call->SetTsType(callee->AsMemberExpression()->Object()->TsType()); + } else { + // Either a functional reference call, or + // function with receiver called in a "normal", "function-like" way: + // function f(x: this) : this { return this } + // f(new A) + ES2PANDA_ASSERT(!call->Arguments().empty()); + call->SetTsType(call->Arguments()[0]->TsType()); + } + } else { + call->SetTsType(call->Signature()->ReturnType()); + } + } + + void HandleDynamicConstructorCall(ir::ETSNewClassInstanceExpression *call) + { + auto *sig = call->GetSignature(); + auto numSysParams = checker::DynamicCall::IsByValue(uctx_->varbinder, call->GetTypeRef()) ? 2 : 3; + for (size_t ix = 0; ix < call->GetArguments().size(); ix++) { + auto *expectedType = sig->Params()[numSysParams + ix]->TsType(); + call->GetArguments()[ix] = AdjustType(uctx_, call->GetArguments()[ix], expectedType); + } + } + + void VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *call) override + { + if (call->GetTypeRef()->TsType()->IsETSDynamicType()) { + HandleDynamicConstructorCall(call); + return; + } + + auto *func = call->GetSignature()->Function(); + HandleDeclarationNode(uctx_, func); + + for (size_t i = 0; i < call->GetArguments().size(); i++) { + auto *arg = call->GetArguments()[i]; + + if (i >= func->Signature()->Params().size()) { + auto *restVar = call->GetSignature()->RestVar(); + if (restVar != nullptr && + !arg->IsSpreadElement()) { // NOTE(gogabr) should we try to unbox spread elements? + auto *restElemType = GetArrayElementType(restVar->TsType()); + call->GetArguments()[i] = AdjustType(uctx_, arg, restElemType); + } + } else { + auto *origSigType = func->Signature()->Params()[i]->TsType(); + if (origSigType->IsETSPrimitiveType()) { + call->GetSignature()->Params()[i]->SetTsType(origSigType); + call->GetArguments()[i] = AdjustType(uctx_, arg, origSigType); + } else { + call->GetArguments()[i] = AdjustType(uctx_, arg, call->GetSignature()->Params()[i]->TsType()); + } + } + } + + call->SetTsType(call->GetTypeRef()->TsType()); + } + + void VisitSpreadElement(ir::SpreadElement *spread) override + { + spread->SetTsType(spread->Argument()->TsType()); + } + + void VisitArrayExpression(ir::ArrayExpression *aexpr) override + { + auto *unboxedType = MaybeRecursivelyUnboxType(uctx_, aexpr->TsType()); + aexpr->SetTsType(unboxedType); + + for (size_t i = 0; i < aexpr->Elements().size(); i++) { + checker::Type *expectedType; + if (aexpr->TsType()->IsETSTupleType()) { + expectedType = aexpr->TsType()->AsETSTupleType()->GetTypeAtIndex(i); + } else if (aexpr->TsType()->IsETSArrayType() || aexpr->TsType()->IsETSResizableArrayType()) { + expectedType = GetArrayElementType(aexpr->TsType()); + } else { + ES2PANDA_UNREACHABLE(); + } + aexpr->Elements()[i] = AdjustType(uctx_, aexpr->Elements()[i], expectedType); + } + } + + void HandleArithmeticLike(ir::BinaryExpression *bexpr) + { + bexpr->SetTsType(uctx_->checker->MaybeUnboxType(bexpr->TsType())); + bexpr->SetOperationType(uctx_->checker->MaybeUnboxType(bexpr->OperationType())); + if (TypeIsBoxedPrimitive(bexpr->Left()->TsType())) { + bexpr->SetLeft(InsertUnboxing(uctx_, bexpr->Left())); + } + if (TypeIsBoxedPrimitive(bexpr->Right()->TsType())) { + bexpr->SetRight(InsertUnboxing(uctx_, bexpr->Right())); + } + } + + void HandleEqualityOrInequality(ir::BinaryExpression *bexpr) + { + auto *leftTp = bexpr->Left()->TsType(); + auto *rightTp = bexpr->Right()->TsType(); + + checker::Type *opType = nullptr; + if ((leftTp->IsETSPrimitiveType() || TypeIsBoxedPrimitive(leftTp)) && + (rightTp->IsETSPrimitiveType() || TypeIsBoxedPrimitive(rightTp))) { + auto *newLeftTp = uctx_->checker->MaybeUnboxType(leftTp); + auto *newRightTp = uctx_->checker->MaybeUnboxType(rightTp); + bexpr->SetLeft(AdjustType(uctx_, bexpr->Left(), newLeftTp)); + bexpr->SetRight(AdjustType(uctx_, bexpr->Right(), newRightTp)); + + opType = EffectiveTypeOfNumericOrEqualsOp(uctx_->checker, newLeftTp, newRightTp); + bexpr->SetLeft(InsertConversionBetweenPrimitivesIfNeeded(uctx_, bexpr->Left(), opType)); + bexpr->SetRight(InsertConversionBetweenPrimitivesIfNeeded(uctx_, bexpr->Right(), opType)); + } else { + bexpr->SetLeft(AdjustType(uctx_, bexpr->Left(), uctx_->checker->MaybeBoxType(leftTp))); + bexpr->SetRight(AdjustType(uctx_, bexpr->Right(), uctx_->checker->MaybeBoxType(rightTp))); + opType = bexpr->OperationType(); + } + + bexpr->SetOperationType(opType); + bexpr->SetTsType(uctx_->checker->GlobalETSBooleanType()); + } + + void HandleLogical(ir::BinaryExpression *bexpr) + { + auto *leftType = bexpr->Left()->TsType(); + auto *rightType = bexpr->Right()->TsType(); + if (uctx_->checker->Relation()->IsIdenticalTo(leftType, rightType)) { + bexpr->SetTsType(leftType); + bexpr->SetOperationType(leftType); + } else { + // NOTE(gogabr): simplify codegen here. Lower logical operators. + auto *oldLeft = bexpr->Left(); + auto *oldRight = bexpr->Right(); + auto *leftBoxed = uctx_->checker->MaybeBoxType(leftType); + auto *rightBoxed = uctx_->checker->MaybeBoxType(rightType); + auto *resType = uctx_->checker->MaybeUnboxType(uctx_->checker->CreateETSUnionType( + {leftBoxed, rightBoxed})); // currently CreateETSUnionType returns nonunion numeric type if you try to + // create a *Numeric*|*OtherNumeric* + if (bexpr->Right()->IsNumberLiteral()) { + resType = leftBoxed; + } + if (bexpr->Left()->IsNumberLiteral()) { + resType = rightBoxed; + } + + bexpr->SetLeft(AdjustType(uctx_, oldLeft, resType)); + bexpr->SetRight(AdjustType(uctx_, oldRight, resType)); + if (bexpr->Result() == oldLeft) { + bexpr->SetResult(bexpr->Left()); + } else if (bexpr->Result() == oldRight) { + bexpr->SetResult(bexpr->Right()); + } + bexpr->SetTsType(resType); + bexpr->SetOperationType(bexpr->TsType()); + } + } + + void VisitBinaryExpression(ir::BinaryExpression *bexpr) override + { + if (bexpr->IsArithmetic() || bexpr->IsBitwise() || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LESS_THAN || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_GREATER_THAN || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LEFT_SHIFT || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT) { + HandleArithmeticLike(bexpr); + return; + } + if (bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_STRICT_EQUAL || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_EQUAL || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_NOT_EQUAL) { + HandleEqualityOrInequality(bexpr); + return; + } + if (bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_NULLISH_COALESCING) { + bexpr->SetLeft( + AdjustType(uctx_, bexpr->Left(), + uctx_->checker->CreateETSUnionType({bexpr->TsType(), uctx_->checker->GlobalETSNullType(), + uctx_->checker->GlobalETSUndefinedType()}))); + bexpr->SetRight(AdjustType(uctx_, bexpr->Right(), bexpr->TsType())); + return; + } + if (bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_AND || + bexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_LOGICAL_OR) { + HandleLogical(bexpr); + return; + } + + if (bexpr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF) { + bexpr->SetLeft(AdjustType(uctx_, bexpr->Left(), uctx_->checker->MaybeBoxType(bexpr->Left()->TsType()))); + bexpr->SetTsType(uctx_->checker->GlobalETSBooleanType()); + return; + } + } + + void VisitUnaryExpression(ir::UnaryExpression *uexpr) override + { + if (uexpr->OperatorType() == lexer::TokenType::PUNCTUATOR_TILDE) { + uexpr->SetArgument(AdjustType(uctx_, uexpr->Argument(), uexpr->TsType())); + } + + uexpr->SetTsType(uctx_->checker->MaybeUnboxType(uexpr->TsType())); + if (TypeIsBoxedPrimitive(uexpr->Argument()->TsType())) { + uexpr->SetArgument(InsertUnboxing(uctx_, uexpr->Argument())); + } + } + + static bool IsStaticMemberExpression(ir::MemberExpression *mexpr) + { + ES2PANDA_ASSERT(mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS); + + auto *propDeclNode = mexpr->Property()->Variable()->Declaration()->Node(); + if (propDeclNode->IsMethodDefinition()) { + return propDeclNode->AsMethodDefinition()->IsStatic(); + } + if (propDeclNode->IsClassProperty()) { + return propDeclNode->AsClassProperty()->IsStatic(); + } + return propDeclNode->IsTSEnumMember(); + } + + static int GetNumberLiteral(ir::Expression *expr) // NOTE(gogabr): should use code from ConstantExpressionLowering + { + if (expr->IsNumberLiteral()) { + return static_cast(expr->AsNumberLiteral()->Number().GetDouble()); + } + // References to temp variables can appear in lowerings + if (expr->IsIdentifier()) { + auto *declNode = expr->Variable()->Declaration()->Node()->Parent()->AsVariableDeclarator(); + auto *initVal = declNode->Init(); + while (initVal->IsTSAsExpression()) { + initVal = initVal->AsTSAsExpression()->Expr(); + } + ES2PANDA_ASSERT(initVal->IsNumberLiteral()); + return initVal->AsNumberLiteral()->Number().GetInt(); + } + ES2PANDA_UNREACHABLE(); + } + + checker::Type *GetHandledGetterSetterType(ir::MemberExpression *mexpr, checker::Type *propType) + { + if (propType->IsETSMethodType()) { + bool needSetter = + mexpr->Parent()->IsAssignmentExpression() && mexpr == mexpr->Parent()->AsAssignmentExpression()->Left(); + if (needSetter) { // CC-OFF(G.FUN.01-CPP, C_RULE_ID_FUNCTION_NESTING_LEVEL) solid logic + if (auto *setterSig = propType->AsETSFunctionType()->FindSetter(); setterSig != nullptr) { + HandleDeclarationNode(uctx_, setterSig->Function()); + propType = setterSig->Params()[0]->TsType(); + } + } else if (auto *getterSig = propType->AsETSFunctionType()->FindGetter(); getterSig != nullptr) { + HandleDeclarationNode(uctx_, getterSig->Function()); + propType = getterSig->ReturnType(); + } + } else if (mexpr->Property()->Variable() != nullptr) { + /* Adjustment needed for Readonly types and possibly some other cases */ + mexpr->Property()->Variable()->SetTsType(propType); + } + return propType; + } + + // CC-OFFNXT(C_RULE_ID_FUNCTION_NESTING_LEVEL, huge_method[C++], huge_cca_cyclomatic_complexity[C++]) solid logic + // CC-OFFNXT(huge_cyclomatic_complexity, huge_depth[C++], huge_depth, huge_method, G.FUN.01-CPP, G.FUN.05) solid + void VisitMemberExpression(ir::MemberExpression *mexpr) override + { + if (mexpr->Object()->TsType()->IsETSDynamicType()) { + return; + } + if (mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS || + /* Workaround for memo plugin */ + mexpr->Kind() == ir::MemberExpressionKind::NONE || mexpr->Kind() == ir::MemberExpressionKind::GETTER || + mexpr->Kind() == ir::MemberExpressionKind::SETTER) { + if (mexpr->Property()->Variable() != nullptr) { + checker::Type *propType = nullptr; + if (mexpr->Property()->Variable()->Declaration() != nullptr && + mexpr->Property()->Variable()->Declaration()->Node() != nullptr && + mexpr->Property()->Variable()->Declaration()->Node()->IsTyped() && + mexpr->Property()->Variable()->Declaration()->Node()->AsTyped()->TsType() != nullptr) { + HandleDeclarationNode(uctx_, mexpr->Property()->Variable()->Declaration()->Node()); + propType = mexpr->Property()->Variable()->Declaration()->Node()->AsTyped()->TsType(); + } else if (mexpr->Property()->Variable()->TsType() != nullptr) { + propType = mexpr->Property()->Variable()->TsType(); + } else { + propType = mexpr->Property()->TsType(); + } + ES2PANDA_ASSERT(propType != nullptr); + + /* Special handling for getters/setters. */ + if (propType->IsETSMethodType()) { + propType = GetHandledGetterSetterType(mexpr, propType); + } else if (mexpr->Property()->Variable() != nullptr) { + /* Adjustment needed for Readonly types and possibly some other cases */ + mexpr->Property()->Variable()->SetTsType(propType); + } + + if (IsRecursivelyUnboxed(propType)) { + mexpr->Property()->SetTsType(propType); + mexpr->SetTsType(propType); + } + } else if (mexpr->Property()->Variable() == nullptr && mexpr->Object()->TsType()->IsETSArrayType() && + mexpr->Property()->AsIdentifier()->Name() == "length") { + mexpr->SetTsType(uctx_->checker->GlobalIntType()); + } + if (mexpr->Object()->TsType()->IsETSPrimitiveType() && !IsStaticMemberExpression(mexpr)) { + // NOTE(gogabr): need to handle some elementary method calls as intrinsics + mexpr->SetObject(InsertBoxing(uctx_, mexpr->Object())); + } + } else if (mexpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) { + /* Getters are already handled in a lowering, we need a primtive as an index */ + if (TypeIsBoxedPrimitive(mexpr->Property()->TsType())) { + mexpr->SetProperty(InsertUnboxing(uctx_, mexpr->Property())); + } + + if (mexpr->Object()->TsType()->IsETSTupleType()) { + auto tupType = mexpr->Object()->TsType()->AsETSTupleType(); + auto index = GetNumberLiteral(mexpr->Property()); + ES2PANDA_ASSERT(index >= 0 && (size_t)index < tupType->GetTupleSize()); + mexpr->SetTsType(tupType->GetTupleTypesList()[index]); + } else if (mexpr->Object()->TsType()->IsETSArrayType()) { + mexpr->SetTsType(GetArrayElementType(mexpr->Object()->TsType())); + } + /* mexpr->Object() may also have never type; nothing needs to be done in that case */ + } else { + ES2PANDA_UNREACHABLE(); + } + } + + void VisitTSAsExpression(ir::TSAsExpression *asExpr) override + { + auto *exprType = asExpr->Expr()->TsType(); + auto *targetType = asExpr->TypeAnnotation()->TsType(); + if (targetType->IsETSPrimitiveType() || TypeIsBoxedPrimitive(targetType)) { + if (exprType->IsETSPrimitiveType() || TypeIsBoxedPrimitive(exprType) || exprType->IsETSDynamicType()) { + auto *primTargetType = MaybeRecursivelyUnboxType(uctx_, targetType); + asExpr->TypeAnnotation()->SetTsType(primTargetType); + asExpr->SetExpr(AdjustType(uctx_, asExpr->Expr(), MaybeRecursivelyUnboxType(uctx_, exprType))); + asExpr->SetTsType(primTargetType); + } else { + auto *boxedTargetType = uctx_->checker->MaybeBoxType(targetType); + asExpr->TypeAnnotation()->SetTsType(boxedTargetType); + asExpr->SetTsType(boxedTargetType); + } + } else if (exprType->IsETSPrimitiveType()) { + asExpr->SetExpr(AdjustType(uctx_, asExpr->Expr(), targetType)); + } + asExpr->SetTsType(asExpr->TypeAnnotation()->TsType()); + } + + void VisitConditionalExpression(ir::ConditionalExpression *cexpr) override + { + if (TypeIsBoxedPrimitive(cexpr->Test()->TsType())) { + cexpr->SetTest(InsertUnboxing(uctx_, cexpr->Test())); + } + + auto *tp = cexpr->TsType(); + if (!tp->IsETSPrimitiveType() && !TypeIsBoxedPrimitive(tp)) { + // Box if needed + cexpr->SetConsequent(AdjustType(uctx_, cexpr->Consequent(), tp)); + cexpr->SetAlternate(AdjustType(uctx_, cexpr->Alternate(), tp)); + } else { + // Unbox if needed + auto *primTp = uctx_->checker->MaybeUnboxType(tp); + cexpr->SetConsequent(AdjustType(uctx_, cexpr->Consequent(), primTp)); + cexpr->SetAlternate(AdjustType(uctx_, cexpr->Alternate(), primTp)); + cexpr->SetTsType(primTp); + } + } + + void VisitETSNewArrayInstanceExpression(ir::ETSNewArrayInstanceExpression *nexpr) override + { + auto unboxedType = MaybeRecursivelyUnboxType(uctx_, nexpr->TsType()); + nexpr->SetTsType(unboxedType); + nexpr->TypeReference()->SetTsType(GetArrayElementType(unboxedType)); + + nexpr->SetDimension( + AdjustType(uctx_, nexpr->Dimension(), uctx_->checker->MaybeUnboxType(nexpr->Dimension()->TsType()))); + } + + void VisitETSNewMultiDimArrayInstanceExpression(ir::ETSNewMultiDimArrayInstanceExpression *nexpr) override + { + auto *unboxedType = MaybeRecursivelyUnboxType(uctx_, nexpr->TsType()); + nexpr->SetTsType(unboxedType); + + auto toUnbox = unboxedType; + for (auto &dim : nexpr->Dimensions()) { + dim = AdjustType(uctx_, dim, uctx_->checker->MaybeUnboxType(dim->TsType())); + toUnbox = GetArrayElementType(toUnbox); + } + + nexpr->TypeReference()->SetTsType(toUnbox); + nexpr->SetSignature( + uctx_->checker->CreateBuiltinArraySignature(unboxedType->AsETSArrayType(), nexpr->Dimensions().size())); + } + + void VisitBlockExpression(ir::BlockExpression *bexpr) override + { + auto &stmts = bexpr->Statements(); + auto *lastStmt = stmts[stmts.size() - 1]; + ES2PANDA_ASSERT(lastStmt->IsExpressionStatement()); + + bexpr->SetTsType(lastStmt->AsExpressionStatement()->GetExpression()->TsType()); + } + + void VisitSequenceExpression(ir::SequenceExpression *sexpr) override + { + sexpr->SetTsType(sexpr->Sequence().back()->TsType()); + } + + void HandleLiteral(ir::Literal *lit) + { + if (lit->TsType() == nullptr) { + return; + } + lit->SetTsType(uctx_->checker->MaybeUnboxType(lit->TsType())); + } + + void VisitBooleanLiteral(ir::BooleanLiteral *blit) override + { + HandleLiteral(blit); + } + void VisitCharLiteral(ir::CharLiteral *clit) override + { + HandleLiteral(clit); + } + void VisitNumberLiteral(ir::NumberLiteral *nlit) override + { + HandleLiteral(nlit); + } + + void HandleVariableRef(ir::Expression *expr) + { + auto *var = expr->Variable(); + if (var == nullptr || var->TsType() == nullptr || expr->TsType() == nullptr || + var->Declaration() == nullptr) { // lambda invoke function + return; + } + auto *declNode = var->Declaration()->Node(); + if (declNode->IsClassProperty()) { + HandleDeclarationNode(uctx_, declNode); + } + if (declNode->IsClassDeclaration() || declNode->IsTSEnumDeclaration() || declNode->IsTSInterfaceDeclaration()) { + return; + } + if (expr->Variable()->TsType()->IsETSPrimitiveType()) { + expr->SetTsType(expr->Variable()->TsType()); + } else if (expr->TsType()->IsETSPrimitiveType()) { + expr->SetTsType(uctx_->checker->MaybeBoxType(expr->TsType())); + } else { + expr->SetTsType(NormalizeType(uctx_, expr->TsType())); + } + } + + void VisitIdentifier(ir::Identifier *id) override + { + HandleVariableRef(id); + } + + void VisitTSQualifiedName(ir::TSQualifiedName *qname) override + { + HandleVariableRef(qname); + } + + void VisitAssignmentExpression(ir::AssignmentExpression *aexpr) override + { + aexpr->SetRight(AdjustType(uctx_, aexpr->Right(), aexpr->Left()->TsType())); + aexpr->SetTsType(aexpr->Left()->TsType()); + } + + void VisitClassProperty(ir::ClassProperty *prop) override + { + prop->SetValue(AdjustType(uctx_, prop->Value(), prop->Key()->Variable()->TsType())); + } + + void VisitETSParameterExpression(ir::ETSParameterExpression *pexpr) override + { + pexpr->AsETSParameterExpression()->SetInitializer( + AdjustType(uctx_, pexpr->Initializer(), pexpr->Ident()->TsType())); + } + + void VisitVariableDeclarator(ir::VariableDeclarator *vdecl) override + { + if (vdecl->Init() != nullptr) { + vdecl->SetInit(AdjustType(uctx_, vdecl->Init(), vdecl->Id()->Variable()->TsType())); + } + } + + void VisitTSNonNullExpression(ir::TSNonNullExpression *nnexpr) override + { + if (nnexpr->Expr()->TsType()->IsETSPrimitiveType()) { + ReplaceInParent(nnexpr, nnexpr->Expr()); + return; + } + nnexpr->SetTsType(uctx_->checker->GetNonNullishType(nnexpr->Expr()->TsType())); + nnexpr->SetOriginalType(nnexpr->TsType()); + } + + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes, readability-identifier-naming, G.NAM.03-CPP) + UnboxContext *uctx_; +}; +} // namespace + +// Extracted just to avoid large depth of method 'SetUpBuiltinConstructorsAndMethods(UnboxContext *uctx)'. +static void HandleInstanceMethodsDeclaration(checker::Type *tp, UnboxContext *uctx) +{ + for (auto [_, var] : tp->AsETSObjectType()->InstanceMethods()) { + auto *nd = var->Declaration()->Node(); + HandleDeclarationNode(uctx, nd); + if (nd->IsMethodDefinition()) { + for (auto overload : nd->AsMethodDefinition()->Overloads()) { + HandleDeclarationNode(uctx, overload); + } + } + } +} + +// Extracted just to avoid large depth of method 'SetUpBuiltinConstructorsAndMethods(UnboxContext *uctx)'. +static void HandleStaticMethodDeclaration(checker::Type *tp, UnboxContext *uctx) +{ + for (auto [_, var] : tp->AsETSObjectType()->StaticMethods()) { + auto *nd = var->Declaration()->Node(); + HandleDeclarationNode(uctx, nd); + if (nd->IsMethodDefinition()) { + for (auto overload : nd->AsMethodDefinition()->Overloads()) { + HandleDeclarationNode(uctx, overload); + } + } + } +} + +// We need to convert function declarations that can be referenced even without explicit mention +// in the source code. +void SetUpBuiltinConstructorsAndMethods(UnboxContext *uctx) +{ + auto *checker = uctx->checker; + auto setUpType = [&uctx](checker::Type *tp) { + if (tp == nullptr || !tp->IsETSObjectType()) { + return; + } + for (auto *sig : tp->AsETSObjectType()->ConstructSignatures()) { + HandleDeclarationNode(uctx, sig->Function()); + } + HandleInstanceMethodsDeclaration(tp, uctx); + HandleStaticMethodDeclaration(tp, uctx); + }; + + for (auto tpix = (size_t)checker::GlobalTypeId::ETS_BOOLEAN; tpix < (size_t)checker::GlobalTypeId::ETS_BIG_INT; + tpix++) { + setUpType(checker->GetGlobalTypesHolder()->GlobalTypes().at(tpix)); + } +} + +template +static void VisitExternalPrograms(UnboxVisitor *visitor, parser::Program *program) +{ + for (auto &[_, extPrograms] : program->ExternalSources()) { + (void)_; + for (auto *extProg : extPrograms) { + VisitExternalPrograms(visitor, extProg); + } + } + + if constexpr (!PROG_IS_EXTERNAL) { + return; + } + + auto annotationIterator = [visitor](auto *child) { + if (child->IsClassProperty()) { + auto prop = child->AsClassProperty(); + HandleClassProperty(visitor->uctx_, prop); + if (prop->Value() != nullptr) { + ES2PANDA_ASSERT(prop->Value()->IsLiteral() || prop->Value()->IsArrayExpression() || + (prop->Value()->IsTyped() && prop->Value()->AsTyped()->TsType()->IsETSEnumType())); + prop->Value()->Accept(visitor); + } + visitor->VisitClassProperty(child->AsClassProperty()); + }; + }; + + program->Ast()->IterateRecursivelyPostorder([&annotationIterator](ir::AstNode *ast) { + if (ast->IsAnnotationDeclaration() || ast->IsAnnotationUsage()) { + ast->Iterate(annotationIterator); + } + }); +} + +bool UnboxPhase::PerformForModule(public_lib::Context *ctx, parser::Program *program) +{ + auto uctx = UnboxContext(ctx); + + SetUpBuiltinConstructorsAndMethods(&uctx); + + NormalizeAllTypes(&uctx, program->Ast()); + + program->Ast()->IterateRecursivelyPostorder([&uctx](ir::AstNode *ast) { + if (ast->IsClassProperty() || ast->IsScriptFunction() || ast->IsVariableDeclarator()) { + HandleDeclarationNode(&uctx, ast); + } else if (ast->IsForOfStatement()) { + HandleForOfStatement(&uctx, ast->AsForOfStatement()); + } + }); + + UnboxVisitor visitor(&uctx); + program->Ast()->IterateRecursivelyPostorder([&visitor](ir::AstNode *ast) { ast->Accept(&visitor); }); + VisitExternalPrograms(&visitor, program); + + for (auto *stmt : program->Ast()->Statements()) { + RefineSourceRanges(stmt); + } + uctx.checker->ClearApparentTypes(); + + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/boxedTypeLowering.h b/ets2panda/compiler/lowering/ets/unboxLowering.h similarity index 70% rename from ets2panda/compiler/lowering/ets/boxedTypeLowering.h rename to ets2panda/compiler/lowering/ets/unboxLowering.h index c7d21d52b0..6547909d0e 100644 --- a/ets2panda/compiler/lowering/ets/boxedTypeLowering.h +++ b/ets2panda/compiler/lowering/ets/unboxLowering.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,20 +13,23 @@ * limitations under the License. */ -#ifndef ES2PANDA_COMPILER_LOWERING_BOXED_TYPE_LOWERING_H -#define ES2PANDA_COMPILER_LOWERING_BOXED_TYPE_LOWERING_H +#ifndef ES2PANDA_COMPILER_LOWERING_UNBOX_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_UNBOX_LOWERING_H #include "compiler/lowering/phase.h" namespace ark::es2panda::compiler { -class BoxedTypeLowering : public PhaseForDeclarations { +class UnboxPhase : public PhaseForBodies { public: - std::string_view Name() const override; + std::string_view Name() const override + { + return "Unbox"; + } bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; }; } // namespace ark::es2panda::compiler -#endif // ES2PANDA_COMPILER_LOWERING_BOXED_TYPE_LOWERING_H +#endif diff --git a/ets2panda/compiler/lowering/ets/unionLowering.cpp b/ets2panda/compiler/lowering/ets/unionLowering.cpp index ecbedb0619..61cacd86a4 100644 --- a/ets2panda/compiler/lowering/ets/unionLowering.cpp +++ b/ets2panda/compiler/lowering/ets/unionLowering.cpp @@ -202,64 +202,6 @@ static void HandleUnionPropertyAccess(public_lib::Context *ctx, varbinder::VarBi ES2PANDA_ASSERT(expr->PropVar() != nullptr); } -static ir::TSAsExpression *GenAsExpression(public_lib::Context *ctx, checker::Type *const opaqueType, - ir::Expression *const node, ir::AstNode *const parent) -{ - auto *const typeNode = ctx->AllocNode(opaqueType, ctx->Allocator()); - auto *const asExpression = ctx->AllocNode(node, typeNode, false); - asExpression->SetParent(parent); - asExpression->Check(ctx->GetChecker()->AsETSChecker()); - return asExpression; -} - -/* - * Function that generates conversion from (union) to (primitive) type as to `as` expressions: - * (union) as (prim) => ((union) as (ref)) as (prim), - * where (ref) is some unboxable type from union constituent types. - * Finally, `(union) as (prim)` expression replaces union_node that came above. - */ -static ir::TSAsExpression *UnionCastToPrimitive(public_lib::Context *ctx, checker::ETSObjectType *unboxableRef, - checker::Type *unboxedPrim, ir::Expression *unionNode) -{ - auto *const unionAsRefExpression = GenAsExpression(ctx, unboxableRef, unionNode, nullptr); - return GenAsExpression(ctx, unboxedPrim, unionAsRefExpression, unionNode->Parent()); -} - -static ir::TSAsExpression *HandleUnionCastToPrimitive(public_lib::Context *ctx, ir::TSAsExpression *expr) -{ - checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); - auto *const unionType = expr->Expr()->TsType()->AsETSUnionType(); - auto *sourceType = unionType->FindExactOrBoxedType(checker, expr->TsType()); - if (sourceType == nullptr) { - sourceType = unionType->AsETSUnionType()->FindTypeIsCastableToSomeType(expr->Expr(), checker->Relation(), - expr->TsType()); - } - - if (sourceType != nullptr && expr->Expr()->GetBoxingUnboxingFlags() != ir::BoxingUnboxingFlags::NONE) { - auto *maybeUnboxingType = checker->MaybeUnboxInRelation(sourceType); - // when sourceType get `object`, it could cast to any primitive type but can't be unboxed; - if (maybeUnboxingType != nullptr && expr->TsType()->IsETSPrimitiveType()) { - auto *const asExpr = GenAsExpression(ctx, sourceType, expr->Expr(), expr); - asExpr->SetBoxingUnboxingFlags(checker->GetUnboxingFlag(maybeUnboxingType)); - expr->Expr()->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); - expr->SetExpr(asExpr); - } - - return expr; - } - - auto *const unboxableUnionType = sourceType != nullptr ? sourceType : unionType->FindUnboxableType(); - auto *const unboxedUnionType = checker->MaybeUnboxInRelation(unboxableUnionType); - if (unboxableUnionType == nullptr || !unboxableUnionType->IsETSObjectType() || unboxedUnionType == nullptr) { - return expr; - } - - auto *const node = UnionCastToPrimitive(ctx, unboxableUnionType->AsETSObjectType(), unboxedUnionType, expr->Expr()); - node->SetParent(expr->Parent()); - - return node; -} - bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) { checker::ETSChecker *checker = ctx->GetChecker()->AsETSChecker(); @@ -274,12 +216,6 @@ bool UnionLowering::PerformForModule(public_lib::Context *ctx, parser::Program * return ast; } } - if (ast->IsTSAsExpression() && ast->AsTSAsExpression()->Expr()->TsType() != nullptr && - ast->AsTSAsExpression()->Expr()->TsType()->IsETSUnionType() && - ast->AsTSAsExpression()->TsType() != nullptr && - ast->AsTSAsExpression()->TsType()->IsETSPrimitiveType()) { - return HandleUnionCastToPrimitive(ctx, ast->AsTSAsExpression()); - } return ast; }, diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 7525670200..398f549431 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -22,7 +22,6 @@ #include "compiler/lowering/ets/ambientLowering.h" #include "compiler/lowering/ets/arrayLiteralLowering.h" #include "compiler/lowering/ets/bigintLowering.h" -#include "compiler/lowering/ets/boxedTypeLowering.h" #include "compiler/lowering/ets/boxingForLocals.h" #include "compiler/lowering/ets/capturedVariables.h" #include "compiler/lowering/ets/constantExpressionLowering.h" @@ -34,6 +33,7 @@ #include "compiler/lowering/ets/dynamicImportLowering.h" #include "compiler/lowering/ets/enumLowering.h" #include "compiler/lowering/ets/enumPostCheckLowering.h" +#include "compiler/lowering/ets/enumPropertiesInAnnotationsLowering.h" #include "compiler/lowering/ets/restTupleLowering.h" #include "compiler/lowering/ets/expandBrackets.h" #include "compiler/lowering/ets/exportAnonymousConst.h" @@ -53,6 +53,7 @@ #include "compiler/lowering/ets/optionalLowering.h" #include "compiler/lowering/ets/packageImplicitImport.h" #include "compiler/lowering/ets/partialExportClassGen.h" +#include "compiler/lowering/ets/primitiveConversionPhase.h" #include "compiler/lowering/ets/promiseVoid.h" #include "compiler/lowering/ets/recordLowering.h" #include "compiler/lowering/ets/resizableArrayLowering.h" @@ -64,6 +65,7 @@ #include "compiler/lowering/ets/stringConstantsLowering.h" #include "compiler/lowering/ets/stringConstructorLowering.h" #include "compiler/lowering/ets/topLevelStmts/topLevelStmts.h" +#include "compiler/lowering/ets/unboxLowering.h" #include "compiler/lowering/ets/unionLowering.h" #include "compiler/lowering/ets/typeFromLowering.h" #include "compiler/lowering/plugin_phase.h" @@ -123,7 +125,7 @@ std::vector GetETSPhaseList() new CheckerPhase, // pluginsAfterCheck has to go right after checkerPhase, nothing should be between them new PluginPhase {g_pluginsAfterCheck, ES2PANDA_STATE_CHECKED, &util::Plugin::AfterCheck}, - new ConvertPrimitiveCastMethodCall, + // new ConvertPrimitiveCastMethodCall, new AnnotationCopyPostLowering, new DynamicImportLowering, new AsyncMethodLowering, @@ -138,7 +140,6 @@ std::vector GetETSPhaseList() new ExtensionAccessorPhase, new BoxingForLocals, new RecordLowering, - new BoxedTypeLowering, new ObjectIndexLowering, new ObjectIteratorLowering, new LambdaConversionPhase, @@ -153,6 +154,8 @@ std::vector GetETSPhaseList() new OptionalArgumentsLowering, // #22952 could be moved to earlier phase new GenericBridgesPhase, new TypeFromLowering, + new PrimitiveConversionPhase, + new UnboxPhase, // pluginsAfterLowerings has to come at the very end, nothing should go after it new PluginPhase{g_pluginsAfterLowering, ES2PANDA_STATE_LOWERED, &util::Plugin::AfterLowerings}, diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index e19ee51185..49e83d88f1 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -1082,7 +1082,7 @@ void InitScopesPhaseETS::VisitTSEnumMember(ir::TSEnumMember *enumMember) if (var = VarBinder()->GetScope()->FindLocal(name, varbinder::ResolveBindingOptions::STATIC_VARIABLES); var == nullptr) { varbinder::Decl *decl = nullptr; - std::tie(decl, var) = VarBinder()->NewVarDecl(ident->Start(), name); + std::tie(decl, var) = VarBinder()->NewVarDecl(ident->Start(), name); var->SetScope(VarBinder()->GetScope()); var->AddFlag(varbinder::VariableFlags::STATIC); decl->BindNode(enumMember); diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index a80338b1f7..818ba9c8bd 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -308,6 +308,15 @@ ir::AstNode *DeclarationFromIdentifier(const ir::Identifier *node) return decl->Node(); } +// Note: run varbinder on the new node generated in lowering phases (without ClearTypesVariablesAndScopes) +void BindLoweredNode(varbinder::ETSBinder *varBinder, ir::AstNode *node) +{ + RefineSourceRanges(node); + InitScopesPhaseETS::RunExternalNode(node, varBinder); + auto *scope = NearestScope(node); + varBinder->ResolveReferencesForScopeWithContext(node, scope); +} + // Note: run varbinder and checker on the new node generated in lowering phases (without ClearTypesVariablesAndScopes) void CheckLoweredNode(varbinder::ETSBinder *varBinder, checker::ETSChecker *checker, ir::AstNode *node) { diff --git a/ets2panda/compiler/lowering/util.h b/ets2panda/compiler/lowering/util.h index 423035454f..f4b13825fc 100644 --- a/ets2panda/compiler/lowering/util.h +++ b/ets2panda/compiler/lowering/util.h @@ -43,8 +43,12 @@ void Recheck(PhaseManager *phaseManager, varbinder::ETSBinder *varBinder, checke // NOTE: used to get the declaration from identifier in Plugin API and LSP ir::AstNode *DeclarationFromIdentifier(const ir::Identifier *node); +// Note: run varbinder on the new node generated in lowering phases +void BindLoweredNode(varbinder::ETSBinder *varBinder, ir::AstNode *node); + // Note: run varbinder and checker on the new node generated in lowering phases void CheckLoweredNode(varbinder::ETSBinder *varBinder, checker::ETSChecker *checker, ir::AstNode *node); + bool IsAnonymousClassType(const checker::Type *type); bool ClassDefinitionIsEnumTransformed(const ir::AstNode *node); } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index ba71dc0e6c..7cfa309206 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -215,6 +215,20 @@ defines: ref: MIN_ARGSCOUNT_OF_FUNC - name: 'gensym%%_anonymous_const' ref: EXPORT_DEFAULT_CONSTANT_ANONYMOUSLY + - name: 'toByte' + ref: BYTE_CAST + - name: 'toShort' + ref: SHORT_CAST + - name: 'toInt' + ref: INT_CAST + - name: 'toLong' + ref: LONG_CAST + - name: 'toFloat' + ref: FLOAT_CAST + - name: 'toDouble' + ref: DOUBLE_CAST + - name: 'toChar' + ref: CHAR_CAST - name: 'NamedFunctionObject' ref: NAMED_FUNCTION_OBJECT - name: 'InterfaceObjectLiteral' @@ -1467,6 +1481,12 @@ signatures: return_type: BUILTIN_JSVALUE ref: BUILTIN_JSRUNTIME_GET_UNDEFINED + - callee: BUILTIN_JSRUNTIME + method_name: getNull + params: [] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_GET_NULL + - callee: BUILTIN_JSRUNTIME method_name: strictEqual params: [BUILTIN_JSVALUE, BUILTIN_JSVALUE] @@ -1794,3 +1814,4 @@ dynamiclangs: - type: dynamic builtin: BUILTIN_JSRUNTIME_SET_ELEMENT_JSVALUE get_undefined: BUILTIN_JSRUNTIME_GET_UNDEFINED + get_null: BUILTIN_JSRUNTIME_GET_NULL diff --git a/ets2panda/compiler/templates/signatures.h.erb b/ets2panda/compiler/templates/signatures.h.erb index 8f09ce2292..afd5719623 100644 --- a/ets2panda/compiler/templates/signatures.h.erb +++ b/ets2panda/compiler/templates/signatures.h.erb @@ -162,6 +162,17 @@ public: ES2PANDA_UNREACHABLE(); } + static std::string_view GetNullBuiltin(Language lang) + { + ES2PANDA_ASSERT(IsSupported(lang)); +% Signatures::DYNAMIC.each do |lang, data| + if (lang.GetId() == Language::Id::<%= lang.upcase %>) { + return <%= data.builtins.get_null %>; + } +% end + ES2PANDA_UNREACHABLE(); + } + % def generate(attr, pref) % builtins = Hash.new() % Signatures::DYNAMIC.each do |lang, data| diff --git a/ets2panda/evaluate/debugInfoDeserialization/methodBuilder.cpp b/ets2panda/evaluate/debugInfoDeserialization/methodBuilder.cpp index 2f79f32dbf..581b830fde 100644 --- a/ets2panda/evaluate/debugInfoDeserialization/methodBuilder.cpp +++ b/ets2panda/evaluate/debugInfoDeserialization/methodBuilder.cpp @@ -64,7 +64,8 @@ ir::ReturnStatement *CreateTypedReturnStatement(checker::ETSChecker *checker, ir auto *callee = checker->AllocNode(apiClass, prop, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - ArenaVector args(1, checker->AllocNode("0"), allocator->Adapter()); + ArenaVector args(1, checker->AllocNode(lexer::Number((int64_t)0)), + allocator->Adapter()); auto *callExpression = checker->AllocNode(callee, std::move(args), nullptr, false); auto *asExpression = checker->AllocNode(callExpression, type->Clone(allocator, nullptr), false); diff --git a/ets2panda/evaluate/irCheckHelper.cpp b/ets2panda/evaluate/irCheckHelper.cpp index b963be112b..2ae79653f3 100644 --- a/ets2panda/evaluate/irCheckHelper.cpp +++ b/ets2panda/evaluate/irCheckHelper.cpp @@ -65,15 +65,16 @@ void IrCheckHelper::PreCheck() isPrecheckPassed_ = true; } +// NOLINTBEGIN(readability-identifier-naming) void IrCheckHelper::CheckDecls() { // All dependent user-classes must be created at this point, so we can run checker. while (!recursiveDecls_.empty()) { auto [program, scope, parent, node] = recursiveDecls_.front(); recursiveDecls_.pop_front(); - helpers::DoScopedAction(checker_, varBinder_, program, scope, parent, [this, node = node, scope = scope]() { - varBinder_->ResolveReferencesForScope(node, scope); - node->Check(checker_); + helpers::DoScopedAction(checker_, varBinder_, program, scope, parent, [this, node_ = node, scope_ = scope]() { + varBinder_->ResolveReferencesForScope(node_, scope_); + node_->Check(checker_); }); } } @@ -87,10 +88,11 @@ void IrCheckHelper::HandleCustomNodes() // Hence we delay `ETSChecker::Check` until all required classes are built and initialized in varbinder. auto [program, scope, parent, node] = *iter; helpers::DoScopedAction(checker_, varBinder_, program, scope, parent, - [varBinder = varBinder_, node = node]() { varBinder->HandleCustomNodes(node); }); + [varBinder = varBinder_, node_ = node]() { varBinder->HandleCustomNodes(node_); }); ++iter; } } +// NOLINTEND(readability-identifier-naming) void IrCheckHelper::CheckGlobalEntity(parser::Program *program, ir::AstNode *node, bool mustCheck) { diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 3b8a45b1bc..9661f1c36c 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -130,10 +130,35 @@ void AstNode::TransformChildrenRecursively(const NodeTransformer &cb, std::strin TransformChildrenRecursivelyPostorder(cb, transformationName); } +void AstNode::TransformChildrenRecursively(const NodeTransformer &pre, const NodeTraverser &post, + std::string_view transformationName) +{ + TransformChildren( + [&pre, &post, transformationName](AstNode *child) { + auto *childReplacement = pre(child); + childReplacement->TransformChildrenRecursively(pre, post, transformationName); + post(childReplacement); + return childReplacement; + }, + transformationName); +} + +void AstNode::TransformChildrenRecursively(const NodeTraverser &pre, const NodeTransformer &post, + std::string_view transformationName) +{ + TransformChildren( + [&pre, &post, transformationName](AstNode *child) { + pre(child); + child->TransformChildrenRecursively(pre, post, transformationName); + return post(child); + }, + transformationName); +} + void AstNode::TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName) { TransformChildren( - [=](AstNode *child) { + [&cb, transformationName](AstNode *child) { auto *res = cb(child); res->TransformChildrenRecursivelyPreorder(cb, transformationName); return res; @@ -144,7 +169,7 @@ void AstNode::TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, st void AstNode::TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName) { TransformChildren( - [=](AstNode *child) { + [&cb, transformationName](AstNode *child) { child->TransformChildrenRecursivelyPostorder(cb, transformationName); return cb(child); }, @@ -158,7 +183,7 @@ void AstNode::IterateRecursively(const NodeTraverser &cb) const void AstNode::IterateRecursivelyPreorder(const NodeTraverser &cb) const { - Iterate([=](AstNode *child) { + Iterate([&cb](AstNode *child) { cb(child); child->IterateRecursivelyPreorder(cb); }); @@ -166,7 +191,7 @@ void AstNode::IterateRecursivelyPreorder(const NodeTraverser &cb) const void AstNode::IterateRecursivelyPostorder(const NodeTraverser &cb) const { - Iterate([=](AstNode *child) { + Iterate([&cb](AstNode *child) { child->IterateRecursivelyPostorder(cb); cb(child); }); @@ -183,7 +208,7 @@ void AnyChildHelper(bool *found, const NodePredicate &cb, AstNode *ast) return; } - ast->Iterate([=](AstNode *child) { AnyChildHelper(found, cb, child); }); + ast->Iterate([&cb, found](AstNode *child) { AnyChildHelper(found, cb, child); }); } bool AstNode::IsAnyChild(const NodePredicate &cb) const @@ -282,6 +307,7 @@ void AstNode::CleanUp() } if (IsTyped()) { this->AsTyped()->SetTsType(nullptr); + this->AsTyped()->SetPreferredType(nullptr); } } @@ -331,7 +357,6 @@ void AstNode::CopyTo(AstNode *other) const other->range_ = range_; other->flags_ = flags_; other->astNodeFlags_ = astNodeFlags_; - other->boxingUnboxingFlags_ = boxingUnboxingFlags_; other->history_ = history_; other->variable_ = variable_; other->originalNode_ = originalNode_; diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 5489ceb5f6..1fd37c07dd 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -514,7 +514,6 @@ public: } \ } - DECLARE_FLAG_OPERATIONS(BoxingUnboxingFlags, boxingUnboxingFlags_); DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_); #undef DECLARE_FLAG_OPERATIONS @@ -537,6 +536,12 @@ public: virtual void Iterate(const NodeTraverser &cb) const = 0; void TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName); + void TransformChildrenRecursively(const NodeTransformer &pre, const NodeTraverser &post, + std::string_view transformationName); + void TransformChildrenRecursively(const NodeTraverser &pre, const NodeTransformer &post, + std::string_view transformationName); + // CC-OFFNXT(C_RULE_ID_FUNCTION_HEADER, G.CMT.04) false positive + // Keep these for perf reasons: void TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName); void TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName); @@ -619,7 +624,6 @@ protected: AstNodeType type_; ModifierFlags flags_ {}; mutable AstNodeFlags astNodeFlags_ {}; - mutable BoxingUnboxingFlags boxingUnboxingFlags_ {}; AstNodeHistory *history_ {nullptr}; // NOLINTEND(misc-non-private-member-variables-in-classes) diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index 617e3e42f8..88169f4b56 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -112,30 +112,6 @@ enum class ScriptFunctionFlags : uint32_t { enum class TSOperatorType { READONLY, KEYOF, UNIQUE }; enum class MappedOption { NO_OPTS, PLUS, MINUS }; -enum class BoxingUnboxingFlags : uint32_t { - NONE = 0U, - BOX_TO_BOOLEAN = 1U << 0U, - BOX_TO_BYTE = 1U << 1U, - BOX_TO_SHORT = 1U << 2U, - BOX_TO_CHAR = 1U << 3U, - BOX_TO_INT = 1U << 4U, - BOX_TO_LONG = 1U << 5U, - BOX_TO_FLOAT = 1U << 6U, - BOX_TO_DOUBLE = 1U << 7U, - BOX_TO_ENUM = 1U << 8U, - UNBOX_TO_BOOLEAN = 1U << 9U, - UNBOX_TO_BYTE = 1U << 10U, - UNBOX_TO_SHORT = 1U << 11U, - UNBOX_TO_CHAR = 1U << 12U, - UNBOX_TO_INT = 1U << 13U, - UNBOX_TO_LONG = 1U << 14U, - UNBOX_TO_FLOAT = 1U << 15U, - UNBOX_TO_DOUBLE = 1U << 16U, - BOXING_FLAG = BOX_TO_BOOLEAN | BOX_TO_BYTE | BOX_TO_SHORT | BOX_TO_CHAR | BOX_TO_INT | BOX_TO_LONG | BOX_TO_FLOAT | - BOX_TO_DOUBLE | BOX_TO_ENUM, - UNBOXING_FLAG = UNBOX_TO_BOOLEAN | UNBOX_TO_BYTE | UNBOX_TO_SHORT | UNBOX_TO_CHAR | UNBOX_TO_INT | UNBOX_TO_LONG | - UNBOX_TO_FLOAT | UNBOX_TO_DOUBLE, -}; } // namespace ark::es2panda::ir namespace enumbitops { @@ -152,10 +128,6 @@ template <> struct IsAllowedType : std::true_type { }; -template <> -struct IsAllowedType : std::true_type { -}; - } // namespace enumbitops #endif diff --git a/ets2panda/ir/base/classDefinition.h b/ets2panda/ir/base/classDefinition.h index 7a8c0ed2ef..fd71f32cd3 100644 --- a/ets2panda/ir/base/classDefinition.h +++ b/ets2panda/ir/base/classDefinition.h @@ -378,12 +378,12 @@ public: return GetHistoryNodeAs()->localIndex_; } - [[nodiscard]] util::StringView FunctionalReferenceReferencedMethod() const noexcept + [[nodiscard]] MethodDefinition *FunctionalReferenceReferencedMethod() const noexcept { return functionalReferenceReferencedMethod_; } - void SetFunctionalReferenceReferencedMethod(util::StringView functionalReferenceReferencedMethod) + void SetFunctionalReferenceReferencedMethod(MethodDefinition *functionalReferenceReferencedMethod) { functionalReferenceReferencedMethod_ = functionalReferenceReferencedMethod; } @@ -568,7 +568,7 @@ private: static std::atomic classCounter_; int localIndex_ {}; std::string localPrefix_ {}; - util::StringView functionalReferenceReferencedMethod_ {}; + MethodDefinition *functionalReferenceReferencedMethod_ {}; ArenaVector exportedClasses_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index a3356c3c10..db8c7b5eea 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -107,14 +107,13 @@ void ETSNewArrayInstanceExpression::ClearPreferredType() { SetPreferredType(nullptr); SetTsType(nullptr); - TypeReference()->SetBoxingUnboxingFlags(BoxingUnboxingFlags::NONE); } void ETSNewArrayInstanceExpression::SetPreferredTypeBasedOnFuncParam(checker::ETSChecker *checker, checker::Type *param, checker::TypeRelationFlag flags) { // NOTE (mmartin): This needs a complete solution - if (preferredType_ != nullptr) { + if (PreferredType() != nullptr) { return; } diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index 37e56f212a..b1b4885340 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -75,21 +75,6 @@ public: return defaultConstructorSignature_; } - void SetPreferredType(checker::Type *preferredType) noexcept - { - preferredType_ = preferredType; - } - - [[nodiscard]] checker::Type *GetPreferredType() noexcept - { - return preferredType_; - } - - [[nodiscard]] checker::Type const *GetPreferredType() const noexcept - { - return preferredType_; - } - void SetDimension(ir::Expression *dimension) noexcept { dimension_ = dimension; @@ -133,7 +118,6 @@ private: ir::TypeNode *typeReference_; ir::Expression *dimension_; checker::Signature *defaultConstructorSignature_ {}; - checker::Type *preferredType_ {}; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index a79d71241b..d5cd0530e8 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -87,7 +87,6 @@ void ETSNewMultiDimArrayInstanceExpression::ClearPreferredType() { SetPreferredType(nullptr); SetTsType(nullptr); - TypeReference()->SetBoxingUnboxingFlags(BoxingUnboxingFlags::NONE); } ETSNewMultiDimArrayInstanceExpression::ETSNewMultiDimArrayInstanceExpression( @@ -119,7 +118,7 @@ void ETSNewMultiDimArrayInstanceExpression::SetPreferredTypeBasedOnFuncParam(che checker::TypeRelationFlag flags) { // NOTE (mmartin): This needs a complete solution - if (preferredType_ != nullptr) { + if (PreferredType() != nullptr) { return; } if (!param->IsETSArrayType()) { diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 788da436fd..31aab67ffa 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -79,21 +79,6 @@ public: return signature_; } - [[nodiscard]] checker::Type *GetPreferredType() noexcept - { - return preferredType_; - } - - [[nodiscard]] checker::Type const *GetPreferredType() const noexcept - { - return preferredType_; - } - - void SetPreferredType(checker::Type *preferredType) noexcept - { - preferredType_ = preferredType; - } - void SetSignature(checker::Signature *signature) noexcept { signature_ = signature; @@ -130,7 +115,6 @@ private: ir::TypeNode *typeReference_; ArenaVector dimensions_; checker::Signature *signature_ {}; - checker::Type *preferredType_ {}; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ets/etsPrimitiveType.cpp b/ets2panda/ir/ets/etsPrimitiveType.cpp index c4d18a628d..6fc11fec68 100644 --- a/ets2panda/ir/ets/etsPrimitiveType.cpp +++ b/ets2panda/ir/ets/etsPrimitiveType.cpp @@ -106,35 +106,35 @@ checker::Type *ETSPrimitiveType::GetType([[maybe_unused]] checker::ETSChecker *c { switch (GetPrimitiveType()) { case PrimitiveType::BYTE: { - SetTsType(checker->GlobalByteType()); + SetTsType(checker->GlobalByteBuiltinType()); return TsType(); } case PrimitiveType::SHORT: { - SetTsType(checker->GlobalShortType()); + SetTsType(checker->GlobalShortBuiltinType()); return TsType(); } case PrimitiveType::INT: { - SetTsType(checker->GlobalIntType()); + SetTsType(checker->GlobalIntBuiltinType()); return TsType(); } case PrimitiveType::LONG: { - SetTsType(checker->GlobalLongType()); + SetTsType(checker->GlobalLongBuiltinType()); return TsType(); } case PrimitiveType::FLOAT: { - SetTsType(checker->GlobalFloatType()); + SetTsType(checker->GlobalFloatBuiltinType()); return TsType(); } case PrimitiveType::DOUBLE: { - SetTsType(checker->GlobalDoubleType()); + SetTsType(checker->GlobalDoubleBuiltinType()); return TsType(); } case PrimitiveType::BOOLEAN: { - SetTsType(checker->GlobalETSBooleanType()); + SetTsType(checker->GlobalETSBooleanBuiltinType()); return TsType(); } case PrimitiveType::CHAR: { - SetTsType(checker->GlobalCharType()); + SetTsType(checker->GlobalCharBuiltinType()); return TsType(); } case PrimitiveType::VOID: { diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 79b9e906fb..3b143a0872 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -92,10 +92,8 @@ checker::Type *ETSTuple::GetHolderTypeForTuple(checker::ETSChecker *const checke return typeList[0]; } - std::for_each(typeList.begin(), typeList.end(), [checker](auto &t) { t = checker->MaybeBoxType(t); }); - - auto ctypes = typeList; - return checker->CreateETSUnionType(std::move(ctypes)); + /* NOTE(gogabr): if we compute a union type, we'll lose smaller numeric types, so just return Object */ + return checker->GlobalETSAnyType(); } checker::Type *ETSTuple::GetType(checker::ETSChecker *const checker) diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index cc9ec65885..418e936818 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -31,7 +31,7 @@ ArrayExpression::ArrayExpression([[maybe_unused]] Tag const tag, ArrayExpression decorators_(allocator->Adapter()), elements_(allocator->Adapter()) { - preferredType_ = other.preferredType_; + SetPreferredType(other.PreferredType()); isDeclaration_ = other.isDeclaration_; trailingComma_ = other.trailingComma_; optional_ = other.optional_; @@ -355,7 +355,6 @@ void ArrayExpression::ClearPreferredType() SetPreferredType(nullptr); SetTsType(nullptr); for (auto element : Elements()) { - element->SetBoxingUnboxingFlags(ir::BoxingUnboxingFlags::NONE); element->SetTsType(nullptr); element->SetAstNodeFlags(ir::AstNodeFlags::NO_OPTS); if (element->IsArrayExpression()) { @@ -373,25 +372,25 @@ bool ArrayExpression::TrySetPreferredTypeForNestedArrayExpr(checker::ETSChecker checker->IsArrayExprSizeValidForTuple(nestedArrayExpr, possibleTupleType->AsETSTupleType()); }; - if (GetPreferredType()->IsETSTupleType()) { - if (idx >= preferredType_->AsETSTupleType()->GetTupleSize()) { + if (PreferredType()->IsETSTupleType()) { + if (idx >= PreferredType()->AsETSTupleType()->GetTupleSize()) { return false; } - auto *const typeInTupleAtIdx = preferredType_->AsETSTupleType()->GetTypeAtIndex(idx); + auto *const typeInTupleAtIdx = PreferredType()->AsETSTupleType()->GetTypeAtIndex(idx); nestedArrayExpr->SetPreferredType(typeInTupleAtIdx); return doesArrayExprFitInTuple(typeInTupleAtIdx); } - if (GetPreferredType()->IsETSArrayType()) { - auto *const arrayElementType = preferredType_->AsETSArrayType()->ElementType(); + if (PreferredType()->IsETSArrayType()) { + auto *const arrayElementType = PreferredType()->AsETSArrayType()->ElementType(); nestedArrayExpr->SetPreferredType(arrayElementType); return doesArrayExprFitInTuple(arrayElementType); } - if (preferredType_->IsETSResizableArrayType()) { - auto *const arrayElementType = preferredType_->AsETSObjectType()->TypeArguments()[0]; + if (PreferredType()->IsETSResizableArrayType()) { + auto *const arrayElementType = PreferredType()->AsETSObjectType()->TypeArguments()[0]; if (!doesArrayExprFitInTuple(arrayElementType)) { return false; } @@ -399,8 +398,8 @@ bool ArrayExpression::TrySetPreferredTypeForNestedArrayExpr(checker::ETSChecker return true; } - if (nestedArrayExpr->GetPreferredType() == nullptr) { - nestedArrayExpr->SetPreferredType(preferredType_); + if (nestedArrayExpr->PreferredType() == nullptr) { + nestedArrayExpr->SetPreferredType(PreferredType()); } return true; @@ -433,7 +432,7 @@ void ArrayExpression::SetPreferredTypeBasedOnFuncParam(checker::ETSChecker *chec checker::TypeRelationFlag flags) { // NOTE (mmartin): This needs a complete solution - if (preferredType_ != nullptr) { + if (PreferredType() != nullptr) { return; } @@ -444,7 +443,7 @@ void ArrayExpression::SetPreferredTypeBasedOnFuncParam(checker::ETSChecker *chec param = possiblePreferredType.value(); if (param->IsETSTupleType()) { - preferredType_ = param; + SetPreferredType(param); return; } @@ -458,14 +457,14 @@ void ArrayExpression::SetPreferredTypeBasedOnFuncParam(checker::ETSChecker *chec bool isAssignable = true; for (auto *const elem : elements_) { - checker->SetPreferredTypeIfPossible(elem, elementType); + elem->SetPreferredType(elementType); checker::AssignmentContext assignCtx(checker->Relation(), elem, elem->Check(checker), elementType, elem->Start(), std::nullopt, checker::TypeRelationFlag::NO_THROW | flags); isAssignable &= assignCtx.IsAssignable(); } if (isAssignable) { - preferredType_ = param; + SetPreferredType(param); } } diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 2af3767f2b..f2028094c1 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -99,21 +99,6 @@ public: optional_ = optional; } - void SetPreferredType(checker::Type *preferredType) noexcept - { - preferredType_ = preferredType; - } - - [[nodiscard]] checker::Type *GetPreferredType() noexcept - { - return preferredType_; - } - - [[nodiscard]] checker::Type const *GetPreferredType() const noexcept - { - return preferredType_; - } - [[nodiscard]] const ArenaVector &Decorators() const noexcept { return decorators_; @@ -132,7 +117,7 @@ public: void CleanUp() override { AstNode::CleanUp(); - preferredType_ = nullptr; + SetPreferredType(nullptr); } void ClearPreferredType(); @@ -165,7 +150,6 @@ public: private: ArenaVector decorators_; ArenaVector elements_; - checker::Type *preferredType_ {}; bool isDeclaration_ {}; bool trailingComma_ {}; bool optional_ {}; diff --git a/ets2panda/ir/expressions/binaryExpression.h b/ets2panda/ir/expressions/binaryExpression.h index e7accbe3b4..97de660fce 100644 --- a/ets2panda/ir/expressions/binaryExpression.h +++ b/ets2panda/ir/expressions/binaryExpression.h @@ -114,21 +114,18 @@ public: { left_ = expr; left_->SetParent(this); - SetStart(left_->Start()); } void SetRight(Expression *expr) noexcept { right_ = expr; right_->SetParent(this); - SetEnd(right_->End()); } void SetResult(Expression *expr) noexcept { result_ = expr; result_->SetParent(this); - SetStart(result_->Start()); } void SetOperator(lexer::TokenType operatorType) noexcept diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index b5c0e1b6ed..7689fcca37 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -461,7 +461,8 @@ bool Identifier::CheckDeclarationsPart2(const ir::AstNode *parent, ScriptExtensi } if (parent->Parent() != nullptr) { - if (parent->Parent()->IsTSEnumDeclaration()) { + if (parent->Parent()->IsTSEnumDeclaration() && + !(parent->IsTSEnumMember() && parent->AsTSEnumMember()->Init() == this)) { return true; } } diff --git a/ets2panda/ir/expressions/literal.h b/ets2panda/ir/expressions/literal.h index e4ad8c033a..b8e7ea3b86 100644 --- a/ets2panda/ir/expressions/literal.h +++ b/ets2panda/ir/expressions/literal.h @@ -32,8 +32,21 @@ public: return true; } + [[nodiscard]] bool IsFolded() const noexcept + { + return folded_; + } + + void SetFolded(bool folded = true) noexcept + { + folded_ = folded; + } + protected: explicit Literal(AstNodeType const type) : Expression(type) {} + +private: + bool folded_ = false; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp index 877c53e20d..0f26558966 100644 --- a/ets2panda/ir/expressions/literals/bigIntLiteral.cpp +++ b/ets2panda/ir/expressions/literals/bigIntLiteral.cpp @@ -65,6 +65,7 @@ BigIntLiteral *BigIntLiteral::Clone(ArenaAllocator *const allocator, AstNode *co clone->SetParent(parent); } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/booleanLiteral.cpp b/ets2panda/ir/expressions/literals/booleanLiteral.cpp index 2b24ef60ff..70978bdfeb 100644 --- a/ets2panda/ir/expressions/literals/booleanLiteral.cpp +++ b/ets2panda/ir/expressions/literals/booleanLiteral.cpp @@ -65,6 +65,7 @@ BooleanLiteral *BooleanLiteral::Clone(ArenaAllocator *const allocator, AstNode * clone->SetParent(parent); } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } diff --git a/ets2panda/ir/expressions/literals/charLiteral.cpp b/ets2panda/ir/expressions/literals/charLiteral.cpp index c97c0216f0..de15b808ba 100644 --- a/ets2panda/ir/expressions/literals/charLiteral.cpp +++ b/ets2panda/ir/expressions/literals/charLiteral.cpp @@ -35,13 +35,7 @@ void CharLiteral::Dump(ir::AstDumper *dumper) const void CharLiteral::Dump(ir::SrcDumper *dumper) const { - std::string utf8Str = util::Helpers::UTF16toUTF8(char_); - if (UNLIKELY(utf8Str.empty())) { - dumper->Add(std::to_string(char_)); - return; - } - - dumper->Add("c\'" + util::Helpers::CreateEscapedString(utf8Str) + "\'"); + dumper->Add("c\'" + ToString() + "\'"); } void CharLiteral::Compile([[maybe_unused]] compiler::PandaGen *pg) const @@ -72,13 +66,17 @@ CharLiteral *CharLiteral::Clone(ArenaAllocator *const allocator, AstNode *const } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } std::string CharLiteral::ToString() const { - std::string charStr; - util::StringView::Mutf8Encode(&charStr, char_); - return charStr; + std::string utf8Str = util::Helpers::UTF16toUTF8(char_); + if (UNLIKELY(utf8Str.empty())) { + return std::to_string(char_); + } + return util::Helpers::CreateEscapedString(utf8Str); } + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/nullLiteral.cpp b/ets2panda/ir/expressions/literals/nullLiteral.cpp index 740902912d..0155309c84 100644 --- a/ets2panda/ir/expressions/literals/nullLiteral.cpp +++ b/ets2panda/ir/expressions/literals/nullLiteral.cpp @@ -65,6 +65,7 @@ NullLiteral *NullLiteral::Clone(ArenaAllocator *const allocator, AstNode *const } clone->SetTsType(TsType()); clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/numberLiteral.cpp b/ets2panda/ir/expressions/literals/numberLiteral.cpp index 7a2c2267dc..2d21d34317 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.cpp +++ b/ets2panda/ir/expressions/literals/numberLiteral.cpp @@ -62,6 +62,16 @@ void NumberLiteral::Dump(ir::SrcDumper *dumper) const dumper->Add(number_.GetDouble()); return; } + + if (number_.IsShort()) { + dumper->Add(number_.GetShort()); + return; + } + + if (number_.IsByte()) { + dumper->Add(number_.GetByte()); + return; + } } dumper->Add(std::string(number_.Str())); } @@ -93,6 +103,7 @@ NumberLiteral *NumberLiteral::Clone(ArenaAllocator *const allocator, AstNode *co clone->SetParent(parent); } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } @@ -387,6 +398,14 @@ std::string NumberLiteral::ToString() const FpToString(number_.GetFloat(), result); } + if (number_.IsShort()) { + IntegerToString(number_.GetShort(), result); + } + + if (number_.IsByte()) { + IntegerToString(static_cast(number_.GetByte()), result); + } + ES2PANDA_ASSERT(!result.empty()); return result; } diff --git a/ets2panda/ir/expressions/literals/numberLiteral.h b/ets2panda/ir/expressions/literals/numberLiteral.h index c9c4b5e2bc..00dfc4b098 100644 --- a/ets2panda/ir/expressions/literals/numberLiteral.h +++ b/ets2panda/ir/expressions/literals/numberLiteral.h @@ -29,7 +29,6 @@ public: NO_COPY_SEMANTIC(NumberLiteral); NO_MOVE_SEMANTIC(NumberLiteral); - explicit NumberLiteral(util::StringView const str) : Literal(AstNodeType::NUMBER_LITERAL), number_(str) {} explicit NumberLiteral(lexer::Number const number) : Literal(AstNodeType::NUMBER_LITERAL), number_(number) {} [[nodiscard]] const util::StringView &Str() const noexcept diff --git a/ets2panda/ir/expressions/literals/regExpLiteral.cpp b/ets2panda/ir/expressions/literals/regExpLiteral.cpp index f0f29978d4..88bbde3447 100644 --- a/ets2panda/ir/expressions/literals/regExpLiteral.cpp +++ b/ets2panda/ir/expressions/literals/regExpLiteral.cpp @@ -65,6 +65,7 @@ RegExpLiteral *RegExpLiteral::Clone(ArenaAllocator *const allocator, AstNode *co clone->SetParent(parent); } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/stringLiteral.cpp b/ets2panda/ir/expressions/literals/stringLiteral.cpp index f47fe3ea32..804404ffdf 100644 --- a/ets2panda/ir/expressions/literals/stringLiteral.cpp +++ b/ets2panda/ir/expressions/literals/stringLiteral.cpp @@ -64,6 +64,7 @@ StringLiteral *StringLiteral::Clone(ArenaAllocator *const allocator, AstNode *co clone->SetParent(parent); } clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp index c044fbcd04..c70b049e0c 100644 --- a/ets2panda/ir/expressions/literals/undefinedLiteral.cpp +++ b/ets2panda/ir/expressions/literals/undefinedLiteral.cpp @@ -69,6 +69,7 @@ UndefinedLiteral *UndefinedLiteral::Clone(ArenaAllocator *allocator, AstNode *pa } clone->SetTsType(TsType()); clone->SetRange(Range()); + clone->SetFolded(IsFolded()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index 9b8569317c..52dba84685 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -319,33 +319,10 @@ checker::Type *MemberExpression::SetAndAdjustType(checker::ETSChecker *checker, std::optional MemberExpression::GetTupleIndexValue() const { - auto *propType = property_->TsType(); - if (object_->TsType() == nullptr || !object_->TsType()->IsETSTupleType() || - !propType->HasTypeFlag(checker::TypeFlag::CONSTANT | checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC)) { + if (object_->TsType() == nullptr || !object_->TsType()->IsETSTupleType() || !property_->IsNumberLiteral()) { return std::nullopt; } - - if (propType->IsByteType()) { - return propType->AsByteType()->GetValue(); - } - - if (propType->IsShortType()) { - return propType->AsShortType()->GetValue(); - } - - if (propType->IsIntType()) { - return propType->AsIntType()->GetValue(); - } - - if (propType->IsLongType()) { - if (auto val = propType->AsLongType()->GetValue(); - val <= std::numeric_limits::max() && val >= std::numeric_limits::min()) { - return static_cast(val); - } - return std::nullopt; - } - - ES2PANDA_UNREACHABLE(); + return property_->AsNumberLiteral()->Number().GetValueAndCastTo(); } bool MemberExpression::CheckArrayIndexValue(checker::ETSChecker *checker) const @@ -355,7 +332,7 @@ bool MemberExpression::CheckArrayIndexValue(checker::ETSChecker *checker) const auto const &number = property_->AsNumberLiteral()->Number(); if (number.IsInteger()) { - auto const value = number.GetLong(); + auto const value = number.GetValueAndCastTo(); if (value < 0) { checker->LogError(diagnostic::NEGATIVE_INDEX, {}, property_->Start()); return false; @@ -363,8 +340,7 @@ bool MemberExpression::CheckArrayIndexValue(checker::ETSChecker *checker) const index = static_cast(value); } else { ES2PANDA_ASSERT(number.IsReal()); - - double value = number.GetDouble(); + auto value = number.GetValueAndCastTo(); double fraction = std::modf(value, &value); if (value < 0.0 || fraction >= std::numeric_limits::epsilon()) { checker->LogError(diagnostic::INDEX_NEGATIVE_OR_FRACTIONAL, {}, property_->Start()); @@ -453,20 +429,8 @@ checker::Type *MemberExpression::CheckIndexAccessMethod(checker::ETSChecker *che checker::Type *MemberExpression::GetTypeOfTupleElement(checker::ETSChecker *checker, checker::Type *baseType) { ES2PANDA_ASSERT(baseType->IsETSTupleType()); - checker::Type *type = nullptr; - if (Property()->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOXING_FLAG)) { - ES2PANDA_ASSERT(Property()->Variable()->Declaration()->Node()->AsClassElement()->Value()); - type = Property()->Variable()->Declaration()->Node()->AsClassElement()->Value()->TsType(); - } else { - type = Property()->TsType(); - } - - auto idxIfAny = checker->GetTupleElementAccessValue(type); - if (!idxIfAny.has_value()) { - return nullptr; - } - - return baseType->AsETSTupleType()->GetTypeAtIndex(*idxIfAny); + auto const idxIfAny = checker->GetTupleElementAccessValue(Property()); + return idxIfAny.has_value() ? baseType->AsETSTupleType()->GetTypeAtIndex(*idxIfAny) : nullptr; } static void CastTupleElementFromClassMemberType(checker::ETSChecker *checker, diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index 11e04243c2..81da3dda08 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -26,7 +26,7 @@ ObjectExpression::ObjectExpression([[maybe_unused]] Tag const tag, ObjectExpress decorators_(allocator->Adapter()), properties_(allocator->Adapter()) { - preferredType_ = other.preferredType_; + SetPreferredType(other.PreferredType()); isDeclaration_ = other.isDeclaration_; trailingComma_ = other.trailingComma_; optional_ = other.optional_; diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 45e893cb51..350633d4df 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -66,16 +66,6 @@ public: return optional_; } - void SetPreferredType(checker::Type *const preferredType) noexcept - { - preferredType_ = preferredType; - } - - [[nodiscard]] checker::Type *PreferredType() const noexcept - { - return preferredType_; - } - [[nodiscard]] const ArenaVector &Decorators() const noexcept { return decorators_; @@ -126,7 +116,7 @@ public: void CleanUp() override { AstNode::CleanUp(); - preferredType_ = nullptr; + SetPreferredType(nullptr); } private: @@ -135,7 +125,6 @@ private: ArenaVector decorators_; ArenaVector properties_; - checker::Type *preferredType_ {}; bool isDeclaration_ {}; bool trailingComma_ {}; bool optional_ {}; diff --git a/ets2panda/ir/expressions/unaryExpression.h b/ets2panda/ir/expressions/unaryExpression.h index ac4d753d4e..18ae810939 100644 --- a/ets2panda/ir/expressions/unaryExpression.h +++ b/ets2panda/ir/expressions/unaryExpression.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -63,6 +63,11 @@ public: return argument_; } + void SetArgument(Expression *arg) + { + argument_ = arg; + } + [[nodiscard]] UnaryExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; diff --git a/ets2panda/ir/srcDump.cpp b/ets2panda/ir/srcDump.cpp index 0002996a89..da7293ca38 100644 --- a/ets2panda/ir/srcDump.cpp +++ b/ets2panda/ir/srcDump.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2025 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -66,6 +66,16 @@ void SrcDumper::Add(const std::string &str) ss_ << str; } +void SrcDumper::Add(int8_t i) +{ + ss_ << static_cast(i); +} + +void SrcDumper::Add(int16_t i) +{ + ss_ << i; +} + void SrcDumper::Add(int32_t i) { ss_ << i; diff --git a/ets2panda/ir/srcDump.h b/ets2panda/ir/srcDump.h index f218ace82d..f21bcc31e8 100644 --- a/ets2panda/ir/srcDump.h +++ b/ets2panda/ir/srcDump.h @@ -45,6 +45,8 @@ public: explicit SrcDumper(const ir::AstNode *node, bool isDeclgen, bool isIsolatedDeclgen = false); void Add(const std::string &str); + void Add(int8_t i); + void Add(int16_t i); void Add(int32_t i); void Add(int64_t l); void Add(float f); diff --git a/ets2panda/ir/statements/annotationUsage.cpp b/ets2panda/ir/statements/annotationUsage.cpp index f45e552769..3ef4f21faf 100644 --- a/ets2panda/ir/statements/annotationUsage.cpp +++ b/ets2panda/ir/statements/annotationUsage.cpp @@ -23,7 +23,7 @@ void AnnotationUsage::TransformChildren(const NodeTransformer &cb, std::string_v { if (auto *transformedNode = cb(expr_); expr_ != transformedNode) { expr_->SetTransformedNode(transformationName, transformedNode); - expr_ = transformedNode->AsIdentifier(); + expr_ = transformedNode->AsExpression(); } for (auto *&it : VectorIterationGuard(properties_)) { diff --git a/ets2panda/ir/statements/forOfStatement.cpp b/ets2panda/ir/statements/forOfStatement.cpp index 31198b09a9..953d282268 100644 --- a/ets2panda/ir/statements/forOfStatement.cpp +++ b/ets2panda/ir/statements/forOfStatement.cpp @@ -27,12 +27,11 @@ checker::Type *ForOfStatement::CreateUnionIteratorTypes(checker::ETSChecker *che for (auto it : exprType->AsETSUnionType()->ConstituentTypes()) { if (it->IsETSStringType()) { - types.push_back(checker->GetGlobalTypesHolder()->GlobalCharType()); + types.emplace_back(checker->GlobalCharBuiltinType()); } else if (it->IsETSObjectType()) { - types.push_back(this->CheckIteratorMethodForObject(checker, it->AsETSObjectType())); + types.emplace_back(this->CheckIteratorMethodForObject(checker, it->AsETSObjectType())); } else if (it->IsETSArrayType()) { - types.push_back(it->AsETSArrayType()->ElementType()->Instantiate(checker->Allocator(), checker->Relation(), - checker->GetGlobalTypesHolder())); + types.emplace_back(it->AsETSArrayType()->ElementType()->Clone(checker)); types.back()->RemoveTypeFlag(checker::TypeFlag::CONSTANT); } else { return nullptr; diff --git a/ets2panda/ir/statements/ifStatement.h b/ets2panda/ir/statements/ifStatement.h index 31860fefa6..8d6eaffbaa 100644 --- a/ets2panda/ir/statements/ifStatement.h +++ b/ets2panda/ir/statements/ifStatement.h @@ -49,6 +49,11 @@ public: return test_; } + void SetTest(Expression *test) noexcept + { + test_ = test; + } + [[nodiscard]] const Statement *Consequent() const noexcept { return consequent_; diff --git a/ets2panda/ir/statements/returnStatement.cpp b/ets2panda/ir/statements/returnStatement.cpp index 67e8bd3a5f..a14d552090 100644 --- a/ets2panda/ir/statements/returnStatement.cpp +++ b/ets2panda/ir/statements/returnStatement.cpp @@ -89,7 +89,6 @@ void ReturnStatement::SetReturnType(checker::ETSChecker *checker, checker::Type checker->LogError(diagnostic::INVALID_EXPR_IN_RETURN, {}, argument_->Start()); return; } - argument_->AddBoxingUnboxingFlags(checker->GetBoxingFlag(argumentType)); relation->SetNode(nullptr); } diff --git a/ets2panda/ir/statements/switchCaseStatement.cpp b/ets2panda/ir/statements/switchCaseStatement.cpp index 1585c3b5bc..77df9b94db 100644 --- a/ets2panda/ir/statements/switchCaseStatement.cpp +++ b/ets2panda/ir/statements/switchCaseStatement.cpp @@ -106,7 +106,7 @@ void SwitchCaseStatement::CheckAndTestCase(checker::ETSChecker *checker, checker checker::Type *unboxedDiscType, ir::Expression *node, bool &isDefaultCase) { if (test_ != nullptr) { - auto caseType = test_->Check(checker); + auto *caseType = checker->MaybeUnboxType(test_->Check(checker)); bool validCaseType = true; if (caseType->HasTypeFlag(checker::TypeFlag::CHAR)) { diff --git a/ets2panda/ir/statements/whileStatement.h b/ets2panda/ir/statements/whileStatement.h index 7fe2484669..7280ef306b 100644 --- a/ets2panda/ir/statements/whileStatement.h +++ b/ets2panda/ir/statements/whileStatement.h @@ -42,6 +42,11 @@ public: return test_; } + void SetTest(Expression *test) + { + test_ = test; + } + const Statement *Body() const { return body_; diff --git a/ets2panda/ir/typed.h b/ets2panda/ir/typed.h index cec0ce52c3..d5170eeb1d 100644 --- a/ets2panda/ir/typed.h +++ b/ets2panda/ir/typed.h @@ -55,6 +55,16 @@ public: return tsType; } + [[nodiscard]] checker::Type *PreferredType() const noexcept + { + return preferredType_; + } + + checker::Type *SetPreferredType(checker::Type *type) noexcept + { + return (preferredType_ = type); + } + bool IsTyped() const override { return true; @@ -71,12 +81,14 @@ protected: { auto otherImpl = static_cast *>(other); otherImpl->tsType_ = tsType_; + otherImpl->preferredType_ = preferredType_; T::CopyTo(other); } private: friend class SizeOfNodeTest; checker::Type *tsType_ {}; + checker::Type *preferredType_ {}; // used by the checker to supply information from context }; class TypedAstNode : public Typed { diff --git a/ets2panda/lexer/lexer.h b/ets2panda/lexer/lexer.h index 16c74fbdf2..0725fc2d8f 100644 --- a/ets2panda/lexer/lexer.h +++ b/ets2panda/lexer/lexer.h @@ -614,6 +614,7 @@ bool Lexer::ScanNumberRadix(bool leadingMinus, bool allowNumericSeparator) } GetToken().number_ = lexer::Number(number); + GetToken().number_.SetStr(SourceView(GetToken().Start().index, Iterator().Index())); return true; } diff --git a/ets2panda/lexer/token/number.h b/ets2panda/lexer/token/number.h index 47d8b2d0d1..1e053da19a 100644 --- a/ets2panda/lexer/token/number.h +++ b/ets2panda/lexer/token/number.h @@ -55,15 +55,16 @@ template inline constexpr bool dependent_false_v = false; // NOLINTEND(readability-identifier-naming) -// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) class Number { public: - // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) explicit Number() noexcept : num_(static_cast(0)) {}; - explicit Number(util::StringView str) noexcept : str_(str) {} // NOLINTNEXTLINE(bugprone-exception-escape) explicit Number(util::StringView str, NumberFlags flags) noexcept; explicit Number(util::StringView str, double num) noexcept : str_(str), num_(num) {} + explicit Number(uint8_t num) noexcept : Number(static_cast(num)) {} + explicit Number(int8_t num) noexcept : num_(num) {} + explicit Number(uint16_t num) noexcept : Number(static_cast(num)) {} + explicit Number(int16_t num) noexcept : num_(num) {} explicit Number(uint32_t num) noexcept : Number(static_cast(num)) {} explicit Number(int32_t num) noexcept : num_(num) {} explicit Number(uint64_t num) noexcept : Number(static_cast(num)) {} @@ -73,7 +74,16 @@ public: DEFAULT_COPY_SEMANTIC(Number); DEFAULT_MOVE_SEMANTIC(Number); ~Number() = default; - // NOLINTEND(cppcoreguidelines-pro-type-member-init) + + bool IsByte() const noexcept + { + return std::holds_alternative(num_); + } + + bool IsShort() const noexcept + { + return std::holds_alternative(num_); + } bool IsInt() const noexcept { @@ -87,7 +97,7 @@ public: bool IsInteger() const noexcept { - return IsInt() || IsLong(); + return IsByte() || IsShort() || IsInt() || IsLong(); } bool IsFloat() const noexcept @@ -110,34 +120,56 @@ public: return (flags_ & NumberFlags::ERROR) != 0; } + int8_t GetByte() const + { + ES2PANDA_ASSERT(IsByte()); + return std::get(num_); + } + + int16_t GetShort() const + { + return std::visit(overloaded {[](int16_t value) { return value; }, + [](int8_t value) { return static_cast(value); }, + []([[maybe_unused]] auto value) -> int16_t { ES2PANDA_UNREACHABLE(); }}, + num_); + } + int32_t GetInt() const { - ES2PANDA_ASSERT(IsInt()); - return std::get(num_); + return std::visit(overloaded {[](int32_t value) { return value; }, + [](int16_t value) { return static_cast(value); }, + [](int8_t value) { return static_cast(value); }, + []([[maybe_unused]] auto value) -> int32_t { ES2PANDA_UNREACHABLE(); }}, + num_); } int64_t GetLong() const { return std::visit(overloaded {[](int64_t value) { return value; }, [](int32_t value) { return static_cast(value); }, - []([[maybe_unused]] auto value) { - ES2PANDA_ASSERT(false); - return static_cast(0); - }}, + [](int16_t value) { return static_cast(value); }, + [](int8_t value) { return static_cast(value); }, + []([[maybe_unused]] auto value) -> int64_t { ES2PANDA_UNREACHABLE(); }}, num_); } float GetFloat() const { - ES2PANDA_ASSERT(IsFloat()); - return std::get(num_); + return std::visit(overloaded {[](float value) { return value; }, + [](int64_t value) { return static_cast(value); }, + [](int32_t value) { return static_cast(value); }, + [](int16_t value) { return static_cast(value); }, + [](int8_t value) { return static_cast(value); }, + []([[maybe_unused]] auto value) -> float { ES2PANDA_UNREACHABLE(); }}, + num_); } double GetDouble() const { - return std::visit( - overloaded {[](double value) { return value; }, [](auto value) { return static_cast(value); }}, - num_); + return std::visit(overloaded {[]([[maybe_unused]] std::monostate value) -> double { ES2PANDA_UNREACHABLE(); }, + [](double value) { return value; }, + [](auto value) { return static_cast(value); }}, + num_); } const util::StringView &Str() const @@ -145,9 +177,16 @@ public: return str_; } + void SetStr(util::StringView str) + { + str_ = str; + } + void Negate() { - std::visit(overloaded {[](auto &value) { value = -value; }}, num_); + std::visit(overloaded {[]([[maybe_unused]] std::monostate value) { ES2PANDA_UNREACHABLE(); }, + [](auto &value) { value = -value; }}, + num_); if (std::holds_alternative(num_)) { int64_t num = std::get(num_); if (num == INT32_MIN) { @@ -156,6 +195,14 @@ public: } } + bool IsZero() const + { + return std::visit(overloaded {[]([[maybe_unused]] std::monostate value) -> bool { ES2PANDA_UNREACHABLE(); }, + [](auto &value) { return value == 0; }}, + num_); + } + + // NOLINTBEGIN(readability-else-after-return) template bool CanGetValue() const noexcept { @@ -164,11 +211,15 @@ public: if constexpr (std::is_same_v) { return IsInteger(); } else if constexpr (std::is_same_v) { - return IsInt(); + return IsInt() || IsShort() || IsByte(); } else if constexpr (std::is_same_v) { return true; } else if constexpr (std::is_same_v) { - return IsFloat(); + return IsInteger() || IsFloat(); + } else if constexpr (std::is_same_v) { + return IsShort() || IsByte(); + } else if constexpr (std::is_same_v) { + return IsByte(); } else { return false; } @@ -187,18 +238,42 @@ public: return GetDouble(); } else if constexpr (std::is_same_v) { return GetFloat(); + } else if constexpr (std::is_same_v) { + return GetShort(); + } else if constexpr (std::is_same_v) { + return GetByte(); } else { static_assert(dependent_false_v, "Invalid value type was requested for Number."); } } + template + TargetType GetValueAndCastTo() const + { + if (IsByte()) { + return static_cast(GetByte()); + } else if (IsShort()) { + return static_cast(GetShort()); + } else if (IsInt()) { + return static_cast(GetInt()); + } else if (IsLong()) { + return static_cast(GetLong()); + } else if (IsFloat()) { + return static_cast(GetFloat()); + } else if (IsDouble()) { + return static_cast(GetDouble()); + } + ES2PANDA_UNREACHABLE(); + } + // NOLINTEND(readability-else-after-return) + template void SetValue(RT &&value) { using T = typename std::remove_cv_t>; - if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_same_v) { num_ = std::forward(value); } else { static_assert(dependent_false_v, "Invalid value type was requested for Number."); @@ -207,7 +282,7 @@ public: private: util::StringView str_ {}; - std::variant num_; + std::variant num_; NumberFlags flags_ {NumberFlags::NONE}; }; } // namespace ark::es2panda::lexer diff --git a/ets2panda/lsp/src/isolated_declaration.cpp b/ets2panda/lsp/src/isolated_declaration.cpp index 621b219c41..d4df74d45d 100644 --- a/ets2panda/lsp/src/isolated_declaration.cpp +++ b/ets2panda/lsp/src/isolated_declaration.cpp @@ -49,7 +49,8 @@ std::optional GenUnionType(const checker::ETSUnionType *unionType, const char splitChar); template -std::vector FilterUnionTypes(const ArenaVector &originTypes, checker::ETSChecker *checker) +std::vector FilterUnionTypes(const ArenaVector &originTypes, + [[maybe_unused]] checker::ETSChecker *checker) { if (originTypes.empty()) { return {}; diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 70d4452803..f5b2765732 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -15,16 +15,9 @@ #include "ETSparser.h" -#include "generated/tokenType.h" #include "lexer/lexer.h" #include "ir/expressions/literals/undefinedLiteral.h" #include "ir/ets/etsTuple.h" -#include "macros.h" -#include "parserFlags.h" -#include "util/errorRecovery.h" -#include "generated/diagnostic.h" -#include "parserImpl.h" -#include "util/recursiveGuard.h" namespace ark::es2panda::parser { class FunctionContext; @@ -110,14 +103,24 @@ ir::Expression *ETSParser::ResolveArgumentUnaryExpr(ExpressionParseFlags flags) ir::Expression *ETSParser::CreateUnaryExpressionFromArgument(ir::Expression *argument, lexer::TokenType operatorType, char32_t beginningChar) { + auto checkLiteral = [argument, beginningChar]() -> bool { + ir::NumberLiteral *literal = nullptr; + if (argument->IsNumberLiteral()) { + literal = argument->AsNumberLiteral(); + } else if (argument->IsCallExpression() && argument->AsCallExpression()->Callee()->IsMemberExpression() && + argument->AsCallExpression()->Callee()->AsMemberExpression()->Object()->IsNumberLiteral()) { + literal = argument->AsCallExpression()->Callee()->AsMemberExpression()->Object()->AsNumberLiteral(); + } + return literal != nullptr && ((beginningChar >= '0' && beginningChar <= '9') || (beginningChar == '.')); + }; + ir::Expression *returnExpr = nullptr; if (lexer::Token::IsUpdateToken(operatorType)) { returnExpr = AllocNode(argument, operatorType, true); } else if (operatorType == lexer::TokenType::KEYW_TYPEOF) { returnExpr = AllocNode(argument); - } else if (operatorType == lexer::TokenType::PUNCTUATOR_MINUS && argument->IsNumberLiteral()) { - bool argBeginWithDigitOrDot = (beginningChar >= '0' && beginningChar <= '9') || (beginningChar == '.'); - returnExpr = argBeginWithDigitOrDot ? argument : AllocNode(argument, operatorType); + } else if (operatorType == lexer::TokenType::PUNCTUATOR_MINUS && checkLiteral()) { + returnExpr = argument; } else { returnExpr = AllocNode(argument, operatorType); } diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 8df91d24af..14a173532e 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -501,7 +501,9 @@ __attribute__((unused)) static Context *Parse(Context *ctx) ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); } ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_PARSED : ES2PANDA_STATE_ERROR; - ctx->diagnosticEngine->FlushDiagnostic(); + if (ctx->state == ES2PANDA_STATE_ERROR) { + ctx->diagnosticEngine->FlushDiagnostic(); + } ctx->phaseManager->SetCurrentPhaseIdToAfterParse(); return ctx; } diff --git a/ets2panda/public/headers_parser/supported_types.py b/ets2panda/public/headers_parser/supported_types.py index be10e6eb98..3934a02ee8 100644 --- a/ets2panda/public/headers_parser/supported_types.py +++ b/ets2panda/public/headers_parser/supported_types.py @@ -187,7 +187,6 @@ all_types_supported = [ "void", # enums "AstNodeFlags", - "BoxingUnboxingFlags", "ModifierFlags", "ScriptFunctionFlags", "TSOperatorType", diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index 46ddf91b4c..8ae7475ff7 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -24,7 +24,7 @@ #include "compiler/core/compileQueue.h" #include "parser/ETSparser.h" -#include "checker/checker.h" +#include "checker/ETSchecker.h" #include "checker/IsolatedDeclgenChecker.h" #include "compiler/core/emitter.h" diff --git a/ets2panda/scripts/arkui.properties b/ets2panda/scripts/arkui.properties index bcd5168bfd..54df76e008 100644 --- a/ets2panda/scripts/arkui.properties +++ b/ets2panda/scripts/arkui.properties @@ -1,3 +1,3 @@ ARKUI_DEV_REPO=https://gitee.com/rri_opensource/koala_projects.git -ARKUI_DEV_BRANCH=panda_rev_8_any_2 +ARKUI_DEV_BRANCH=panda_rev_8-remove-primitives ARKUI_DEST=koala-sig diff --git a/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets b/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets index 00f05b825e..9e0ebf92e4 100644 --- a/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets +++ b/ets2panda/test/ast/compiler/ets/DeclareCheckAssign.ets @@ -26,7 +26,7 @@ export declare const int_17 = 12345 export declare const int_18: number = 12345 declare const x1: int = 5 declare const x2: int = -5 -declare const y1: float = 5.55 +declare const y1: float = 5.55f declare const y2: double = -5.55 declare const x3: int = 0x5 declare const x4: int = 0b101 @@ -50,7 +50,6 @@ declare const x51 = "abc" /* @@? 18:38 Error TypeError: Initializers are not allowed in ambient contexts: byte_13 */ /* @@? 18:70 Error TypeError: Initializers are not allowed in ambient contexts: byte_23 */ /* @@? 19:38 Error TypeError: Initializers are not allowed in ambient contexts: byte_14 */ -/* @@? 20:30 Error TypeError: A 'const' initializer in an ambient context must be a string or numeric literal: int_1 */ /* @@? 22:31 Error TypeError: A 'const' initializer in an ambient context must be a string or numeric literal: int_12 */ /* @@? 24:36 Error TypeError: Initializers are not allowed in ambient contexts: int_16 */ /* @@? 26:39 Error TypeError: Initializers are not allowed in ambient contexts: int_18 */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationDecl_bad_initializer08.ets b/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationDecl_bad_initializer08.ets index 3de0187673..abbbc6bcca 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationDecl_bad_initializer08.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationDecl_bad_initializer08.ets @@ -24,10 +24,10 @@ enum Size{S, M, L, XL, XXL} testProperty5: FixedArray = [Color.GREEN, Color.BLUE] } -/* @@? 20:29 Error TypeError: Type 'int' cannot be assigned to type 'String' */ -/* @@? 21:30 Error TypeError: Type '"false"' cannot be assigned to type 'boolean' */ -/* @@? 22:39 Error TypeError: Array element at index 0 with type 'double' is not compatible with the target array element type 'int' */ -/* @@? 22:44 Error TypeError: Array element at index 1 with type 'double' is not compatible with the target array element type 'int' */ +/* @@? 20:29 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ +/* @@? 21:30 Error TypeError: Type '"false"' cannot be assigned to type 'Boolean' */ +/* @@? 22:39 Error TypeError: Array element at index 0 with type 'Double' is not compatible with the target array element type 'Int' */ +/* @@? 22:44 Error TypeError: Array element at index 1 with type 'Double' is not compatible with the target array element type 'Int' */ /* @@? 23:28 Error TypeError: Type 'Size' cannot be assigned to type 'Color' */ /* @@? 24:40 Error TypeError: Array element at index 0 with type 'Color' is not compatible with the target array element type 'Size' */ /* @@? 24:53 Error TypeError: Array element at index 1 with type 'Color' is not compatible with the target array element type 'Size' */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationUsage_bad_param09.ets b/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationUsage_bad_param09.ets index dc97fe475c..5199df48ef 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationUsage_bad_param09.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/annotation_tests/annotationUsage_bad_param09.ets @@ -35,10 +35,10 @@ class B{ foo(){} } -/* @@? 29:24 Error TypeError: Type 'int' cannot be assigned to type 'String' */ -/* @@? 30:24 Error TypeError: Type '"false"' cannot be assigned to type 'boolean' */ -/* @@? 31:25 Error TypeError: Array element at index 0 with type 'double' is not compatible with the target array element type 'int' */ -/* @@? 31:30 Error TypeError: Array element at index 1 with type 'double' is not compatible with the target array element type 'int' */ +/* @@? 29:24 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ +/* @@? 30:24 Error TypeError: Type '"false"' cannot be assigned to type 'Boolean' */ +/* @@? 31:25 Error TypeError: Array element at index 0 with type 'Double' is not compatible with the target array element type 'Int' */ +/* @@? 31:30 Error TypeError: Array element at index 1 with type 'Double' is not compatible with the target array element type 'Int' */ /* @@? 32:24 Error TypeError: Type 'Size' cannot be assigned to type 'Color' */ /* @@? 33:25 Error TypeError: Array element at index 0 with type 'Color' is not compatible with the target array element type 'Size' */ /* @@? 33:38 Error TypeError: Array element at index 1 with type 'Color' is not compatible with the target array element type 'Size' */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/lambda_type_mismatch.ets b/ets2panda/test/ast/compiler/ets/FixedArray/lambda_type_mismatch.ets index 0a1736214b..f7e4961dcd 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/lambda_type_mismatch.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/lambda_type_mismatch.ets @@ -19,6 +19,6 @@ let fob:(...args:FixedArray)=>number = (...args:FixedArray) =>{} let foc:(c:string, ...args:FixedArray)=>string = (c:number, ...args:FixedArray):string=>{} -/* @@? 16:56 Error TypeError: Type '(c: Double, ...args: FixedArray) => void' cannot be assigned to type '(c: String, ...args: FixedArray) => void' */ -/* @@? 18:48 Error TypeError: Type '(...args: FixedArray) => void' cannot be assigned to type '(...args: FixedArray) => Double' */ -/* @@? 20:58 Error TypeError: Type '(c: Double, ...args: FixedArray) => String' cannot be assigned to type '(c: String, ...args: FixedArray) => String' */ +/* @@? 16:56 Error TypeError: Type '(c: Double, ...args: FixedArray) => void' cannot be assigned to type '(c: String, ...args: FixedArray) => void' */ +/* @@? 18:48 Error TypeError: Type '(...args: FixedArray) => void' cannot be assigned to type '(...args: FixedArray) => Double' */ +/* @@? 20:58 Error TypeError: Type '(c: Double, ...args: FixedArray) => String' cannot be assigned to type '(c: String, ...args: FixedArray) => String' */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets b/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets index e53edf414f..05c91630b4 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets @@ -17,7 +17,7 @@ class C { public met(...p: FixedArray): string { return "nR" } - public met(...p: FixedArray): string { + public met(...p: FixedArray): string { return "NR" } } diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/callExpr_pos.ets b/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/callExpr_pos.ets index d341281cb7..80478738c5 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/callExpr_pos.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/callExpr_pos.ets @@ -25,5 +25,4 @@ foo(1,2) foo(1.1) -/* @@? 17:1 Warning Warning: Function foo with this assembly signature already declared. */ /* @@? 23:5 Error TypeError: Variable 'b' is used before being assigned. */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/overload_signature_pos_2.ets b/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/overload_signature_pos_2.ets index 2af023757f..9c64efd7b2 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/overload_signature_pos_2.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/same_assembly_overload/overload_signature_pos_2.ets @@ -15,11 +15,8 @@ //With rest parameter export class A {} -export declare function foo(a:A):void +export declare function foo(a:A):void export declare function foo(a:A):number export declare function foo(a:int, b:int):void export declare function foo(a:double):void export declare function foo(...args:FixedArray):void - -/* @@? 18:8 Warning Warning: Function foo with this assembly signature already declared. */ - diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/spreadMultiArrayInTuple.ets b/ets2panda/test/ast/compiler/ets/FixedArray/spreadMultiArrayInTuple.ets new file mode 100644 index 0000000000..de366a4ce9 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/FixedArray/spreadMultiArrayInTuple.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let x1 = [1, "a"] + let y1: [int, string, int, string] = /* @@ label */[/* @@ label1 */...x1, /* @@ label2 */...x1] + let x2 = [2] + let x3 = ["abc", "abc"] + let y2: [boolean, int, string, string] = /* @@ label3 */[true, /* @@ label4 */...x2, /* @@ label5 */...x3] +} + +/* @@? 18:56 Error TypeError: Initializer has 2 elements, but tuple requires 4 */ +/* @@? 18:72 Error TypeError: 'Array' cannot be spread in tuple. */ +/* @@? 18:94 Error TypeError: 'Array' cannot be spread in tuple. */ +/* @@? 21:61 Error TypeError: Initializer has 3 elements, but tuple requires 4 */ +/* @@? 21:83 Error TypeError: 'Array' cannot be spread in tuple. */ +/* @@? 21:105 Error TypeError: 'Array' cannot be spread in tuple. */ diff --git a/ets2panda/test/ast/compiler/ets/FixedArray/unionCommonMember_neg.ets b/ets2panda/test/ast/compiler/ets/FixedArray/unionCommonMember_neg.ets index 616aaac57f..bffcc4a776 100644 --- a/ets2panda/test/ast/compiler/ets/FixedArray/unionCommonMember_neg.ets +++ b/ets2panda/test/ast/compiler/ets/FixedArray/unionCommonMember_neg.ets @@ -42,7 +42,7 @@ function getUnion(): A | B { function main() { const u = getUnion() assertEQ(/* @@ label1 */u.fld1, 42) - assertEQ(/* @@ label2 */u.fld2, 42.0) + assertEQ(u.fld2, 42.0) assertEQ(/* @@ label3 */u.fld3[0], "abc") assertEQ(/* @@ label4 */u.fld4[0], "def") assertEQ(/* @@ label5 */u.fld5, 42.0) @@ -52,7 +52,6 @@ function main() { } /* @@@ label1 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label2 Error TypeError: Member type must be the same for all union objects. */ /* @@@ label3 Error TypeError: Member type must be the same for all union objects. */ /* @@@ label4 Error TypeError: Member type must be the same for all union objects. */ /* @@@ label5 Error TypeError: Member type must be the same for all union objects. */ diff --git a/ets2panda/test/ast/compiler/ets/FunctionType10.ets b/ets2panda/test/ast/compiler/ets/FunctionType10.ets index 2c1abfa1d1..fc1a41058c 100644 --- a/ets2panda/test/ast/compiler/ets/FunctionType10.ets +++ b/ets2panda/test/ast/compiler/ets/FunctionType10.ets @@ -21,4 +21,4 @@ function main() { let goo : int = /* @@ label */foo } -/* @@@ label Error TypeError: Type '() => Int' cannot be assigned to type 'int' */ +/* @@@ label Error TypeError: Type '() => Int' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/FunctionType3.ets b/ets2panda/test/ast/compiler/ets/FunctionType3.ets index b4524e83ec..0e68f79c69 100644 --- a/ets2panda/test/ast/compiler/ets/FunctionType3.ets +++ b/ets2panda/test/ast/compiler/ets/FunctionType3.ets @@ -24,4 +24,4 @@ function main(): void { } /* @@@ label1 Error TypeError: Type '"foo"' is not compatible with type 'Int' at index 2 */ -/* @@@ label Error TypeError: No matching call signature for (int, "foo") */ +/* @@@ label Error TypeError: No matching call signature for (Int, "foo") */ diff --git a/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_1.ets b/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_1.ets index f3352a60e9..367544573f 100644 --- a/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_1.ets +++ b/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_1.ets @@ -16,4 +16,4 @@ class A>{} class B{} class C extends A/* @@ label */{} -/* @@@ label Error TypeError: Type B is not assignable to constraint type A */ +/* @@@ label Error TypeError: Type argument 'B' should be a subtype of 'A'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_2.ets b/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_2.ets index 9b39a2bf97..da65d44cd5 100644 --- a/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_2.ets +++ b/ets2panda/test/ast/compiler/ets/TypeError_recursive_parameter_2.ets @@ -17,4 +17,4 @@ class A>{} class P2{} class P1 extends A/* @@ label */{} -/* @@@ label Error TypeError: Type P2 is not assignable to constraint type A */ +/* @@@ label Error TypeError: Type argument 'P2' should be a subtype of 'A'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/Retension_invalid_params.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/Retension_invalid_params.ets index 7bd3abdd3c..c3ec1fa0a1 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/Retension_invalid_params.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/Retension_invalid_params.ets @@ -21,3 +21,4 @@ /* @@? 16:12 Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ /* @@? 16:12 Error TypeError: Invalid value for 'policy' field. The policy must be one of the following:'SOURCE', 'CLASS', or 'RUNTIME'. */ /* @@? 16:12 Error TypeError: Unresolved reference policy */ +/* @@? 16:12 Error TypeError: Invalid value for annotation field, expected a constant literal. */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationDecl_bad_initializer08.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationDecl_bad_initializer08.ets index 6e6a14c6ef..c335fe0f28 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationDecl_bad_initializer08.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationDecl_bad_initializer08.ets @@ -24,10 +24,10 @@ enum Size{S, M, L, XL, XXL} testProperty5: Size[] = [Color.GREEN, Color.BLUE] } -/* @@? 20:29 Error TypeError: Type 'int' cannot be assigned to type 'String' */ -/* @@? 21:30 Error TypeError: Type '"false"' cannot be assigned to type 'boolean' */ -/* @@? 22:29 Error TypeError: Array element at index 0 with type 'double' is not compatible with the target array element type 'Int' */ -/* @@? 22:34 Error TypeError: Array element at index 1 with type 'double' is not compatible with the target array element type 'Int' */ +/* @@? 20:29 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ +/* @@? 21:30 Error TypeError: Type '"false"' cannot be assigned to type 'Boolean' */ +/* @@? 22:29 Error TypeError: Array element at index 0 with type 'Double' is not compatible with the target array element type 'Int' */ +/* @@? 22:34 Error TypeError: Array element at index 1 with type 'Double' is not compatible with the target array element type 'Int' */ /* @@? 23:28 Error TypeError: Type 'Size' cannot be assigned to type 'Color' */ /* @@? 24:30 Error TypeError: Array element at index 0 with type 'Color' is not compatible with the target array element type 'Size' */ /* @@? 24:43 Error TypeError: Array element at index 1 with type 'Color' is not compatible with the target array element type 'Size' */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_as_type10.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_as_type10.ets index 6c78910e89..679bc167bb 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_as_type10.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_as_type10.ets @@ -19,4 +19,4 @@ let a = 1 instanceof MyAnno /* @@? 19:22 Error TypeError: Annotations cannot be used as a type. */ -/* @@? 19:9 Error TypeError: Bad operand type, the types of the operands must be same type. */ +/* @@? 19:22 Error TypeError: Annotations cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param07.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param07.ets index b18eb027e5..4904fabba8 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param07.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param07.ets @@ -21,5 +21,5 @@ @MyAnno({testProperty1: /* @@ label */1, testProperty2: /* @@ label1 */""}) function foo(){} -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type 'String' */ -/* @@@ label1 Error TypeError: Type '""' cannot be assigned to type 'double' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type 'String' */ +/* @@@ label1 Error TypeError: Type '""' cannot be assigned to type 'Double' */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param09.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param09.ets index ba05db9e13..09bee29a1d 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param09.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_bad_param09.ets @@ -35,10 +35,10 @@ class B{ foo(){} } -/* @@? 29:24 Error TypeError: Type 'int' cannot be assigned to type 'String' */ -/* @@? 30:24 Error TypeError: Type '"false"' cannot be assigned to type 'boolean' */ -/* @@? 31:25 Error TypeError: Array element at index 0 with type 'double' is not compatible with the target array element type 'Int' */ -/* @@? 31:30 Error TypeError: Array element at index 1 with type 'double' is not compatible with the target array element type 'Int' */ +/* @@? 29:24 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ +/* @@? 30:24 Error TypeError: Type '"false"' cannot be assigned to type 'Boolean' */ +/* @@? 31:25 Error TypeError: Array element at index 0 with type 'Double' is not compatible with the target array element type 'Int' */ +/* @@? 31:30 Error TypeError: Array element at index 1 with type 'Double' is not compatible with the target array element type 'Int' */ /* @@? 32:24 Error TypeError: Type 'Size' cannot be assigned to type 'Color' */ /* @@? 33:25 Error TypeError: Array element at index 0 with type 'Color' is not compatible with the target array element type 'Size' */ /* @@? 33:38 Error TypeError: Array element at index 1 with type 'Color' is not compatible with the target array element type 'Size' */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_unordered_params.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_unordered_params.ets index 065c6baad1..a61fa5db89 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_unordered_params.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotationUsage_unordered_params.ets @@ -21,5 +21,5 @@ @MyAnno({testProperty2: /* @@ label */"Bob", testProperty1: /* @@ label1 */1}) class A{} -/* @@@ label Error TypeError: Type '"Bob"' cannot be assigned to type 'double' */ -/* @@@ label1 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type '"Bob"' cannot be assigned to type 'Double' */ +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_as_negative_case.ets b/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_as_negative_case.ets index e358f9440e..3de515f15a 100644 --- a/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_as_negative_case.ets +++ b/ets2panda/test/ast/compiler/ets/annotation_tests/annotation_as_negative_case.ets @@ -20,6 +20,6 @@ class A {} } -/* @@? 18:18 Error TypeError: Cannot cast type 'int' to 'String' */ -/* @@? 19:15 Error TypeError: Cannot cast type 'int' to 'A' */ -/* @@? 19:15 Error TypeError: Type 'A' cannot be assigned to type 'int' */ \ No newline at end of file +/* @@? 18:18 Error TypeError: Cannot cast type 'Int' to 'String' */ +/* @@? 19:15 Error TypeError: Cannot cast type 'Int' to 'A' */ +/* @@? 19:15 Error TypeError: Type 'A' cannot be assigned to type 'Int' */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/assert_bad.ets b/ets2panda/test/ast/compiler/ets/assert_bad.ets index 0e9743b4bd..2e425b5250 100644 --- a/ets2panda/test/ast/compiler/ets/assert_bad.ets +++ b/ets2panda/test/ast/compiler/ets/assert_bad.ets @@ -19,5 +19,5 @@ function main(): int { return 0; } -/* @@@ label1 Error TypeError: No matching call signature for assertEQ(int, int, int) */ -/* @@@ label2 Error TypeError: Type 'int' is not compatible with type 'String|undefined' at index 3 */ \ No newline at end of file +/* @@@ label1 Error TypeError: No matching call signature for assertEQ(Int, Int, Int) */ +/* @@@ label2 Error TypeError: Type 'Int' is not compatible with type 'String|undefined' at index 3 */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/async_import_3.ets b/ets2panda/test/ast/compiler/ets/async_import_3.ets index 3622080a97..165c0f7649 100644 --- a/ets2panda/test/ast/compiler/ets/async_import_3.ets +++ b/ets2panda/test/ast/compiler/ets/async_import_3.ets @@ -16,4 +16,4 @@ import {foo} from './async_import_4' let prop: int = foo() /* @@? 16:17 Error TypeError: Cannot use type 'void' as value. */ -/* @@? 16:17 Error TypeError: Type 'void' cannot be assigned to type 'int' */ \ No newline at end of file +/* @@? 16:17 Error TypeError: Type 'void' cannot be assigned to type 'Int' */ \ No newline at end of file diff --git a/ets2panda/checker/ets/narrowingConverter.cpp b/ets2panda/test/ast/compiler/ets/boxed_primitives_overloading.sts similarity index 54% rename from ets2panda/checker/ets/narrowingConverter.cpp rename to ets2panda/test/ast/compiler/ets/boxed_primitives_overloading.sts index 3b2d1cf9e0..8e8a1ea0ff 100644 --- a/ets2panda/checker/ets/narrowingConverter.cpp +++ b/ets2panda/test/ast/compiler/ets/boxed_primitives_overloading.sts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,7 +13,18 @@ * limitations under the License. */ -#include "narrowingConverter.h" +class A { + func(a: Double): String { return a.toExponential() } + func(a: Float): String { return a.toString() } + func(a: Int): String { return a.toString() } +} -namespace ark::es2panda::checker { -} // namespace ark::es2panda::checker +function main(): int{ + let c1: A = new A(); + let helpbyte: Byte = new Byte(1 as byte); + let helpdouble: Double = new Double(1 as double); + if (c1.func(helpbyte) != helpdouble.toExponential()) { + return 1; + } + return 0; +} diff --git a/ets2panda/test/ast/compiler/ets/boxingConversion1.ets b/ets2panda/test/ast/compiler/ets/boxingConversion1.ets index 656ce82e1b..10aaa0dbfc 100644 --- a/ets2panda/test/ast/compiler/ets/boxingConversion1.ets +++ b/ets2panda/test/ast/compiler/ets/boxingConversion1.ets @@ -15,9 +15,5 @@ function main() : void { let a: Byte = 2; - let b: Byte = /* @@ label */new Byte(2); + let b: Byte = new Byte(2); } - -/* @@@ label Error TypeError: Expected 0 arguments, got 1. */ -/* @@@ label Error TypeError: No matching construct signature for std.core.Byte(int) */ -/* @@? 18:42 Error TypeError: Type 'int' is not compatible with type 'byte' at index 1 */ diff --git a/ets2panda/test/ast/compiler/ets/boxingConversion4.ets b/ets2panda/test/ast/compiler/ets/boxingConversion4.ets index ff64829de2..4b463095b7 100644 --- a/ets2panda/test/ast/compiler/ets/boxingConversion4.ets +++ b/ets2panda/test/ast/compiler/ets/boxingConversion4.ets @@ -16,15 +16,12 @@ function refInt(a: Int): void {} function main() : void { - let a: Short = /* @@ label */new Short(3); // 3 is int, invocation context won't allow primitive narrowing + let a: Short = new Short(3); // 3 is of type short in this context let b: short = 2; let c: short = /* @@ label1 */-b; // due to unary operator promotion, '-b' will be int, which is not assignable let d: short = /* @@ label2 */b | b; // due to binary operator promotion, 'b | b' will be int, which is not assignable - refInt(b); // primitive widening before boxing is not allowed + refInt(b); } -/* @@@ label Error TypeError: Expected 0 arguments, got 1. */ -/* @@@ label Error TypeError: No matching construct signature for std.core.Short(int) */ -/* @@? 19:44 Error TypeError: Type 'int' is not compatible with type 'short' at index 1 */ -/* @@@ label1 Error TypeError: Type 'int' cannot be assigned to type 'short' */ -/* @@@ label2 Error TypeError: Type 'int' cannot be assigned to type 'short' */ +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type 'Short' */ +/* @@@ label2 Error TypeError: Type 'Int' cannot be assigned to type 'Short' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType1.ets b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType1.ets index a19a44352a..020e690781 100644 --- a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType1.ets +++ b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType1.ets @@ -16,5 +16,3 @@ function foo(data : T): void { let aNumber = data! as boolean } - -/* @@? 17:19 Error TypeError: Cannot cast type 'NonNullable' to 'boolean' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType2.ets b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType2.ets index 1494ec034e..e2f0327a04 100644 --- a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType2.ets +++ b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType2.ets @@ -16,5 +16,3 @@ function foo(data : T): void { let aNumber = data! as int } - -/* @@? 17:19 Error TypeError: Cannot cast type 'NonNullable' to 'int' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType3.ets b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType3.ets index 5a6a68e66b..235ac7461a 100644 --- a/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType3.ets +++ b/ets2panda/test/ast/compiler/ets/cast_NonNullishType_to_PrimitiveType3.ets @@ -17,4 +17,3 @@ function foo(data : T): void { let aNumber = data! as number } -/* @@? 17:19 Error TypeError: Cannot cast type 'NonNullable' to 'double' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType1.ets b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType1.ets index a2c9561af5..41fa96e0b9 100644 --- a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType1.ets +++ b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType1.ets @@ -17,4 +17,3 @@ function foo(data : T): void { let aNumber = data as boolean } -/* @@? 17:19 Error TypeError: Cannot cast type 'T' to 'boolean' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType2.ets b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType2.ets index 6ee459478d..7b3d28faf8 100644 --- a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType2.ets +++ b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType2.ets @@ -17,4 +17,3 @@ function foo(data : T): void { let aNumber = data as int } -/* @@? 17:19 Error TypeError: Cannot cast type 'T' to 'int' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType3.ets b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType3.ets index c07d310c30..89bcb6c610 100644 --- a/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType3.ets +++ b/ets2panda/test/ast/compiler/ets/cast_TypeParameter_to_PrimitiveType3.ets @@ -17,4 +17,3 @@ function foo(data : T): void { let aNumber = data as number } -/* @@? 17:19 Error TypeError: Cannot cast type 'T' to 'double' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType1.ets b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType1.ets index 55d610c6b9..252c90bce1 100644 --- a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType1.ets +++ b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType1.ets @@ -16,5 +16,3 @@ function foo(data: T | boolean | null): void { let aNumber = data as int } - -/* @@? 17:19 Error TypeError: Cannot cast type 'T|Boolean|null' to 'int' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType2.ets b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType2.ets index 8a088bee5f..5400381949 100644 --- a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType2.ets +++ b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType2.ets @@ -19,4 +19,3 @@ function foo(data: T | A): void { let aNumber = data as int } -/* @@? 19:19 Error TypeError: Cannot cast type 'T|A' to 'int' */ diff --git a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType3.ets b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType3.ets index 5c261ef099..9c91b473e7 100644 --- a/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType3.ets +++ b/ets2panda/test/ast/compiler/ets/cast_UnionType_to_PrimitiveType3.ets @@ -18,4 +18,3 @@ function foo(data: T, x: boolean): void { let aNumber = data2 as int } -/* @@? 18:19 Error TypeError: Cannot cast type 'Boolean|NonNullable' to 'int' */ diff --git a/ets2panda/test/runtime/ets/enum-initialize-with-enum2.ets b/ets2panda/test/ast/compiler/ets/cast_boxed_primitives_invoke_context_and_unions.sts similarity index 65% rename from ets2panda/test/runtime/ets/enum-initialize-with-enum2.ets rename to ets2panda/test/ast/compiler/ets/cast_boxed_primitives_invoke_context_and_unions.sts index 16af540515..bbb82aee67 100644 --- a/ets2panda/test/runtime/ets/enum-initialize-with-enum2.ets +++ b/ets2panda/test/ast/compiler/ets/cast_boxed_primitives_invoke_context_and_unions.sts @@ -13,11 +13,23 @@ * limitations under the License. */ -enum Color { Red } -enum Color2 { Red = Color.Red } -enum Color3 { Red = Color2.Red } -enum Color4 { Red = Color3.Red } +class A {} -assertEQ(Color2.Red.valueOf(), 0) -assertEQ(Color3.Red.valueOf(), 0) -assertEQ(Color4.Red.valueOf(), 0) +function foo(a: Float): Float { + return a; +} + +function main(): int { + let c: A | Double = new Double(10.0); + let b: Int = new Int(9); + c = b + if (c != 9) { + return 1; + } + let k: Int = new Int(10); + let v: Float = foo(k) + if (v.isNaN()) { + return 1; + } + return 0; +} diff --git a/ets2panda/test/ast/compiler/ets/circular_variable_init.ets b/ets2panda/test/ast/compiler/ets/circular_variable_init.ets index af59760eb5..fc6881da7f 100644 --- a/ets2panda/test/ast/compiler/ets/circular_variable_init.ets +++ b/ets2panda/test/ast/compiler/ets/circular_variable_init.ets @@ -47,7 +47,7 @@ function main() { /* @@? 23:19 Error TypeError: Circular dependency detected for identifier: b */ /* @@? 31:15 Error TypeError: Unresolved reference globalb */ /* @@? 33:5 Error TypeError: Circular dependency detected for identifier: globalc */ -/* @@? 37:7 Error TypeError: Circular dependency detected for identifier: constb */ +/* @@? 36:7 Error TypeError: Circular dependency detected for identifier: consta */ /* @@? 40:17 Error TypeError: Unresolved reference mainb */ /* @@? 42:17 Error TypeError: Variable 'maind' is accessed before it's initialization. */ /* @@? 43:9 Error TypeError: Circular dependency detected for identifier: maind */ diff --git a/ets2panda/test/ast/compiler/ets/conversion_call-context_Int-to-Double_typeerror.ets b/ets2panda/test/ast/compiler/ets/conversion_call-context_Int-to-Double_typeerror.ets index 8be10405f5..49d1373772 100644 --- a/ets2panda/test/ast/compiler/ets/conversion_call-context_Int-to-Double_typeerror.ets +++ b/ets2panda/test/ast/compiler/ets/conversion_call-context_Int-to-Double_typeerror.ets @@ -17,9 +17,7 @@ function foo(x: Double) {} function main(): void { let a : Int = new Int(2); - /* @@ label */foo(/* @@ label1 */a); + foo(a); return; } -/* @@@ label1 Error TypeError: Type 'Int' is not compatible with type 'Double' at index 1 */ -/* @@@ label Error TypeError: No matching call signature for foo(Int) */ diff --git a/ets2panda/test/ast/compiler/ets/declareType_neg_2.ets b/ets2panda/test/ast/compiler/ets/declareType_neg_2.ets index 2a64b2993b..ba03a78da1 100644 --- a/ets2panda/test/ast/compiler/ets/declareType_neg_2.ets +++ b/ets2panda/test/ast/compiler/ets/declareType_neg_2.ets @@ -21,5 +21,4 @@ declare type type_utility = Partial; let a : type_utility = {description : 1234} -/* @@? 22:39 Error TypeError: Type 'int' is not compatible with type 'String|undefined' at property 'description' */ - +/* @@? 22:39 Error TypeError: Type 'Int' is not compatible with type 'String|undefined' at property 'description' */ diff --git a/ets2panda/checker/ets/narrowingWideningConverter.cpp b/ets2panda/test/ast/compiler/ets/division-by-zero.ets similarity index 51% rename from ets2panda/checker/ets/narrowingWideningConverter.cpp rename to ets2panda/test/ast/compiler/ets/division-by-zero.ets index 41ed3aeb8c..85b5646d73 100644 --- a/ets2panda/checker/ets/narrowingWideningConverter.cpp +++ b/ets2panda/test/ast/compiler/ets/division-by-zero.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,7 +13,14 @@ * limitations under the License. */ -#include "narrowingWideningConverter.h" +function main() : void { + let div_int : int = /* @@ label1 */1 / 0; + let div_long: long = /* @@ label2 */1 / 0; + let mod_int : int = /* @@ label3 */1 % 0; + let mod_long: long = /* @@ label4 */1 % 0; +} -namespace ark::es2panda::checker { -} // namespace ark::es2panda::checker +/* @@@ label1 Error SyntaxError: Division by zero is not allowed. */ +/* @@@ label2 Error SyntaxError: Division by zero is not allowed. */ +/* @@@ label3 Error SyntaxError: Division by zero is not allowed. */ +/* @@@ label4 Error SyntaxError: Division by zero is not allowed. */ diff --git a/ets2panda/test/ast/compiler/ets/enum-to-int-conversion.ets b/ets2panda/test/ast/compiler/ets/enum-to-int-conversion.ets index ace31b83f7..6ee37e69b8 100644 --- a/ets2panda/test/ast/compiler/ets/enum-to-int-conversion.ets +++ b/ets2panda/test/ast/compiler/ets/enum-to-int-conversion.ets @@ -18,6 +18,6 @@ SECOND = 12345678910 } - let a: int = /* @@ label */E.FIRST + let a: int = E.FIRST - /* @@@ label Error TypeError: Type 'long' cannot be assigned to type 'int' */ \ No newline at end of file + /* @@? 16:2 Error TypeError: Type 'Long' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/runtime/ets/constant_char.ets b/ets2panda/test/ast/compiler/ets/enum_expressions/constant_char.ets similarity index 84% rename from ets2panda/test/runtime/ets/constant_char.ets rename to ets2panda/test/ast/compiler/ets/enum_expressions/constant_char.ets index 0fcb260555..48c9d6f34c 100644 --- a/ets2panda/test/runtime/ets/constant_char.ets +++ b/ets2panda/test/ast/compiler/ets/enum_expressions/constant_char.ets @@ -21,3 +21,5 @@ function main() { assertEQ(constchar,101) assertEQ(TestEnum.One.valueOf(),101) } + +/* @@? 20:27 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/constant_char_asexpression.ets b/ets2panda/test/ast/compiler/ets/enum_expressions/constant_char_asexpression.ets similarity index 60% rename from ets2panda/test/runtime/ets/constant_char_asexpression.ets rename to ets2panda/test/ast/compiler/ets/enum_expressions/constant_char_asexpression.ets index 6b12b15f07..bc82e173aa 100644 --- a/ets2panda/test/runtime/ets/constant_char_asexpression.ets +++ b/ets2panda/test/ast/compiler/ets/enum_expressions/constant_char_asexpression.ets @@ -36,3 +36,13 @@ function main() { enum TestEnum4 { One = constcharToLong } assertEQ(TestEnum4.One.valueOf(),112) } + + +/* @@? 19:29 Error TypeError: Cannot cast type 'Char' to 'Byte' */ +/* @@? 21:28 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 24:30 Error TypeError: Cannot cast type 'Char' to 'Short' */ +/* @@? 26:28 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 29:28 Error TypeError: Cannot cast type 'Char' to 'Int' */ +/* @@? 31:28 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 34:29 Error TypeError: Cannot cast type 'Char' to 'Long' */ +/* @@? 36:28 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ diff --git a/ets2panda/test/runtime/ets/enum-initialize-with-enum1.ets b/ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum1.ets similarity index 79% rename from ets2panda/test/runtime/ets/enum-initialize-with-enum1.ets rename to ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum1.ets index 9334c5a958..ece68b6779 100644 --- a/ets2panda/test/runtime/ets/enum-initialize-with-enum1.ets +++ b/ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum1.ets @@ -17,4 +17,6 @@ enum Color { Red, Green = 3, Blue } enum Color2 { a = Color.Red, b = Color.Green} assertEQ(Color2.a.valueOf(), 0) -assertEQ(Color2.b.valueOf(), 3) \ No newline at end of file +assertEQ(Color2.b.valueOf(), 3) + +/* @@? 17:19 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ diff --git a/ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum2.ets b/ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum2.ets new file mode 100644 index 0000000000..2dd4590685 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/enum_expressions/enum-initialize-with-enum2.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum Color { Red } +enum Color2 { Red = Color.Red } +enum Color3 { Red = Color2.Red } +enum Color4 { Red = Color3.Red } + +assertEQ(Color2.Red.valueOf(), 0) +assertEQ(Color3.Red.valueOf(), 0) +assertEQ(Color4.Red.valueOf(), 0) + +/* @@? 17:21 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 18:21 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 19:21 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ diff --git a/ets2panda/test/ast/compiler/ets/etsObjectToString0.ets b/ets2panda/test/ast/compiler/ets/etsObjectToString0.ets index a04bb52e2b..724f1b214d 100644 --- a/ets2panda/test/ast/compiler/ets/etsObjectToString0.ets +++ b/ets2panda/test/ast/compiler/ets/etsObjectToString0.ets @@ -20,4 +20,4 @@ function test(): int{ return /* @@ label */a; } -/* @@@ label Error TypeError: Type 'A|null' is not compatible with the enclosing method's return type 'int' */ +/* @@@ label Error TypeError: Type 'A|null' is not compatible with the enclosing method's return type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/etsObjectToString4.ets b/ets2panda/test/ast/compiler/ets/etsObjectToString4.ets index e5873018c8..d46422e571 100644 --- a/ets2panda/test/ast/compiler/ets/etsObjectToString4.ets +++ b/ets2panda/test/ast/compiler/ets/etsObjectToString4.ets @@ -17,4 +17,4 @@ class A{} let f: (() => int) | null = /* @@ label */5; -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type '() => Int|null' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type '() => Int|null' */ diff --git a/ets2panda/test/ast/compiler/ets/explicit_cast_boxed_expressions.ets b/ets2panda/test/ast/compiler/ets/explicit_cast_boxed_expressions.ets index 45197e365f..3a8115afd1 100644 --- a/ets2panda/test/ast/compiler/ets/explicit_cast_boxed_expressions.ets +++ b/ets2panda/test/ast/compiler/ets/explicit_cast_boxed_expressions.ets @@ -25,12 +25,12 @@ let testLongValue: Long = 9223372036854775807; function byte_test(): boolean { let Byte_: Byte = new Byte(42 as byte); // ? - let byte_short = Byte_ as Short; // ? - let byte_int = Byte_ as Int; // ? - let byte_long = Byte_ as Long; // ok - let byte_float = Byte_ as Float; // ok - let byte_double = Byte_ as Double; // ok - let byte_char = Byte_ as Char; // ok + let byte_short = Byte.toShort(Byte_); // ? + let byte_int = Byte.toInt(Byte_); // ? + let byte_long = Byte.toLong(Byte_); // ok + let byte_float = Byte.toFloat(Byte_); // ok + let byte_double = Byte.toDouble(Byte_); // ok + let byte_char = Byte.toChar(Byte_); // ok // true test Type speciefic operations { @@ -57,13 +57,13 @@ function short_test(): boolean { let Short_: Short = new Short(42 as short); - let short_byte = Short_ as Byte; - let short_short = Short_ as Short; - let short_char = Short_ as Char; - let short_int = Short_ as Int; - let short_long = Short_ as Long; - let short_float = Short_ as Float; - let short_double = Short_ as Double; + let short_byte = Short.toByte(Short_); + let short_short = Short.toShort(Short_); + let short_char = Short.toChar(Short_); + let short_int = Short.toInt(Short_); + let short_long = Short.toLong(Short_); + let short_float = Short.toFloat(Short_); + let short_double = Short.toDouble(Short_); // true test Type speciefic operations @@ -90,13 +90,13 @@ function short_test(): boolean { function char_test(): boolean { let Char_: Char = new Char(42 as char); - let char_byte = Char_ as Byte; - let char_short = Char_ as Short; - let char_char = Char_ as Char; - let char_int = Char_ as Int; - let char_long = Char_ as Long; - let char_float = Char_ as Float; - let char_double = Char_ as Double; + let char_byte = Char.toByte(Char_); + let char_short = Char.toShort(Char_); + let char_char = Char.toChar(Char_); + let char_int = Char.toInt(Char_); + let char_long = Char.toLong(Char_); + let char_float = Char.toFloat(Char_); + let char_double = Char.toDouble(Char_); // true test Type speciefic operations { @@ -123,13 +123,13 @@ function int_test(): boolean { let Int_: Int = new Int(42 as int); - let int_byte = Int_ as Byte; - let int_short = Int_ as Short; - let int_char = Int_ as Char; - let int_int = Int_ as Int; - let int_long = Int_ as Long; - let int_float = Int_ as Float; - let int_double = Int_ as Double; + let int_byte = Int.toByte(Int_); + let int_short = Int.toShort(Int_); + let int_char = Int.toChar(Int_); + let int_int = Int.toInt(Int_); + let int_long = Int.toLong(Int_); + let int_float = Int.toFloat(Int_); + let int_double = Int.toDouble(Int_); // true test Type speciefic operations { @@ -155,13 +155,13 @@ function int_test(): boolean { function long_test(): boolean { let Long_: Long = new Long(42 as long); - let long_byte = Long_ as Byte; - let long_short = Long_ as Short; - let long_char = Long_ as Char; - let long_int = Long_ as Int; - let long_long = Long_ as Long; - let long_float = Long_ as Float; - let long_double = Long_ as Double; + let long_byte = Long.toByte(Long_); + let long_short = Long.toShort(Long_); + let long_char = Long.toChar(Long_); + let long_int = Long.toInt(Long_); + let long_long = Long.toLong(Long_); + let long_float = Long.toFloat(Long_); + let long_double = Long.toDouble(Long_); // true test Type speciefic operations { @@ -187,13 +187,13 @@ function long_test(): boolean { function float_test(): boolean { let Float_: Float = new Float(42 as float); - let float_byte = Float_ as Byte; - let float_short = Float_ as Short; - let float_char = Float_ as Char; - let float_int = Float_ as Int; - let float_long = Float_ as Long; - let float_float = Float_ as Float; - let float_double = Float_ as Double; + let float_byte = Float.toByte(Float_); + let float_short = Float.toShort(Float_); + let float_char = Float.toChar(Float_); + let float_int = Float.toInt(Float_); + let float_long = Float.toLong(Float_); + let float_float = Float.toFloat(Float_); + let float_double = Float.toDouble(Float_); // true test Type speciefic operations { if (float_double.toExponential() != testDouble.toExponential()) { @@ -218,13 +218,13 @@ function float_test(): boolean { function double_test(): boolean { let Double_: Double = new Double(42 as double); - let double_byte = Double_ as Byte; - let double_short = Double_ as Short; - let double_char = Double_ as Char; - let double_int = Double_ as Int; - let double_long = Double_ as Long; - let double_float = Double_ as Float; - let double_double = Double_ as Double; + let double_byte = Double.toByte(Double_); + let double_short = Double.toShort(Double_); + let double_char = Double.toChar(Double_); + let double_int = Double.toInt(Double_); + let double_long = Double.toLong(Double_); + let double_float = Double.toFloat(Double_); + let double_double = Double.toDouble(Double_); // true test Type speciefic operations { if (double_double.toExponential() != testDouble.toExponential()) { diff --git a/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithExtensionFunction.ets b/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithExtensionFunction.ets index ce04738954..c97f4b9e8b 100644 --- a/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithExtensionFunction.ets +++ b/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithExtensionFunction.ets @@ -20,13 +20,13 @@ class B { function name(b: B) {} function name(b: B, n: string) {} -get name/* @@ label1 */(this: B): string { - return this.name_; +get name(this: B): string { + return this.name_; } -set name/* @@ label2 */(this: B, n: string) { +set name/* @@ label */(this: B, n: string) { this.name_ = n; } -/* @@@ label1 Error TypeError: Function name with this assembly signature already declared. */ -/* @@@ label2 Error TypeError: Function name with this assembly signature already declared. */ +/* @@@ label Error TypeError: Function name with this assembly signature already declared. */ +/* @@@ label Error TypeError: Function name with this assembly signature already declared. */ diff --git a/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithFunction.ets b/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithFunction.ets index ce04738954..c97f4b9e8b 100644 --- a/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithFunction.ets +++ b/ets2panda/test/ast/compiler/ets/extension_accessor_tests/extensionAccessorNameDuplicatedWithFunction.ets @@ -20,13 +20,13 @@ class B { function name(b: B) {} function name(b: B, n: string) {} -get name/* @@ label1 */(this: B): string { - return this.name_; +get name(this: B): string { + return this.name_; } -set name/* @@ label2 */(this: B, n: string) { +set name/* @@ label */(this: B, n: string) { this.name_ = n; } -/* @@@ label1 Error TypeError: Function name with this assembly signature already declared. */ -/* @@@ label2 Error TypeError: Function name with this assembly signature already declared. */ +/* @@@ label Error TypeError: Function name with this assembly signature already declared. */ +/* @@@ label Error TypeError: Function name with this assembly signature already declared. */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_access_protected_field.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_access_protected_field.ets index c3060b1928..6e0fe6102b 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_access_protected_field.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_access_protected_field.ets @@ -28,5 +28,5 @@ function main() { console.println(banana.name()); } -/* @@@ label Error TypeError: Signature price(): int is not visible here. */ +/* @@@ label Error TypeError: Signature price(): Int is not visible here. */ /* @@@ label Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_called_by_class.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_called_by_class.ets index cdfab18224..fb813f1d31 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_called_by_class.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_called_by_class.ets @@ -27,4 +27,12 @@ function main() { console.println(A./* @@ label */price(1)); } -/* @@@ label Error TypeError: Property 'price' does not exist on type 'A' */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Boolean): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Byte): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Short): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Char): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Int): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Long): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Float): void` */ +/* @@? 27:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Double): void` */ +/* @@@ label Error TypeError: Property 'price' does not exist on type 'A' */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_duplicated_with_private_field.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_duplicated_with_private_field.ets index 4ce3aa69d4..ab7af4dedc 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_duplicated_with_private_field.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_duplicated_with_private_field.ets @@ -28,4 +28,12 @@ function main() { console.println(/* @@label */banana.name(2)); } -/* @@? 28:34 Error TypeError: No matching call signature for name(int) */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Boolean): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Byte): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Short): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Char): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Int): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Long): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Float): void` */ +/* @@? 28:5 Error TypeError: Call to `println` is ambiguous as `2` versions of `println` are available: `println(i: String): void` and `println(i: Double): void` */ +/* @@? 28:34 Error TypeError: No matching call signature for name(Int) */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_miss_signature.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_miss_signature.ets index e35530840d..2e8df50de7 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_miss_signature.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_miss_signature.ets @@ -39,6 +39,6 @@ function main() { asMethodCall(); } -/* @@? 30:5 Error TypeError: Expected 2 arguments, got 3. */ -/* @@? 30:5 Error TypeError: No matching call signature for foo(Fruit, double, double) */ -/* @@? 34:5 Error TypeError: No matching call signature for foo(double, double) */ +/* @@? 30:5 Error TypeError: Expected 2 arguments, got 3. */ +/* @@? 30:5 Error TypeError: No matching call signature for foo(Fruit, Double, Double) */ +/* @@? 34:5 Error TypeError: No matching call signature for foo(Double, Double) */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_primitive.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_primitive.ets index 131c49af3d..ec9bcf5d75 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_primitive.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_primitive.ets @@ -17,4 +17,4 @@ return 1.2; } -/* @@@ label Error TypeError: Extension function can only defined for class, interface or array. */ +/* @@? 16:52 Error TypeError: The extension accessor or extension function 'value' has the same name with field of class Double */ diff --git a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_return_this_neg.ets b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_return_this_neg.ets index b41dbe9f88..1c4439bcc7 100644 --- a/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_return_this_neg.ets +++ b/ets2panda/test/ast/compiler/ets/extension_function_tests/extension_function_return_this_neg.ets @@ -21,4 +21,4 @@ function foo(this: B): this { return /* @@ label */2; } -/* @@@ label Error TypeError: Type 'int' is not compatible with the enclosing method's return type 'B' */ +/* @@@ label Error TypeError: Type 'Int' is not compatible with the enclosing method's return type 'B' */ diff --git a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_1.ets b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_1.ets index fe79788787..11b245f328 100644 --- a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_1.ets +++ b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_1.ets @@ -22,4 +22,4 @@ function main(): void { let b : Person ={name: /* @@ label */42, age:25} } -/* @@@ label Error TypeError: Type 'int' is not compatible with type 'String' at property 'name' */ +/* @@@ label Error TypeError: Type 'Int' is not compatible with type 'String' at property 'name' */ diff --git a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_2.ets b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_2.ets index 0980e0579b..d12d67284b 100644 --- a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_2.ets +++ b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_2.ets @@ -22,4 +22,4 @@ function main(): void { let b : Person/* @@ label */ ={name: "John", age:25} } -/* @@@ label Error TypeError: Type String is not assignable to constraint type Double */ +/* @@@ label Error TypeError: Type argument 'String' should be a subtype of 'Double'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_3.ets b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_3.ets index 87ee607302..fd7eed0b9e 100644 --- a/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_3.ets +++ b/ets2panda/test/ast/compiler/ets/genericObjectLiteral_neg_3.ets @@ -22,5 +22,5 @@ function main(): void { let b : Person/* @@ label */ ={name: "John", age:/* @@ label1 */"25"} } -/* @@@ label Error TypeError: Type Double is not assignable to constraint type String */ +/* @@@ label Error TypeError: Type argument 'Double' should be a subtype of 'String'-constraint */ /* @@@ label1 Error TypeError: Type '"25"' is not compatible with type 'Double' at property 'age' */ diff --git a/ets2panda/test/ast/compiler/ets/generic_typealias_5_neg.ets b/ets2panda/test/ast/compiler/ets/generic_typealias_5_neg.ets index 0bfcb0ae7d..1905464507 100644 --- a/ets2panda/test/ast/compiler/ets/generic_typealias_5_neg.ets +++ b/ets2panda/test/ast/compiler/ets/generic_typealias_5_neg.ets @@ -22,4 +22,4 @@ function main(): void { let a: A/* @@ label */; } -/* @@@ label Error TypeError: Type B is not assignable to constraint type Comparable */ +/* @@@ label Error TypeError: Type argument 'B' should be a subtype of 'Comparable'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets b/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets index a698d21b0f..c8f046fedf 100644 --- a/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets +++ b/ets2panda/test/ast/compiler/ets/generics_primitive_type_param_neg_1.ets @@ -22,10 +22,9 @@ function main(): void { let prim_int = 5; switch(prim_int) { - /* @@ label */case /* @@ label1 */a_int.value: // not allowed, because type of a_int.value is Int + /* @@ label */case a_int.value: // not allowed, because type of a_int.value is Int default: } } -/* @@@ label1 Error TypeError: Switch case type 'Int' is not comparable to discriminant type 'int' */ /* @@@ label Error TypeError: Constant expression required */ diff --git a/ets2panda/test/ast/compiler/ets/greater_than_neg.ets b/ets2panda/test/ast/compiler/ets/greater_than_neg.ets index 6b50c26efd..f5dea30ef1 100644 --- a/ets2panda/test/ast/compiler/ets/greater_than_neg.ets +++ b/ets2panda/test/ast/compiler/ets/greater_than_neg.ets @@ -16,7 +16,7 @@ let a: Array>>=2 let b: Array>=2 -/* @@? 16:21 Error SyntaxError: Unexpected token '>>='. */ -/* @@? 16:24 Error SyntaxError: Unexpected token '2'. */ -/* @@? 17:21 Error SyntaxError: Unexpected token '>='. */ -/* @@? 17:23 Error SyntaxError: Unexpected token '2'. */ +/* @@? 16:21 Error SyntaxError: Unexpected token '>>='. */ +/* @@? 16:24 Error SyntaxError: Unexpected token '2'. */ +/* @@? 17:21 Error SyntaxError: Unexpected token '>='. */ +/* @@? 17:23 Error SyntaxError: Unexpected token '2'. */ diff --git a/ets2panda/test/ast/compiler/ets/identifierReference10.ets b/ets2panda/test/ast/compiler/ets/identifierReference10.ets index 161213981b..bb75765d53 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference10.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference10.ets @@ -25,4 +25,4 @@ class A { } } -/* @@@ label Error TypeError: Type '"foo"' cannot be assigned to type 'int' */ +/* @@@ label Error TypeError: Type '"foo"' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/identifierReference12.ets b/ets2panda/test/ast/compiler/ets/identifierReference12.ets index 6b2358f878..1c34cf4214 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference12.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference12.ets @@ -25,4 +25,4 @@ class A { } } -/* @@@ label Error TypeError: Type 'int' has no call signatures. */ +/* @@@ label Error TypeError: Type 'Int' has no call signatures. */ diff --git a/ets2panda/test/ast/compiler/ets/identifierReference16.ets b/ets2panda/test/ast/compiler/ets/identifierReference16.ets index e21f088772..aefc534f96 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference16.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference16.ets @@ -45,4 +45,4 @@ class A extends B { /* @@@ label Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ /* @@? 41:7 Error TypeError: Expected 0 arguments, got 1. */ -/* @@? 41:7 Error TypeError: No matching call signature for foo(int) */ +/* @@? 41:7 Error TypeError: No matching call signature for foo(Int) */ diff --git a/ets2panda/test/ast/compiler/ets/identifierReference3.ets b/ets2panda/test/ast/compiler/ets/identifierReference3.ets index 69a7d28c11..ddc353921b 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference3.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference3.ets @@ -21,4 +21,4 @@ class A { } } -/* @@@ label Error TypeError: Type '"foo"' cannot be assigned to type 'int' */ +/* @@@ label Error TypeError: Type '"foo"' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/identifierReference9.ets b/ets2panda/test/ast/compiler/ets/identifierReference9.ets index 6303c2f318..006fc0197d 100644 --- a/ets2panda/test/ast/compiler/ets/identifierReference9.ets +++ b/ets2panda/test/ast/compiler/ets/identifierReference9.ets @@ -25,4 +25,4 @@ class A { } } -/* @@? 24:16 Error TypeError: Type 'int' cannot be assigned to type '() => void' */ +/* @@? 24:16 Error TypeError: Type 'Int' cannot be assigned to type '() => void' */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_1.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_1.ets index 35ac4831a4..810b288169 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_1.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_1.ets @@ -17,4 +17,4 @@ package mypackage; let myvar: number = exist_but_checker_fails_in_file; -/* @@? package_module_2.ets:19:39 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? package_module_2.ets:19:39 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_2.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_2.ets index ba854d07c8..cf77170f19 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_2.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_6/package_module_2.ets @@ -18,4 +18,4 @@ package mypackage; let exist_but_checker_fails_in_file: number = 8; let wong_type: string = /* @@ label */9; -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module.ets index 633c6b84c8..3eaf30089d 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module.ets @@ -17,7 +17,7 @@ package mypack; // That is the main file, from which we will compile full package -/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'int' */ +/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'Int' */ /* @@? package_module_with_syntax_error.ets:18:1 Error SyntaxError: Unexpected token '='. */ /* @@? package_module_with_syntax_error.ets:18:1 Error SyntaxError: Invalid package toplevel statement */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_semantic_error.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_semantic_error.ets index 0c0e927f3b..ecb87c42d0 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_semantic_error.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_semantic_error.ets @@ -27,4 +27,4 @@ let a: int = "I am a number, I promise..."; /* @@? package_with_both_errors.ets:21:21 Error TypeError: No static $_invoke method and static $_instantiate method in Day. Day() is not allowed. */ /* @@? package_with_both_errors.ets:21:21 Error TypeError: Type 'Day' has no call signatures. */ -/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'int' */ +/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_syntax_error.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_syntax_error.ets index e010aad578..18341d2998 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_syntax_error.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_module_with_syntax_error.ets @@ -17,7 +17,7 @@ package mypack; =) -/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'int' */ +/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'Int' */ /* @@? package_with_both_errors.ets:21:16 Error TypeError: Cannot find type 'good'. */ /* @@? package_with_both_errors.ets:21:21 Error SyntaxError: Unexpected token 'Day'. */ diff --git a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_with_both_errors.ets b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_with_both_errors.ets index c90c429c15..bab0e7b0a5 100644 --- a/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_with_both_errors.ets +++ b/ets2panda/test/ast/compiler/ets/implicit_package_import/package_test_9/package_with_both_errors.ets @@ -21,7 +21,7 @@ function foo(): Day { return new good Day(); } -/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'int' */ +/* @@? package_module_with_semantic_error.ets:18:14 Error TypeError: Type '"I am a number, I promise..."' cannot be assigned to type 'Int' */ /* @@? package_module_with_syntax_error.ets:18:1 Error SyntaxError: Unexpected token '='. */ /* @@? package_module_with_syntax_error.ets:18:1 Error SyntaxError: Invalid package toplevel statement */ diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_1.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_1.ets index 0f43b46007..22afeef200 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_1.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_1.ets @@ -24,9 +24,9 @@ export class A { let 1: number // First level import with both types of error -/* @@? import_1.ets:21:17 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? import_1.ets:21:17 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? import_1.ets:24:5 Error SyntaxError: Identifier expected, got 'number literal'. */ // Second level import import with both types of error -/* @@? import_2.ets:17:17 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? import_2.ets:17:17 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? import_2.ets:20:5 Error SyntaxError: 'var' keyword is not supported. Use 'let' instead. */ diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_2.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_2.ets index 0af436edc7..ce4e0f0704 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_2.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/import_2.ets @@ -20,5 +20,6 @@ export class B { var not_ok = false // Second level import import with both types of error -/* @@? import_2.ets:17:17 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? import_2.ets:17:17 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? import_2.ets:20:5 Error SyntaxError: 'var' keyword is not supported. Use 'let' instead. */ + diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/master_file.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/master_file.ets index 787a60dba2..fd416a1cde 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/master_file.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_chain_with_errors/master_file.ets @@ -18,13 +18,15 @@ import {A, B} from "./import_1.ets" let b = new B(10); // First level import with both types of error -/* @@? import_1.ets:21:17 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? import_1.ets:21:17 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? import_1.ets:24:5 Error SyntaxError: Identifier expected, got 'number literal'. */ // Second level import import with both types of error -/* @@? import_2.ets:17:17 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? import_2.ets:17:17 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? import_2.ets:20:5 Error SyntaxError: 'var' keyword is not supported. Use 'let' instead. */ // Error in main file based on class from the most distant file /* @@? master_file.ets:18:9 Error TypeError: Expected 0 arguments, got 1. */ -/* @@? master_file.ets:18:9 Error TypeError: No matching construct signature for import_2.B(int) */ +/* @@? master_file.ets:18:9 Error TypeError: No matching construct signature for import_2.B(Int) */ +/* @@? master_file.ets:18:9 Error TypeError: Expected 0 arguments, got 1. */ +/* @@? master_file.ets:18:9 Error TypeError: No matching construct signature for import_2.B(Int) */ diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/import_in_package_with_error.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/import_in_package_with_error.ets index 27ee426de3..d7c0b1872b 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/import_in_package_with_error.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/import_in_package_with_error.ets @@ -21,7 +21,7 @@ function bar(x: notInit) { (=_=) } /* @@? distant_package.ets:22:22 Error SyntaxError: Variable must be initialized or it's type must be declared. */ -/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'double' */ +/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'Double' */ /* @@? package_with_errors_2.ets:19:16 Error SyntaxError: Non-constant initializer of Package should be apply in Initializer Block. */ /* @@? package_with_errors_2.ets:19:16 Error TypeError: Unresolved reference foo */ diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_1.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_1.ets index 59fdefced0..8ea80e1135 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_1.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_1.ets @@ -29,4 +29,4 @@ export let moreImportantInfo = importantInfo as number; /* @@? package_with_errors_2.ets:19:16 Error TypeError: Unresolved reference foo */ /* @@? package_with_errors_2.ets:19:16 Error TypeError: This expression is not callable. */ -/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'double' */ +/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'Double' */ diff --git a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_2.ets b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_2.ets index e3daaf55a4..bd2e68d923 100644 --- a/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_2.ets +++ b/ets2panda/test/ast/compiler/ets/import_tests/import_distant_package/package_with_errors/package_with_errors_2.ets @@ -27,7 +27,7 @@ export notInit /* @@? distant_package.ets:22:22 Error SyntaxError: Variable must be initialized or it's type must be declared. */ -/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'double' */ +/* @@? package_with_errors_1.ets:19:32 Error TypeError: Cannot cast type 'String' to 'Double' */ /* @@? package_with_errors_2.ets:19:16 Error SyntaxError: Non-constant initializer of Package should be apply in Initializer Block. */ /* @@? package_with_errors_2.ets:19:16 Error TypeError: Unresolved reference foo */ diff --git a/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets b/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets index 7ccba2d83e..c8400f2b11 100644 --- a/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets +++ b/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets @@ -16,7 +16,6 @@ let a = [1, 2, 3] a[0] = /* @@ label */"1" -/* @@? 17:1 Error TypeError: No matching indexing signature for $_set(int, "1") */ -/* @@? 17:3 Error TypeError: Type 'int' is not compatible with type 'double' at index 1 */ +/* @@? 17:1 Error TypeError: No matching indexing signature for $_set(Int, "1") */ /* @@? 17:3 Error TypeError: Cannot find index access method with the required signature. */ /* @@? 17:22 Error TypeError: Type '"1"' is not compatible with type 'Double' at index 2 */ diff --git a/ets2panda/test/ast/compiler/ets/infinityNarrowing.ets b/ets2panda/test/ast/compiler/ets/infinityNarrowing.ets index 821efecc9a..d885bc01af 100644 --- a/ets2panda/test/ast/compiler/ets/infinityNarrowing.ets +++ b/ets2panda/test/ast/compiler/ets/infinityNarrowing.ets @@ -13,9 +13,13 @@ * limitations under the License. */ -export const floatInf: float = 1.0 / 0.0 +export const floatInf: float = /* @@ label2 */1.0 / 0.0 export const byteInf: byte = /* @@ label */1.0 / 0.0 export const shortInf: short = /* @@ label1 */1.0 / 0.0 -/* @@@ label Error TypeError: Type 'double' cannot be assigned to type 'byte' */ -/* @@@ label1 Error TypeError: Type 'double' cannot be assigned to type 'short' */ +/* @@@ label Error TypeError: Type 'Double' cannot be assigned to type 'Byte' */ +/* @@@ label1 Error TypeError: Type 'Double' cannot be assigned to type 'Short' */ +/* @@@ label2 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ +/* @@@ label2 Error TypeError: Floating-point value cannot be converted */ +/* @@@ label1 Error TypeError: Floating-point value cannot be converted */ +/* @@@ label Error TypeError: Floating-point value cannot be converted */ diff --git a/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromClass.ets b/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromClass.ets index 8615346ac5..ee01f2ea07 100644 --- a/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromClass.ets +++ b/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromClass.ets @@ -34,5 +34,5 @@ function main(): void { assertEQ(instance.getX(), true); } -/* @@@ label1 Error TypeError: Type 'boolean' has no call signatures. */ +/* @@@ label1 Error TypeError: Type 'Boolean' has no call signatures. */ /* @@@ label Error TypeError: Cannot inherit from class C, because field x is inherited with a different declaration type */ diff --git a/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromInterface.ets b/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromInterface.ets index f9dca62195..7fdc5051d5 100644 --- a/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromInterface.ets +++ b/ets2panda/test/ast/compiler/ets/invalidIndirectInheritanceFromInterface.ets @@ -34,5 +34,5 @@ function main(): void { assertEQ(instance.getX(), true); } -/* @@@ label1 Error TypeError: Type 'boolean' has no call signatures. */ +/* @@@ label1 Error TypeError: Type 'Boolean' has no call signatures. */ /* @@@ label Error TypeError: Cannot inherit from class C, because field x is inherited with a different declaration type */ diff --git a/ets2panda/test/ast/compiler/ets/invalidInheritanceFromClass.ets b/ets2panda/test/ast/compiler/ets/invalidInheritanceFromClass.ets index 0569baa08c..1e78d0e9b2 100644 --- a/ets2panda/test/ast/compiler/ets/invalidInheritanceFromClass.ets +++ b/ets2panda/test/ast/compiler/ets/invalidInheritanceFromClass.ets @@ -30,5 +30,5 @@ function main(): void { let instance: B = new B(); assertEQ(instance.getX(), true); } -/* @@@ label1 Error TypeError: Type 'boolean' has no call signatures. */ +/* @@@ label1 Error TypeError: Type 'Boolean' has no call signatures. */ /* @@@ label Error TypeError: Cannot inherit from class A, because field x is inherited with a different declaration type */ diff --git a/ets2panda/test/ast/compiler/ets/invalidInheritanceFromInterface.ets b/ets2panda/test/ast/compiler/ets/invalidInheritanceFromInterface.ets index f06ab002a2..781569a6a1 100644 --- a/ets2panda/test/ast/compiler/ets/invalidInheritanceFromInterface.ets +++ b/ets2panda/test/ast/compiler/ets/invalidInheritanceFromInterface.ets @@ -30,5 +30,5 @@ function main(): void { let instance: B = new B(); assertEQ(instance.getX(), true); } -/* @@@ label1 Error TypeError: Type 'boolean' has no call signatures. */ +/* @@@ label1 Error TypeError: Type 'Boolean' has no call signatures. */ /* @@@ label Error TypeError: Cannot inherit from interface A because field x is inherited with a different declaration type */ diff --git a/ets2panda/test/ast/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets b/ets2panda/test/ast/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets index b9c050c4e8..30a62660c7 100644 --- a/ets2panda/test/ast/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets +++ b/ets2panda/test/ast/compiler/ets/lambdaExpressionWithoutBlockStatementDifferentTypeInfunction.ets @@ -22,4 +22,4 @@ function main(): void { test1() } -/* @@@ label Error TypeError: Type 'String' is not compatible with the enclosing method's return type 'int' */ +/* @@@ label Error TypeError: Type 'String' is not compatible with the enclosing method's return type 'Int' */ diff --git a/ets2panda/test/ast/compiler/ets/lambdaFunction5.ets b/ets2panda/test/ast/compiler/ets/lambdaFunction5.ets index bfd45ae78c..259a8abf16 100644 --- a/ets2panda/test/ast/compiler/ets/lambdaFunction5.ets +++ b/ets2panda/test/ast/compiler/ets/lambdaFunction5.ets @@ -36,4 +36,4 @@ function main(): void { } /* @@@ label1 Error TypeError: Type '"foo"' is not compatible with type 'Int' at index 2 */ -/* @@@ label Error TypeError: No matching call signature for (int, "foo") */ +/* @@@ label Error TypeError: No matching call signature for (Int, "foo") */ diff --git a/ets2panda/test/ast/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets b/ets2panda/test/ast/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets index 0f6a071170..670b535d0d 100644 --- a/ets2panda/test/ast/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets +++ b/ets2panda/test/ast/compiler/ets/method-resolution-class-and-interface-in-signatures_6.ets @@ -42,4 +42,6 @@ function main(): int { let asd5: double = /* @@ label */foo(new A(), 2.1); return 0; } -/* @@@ label Error TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(a: J, d: double): double` and `foo(a: I, d: double): double` */ +/* @@? 38:21 Error TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(b: Int, a: I): Int` and `foo(d: Double, a: J): Double` */ +/* @@? 41:21 Error TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(a: I, b: Int): Int` and `foo(a: J, d: Double): Double` */ +/* @@@ label Error TypeError: Call to `foo` is ambiguous as `2` versions of `foo` are available: `foo(a: J, d: Double): Double` and `foo(a: I, d: Double): Double` */ diff --git a/ets2panda/test/ast/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets b/ets2panda/test/ast/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets index d2cac0dc0b..7650215aa6 100644 --- a/ets2panda/test/ast/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets +++ b/ets2panda/test/ast/compiler/ets/n_assignGenericWithNullableTypeParamToNonNullable.ets @@ -18,7 +18,8 @@ class B {} function main(): void { let abn : A = /* @@ label */new A(); // should not work: non nullable B is the subtype of nullable B, but T has no variance mark - let ab : A = abn; // should not work: nullable B (the type of abn) is not the subtype of non nullable B + let ab : A = /* @@ label1 */abn; // should not work: nullable B (the type of abn) is not the subtype of non nullable B } /* @@@ label Error TypeError: Type 'A' cannot be assigned to type 'A' */ +/* @@@ label1 Error TypeError: Type 'A' cannot be assigned to type 'A' */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.ets b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.ets index c81755739a..0b828cc131 100644 --- a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.ets +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_access_violation_import_conflicts.ets @@ -24,6 +24,6 @@ Space1.foo(); // CTE Space1.foo(1234); //ok /* @@? 19:31 Error TypeError: Property 'constant' does not exist on type 'Space2' */ -/* @@? 20:23 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? 20:23 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ /* @@? 23:1 Error TypeError: Expected 1 arguments, got 0. */ /* @@? 23:1 Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.ets b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.ets index 73967a0bb8..89f6b4e676 100644 --- a/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.ets +++ b/ets2panda/test/ast/compiler/ets/namespace_tests/namespace_as_type10.ets @@ -19,4 +19,4 @@ namespace MySpace { let a = 1 instanceof MySpace /* @@? 19:22 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ -/* @@? 19:9 Error TypeError: Bad operand type, the types of the operands must be same type. */ +/* @@? 19:22 Error TypeError: Namespace 'MySpace' cannot be used as a type. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/null_coalescing_neg_01.ets b/ets2panda/test/ast/compiler/ets/null_coalescing_neg_01.ets new file mode 100644 index 0000000000..095090df6f --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/null_coalescing_neg_01.ets @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function foo1(z: int|undefined) { + let x = z ?? /* @@ label1 */10000000000; + return x; +} + +function foo2(z: short|undefined) { + let x = z ?? /* @@ label2 */10000000; + return x; +} + +function foo3(z: byte|undefined) { + let x = z ?? /* @@ label3 */10000; + return x; +} + +function foo4(z: int|undefined) { + let x = z ?? /* @@ label4 */100.0; + return x; +} + +function foo5(z: long|undefined) { + let x = z ?? /* @@ label5 */100000.0f; + return x; +} + +function foo6(z: float|undefined) { + let x = z ?? /* @@ label6 */100000.0; + return x; +} + + +/* @@@ label1 Error TypeError: Value is out of range */ +/* @@@ label2 Error TypeError: Value is out of range */ +/* @@@ label3 Error TypeError: Value is out of range */ +/* @@@ label4 Error TypeError: Type 'Double' cannot be assigned to type 'Int' */ +/* @@@ label5 Error TypeError: Type 'Float' cannot be assigned to type 'Long' */ +/* @@@ label6 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ diff --git a/ets2panda/test/ast/compiler/ets/objectLiteralPrimitiveContextType.ets b/ets2panda/test/ast/compiler/ets/objectLiteralPrimitiveContextType.ets index 44c12cb3bf..f703cbe4a9 100644 --- a/ets2panda/test/ast/compiler/ets/objectLiteralPrimitiveContextType.ets +++ b/ets2panda/test/ast/compiler/ets/objectLiteralPrimitiveContextType.ets @@ -14,4 +14,4 @@ */ let x: int = /* @@ label */{}; -/* @@@ label Error TypeError: Target type for class composite needs to be an object type, found 'int' */ + diff --git a/ets2panda/test/ast/compiler/ets/objectLiteralWrongValueType.ets b/ets2panda/test/ast/compiler/ets/objectLiteralWrongValueType.ets index 38d5711cf9..ce025f5c2a 100644 --- a/ets2panda/test/ast/compiler/ets/objectLiteralWrongValueType.ets +++ b/ets2panda/test/ast/compiler/ets/objectLiteralWrongValueType.ets @@ -21,4 +21,4 @@ let c: C = { f: /* @@ label */"ouch" }; -/* @@@ label Error TypeError: Type '"ouch"' is not compatible with type 'int' at property 'f' */ +/* @@@ label Error TypeError: Type '"ouch"' is not compatible with type 'Int' at property 'f' */ diff --git a/ets2panda/test/ast/compiler/ets/objectLiteral_abstract_class.ets b/ets2panda/test/ast/compiler/ets/objectLiteral_abstract_class.ets index b7c21affb1..876abd1349 100644 --- a/ets2panda/test/ast/compiler/ets/objectLiteral_abstract_class.ets +++ b/ets2panda/test/ast/compiler/ets/objectLiteral_abstract_class.ets @@ -40,6 +40,6 @@ function main(){ /* @@@ label Error TypeError: type C has no property named field3 */ /* @@@ label2 Error TypeError: Property field2 is not visible here. */ -/* @@@ label3 Error TypeError: Type '"some str"' is not compatible with type 'double' at property 'field1' */ +/* @@@ label3 Error TypeError: Type '"some str"' is not compatible with type 'Double' at property 'field1' */ /* @@@ label4 Error TypeError: Type C2 has no parameterless constructor. Initialization with literals is not supported if the type has no parameterless constructor. Declare the parameterless constructor explicitly or remove parametered constructors! */ /* @@@ label5 Error TypeError: Signature constructor(): void is not visible here. */ diff --git a/ets2panda/test/ast/compiler/ets/override11.ets b/ets2panda/test/ast/compiler/ets/override11.ets index 1bf873cd54..2c43199671 100644 --- a/ets2panda/test/ast/compiler/ets/override11.ets +++ b/ets2panda/test/ast/compiler/ets/override11.ets @@ -21,5 +21,5 @@ class B extends A { override fn(t: int): void { } } -/* @@? 21:14 Error TypeError: fn(t: int): void in B cannot override fn(t: int): int in A because overriding return type is not compatible with the other return type. */ -/* @@? 21:14 Error TypeError: Method fn(t: int): void in B not overriding any method */ +/* @@? 21:14 Error TypeError: fn(t: Int): void in B cannot override fn(t: Int): Int in A because overriding return type is not compatible with the other return type. */ +/* @@? 21:14 Error TypeError: Method fn(t: Int): void in B not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/override14.ets b/ets2panda/test/ast/compiler/ets/override14.ets index 70cdd59cb7..59bca85ba3 100644 --- a/ets2panda/test/ast/compiler/ets/override14.ets +++ b/ets2panda/test/ast/compiler/ets/override14.ets @@ -21,5 +21,3 @@ class B extends A { override fn(t: Object): int { return 1} } -/* @@? 21:14 Error TypeError: fn(t: Object): int in B cannot override fn(t: T): T in A because overriding return type is not compatible with the other return type. */ -/* @@? 21:14 Error TypeError: Method fn(t: Object): int in B not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/override15.ets b/ets2panda/test/ast/compiler/ets/override15.ets index 3a910c970c..22632b2eef 100644 --- a/ets2panda/test/ast/compiler/ets/override15.ets +++ b/ets2panda/test/ast/compiler/ets/override15.ets @@ -21,5 +21,5 @@ interface I2 extends I { fn(): float; } -/* @@? 21:5 Error TypeError: fn(): float in I2 cannot override fn(): int in I because overriding return type is not compatible with the other return type. */ -/* @@? 21:5 Error TypeError: Method fn(): float in I2 not overriding any method */ +/* @@? 21:5 Error TypeError: fn(): Float in I2 cannot override fn(): Int in I because overriding return type is not compatible with the other return type. */ +/* @@? 21:5 Error TypeError: Method fn(): Float in I2 not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/override3.ets b/ets2panda/test/ast/compiler/ets/override3.ets index 0ed1c28b81..4031d36c0c 100644 --- a/ets2panda/test/ast/compiler/ets/override3.ets +++ b/ets2panda/test/ast/compiler/ets/override3.ets @@ -17,5 +17,5 @@ interface I { toString(): int; } -/* @@? 17:11 Error TypeError: toString(): int in I cannot override toString(): String in Object because overriding return type is not compatible with the other return type. */ -/* @@? 17:11 Error TypeError: Method toString(): int in I not overriding any method */ +/* @@? 17:11 Error TypeError: toString(): Int in I cannot override toString(): String in Object because overriding return type is not compatible with the other return type. */ +/* @@? 17:11 Error TypeError: Method toString(): Int in I not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/override7.ets b/ets2panda/test/ast/compiler/ets/override7.ets index 18900c1e84..aca0ae3a32 100644 --- a/ets2panda/test/ast/compiler/ets/override7.ets +++ b/ets2panda/test/ast/compiler/ets/override7.ets @@ -23,5 +23,5 @@ abstract class A implements I { public override fn(): int { return 1; } } -/* @@? 23:21 Error TypeError: fn(): int in A cannot override fn(): void in J because overriding return type is not compatible with the other return type. */ -/* @@? 23:21 Error TypeError: Method fn(): int in A not overriding any method */ +/* @@? 23:21 Error TypeError: fn(): Int in A cannot override fn(): void in J because overriding return type is not compatible with the other return type. */ +/* @@? 23:21 Error TypeError: Method fn(): Int in A not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/overrideModifierNotOverriding.ets b/ets2panda/test/ast/compiler/ets/overrideModifierNotOverriding.ets index 268606ee2e..abc1ea4562 100644 --- a/ets2panda/test/ast/compiler/ets/overrideModifierNotOverriding.ets +++ b/ets2panda/test/ast/compiler/ets/overrideModifierNotOverriding.ets @@ -25,4 +25,4 @@ class B { } } -/* @@@ label Error TypeError: Method foo(a: int): int in B not overriding any method */ +/* @@@ label Error TypeError: Method foo(a: Int): Int in B not overriding any method */ diff --git a/ets2panda/test/ast/compiler/ets/package_invalid_initializer/P3/P3.ets b/ets2panda/test/ast/compiler/ets/package_invalid_initializer/P3/P3.ets index 3609cbb822..809e03282c 100644 --- a/ets2panda/test/ast/compiler/ets/package_invalid_initializer/P3/P3.ets +++ b/ets2panda/test/ast/compiler/ets/package_invalid_initializer/P3/P3.ets @@ -47,8 +47,8 @@ static { /* @@? P3.ets:29:14 Error SyntaxError: Missing initialization for const package property */ /* @@? P3.ets:29:18 Error SyntaxError: Variable must be initialized or it's type must be declared. */ /* @@? P3.ets:30:30 Error SyntaxError: Non-constant initializer of Package should be apply in Initializer Block. */ -/* @@? P3.ets:31:14 Error TypeError: Cannot reassign constant c_nn2 */ /* @@? P3.ets:32:6 Error SyntaxError: Non-constant initializer of Package should be apply in Initializer Block. */ /* @@? P3.ets:33:1 Error SyntaxError: Invalid package toplevel statement */ /* @@? P3.ets:34:1 Error SyntaxError: Invalid package toplevel statement */ +/* @@? P3.ets:36:5 Error TypeError: Invalid left-hand side of assignment expression */ /* @@? P3.ets:39:14 Error SyntaxError: Missing initialization for const package property */ diff --git a/ets2panda/test/ast/compiler/ets/recordWithLambdaFunction2.ets b/ets2panda/test/ast/compiler/ets/recordWithLambdaFunction2.ets index 799b915f10..662eea658f 100644 --- a/ets2panda/test/ast/compiler/ets/recordWithLambdaFunction2.ets +++ b/ets2panda/test/ast/compiler/ets/recordWithLambdaFunction2.ets @@ -23,6 +23,6 @@ function main(): void { handlerMap[2] = 1 } -/* @@? 23:5 Error TypeError: No matching indexing signature for $_set(int, int) */ +/* @@? 23:5 Error TypeError: No matching indexing signature for $_set(Int, Int) */ /* @@? 23:16 Error TypeError: Cannot find index access method with the required signature. */ -/* @@? 23:21 Error TypeError: Type 'int' is not compatible with type '(param: Double) => String' at index 2 */ +/* @@? 23:21 Error TypeError: Type 'Int' is not compatible with type '(param: Double) => String' at index 2 */ diff --git a/ets2panda/test/ast/compiler/ets/recursive_class_neg.ets b/ets2panda/test/ast/compiler/ets/recursive_class_neg.ets index a7d08982f9..f2f1b08aa9 100644 --- a/ets2panda/test/ast/compiler/ets/recursive_class_neg.ets +++ b/ets2panda/test/ast/compiler/ets/recursive_class_neg.ets @@ -17,6 +17,6 @@ class A>>{} class C extends A/* @@ label1 */>{} /* A does not satisfy the constraint due to invariance of T */ -/* @@@ label Error TypeError: Type A is not assignable to constraint type A>> */ -/* @@@ label2 Error TypeError: Type C is not assignable to constraint type A> */ -/* @@@ label1 Error TypeError: Type A is not assignable to constraint type A>> */ +/* @@@ label Error TypeError: Type argument 'A' should be a subtype of 'A>>'-constraint */ +/* @@@ label2 Error TypeError: Type argument 'C' should be a subtype of 'A>'-constraint */ +/* @@@ label1 Error TypeError: Type argument 'A' should be a subtype of 'A>>'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/recursive_interface_neg_1.ets b/ets2panda/test/ast/compiler/ets/recursive_interface_neg_1.ets index 7bfe478c30..9ee831177a 100644 --- a/ets2panda/test/ast/compiler/ets/recursive_interface_neg_1.ets +++ b/ets2panda/test/ast/compiler/ets/recursive_interface_neg_1.ets @@ -16,4 +16,4 @@ interface A>{} interface D{} interface B extends A/* @@ label */{} -/* @@@ label Error TypeError: Type D is not assignable to constraint type A */ +/* @@@ label Error TypeError: Type argument 'D' should be a subtype of 'A'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/recursive_interface_neg_2.ets b/ets2panda/test/ast/compiler/ets/recursive_interface_neg_2.ets index fb2f281725..3596a49b97 100644 --- a/ets2panda/test/ast/compiler/ets/recursive_interface_neg_2.ets +++ b/ets2panda/test/ast/compiler/ets/recursive_interface_neg_2.ets @@ -16,4 +16,4 @@ interface A,T2 extends A>{} interface D{} interface B extends A/* @@ label */{} -/* @@@ label Error TypeError: Type D is not assignable to constraint type A */ +/* @@@ label Error TypeError: Type argument 'D' should be a subtype of 'A'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/recursive_union_neg_1.ets b/ets2panda/test/ast/compiler/ets/recursive_union_neg_1.ets index 7a588b42f8..0238b2626c 100644 --- a/ets2panda/test/ast/compiler/ets/recursive_union_neg_1.ets +++ b/ets2panda/test/ast/compiler/ets/recursive_union_neg_1.ets @@ -19,4 +19,4 @@ class T

{} class C extends A/* @@ label */{} /* Constraint: B|D|C <: A, but B is not a subtype of A due to T invariance */ -/* @@@ label Error TypeError: Type B|D|C is not assignable to constraint type A */ +/* @@@ label Error TypeError: Type argument 'B|D|C' should be a subtype of 'A'-constraint */ diff --git a/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type.ets b/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type.ets index 4c1d8884cf..96838d3c4b 100644 --- a/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type.ets +++ b/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type.ets @@ -27,4 +27,3 @@ function main() { /* @@? 24:17 Error TypeError: Type '() => Double' cannot be assigned to type '() => void|Double' */ /* @@? 25:16 Error TypeError: Cannot use type 'void' as value. */ -/* @@? 25:17 Error TypeError: Cannot cast type '() => Double' to '() => void' */ diff --git a/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type_1.ets b/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type_1.ets index dd877c7254..934b5c8f68 100644 --- a/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type_1.ets +++ b/ets2panda/test/ast/compiler/ets/resolve_func_name_union_type_1.ets @@ -26,3 +26,4 @@ function main() { } /* @@@ label Error TypeError: Type '() => Double' cannot be assigned to type 'String|Double' */ +/* @@? 25:15 Error TypeError: Cannot cast type 'String|Double' to '() => Double' */ diff --git a/ets2panda/test/ast/compiler/ets/same_assembly_overload/callExpr_pos.ets b/ets2panda/test/ast/compiler/ets/same_assembly_overload/callExpr_pos.ets index cfaac5fee9..6d1a172270 100644 --- a/ets2panda/test/ast/compiler/ets/same_assembly_overload/callExpr_pos.ets +++ b/ets2panda/test/ast/compiler/ets/same_assembly_overload/callExpr_pos.ets @@ -25,4 +25,4 @@ foo(1,2) foo(1.1) /* @@? 17:1 Warning Warning: Function foo with this assembly signature already declared. */ -/* @@? 23:5 Error TypeError: Variable 'b' is used before being assigned. */ +/* @@? 23:5 Warning Warning: Variable 'b' is used before being assigned. */ diff --git a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_1.ets b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_1.ets index df5bce8676..78955a8122 100644 --- a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_1.ets +++ b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_1.ets @@ -15,8 +15,7 @@ //declare function has body export class A {} -export declare function foo(a:A):void +export declare function foo(a:A):void export declare function foo(a:A):number {} -/* @@? 18:8 Warning Warning: Function foo with this assembly signature already declared. */ /* @@? 19:49 Error TypeError: Native, Abstract and Declare methods cannot have body. */ diff --git a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_2.ets b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_2.ets index 227dab0f78..27671485ba 100644 --- a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_2.ets +++ b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_neg_2.ets @@ -15,7 +15,7 @@ //Not support non-declare function has same assembly code export class A {} -export declare function foo(a:A):void +export declare function foo(a:A):void export function foo(a:A):number {} -/* @@? 19:8 Error TypeError: Function foo with this assembly signature already declared. */ \ No newline at end of file +/* @@? 19:17 Error TypeError: Function with a non void return type must return a value. */ diff --git a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_1.ets b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_1.ets index 5440079d8e..31d4512f58 100644 --- a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_1.ets +++ b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_1.ets @@ -15,10 +15,7 @@ //Without rest parameter export class A {} -export declare function foo(a:A):void +export declare function foo(a:A):void export declare function foo(a:A):number export declare function foo(a:int, b:int):void export declare function foo(a:double):void - -/* @@? 18:8 Warning Warning: Function foo with this assembly signature already declared. */ - diff --git a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_2.ets b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_2.ets index 9900d58e0c..a35dbbffd6 100644 --- a/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_2.ets +++ b/ets2panda/test/ast/compiler/ets/same_assembly_overload/overload_signature_pos_2.ets @@ -15,11 +15,8 @@ //With rest parameter export class A {} -export declare function foo(a:A):void +export declare function foo(a:A):void export declare function foo(a:A):number export declare function foo(a:int, b:int):void export declare function foo(a:double):void export declare function foo(...args:string[]):void - -/* @@? 18:8 Warning Warning: Function foo with this assembly signature already declared. */ - diff --git a/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets b/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets index 116c419830..9f1621021f 100644 --- a/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets +++ b/ets2panda/test/ast/compiler/ets/switchcaseDuplicate.ets @@ -22,13 +22,13 @@ class IndexStr { indexField: string = "title" foo() { switch (this.indexField) { - /* @@ label */case IndexField.TITLE: + case IndexField.TITLE: assertEQ(this.indexField, IndexField.TITLE) break; - case IndexField.TITLE: + /* @@ label */case IndexField.TITLE: assertEQ(this.indexField, IndexField.TITLE) } } } -/* @@@ label Error TypeError: Variable has same value with another switch case */ \ No newline at end of file +/* @@@ label Error TypeError: Case duplicate */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/tuple_types_10_neg.ets b/ets2panda/test/ast/compiler/ets/tuple_types_10_neg.ets index d874643b8f..b03095bb29 100644 --- a/ets2panda/test/ast/compiler/ets/tuple_types_10_neg.ets +++ b/ets2panda/test/ast/compiler/ets/tuple_types_10_neg.ets @@ -19,4 +19,4 @@ function main(): void { let b: [number, number, number] = /* @@ label */a; } -/* @@@ label Error TypeError: Type '[double, double]' cannot be assigned to type '[double, double, double]' */ +/* @@@ label Error TypeError: Type '[Double, Double]' cannot be assigned to type '[Double, Double, Double]' */ diff --git a/ets2panda/test/ast/compiler/ets/tuple_types_11_neg.ets b/ets2panda/test/ast/compiler/ets/tuple_types_11_neg.ets index 5c6ff60fea..b6a37f7126 100644 --- a/ets2panda/test/ast/compiler/ets/tuple_types_11_neg.ets +++ b/ets2panda/test/ast/compiler/ets/tuple_types_11_neg.ets @@ -19,4 +19,4 @@ function main(): void { let b: [number, number] = /* @@ label */a; } -/* @@@ label Error TypeError: Type '[double, double, double]' cannot be assigned to type '[double, double]' */ +/* @@@ label Error TypeError: Type '[Double, Double, Double]' cannot be assigned to type '[Double, Double]' */ diff --git a/ets2panda/test/ast/compiler/ets/tuple_types_1_neg.ets b/ets2panda/test/ast/compiler/ets/tuple_types_1_neg.ets index 55c0a6e370..ea8e9d99a5 100644 --- a/ets2panda/test/ast/compiler/ets/tuple_types_1_neg.ets +++ b/ets2panda/test/ast/compiler/ets/tuple_types_1_neg.ets @@ -18,4 +18,4 @@ function main(): void { const array: (number|boolean) [] = tuple } -/* @@? 18:40 Error TypeError: Type '[double, double, boolean]' cannot be assigned to type 'Array' */ +/* @@? 18:40 Error TypeError: Type '[Double, Double, Boolean]' cannot be assigned to type 'Array' */ diff --git a/ets2panda/test/ast/compiler/ets/tuple_types_6_neg.ets b/ets2panda/test/ast/compiler/ets/tuple_types_6_neg.ets index 7f792a64d5..0d723e75d4 100644 --- a/ets2panda/test/ast/compiler/ets/tuple_types_6_neg.ets +++ b/ets2panda/test/ast/compiler/ets/tuple_types_6_neg.ets @@ -16,7 +16,6 @@ function main(): void { let a: [number] = [1]; - let b: [Number] = /* @@ label */a; + let b: [Number] = a; } -/* @@@ label Error TypeError: Type '[double]' cannot be assigned to type '[Double]' */ diff --git a/ets2panda/test/ast/compiler/ets/tuple_types_9_neg.ets b/ets2panda/test/ast/compiler/ets/tuple_types_9_neg.ets index d4b386b23d..b02458c719 100644 --- a/ets2panda/test/ast/compiler/ets/tuple_types_9_neg.ets +++ b/ets2panda/test/ast/compiler/ets/tuple_types_9_neg.ets @@ -24,4 +24,4 @@ function main(): void { /* @@? 18:29 Error SyntaxError: Unexpected token '...'. */ /* @@? 18:32 Error SyntaxError: Unexpected token 'Int'. */ /* @@? 18:37 Error SyntaxError: Unexpected token ']'. */ -/* @@@ label Error TypeError: Type '[double, String, *ERROR_TYPE*]' cannot be assigned to type '[double, String, Int]' */ +/* @@@ label Error TypeError: Type '[Double, String, *ERROR_TYPE*]' cannot be assigned to type '[Double, String, Int]' */ diff --git a/ets2panda/test/ast/compiler/ets/type_error_processing/type_handlers.ets b/ets2panda/test/ast/compiler/ets/type_error_processing/type_handlers.ets index 7e42c8c105..f3cc9e64c3 100644 --- a/ets2panda/test/ast/compiler/ets/type_error_processing/type_handlers.ets +++ b/ets2panda/test/ast/compiler/ets/type_error_processing/type_handlers.ets @@ -40,14 +40,11 @@ type T15 = Required /* @@? 22:18 Error TypeError: Invalid number of type parameters for Partial type, should be 1. */ /* @@? 24:18 Error TypeError: Invalid number of type parameters for Partial type, should be 1. */ /* @@? 25:18 Error TypeError: Invalid number of type parameters for Partial type, should be 1. */ -/* @@? 26:18 Error TypeError: Only reference types can be converted to utility types. */ /* @@? 28:19 Error TypeError: Invalid number of type parameters for Readonly type, should be 1. */ /* @@? 30:19 Error TypeError: Invalid number of type parameters for Readonly type, should be 1. */ /* @@? 31:19 Error TypeError: Invalid number of type parameters for Readonly type, should be 1. */ -/* @@? 32:20 Error TypeError: Only reference types can be converted to utility types. */ /* @@? 34:20 Error TypeError: Invalid number of type parameters for Required type, should be 1. */ /* @@? 36:20 Error TypeError: Invalid number of type parameters for Required type, should be 1. */ /* @@? 37:20 Error TypeError: Invalid number of type parameters for Required type, should be 1. */ -/* @@? 38:20 Error TypeError: Only reference types can be converted to utility types. */ diff --git a/ets2panda/test/ast/compiler/ets/unionCommonMember_neg.ets b/ets2panda/test/ast/compiler/ets/unionCommonMember_neg.ets index be96553f9d..25e6f1e043 100644 --- a/ets2panda/test/ast/compiler/ets/unionCommonMember_neg.ets +++ b/ets2panda/test/ast/compiler/ets/unionCommonMember_neg.ets @@ -51,11 +51,10 @@ function main() { assertEQ(/* @@ label8 */u.fld8, new Map()) } -/* @@@ label1 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label2 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label3 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label4 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label5 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label6 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label7 Error TypeError: Member type must be the same for all union objects. */ -/* @@@ label8 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label1 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label3 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label4 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label5 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label6 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label7 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label8 Error TypeError: Member type must be the same for all union objects. */ diff --git a/ets2panda/test/ast/compiler/ets/unmatch_arg_for_trailing_lambda.ets b/ets2panda/test/ast/compiler/ets/unmatch_arg_for_trailing_lambda.ets index b77849bcc5..81037bd2a5 100644 --- a/ets2panda/test/ast/compiler/ets/unmatch_arg_for_trailing_lambda.ets +++ b/ets2panda/test/ast/compiler/ets/unmatch_arg_for_trailing_lambda.ets @@ -19,8 +19,8 @@ foo(1, "2") foo(1, 1) foo(1, () => { return "1" }) -/* @@? 18:1 Error TypeError: No matching call signature for foo(int, "2") */ +/* @@? 18:1 Error TypeError: No matching call signature for foo(Double, "2") */ /* @@? 18:8 Error TypeError: Type '"2"' is not compatible with type '() => void|undefined' at index 2 */ -/* @@? 19:1 Error TypeError: No matching call signature for foo(int, int) */ -/* @@? 19:8 Error TypeError: Type 'int' is not compatible with type '() => void|undefined' at index 2 */ -/* @@? 20:23 Error TypeError: Unexpected return value, enclosing method return type is void. */ \ No newline at end of file +/* @@? 19:1 Error TypeError: No matching call signature for foo(Double, Int) */ +/* @@? 19:8 Error TypeError: Type 'Int' is not compatible with type '() => void|undefined' at index 2 */ +/* @@? 20:23 Error TypeError: Unexpected return value, enclosing method return type is void. */ diff --git a/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error.ets b/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error.ets index 43dba88366..56379e67db 100644 --- a/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error.ets +++ b/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error.ets @@ -14,9 +14,5 @@ */ function main() : void { - let a: Byte = /* @@ label */new Byte(2); + let a: Byte = new Byte(2); } - -/* @@@ label Error TypeError: Expected 0 arguments, got 1. */ -/* @@@ label Error TypeError: No matching construct signature for std.core.Byte(int) */ -/* @@? 17:42 Error TypeError: Type 'int' is not compatible with type 'byte' at index 1 */ diff --git a/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error_more_param.ets b/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error_more_param.ets index d918e3e7d3..a7b4bf5973 100644 --- a/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error_more_param.ets +++ b/ets2panda/test/ast/compiler/ets/validate_signatures_throw_type_error_more_param.ets @@ -19,4 +19,4 @@ function main() : void { /* @@@ label Error TypeError: Expected 0 arguments, got 2. */ /* @@@ label Error TypeError: Expected 1 arguments, got 2. */ -/* @@@ label Error TypeError: No matching construct signature for std.core.Float(int, "3") */ +/* @@@ label Error TypeError: No matching construct signature for std.core.Float(Int, "3") */ diff --git a/ets2panda/test/ast/compiler/ets/voidTypeInBinaryOperation.ets b/ets2panda/test/ast/compiler/ets/voidTypeInBinaryOperation.ets index 14947fde7e..444e753ab6 100644 --- a/ets2panda/test/ast/compiler/ets/voidTypeInBinaryOperation.ets +++ b/ets2panda/test/ast/compiler/ets/voidTypeInBinaryOperation.ets @@ -20,6 +20,6 @@ function main(): void { assertTrue(false || check()) } -/* @@? 20:3 Error TypeError: No matching call signature for assertTrue(void) */ +/* @@? 20:3 Error TypeError: No matching call signature for assertTrue(Boolean|void) */ +/* @@? 20:14 Error TypeError: Type 'Boolean|void' is not compatible with type 'Boolean' at index 1 */ /* @@? 20:23 Error TypeError: Cannot use type 'void' as value. */ -/* @@? 20:23 Error TypeError: Type 'void' is not compatible with type 'boolean' at index 1 */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets b/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets index 5a026a6288..8a366c6af3 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/FunctionalTypeAsArrayElement.ets @@ -19,4 +19,4 @@ function main(){ ] } -/* @@? 17:48 Error TypeError: Type 'Array<() => Int>' cannot be assigned to type '() => FixedArray' */ +/* @@? 17:48 Error TypeError: Type 'Array<() => Int>' cannot be assigned to type '() => FixedArray' */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets b/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets index 6017bb34e3..29c5aced21 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/InvalidStatements3.ets @@ -51,13 +51,12 @@ for (let i = 1 in [0, 1, 2]) {} /* @@? 27:7 Error TypeError: need to specify target type for class composite */ /* @@? 29:1 Error SyntaxError: Expected ')', got 'while'. */ /* @@? 29:7 Error SyntaxError: Expected '(', got 'identification literal'. */ -/* @@? 29:7 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 29:13 Error SyntaxError: Expected ')', got '{'. */ /* @@? 31:9 Error SyntaxError: Unexpected token 'let'. */ /* @@? 31:13 Error SyntaxError: Unexpected token 'x'. */ /* @@? 34:5 Error SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list. */ -/* @@? 38:5 Error SyntaxError: Unexpected token 'private'. */ /* @@? 38:5 Error SyntaxError: Annotation declaration can not have access modifier. */ +/* @@? 38:5 Error SyntaxError: Unexpected token 'private'. */ /* @@? 38:13 Error SyntaxError: Unexpected token '@'. */ /* @@? 38:14 Error TypeError: Cannot find type 'annotate'. */ /* @@? 42:16 Error SyntaxError: for-in loop variable declaration may not have an initializer. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/MultipleParserErrors.ets b/ets2panda/test/ast/parser/ets/FixedArray/MultipleParserErrors.ets index d92079e5b4..d4be463b1d 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/MultipleParserErrors.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/MultipleParserErrors.ets @@ -219,7 +219,7 @@ function main(): void { /* @@? 74:11 Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ /* @@? 77:20 Error TypeError: Interface expected here. */ /* @@? 77:22 Error TypeError: 'I' type does not exist. */ -/* @@? 78:22 Error TypeError: Method fee(): int in B not overriding any method */ +/* @@? 78:22 Error TypeError: Method fee(): Int in B not overriding any method */ /* @@? 83:7 Error TypeError: Merging declarations is not supported, please keep all definitions of classes, interfaces and enums compact in the codebase! */ /* @@? 83:7 Error TypeError: Variable 'A' has already been declared. */ /* @@? 84:3 Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ @@ -267,13 +267,13 @@ function main(): void { /* @@? 137:21 Error SyntaxError: Unexpected token '{'. */ /* @@? 141:16 Error TypeError: This expression is not callable. */ /* @@? 145:18 Error TypeError: A is abstract therefore cannot be instantiated. */ -/* @@? 146:16 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@? 146:20 Error TypeError: Property 'getInner' does not exist on type 'A' */ /* @@? 148:25 Error TypeError: A is abstract therefore cannot be instantiated. */ /* @@? 149:24 Error TypeError: A is abstract therefore cannot be instantiated. */ /* @@? 151:20 Error TypeError: Cannot find type 'D0'. */ /* @@? 151:29 Error TypeError: Cannot find type 'D0'. */ /* @@? 157:16 Error TypeError: A is abstract therefore cannot be instantiated. */ -/* @@? 158:16 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@? 158:18 Error TypeError: Property 'getInner' does not exist on type 'A' */ /* @@? 161:9 Error SyntaxError: Identifier expected, got 'let'. */ /* @@? 162:9 Error SyntaxError: Identifier expected, got 'const'. */ /* @@? 163:9 Error SyntaxError: Identifier expected, got 'new'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/StringFasta.ets b/ets2panda/test/ast/parser/ets/FixedArray/StringFasta.ets index b9680ece6b..b2da14ee6a 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/StringFasta.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/StringFasta.ets @@ -122,15 +122,10 @@ function main(): void { a.run(); } -/* @@@ label Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ -/* @@? 18:46 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 18:18 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 19:50 Error TypeError: Cannot find type 'HashMap'. */ +/* @@? 18:46 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 19:22 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 52:35 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 54:26 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 84:41 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 95:34 Error TypeError: Cannot find type 'HashMap'. */ +/* @@? 19:50 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 21:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 22:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 23:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ @@ -150,6 +145,7 @@ function main(): void { /* @@? 37:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 38:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 39:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ +/* @@@ label Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ /* @@? 47:13 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 47:21 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 47:28 Error TypeError: Static property 'A' must be accessed through it's class 'Random' */ @@ -157,27 +153,29 @@ function main(): void { /* @@? 47:37 Error TypeError: Static property 'M' must be accessed through it's class 'Random' */ /* @@? 48:26 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 48:33 Error TypeError: Static property 'M' must be accessed through it's class 'Random' */ +/* @@? 52:35 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 53:27 Error TypeError: Type 'null' cannot be assigned to type 'Char' */ +/* @@? 54:26 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 54:57 Error TypeError: 'For-of' statement source expression is not of iterable type. */ -/* @@? 71:33 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 71:17 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ -/* @@? 72:24 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 77:33 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 78:24 Error TypeError: Type 'double' has no call signatures. */ +/* @@? 71:33 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 72:24 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 77:33 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 78:24 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 84:41 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 86:9 Error TypeError: Static property 'makeCumulative' must be accessed through it's class 'StringFasta' */ /* @@? 94:34 Error TypeError: Static property 'Random' must be accessed through it's class 'StringFasta' */ +/* @@? 95:34 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 95:65 Error TypeError: 'For-of' statement source expression is not of iterable type. */ -/* @@? 103:20 Error TypeError: Type 'double' has no call signatures. */ +/* @@? 103:20 Error TypeError: Type 'Double' has no call signatures. */ /* @@? 112:16 Error TypeError: Static property 'fastaRepeat' must be accessed through it's class 'StringFasta' */ -/* @@? 112:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 112:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ -/* @@? 112:48 Error TypeError: Static property 'ALU' must be accessed through it's class 'StringFasta' */ +/* @@? 112:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:16 Error TypeError: Static property 'fastaRandom' must be accessed through it's class 'StringFasta' */ -/* @@? 113:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 113:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:46 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 114:16 Error TypeError: Static property 'fastaRandom' must be accessed through it's class 'StringFasta' */ -/* @@? 114:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 114:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 114:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 114:46 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 116:28 Error TypeError: 'expected' is a static property of 'StringFasta' */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/array_type.ets b/ets2panda/test/ast/parser/ets/FixedArray/array_type.ets index 39c8b1c969..e2021d154b 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/array_type.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/array_type.ets @@ -28,4 +28,3 @@ class array_type { /* @@@ label1 Error TypeError: Property 'f' might not have been initialized. */ /* @@@ label2 Error TypeError: Function with a non void return type must return a value. */ /* @@@ label3 Error TypeError: Function with a non void return type must return a value. */ - diff --git a/ets2panda/test/ast/parser/ets/FixedArray/ets_never_type_without_affect_other.ets b/ets2panda/test/ast/parser/ets/FixedArray/ets_never_type_without_affect_other.ets index da4c91a29a..c5987fed62 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/ets_never_type_without_affect_other.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/ets_never_type_without_affect_other.ets @@ -25,5 +25,6 @@ function foo(): number { } return n! } -/* @@? 23:17 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ -/* @@? 26:12 Warning Warning: Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'. */ \ No newline at end of file + +/* @@? 23:17 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 26:12 Error Warning: Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/for_of_02.ets b/ets2panda/test/ast/parser/ets/FixedArray/for_of_02.ets index fd74b049d9..25779dcb62 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/for_of_02.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/for_of_02.ets @@ -32,4 +32,4 @@ function main(): void { } } -/* @@? 30:17 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'float'. */ +/* @@@ label Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'Float'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/illegal_union_member_exp.ets b/ets2panda/test/ast/parser/ets/FixedArray/illegal_union_member_exp.ets index 8e4083148a..a49879c670 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/illegal_union_member_exp.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/illegal_union_member_exp.ets @@ -21,3 +21,5 @@ function main(): void { let b = s ?? a; b.toString(); } + +/* @@? 22:19 Error TypeError: Type String|Int[] is illegal in union member expression. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/invalidTypes.ets b/ets2panda/test/ast/parser/ets/FixedArray/invalidTypes.ets index 718311fef0..5e4dcd90af 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/invalidTypes.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/invalidTypes.ets @@ -45,7 +45,6 @@ let var6: [a0: , a1: ]; /* @@? 24:23 Error SyntaxError: Unexpected token '>'. */ /* @@? 24:26 Error SyntaxError: Unexpected token 'number'. */ /* @@? 24:26 Error TypeError: Type name 'number' used in the wrong context */ -/* @@? 24:26 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 24:33 Error SyntaxError: Unexpected token ','. */ /* @@? 24:35 Error SyntaxError: Unexpected token 'FixedArray'. */ /* @@? 24:35 Error TypeError: Unresolved reference FixedArray */ @@ -59,7 +58,6 @@ let var6: [a0: , a1: ]; /* @@? 26:23 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 26:23 Error SyntaxError: Unexpected token '>'. */ /* @@? 26:26 Error SyntaxError: Unexpected token 'number'. */ -/* @@? 26:26 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 26:26 Error TypeError: Type name 'number' used in the wrong context */ /* @@? 26:33 Error SyntaxError: Unexpected token ','. */ /* @@? 26:35 Error SyntaxError: Unexpected token 'string'. */ @@ -68,14 +66,13 @@ let var6: [a0: , a1: ]; /* @@? 28:18 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 28:18 Error SyntaxError: Unexpected token '?'. */ /* @@? 28:19 Error SyntaxError: Unexpected token ']'. */ -/* @@? 30:18 Error SyntaxError: Unexpected token ':'. */ /* @@? 30:18 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 30:18 Error SyntaxError: Unexpected token ':'. */ /* @@? 30:20 Error SyntaxError: Unexpected token '...'. */ /* @@? 30:23 Error SyntaxError: Unexpected token 'int'. */ /* @@? 30:26 Error SyntaxError: Unexpected token ']'. */ -/* @@? 32:19 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 32:19 Error SyntaxError: Unexpected token 'number'. */ +/* @@? 32:19 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 32:19 Error TypeError: Type name 'number' used in the wrong context */ /* @@? 32:25 Error SyntaxError: Unexpected token ']'. */ /* @@? 35:21 Error SyntaxError: A 'this' type is available only as return type in a non-static method of a class or struct and extension functions. */ @@ -84,5 +81,5 @@ let var6: [a0: , a1: ]; /* @@? 38:14 Error SyntaxError: Unexpected token, expected ',' or ']'. */ /* @@? 38:16 Error SyntaxError: Unexpected token ','. */ /* @@? 38:18 Error SyntaxError: Unexpected token 'a1'. */ -/* @@? 38:22 Error SyntaxError: Unexpected token ']'. */ /* @@? 38:22 Error SyntaxError: Label must be followed by a loop statement. */ +/* @@? 38:22 Error SyntaxError: Unexpected token ']'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/n_arrayHoldingNullValue.ets b/ets2panda/test/ast/parser/ets/FixedArray/n_arrayHoldingNullValue.ets index 89238cd2b0..3bf1015d7a 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/n_arrayHoldingNullValue.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/n_arrayHoldingNullValue.ets @@ -18,5 +18,5 @@ function main(): void { let d: FixedArray = /* @@ label1 */null; } -/* @@? 17:48 Error TypeError: Type 'null' cannot be assigned to type 'FixedArray' */ -/* @@? 18:46 Error TypeError: Type 'null' cannot be assigned to type 'FixedArray' */ +/* @@? 17:48 Error TypeError: Type 'null' cannot be assigned to type 'FixedArray' */ +/* @@? 18:46 Error TypeError: Type 'null' cannot be assigned to type 'FixedArray' */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/nonIntegralIndex.ets b/ets2panda/test/ast/parser/ets/FixedArray/nonIntegralIndex.ets index 6d3751d902..7f0a390e84 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/nonIntegralIndex.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/nonIntegralIndex.ets @@ -19,4 +19,4 @@ export class Test { } } -/* @@@ label Error TypeError: Type 'double' cannot be used as an index type. Only primitive or unboxable integral types can be used as index. */ +/* @@@ label Error TypeError: Type 'Double' cannot be used as an index type. Only primitive or unboxable integral types can be used as index. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/predefined_non_primitive_types.ets b/ets2panda/test/ast/parser/ets/FixedArray/predefined_non_primitive_types.ets index b4ef18b4e9..e096d5945f 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/predefined_non_primitive_types.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/predefined_non_primitive_types.ets @@ -36,5 +36,6 @@ let s: String = "abc"; let a: FixedArray = new int[5]; /* @@@ label Error TypeError: Variable 'non_prim_b' has already been declared. */ +/* @@? 23:25 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ /* @@? 27:31 Error TypeError: Cannot find type 'Bool'. */ -/* @@? 27:38 Error TypeError: Type 'boolean' cannot be assigned to type 'Byte' */ +/* @@? 27:38 Error TypeError: Type 'Boolean' cannot be assigned to type 'Byte' */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test1.ets b/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test1.ets index 2ca4a147db..76821f2070 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test1.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test1.ets @@ -19,5 +19,5 @@ function foo (p: FixedArray) { let x: Readonly> = [] /* @@ label */foo(/* @@ label1 */x) -/* @@? 20:15 Error TypeError: No matching call signature for foo(readonly FixedArray) */ -/* @@? 20:34 Error TypeError: Type 'readonly FixedArray' is not compatible with type 'FixedArray' at index 1 */ +/* @@? 20:15 Error TypeError: No matching call signature for foo(readonly FixedArray) */ +/* @@? 20:34 Error TypeError: Type 'readonly FixedArray' is not compatible with type 'FixedArray' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test4.ets b/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test4.ets index 4b0401da44..516d11b4d2 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test4.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/readonly-parameter-test/Readonly-with-ArrayType-test4.ets @@ -18,4 +18,4 @@ function foo (x: Readonly>) { let x1 : FixedArray x1 = /* @@ label */x } -/* @@? 19:24 Error TypeError: Type 'readonly FixedArray' cannot be assigned to type 'FixedArray' */ +/* @@? 19:24 Error TypeError: Type 'readonly FixedArray' cannot be assigned to type 'FixedArray' */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/record_object_value.ets b/ets2panda/test/ast/parser/ets/FixedArray/record_object_value.ets index 90442a1300..a7f6f9a173 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/record_object_value.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/record_object_value.ets @@ -57,7 +57,7 @@ function main(){ "Mary":["20", "30"] }; } -/* @@@ label Error TypeError: Type '"10"' is not compatible with type 'double' at property 'age' */ -/* @@@ label1 Error TypeError: Type '"100"' is not compatible with type 'double' at property 'salary' */ +/* @@@ label Error TypeError: Type '"10"' is not compatible with type 'Double' at property 'age' */ +/* @@@ label1 Error TypeError: Type '"100"' is not compatible with type 'Double' at property 'salary' */ /* @@@ label2 Error TypeError: type PersonInfoInterface has no property named agee */ /* @@@ label3 Error TypeError: type PersonInfoInterface has no property named other */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/tuple_type_2_neg.ets b/ets2panda/test/ast/parser/ets/FixedArray/tuple_type_2_neg.ets index fb10b017ca..a0436293f7 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/tuple_type_2_neg.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/tuple_type_2_neg.ets @@ -23,7 +23,6 @@ let a: [number, FixedArray<...number>, number] = [1, 2, 3]; /* @@? 17:28 Error SyntaxError: Unexpected token '>'. */ /* @@? 17:31 Error SyntaxError: Unexpected token 'number'. */ /* @@? 17:31 Error TypeError: Type name 'number' used in the wrong context */ -/* @@? 17:31 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 17:38 Error SyntaxError: Unexpected token ','. */ /* @@? 17:40 Error SyntaxError: Unexpected token 'number'. */ /* @@? 17:40 Error TypeError: Type name 'number' used in the wrong context */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_31.ets b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_31.ets index e53b749a07..b7a262d89e 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_31.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_31.ets @@ -27,5 +27,5 @@ function foo(...^number: FixedArray): int { /* @@? 16:48 Error SyntaxError: Unexpected token '{'. */ /* @@? 17:5 Error SyntaxError: return keyword should be used in function body. */ /* @@? 17:12 Error TypeError: Type name 'number' used in the wrong context */ -/* @@? 17:12 Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 17:12 Error TypeError: Indexed signatures are not allowed. Use arrays instead! */ /* @@? 17:12 Error TypeError: All return statements in the function should be empty or have a value. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_36.ets b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_36.ets index aa83ad803a..556218db5c 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_36.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_36.ets @@ -38,6 +38,5 @@ export class AccessNSieve { /* @@? 29:14 Error SyntaxError: Unexpected token ':'. */ /* @@? 29:16 Error SyntaxError: Expected ')', got 'int'. */ /* @@? 29:16 Error SyntaxError: Unexpected token 'int'. */ -/* @@? 29:25 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 29:36 Error SyntaxError: Unexpected token ')'. */ /* @@? 29:38 Error SyntaxError: Unexpected token '{'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_42.ets b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_42.ets index 69c59a936f..9e88ba3b09 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_42.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_42.ets @@ -15,5 +15,5 @@ // Int[1,2,3,4,5] let a: number = new Int[1 -/* @@? 16:17 Error TypeError: Type 'FixedArray' cannot be assigned to type 'double' */ +/* @@? 16:17 Error TypeError: Type 'Array' cannot be assigned to type 'Double' */ /* @@? 20:1 Error SyntaxError: Expected ']', got 'end of stream'. */ diff --git a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_47.ets b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_47.ets index fd63453444..e6bb326eef 100644 --- a/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_47.ets +++ b/ets2panda/test/ast/parser/ets/FixedArray/unexpected_token_47.ets @@ -15,7 +15,7 @@ let isPrime: FixedArray = new int[[]][[] -/* @@? 16:32 Error TypeError: Type 'FixedArray>' cannot be assigned to type 'FixedArray' */ +/* @@? 16:32 Error TypeError: Type 'FixedArray>' cannot be assigned to type 'FixedArray' */ /* @@? 16:40 Error TypeError: Can't resolve array type */ /* @@? 16:44 Error TypeError: Can't resolve array type */ /* @@? 22:1 Error SyntaxError: Expected ']', got 'end of stream'. */ diff --git a/ets2panda/test/ast/parser/ets/InvalidExpressions1.ets b/ets2panda/test/ast/parser/ets/InvalidExpressions1.ets index 0509c0f38c..12d43efaec 100644 --- a/ets2panda/test/ast/parser/ets/InvalidExpressions1.ets +++ b/ets2panda/test/ast/parser/ets/InvalidExpressions1.ets @@ -71,7 +71,7 @@ let a = [1, 2, 3); /* @@? 32:10 Error TypeError: Variable 'f' has already been declared. */ /* @@? 33:5 Error TypeError: Call to 'super' must be first statement in constructor */ /* @@? 33:5 Error TypeError: Expected 0 arguments, got 1. */ -/* @@? 33:5 Error TypeError: No matching call signature for std.core.Object(int) */ +/* @@? 33:5 Error TypeError: No matching call signature for std.core.Object(Int) */ /* @@? 33:10 Error SyntaxError: Unexpected super keyword. */ /* @@? 36:1 Error TypeError: Indexed access is not supported for such expression type. */ /* @@? 36:8 Error SyntaxError: Unexpected token, expected ']'. */ diff --git a/ets2panda/test/ast/parser/ets/InvalidStatements3.ets b/ets2panda/test/ast/parser/ets/InvalidStatements3.ets index 3e4c28cd0e..85b2082bf4 100644 --- a/ets2panda/test/ast/parser/ets/InvalidStatements3.ets +++ b/ets2panda/test/ast/parser/ets/InvalidStatements3.ets @@ -51,7 +51,6 @@ for (let i = 1 in [0, 1, 2]) {} /* @@? 27:7 Error TypeError: need to specify target type for class composite */ /* @@? 29:1 Error SyntaxError: Expected ')', got 'while'. */ /* @@? 29:7 Error SyntaxError: Expected '(', got 'identification literal'. */ -/* @@? 29:7 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 29:13 Error SyntaxError: Expected ')', got '{'. */ /* @@? 31:9 Error SyntaxError: Unexpected token 'let'. */ /* @@? 31:13 Error SyntaxError: Unexpected token 'x'. */ diff --git a/ets2panda/test/ast/parser/ets/MultipleClassErrors.ets b/ets2panda/test/ast/parser/ets/MultipleClassErrors.ets index 99cbb1119e..216d6b70d7 100644 --- a/ets2panda/test/ast/parser/ets/MultipleClassErrors.ets +++ b/ets2panda/test/ast/parser/ets/MultipleClassErrors.ets @@ -32,7 +32,7 @@ class /* @@ label4 */{/* @@ label5 */} /* @@? 17:19 Error SyntaxError: Unexpected token 'function'. */ /* @@? 21:20 Error SyntaxError: Unexpected token 'let'. */ /* @@? 22:20 Error SyntaxError: Unexpected token 'let'. */ -/* @@? 24:17 Error TypeError: Type '"abc"' cannot be assigned to type 'double' */ +/* @@? 24:17 Error TypeError: Type '"abc"' cannot be assigned to type 'Double' */ /* @@? 28:22 Error SyntaxError: Identifier expected, got 'number literal'. */ /* @@? 30:22 Error SyntaxError: Identifier expected, got '{'. */ /* @@? 30:38 Error SyntaxError: Expected '{', got '}'. */ diff --git a/ets2panda/test/ast/parser/ets/MultipleParserErrors.ets b/ets2panda/test/ast/parser/ets/MultipleParserErrors.ets index 79258115c1..801a5f40a3 100644 --- a/ets2panda/test/ast/parser/ets/MultipleParserErrors.ets +++ b/ets2panda/test/ast/parser/ets/MultipleParserErrors.ets @@ -217,7 +217,7 @@ function main(): void { /* @@? 74:11 Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ /* @@? 77:20 Error TypeError: Interface expected here. */ /* @@? 77:22 Error TypeError: 'I' type does not exist. */ -/* @@? 78:22 Error TypeError: Method fee(): int in B not overriding any method */ +/* @@? 78:22 Error TypeError: Method fee(): Int in B not overriding any method */ /* @@? 83:7 Error TypeError: Merging declarations is not supported, please keep all definitions of classes, interfaces and enums compact in the codebase! */ /* @@? 83:7 Error TypeError: Variable 'A' has already been declared. */ /* @@? 84:3 Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ @@ -265,13 +265,13 @@ function main(): void { /* @@? 137:21 Error SyntaxError: Unexpected token '{'. */ /* @@? 141:16 Error TypeError: This expression is not callable. */ /* @@? 145:18 Error TypeError: A is abstract therefore cannot be instantiated. */ -/* @@? 146:16 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@? 146:20 Error TypeError: Property 'getInner' does not exist on type 'A' */ /* @@? 148:25 Error TypeError: A is abstract therefore cannot be instantiated. */ /* @@? 149:24 Error TypeError: A is abstract therefore cannot be instantiated. */ /* @@? 151:20 Error TypeError: Cannot find type 'D0'. */ /* @@? 151:29 Error TypeError: Cannot find type 'D0'. */ /* @@? 157:16 Error TypeError: A is abstract therefore cannot be instantiated. */ -/* @@? 158:16 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@? 158:18 Error TypeError: Property 'getInner' does not exist on type 'A' */ /* @@? 161:9 Error SyntaxError: Identifier expected, got 'let'. */ /* @@? 162:9 Error SyntaxError: Identifier expected, got 'const'. */ /* @@? 163:9 Error SyntaxError: Identifier expected, got 'new'. */ diff --git a/ets2panda/test/ast/parser/ets/StringFasta.ets b/ets2panda/test/ast/parser/ets/StringFasta.ets index a448ec8c02..607b2a5af1 100644 --- a/ets2panda/test/ast/parser/ets/StringFasta.ets +++ b/ets2panda/test/ast/parser/ets/StringFasta.ets @@ -122,15 +122,10 @@ function main(): void { a.run(); } -/* @@@ label Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ -/* @@? 18:46 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 18:18 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 19:50 Error TypeError: Cannot find type 'HashMap'. */ +/* @@? 18:46 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 19:22 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 52:35 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 54:26 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 84:41 Error TypeError: Cannot find type 'HashMap'. */ -/* @@? 95:34 Error TypeError: Cannot find type 'HashMap'. */ +/* @@? 19:50 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 21:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 22:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 23:9 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ @@ -150,6 +145,7 @@ function main(): void { /* @@? 37:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 38:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 39:9 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ +/* @@@ label Error SyntaxError: Unexpected token. A constructor, method, accessor, or property was expected. */ /* @@? 47:13 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 47:21 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 47:28 Error TypeError: Static property 'A' must be accessed through it's class 'Random' */ @@ -157,27 +153,29 @@ function main(): void { /* @@? 47:37 Error TypeError: Static property 'M' must be accessed through it's class 'Random' */ /* @@? 48:26 Error TypeError: Static property 'last' must be accessed through it's class 'Random' */ /* @@? 48:33 Error TypeError: Static property 'M' must be accessed through it's class 'Random' */ +/* @@? 52:35 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 53:27 Error TypeError: Type 'null' cannot be assigned to type 'Char' */ +/* @@? 54:26 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 54:57 Error TypeError: 'For-of' statement source expression is not of iterable type. */ -/* @@? 71:33 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 71:17 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ -/* @@? 72:24 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 77:33 Error TypeError: Type 'double' has no call signatures. */ -/* @@? 78:24 Error TypeError: Type 'double' has no call signatures. */ +/* @@? 71:33 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 72:24 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 77:33 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 78:24 Error TypeError: Type 'Double' has no call signatures. */ +/* @@? 84:41 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 86:9 Error TypeError: Static property 'makeCumulative' must be accessed through it's class 'StringFasta' */ /* @@? 94:34 Error TypeError: Static property 'Random' must be accessed through it's class 'StringFasta' */ +/* @@? 95:34 Error TypeError: Cannot find type 'HashMap'. */ /* @@? 95:65 Error TypeError: 'For-of' statement source expression is not of iterable type. */ -/* @@? 103:20 Error TypeError: Type 'double' has no call signatures. */ +/* @@? 103:20 Error TypeError: Type 'Double' has no call signatures. */ /* @@? 112:16 Error TypeError: Static property 'fastaRepeat' must be accessed through it's class 'StringFasta' */ -/* @@? 112:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 112:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ -/* @@? 112:48 Error TypeError: Static property 'ALU' must be accessed through it's class 'StringFasta' */ +/* @@? 112:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:16 Error TypeError: Static property 'fastaRandom' must be accessed through it's class 'StringFasta' */ -/* @@? 113:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 113:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 113:46 Error TypeError: Static property 'IUB' must be accessed through it's class 'StringFasta' */ /* @@? 114:16 Error TypeError: Static property 'fastaRandom' must be accessed through it's class 'StringFasta' */ -/* @@? 114:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 114:28 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 114:32 Error TypeError: Function name 'count' used in the wrong context */ /* @@? 114:46 Error TypeError: Static property 'HomoSap' must be accessed through it's class 'StringFasta' */ /* @@? 116:28 Error TypeError: 'expected' is a static property of 'StringFasta' */ diff --git a/ets2panda/test/ast/parser/ets/accessor_call.ets b/ets2panda/test/ast/parser/ets/accessor_call.ets index 030d431499..918aaffe39 100644 --- a/ets2panda/test/ast/parser/ets/accessor_call.ets +++ b/ets2panda/test/ast/parser/ets/accessor_call.ets @@ -21,4 +21,4 @@ function main(): void { /* @@ label */new A().x(); } -/* @@@ label Error TypeError: Type 'int' has no call signatures. */ +/* @@@ label Error TypeError: Type 'Int' has no call signatures. */ diff --git a/ets2panda/test/ast/parser/ets/ambiguous_call_2.ets b/ets2panda/test/ast/parser/ets/ambiguous_call_2.ets index 27a91515bc..4d3d2c8539 100644 --- a/ets2panda/test/ast/parser/ets/ambiguous_call_2.ets +++ b/ets2panda/test/ast/parser/ets/ambiguous_call_2.ets @@ -27,5 +27,5 @@ function main (): void { goo (0, new X(), "ambiguous") } -/* @@? 27:5 Error TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(i: int, p1: I1, s: String): void` and `goo(i: int, p2: I5, s: String): void` */ -/* @@? 27:5 Error TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(i: int, p1: I1, s: String): void` and `goo(i: int, p2: I2, s: String): void` */ +/* @@? 27:5 Error TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(i: Int, p1: I1, s: String): void` and `goo(i: Int, p2: I5, s: String): void` */ +/* @@? 27:5 Error TypeError: Call to `goo` is ambiguous as `2` versions of `goo` are available: `goo(i: Int, p1: I1, s: String): void` and `goo(i: Int, p2: I2, s: String): void` */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer06.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer06.ets index be2cfb7042..f1e3bbdc40 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer06.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationDecl_bad_initializer06.ets @@ -20,4 +20,5 @@ class A{} } /* @@@ label Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ +/* @@@ label Error TypeError: Invalid value for annotation field, expected a constant literal. */ /* @@? 19:43 Error TypeError: Type '(a: Int) => void' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param02.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param02.ets index cbe206da45..4b52a661a3 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param02.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param02.ets @@ -23,4 +23,5 @@ class A{} class B{} /* @@@ label Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ +/* @@@ label Error TypeError: Invalid value for annotation field, expected a constant literal. */ /* @@? 22:23 Error TypeError: Type 'A' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets index 8dd647720d..578d3567c6 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param04.ets @@ -21,4 +21,5 @@ @MyAnno({testProperty1: "1", testProperty2: [1, 2, a]}) class B{} +/* @@? 21:45 Error TypeError: Invalid value for annotation field, expected a constant literal. */ /* @@? 21:52 Error TypeError: Unresolved reference a */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param05.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param05.ets index 5a155bd89a..c3539ceb56 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param05.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param05.ets @@ -22,4 +22,5 @@ class B{} /* @@@ label Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ +/* @@@ label Error TypeError: Invalid value for annotation field, expected a constant literal. */ /* @@? 21:40 Error TypeError: type String has no property named s */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param06.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param06.ets index 9c370a5eb2..785dbfea7e 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param06.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_bad_param06.ets @@ -22,3 +22,4 @@ class B{} /* @@@ label Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ /* @@? 20:23 Error TypeError: Type '(a: Int) => void' cannot be assigned to type 'String' */ +/* @@? 20:23 Error TypeError: Invalid value for annotation field, expected a constant literal. */ diff --git a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_tmp.ets b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_tmp.ets index cbe206da45..7173d03c9b 100644 --- a/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_tmp.ets +++ b/ets2panda/test/ast/parser/ets/annotations_tests/annotationUsage_tmp.ets @@ -23,4 +23,5 @@ class A{} class B{} /* @@@ label Error SyntaxError: Invalid value for annotation field, expected a constant literal. */ -/* @@? 22:23 Error TypeError: Type 'A' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Invalid value for annotation field, expected a constant literal. */ +/* @@@ label Error TypeError: Type 'A' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/array_type.ets b/ets2panda/test/ast/parser/ets/array_type.ets index 98f7711690..44f57bdbc2 100644 --- a/ets2panda/test/ast/parser/ets/array_type.ets +++ b/ets2panda/test/ast/parser/ets/array_type.ets @@ -28,4 +28,3 @@ class array_type { /* @@@ label1 Error TypeError: Property 'f' might not have been initialized. */ /* @@@ label2 Error TypeError: Function with a non void return type must return a value. */ /* @@@ label3 Error TypeError: Function with a non void return type must return a value. */ - diff --git a/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_1.ets b/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_1.ets index 4f43f45947..2ee2aaef91 100644 --- a/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_1.ets +++ b/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_1.ets @@ -18,4 +18,4 @@ function main(): void { } /* @@@ label1 Error TypeError: No matching call signature for assertTrue("true") */ -/* @@@ label2 Error TypeError: Type '"true"' is not compatible with type 'boolean' at index 1 */ \ No newline at end of file +/* @@@ label2 Error TypeError: Type '"true"' is not compatible with type 'Boolean' at index 1 */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_2.ets b/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_2.ets index e63562d1a0..425510b440 100644 --- a/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_2.ets +++ b/ets2panda/test/ast/parser/ets/assert_with_not_boolean_type_2.ets @@ -17,5 +17,5 @@ function main(): void { /* @@ label1 */assertTrue(/* @@ label2 */1) } -/* @@@ label1 Error TypeError: No matching call signature for assertTrue(int) */ -/* @@@ label2 Error TypeError: Type 'int' is not compatible with type 'boolean' at index 1 */ +/* @@@ label1 Error TypeError: No matching call signature for assertTrue(Int) */ +/* @@@ label2 Error TypeError: Type 'Int' is not compatible with type 'Boolean' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/assignment_non-functional_variable_to_functional_type_1.ets b/ets2panda/test/ast/parser/ets/assignment_non-functional_variable_to_functional_type_1.ets index d19b824b7b..2d9c1d6732 100644 --- a/ets2panda/test/ast/parser/ets/assignment_non-functional_variable_to_functional_type_1.ets +++ b/ets2panda/test/ast/parser/ets/assignment_non-functional_variable_to_functional_type_1.ets @@ -20,4 +20,4 @@ function main() a = /* @@ label */b } -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type '() => Int' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type '() => Int' */ diff --git a/ets2panda/test/ast/parser/ets/call_expression_for_non_functional_type.ets b/ets2panda/test/ast/parser/ets/call_expression_for_non_functional_type.ets index 1ff5c330df..fca951695d 100644 --- a/ets2panda/test/ast/parser/ets/call_expression_for_non_functional_type.ets +++ b/ets2panda/test/ast/parser/ets/call_expression_for_non_functional_type.ets @@ -27,4 +27,5 @@ function main() /* @@ label */b(1, 2) } -/* @@@ label Error TypeError: This expression is not callable. */ +/* @@@ label Error TypeError: No static $_invoke method and static $_instantiate method in b. b() is not allowed. */ +/* @@@ label Error TypeError: Type 'Int' has no call signatures. */ diff --git a/ets2panda/test/ast/parser/ets/class_optional_property.ets b/ets2panda/test/ast/parser/ets/class_optional_property.ets index ce1be206b3..a0c0ea2857 100644 --- a/ets2panda/test/ast/parser/ets/class_optional_property.ets +++ b/ets2panda/test/ast/parser/ets/class_optional_property.ets @@ -17,4 +17,4 @@ class A { applyNormalAttribute ?: () => void = /* @@ label */1 } -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type '() => void|undefined' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type '() => void|undefined' */ diff --git a/ets2panda/test/ast/parser/ets/constFloatInSwitch.ets b/ets2panda/test/ast/parser/ets/constFloatInSwitch.ets index e20ecb8182..6e8a6bb7ab 100644 --- a/ets2panda/test/ast/parser/ets/constFloatInSwitch.ets +++ b/ets2panda/test/ast/parser/ets/constFloatInSwitch.ets @@ -31,5 +31,5 @@ function main(): void { } } -/* @@@ label1 Error TypeError: Type 'void' is not compatible with the enclosing method's return type 'int' */ -/* @@@ label2 Error TypeError: Unexpected type double */ +/* @@@ label1 Error TypeError: Type 'void' is not compatible with the enclosing method's return type 'Int' */ +/* @@? 25:33 Error TypeError: Switch case type 'double' is not comparable to discriminant type 'int' */ diff --git a/ets2panda/test/ast/parser/ets/constant_expression_divide_zero.ets b/ets2panda/test/ast/parser/ets/constant_expression_divide_zero.ets index f77025113d..56d7728f42 100644 --- a/ets2panda/test/ast/parser/ets/constant_expression_divide_zero.ets +++ b/ets2panda/test/ast/parser/ets/constant_expression_divide_zero.ets @@ -25,5 +25,5 @@ enum Color { } -/* @@? 20:14 Error SyntaxError: Division by zero are not allowed in Enum or Annotation. */ -/* @@? 24:11 Error SyntaxError: Division by zero are not allowed in Enum or Annotation. */ +/* @@? 20:14 Error SyntaxError: Division by zero is not allowed. */ +/* @@? 24:11 Error SyntaxError: Division by zero is not allowed. */ diff --git a/ets2panda/test/ast/parser/ets/cycle_constructor.ets b/ets2panda/test/ast/parser/ets/cycle_constructor.ets index 9640362745..39de52dd45 100644 --- a/ets2panda/test/ast/parser/ets/cycle_constructor.ets +++ b/ets2panda/test/ast/parser/ets/cycle_constructor.ets @@ -30,6 +30,6 @@ class B extends A { } /* @@? 28:9 Error TypeError: Expected 0 arguments, got 1. */ -/* @@? 28:9 Error TypeError: No matching call signature for cycle_constructor.B(int) */ +/* @@? 28:9 Error TypeError: No matching call signature for cycle_constructor.B(Int) */ /* @@? 28:9 Error TypeError: No matching call signature for constructor */ -/* @@? 28:14 Error TypeError: Using super is not allowed in constructor */ +/* @@? 28:14 Error TypeError: Using super is not allowed in constructor */ \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/declare_class_bad_1.ets b/ets2panda/test/ast/parser/ets/declare_class_bad_1.ets index 0c45ca27f6..29c95eb7e7 100644 --- a/ets2panda/test/ast/parser/ets/declare_class_bad_1.ets +++ b/ets2panda/test/ast/parser/ets/declare_class_bad_1.ets @@ -20,4 +20,4 @@ declare class A { /* @@@ label Error SyntaxError: Initializers are not allowed in ambient contexts. */ /* @@? 17:18 Error TypeError: Initializers are not allowed in ambient contexts: f1 */ -/* @@? 17:18 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? 17:18 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/declare_class_bad_3.ets b/ets2panda/test/ast/parser/ets/declare_class_bad_3.ets index 175aac24e6..d826e1d205 100644 --- a/ets2panda/test/ast/parser/ets/declare_class_bad_3.ets +++ b/ets2panda/test/ast/parser/ets/declare_class_bad_3.ets @@ -20,4 +20,4 @@ declare class A { /* @@@ label Error SyntaxError: Initializers are not allowed in ambient contexts. */ /* @@? 17:25 Error TypeError: Initializers are not allowed in ambient contexts: f1 */ -/* @@? 17:25 Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@? 17:25 Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/declare_namespace_5.ets b/ets2panda/test/ast/parser/ets/declare_namespace_5.ets index 61605b9c0d..d517891950 100644 --- a/ets2panda/test/ast/parser/ets/declare_namespace_5.ets +++ b/ets2panda/test/ast/parser/ets/declare_namespace_5.ets @@ -49,6 +49,7 @@ class B { } /* @@? 17:5 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ +/* @@? 18:9 Error TypeError: Unresolved reference dfdfsfdf */ /* @@? 20:5 Error SyntaxError: Namespace is allowed only at the top level or inside a namespace. */ /* @@? 23:20 Error TypeError: Unresolved reference foo */ /* @@? 27:11 Error TypeError: Property 'getInstance' does not exist on type 'B' */ diff --git a/ets2panda/test/ast/parser/ets/differentTypeCompare.ets b/ets2panda/test/ast/parser/ets/differentTypeCompare.ets index e41197292f..445b9063bd 100644 --- a/ets2panda/test/ast/parser/ets/differentTypeCompare.ets +++ b/ets2panda/test/ast/parser/ets/differentTypeCompare.ets @@ -23,4 +23,4 @@ function main(): void { foo(/* @@ label */a == b); } -/* @@@ label Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@@ label Error TypeError: Operator '==' cannot be applied to types '"alma"' and 'Int'. */ diff --git a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_ctor_decl_import_bad.ets b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_ctor_decl_import_bad.ets index e01a4ddc3b..349d936094 100644 --- a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_ctor_decl_import_bad.ets +++ b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_ctor_decl_import_bad.ets @@ -22,5 +22,5 @@ import { A } from "dynamic_import_tests/modules/module" function main(): void { let x = /* @@ label */new A(/* @@ label1 */"abc", 10) } -/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'double' at index 1 */ -/* @@@ label Error TypeError: No matching construct signature for module.A("abc", int) */ +/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'Double' at index 1 */ +/* @@@ label Error TypeError: No matching construct signature for module.A("abc", Int) */ diff --git a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_1.ets b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_1.ets index 6d872c4eab..c2356b47e2 100644 --- a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_1.ets +++ b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_1.ets @@ -22,4 +22,4 @@ import { A } from "dynamic_import_tests/modules/module" function foo(p: A): void { p.f1 = /* @@ label */10 } -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_2.ets b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_2.ets index 39bac5dcae..20edcbd465 100644 --- a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_2.ets +++ b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_field_decl_import_bad_2.ets @@ -22,4 +22,4 @@ import { A } from "dynamic_import_tests/modules/module" function foo(): void { let x: string = /* @@ label */A.f2 } -/* @@@ label Error TypeError: Type 'double' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type 'Double' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_1.ets b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_1.ets index 23eb4a01ec..db83b85465 100644 --- a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_1.ets +++ b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_1.ets @@ -22,5 +22,5 @@ import { A } from "dynamic_import_tests/modules/module" function foo(p: A): void { /* @@ label */p.foo(/* @@ label1 */"abc") } -/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'double' at index 1 */ +/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'Double' at index 1 */ /* @@@ label Error TypeError: No matching call signature for foo("abc") */ diff --git a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_2.ets b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_2.ets index 3acfee0bea..bb4b9e0c59 100644 --- a/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_2.ets +++ b/ets2panda/test/ast/parser/ets/dynamic_import_tests/dynamic_class_method_decl_import_bad_2.ets @@ -22,4 +22,4 @@ import { A } from "dynamic_import_tests/modules/module" function foo(): void { let x: string = /* @@ label */A.bar() } -/* @@@ label Error TypeError: Type 'double' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type 'Double' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/enum15.ets b/ets2panda/test/ast/parser/ets/enum15.ets index f6460b88db..2a32ffa219 100644 --- a/ets2panda/test/ast/parser/ets/enum15.ets +++ b/ets2panda/test/ast/parser/ets/enum15.ets @@ -23,3 +23,4 @@ enum InvalidInitTypeEnum { /* @@? 18:11 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ /* @@? 19:7 Error SyntaxError: Only constant expression is expected in the field */ /* @@? 19:7 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ + diff --git a/ets2panda/test/ast/parser/ets/enum29.ets b/ets2panda/test/ast/parser/ets/enum29.ets index b7981e02d0..266bc01f57 100644 --- a/ets2panda/test/ast/parser/ets/enum29.ets +++ b/ets2panda/test/ast/parser/ets/enum29.ets @@ -66,5 +66,13 @@ function main(): void { } } +/* @@? 19:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 23:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 27:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 31:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 34:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 42:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 46:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 49:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ /* @@@ label Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ /* @@@ label1 Error TypeError: Enum switch case must be unqualified name of an enum constant */ diff --git a/ets2panda/test/ast/parser/ets/enum30.ets b/ets2panda/test/ast/parser/ets/enum30.ets index f166e84ac7..75995f7696 100644 --- a/ets2panda/test/ast/parser/ets/enum30.ets +++ b/ets2panda/test/ast/parser/ets/enum30.ets @@ -43,3 +43,9 @@ enum Colorj { B = "abc", M = ColorF.I == 4 ? ColorG.Red + ColorG.Green : "ac" } +/* @@? 19:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 23:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 27:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 31:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 34:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 44:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ diff --git a/ets2panda/test/ast/parser/ets/enum31.ets b/ets2panda/test/ast/parser/ets/enum31.ets index 9461010796..05a512196d 100644 --- a/ets2panda/test/ast/parser/ets/enum31.ets +++ b/ets2panda/test/ast/parser/ets/enum31.ets @@ -24,5 +24,5 @@ enum ColorC { Green = /* @@ label1 */ColorB.Green } -/* @@@ label Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ -/* @@@ label1 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 19:11 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ +/* @@? 23:11 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ diff --git a/ets2panda/test/ast/parser/ets/enum_default_negative1.ets b/ets2panda/test/ast/parser/ets/enum_default_negative1.ets index d70a08880a..8764bff88c 100644 --- a/ets2panda/test/ast/parser/ets/enum_default_negative1.ets +++ b/ets2panda/test/ast/parser/ets/enum_default_negative1.ets @@ -27,3 +27,4 @@ enum B { /* @@? 17:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ /* @@? 22:9 Error SyntaxError: Only constant expression is expected in the field */ /* @@? 22:9 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ + diff --git a/ets2panda/test/ast/parser/ets/ets_never_type_without_affect_other.ets b/ets2panda/test/ast/parser/ets/ets_never_type_without_affect_other.ets index 6593711c1c..01cd69625e 100644 --- a/ets2panda/test/ast/parser/ets/ets_never_type_without_affect_other.ets +++ b/ets2panda/test/ast/parser/ets/ets_never_type_without_affect_other.ets @@ -25,5 +25,6 @@ function foo(): number { } return n! } -/* @@? 23:17 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ -/* @@? 26:12 Warning Warning: Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'. */ \ No newline at end of file + +/* @@? 23:17 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 26:12 Error Warning: Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'. */ diff --git a/ets2panda/test/ast/parser/ets/for_await_of_loop.ets b/ets2panda/test/ast/parser/ets/for_await_of_loop.ets index aad9c94018..3b41c8b661 100644 --- a/ets2panda/test/ast/parser/ets/for_await_of_loop.ets +++ b/ets2panda/test/ast/parser/ets/for_await_of_loop.ets @@ -19,7 +19,6 @@ for await (let k: int /* @@ label1 */= 0; /* @@ label2 */k < d.length; k++) { /* @@@ label1 Error SyntaxError: for-await-of loop variable declaration may not have an initializer. */ /* @@@ label2 Error SyntaxError: Unexpected token 'k'. */ -/* @@? 16:58 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 16:62 Error TypeError: Unresolved reference d */ /* @@? 17:5 Error TypeError: Cannot reference 'this' in this context. */ /* @@? 17:10 Error TypeError: Property '$_set_unsafe' does not exist on type 'Error' */ diff --git a/ets2panda/test/ast/parser/ets/for_of_02.ets b/ets2panda/test/ast/parser/ets/for_of_02.ets index 535270a596..b30a1e168d 100644 --- a/ets2panda/test/ast/parser/ets/for_of_02.ets +++ b/ets2panda/test/ast/parser/ets/for_of_02.ets @@ -32,4 +32,4 @@ function main(): void { } } -/* @@? 30:17 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'float'. */ +/* @@@ label Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'Float'. */ diff --git a/ets2panda/test/ast/parser/ets/for_of_04.ets b/ets2panda/test/ast/parser/ets/for_of_04.ets index 85923c8781..0b51c9f55c 100644 --- a/ets2panda/test/ast/parser/ets/for_of_04.ets +++ b/ets2panda/test/ast/parser/ets/for_of_04.ets @@ -34,4 +34,5 @@ for (i in 50) { /* @@? 20:21 Error TypeError: Unresolved reference a */ /* @@? 20:22 Error SyntaxError: Unexpected token ')'. */ /* @@? 20:24 Error SyntaxError: Unexpected token '{'. */ +/* @@? 25:11 Error TypeError: Object type doesn't have proper iterator method. */ /* @@? 25:11 Error TypeError: 'For-of' statement source expression is not of iterable type. */ diff --git a/ets2panda/test/ast/parser/ets/for_of_loop_variable.ets b/ets2panda/test/ast/parser/ets/for_of_loop_variable.ets index 167d3297a1..58952390f7 100644 --- a/ets2panda/test/ast/parser/ets/for_of_loop_variable.ets +++ b/ets2panda/test/ast/parser/ets/for_of_loop_variable.ets @@ -30,7 +30,7 @@ for (let value = 40 /* @@ label2 */of iterable2) { console.log(value); } -/* @@? 18:1 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'int'. */ -/* @@? 18:38 Error SyntaxError: for-of loop variable declaration may not have an initializer. */ -/* @@? 28:1 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'int'. */ -/* @@? 28:36 Error SyntaxError: for-of loop variable declaration may not have an initializer. */ +/* @@@ label1 Error SyntaxError: for-of loop variable declaration may not have an initializer. */ +/* @@@ label2 Error SyntaxError: for-of loop variable declaration may not have an initializer. */ +/* @@? 18:1 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'Int'. */ +/* @@? 28:1 Error TypeError: Source element type 'Double' is not assignable to the loop iterator type 'Int'. */ diff --git a/ets2panda/test/ast/parser/ets/function_implicit_return_type4.ets b/ets2panda/test/ast/parser/ets/function_implicit_return_type4.ets index 2d256845c7..89efc28509 100644 --- a/ets2panda/test/ast/parser/ets/function_implicit_return_type4.ets +++ b/ets2panda/test/ast/parser/ets/function_implicit_return_type4.ets @@ -22,5 +22,5 @@ final class B extends A { public override fn(): int { return 42; } } -/* @@? 22:21 Error TypeError: fn(): int in B cannot override fn(): void in A because overriding return type is not compatible with the other return type. */ -/* @@? 22:21 Error TypeError: Method fn(): int in B not overriding any method */ +/* @@? 22:21 Error TypeError: fn(): Int in B cannot override fn(): void in A because overriding return type is not compatible with the other return type. */ +/* @@? 22:21 Error TypeError: Method fn(): Int in B not overriding any method */ diff --git a/ets2panda/test/ast/parser/ets/function_implicit_return_type7.ets b/ets2panda/test/ast/parser/ets/function_implicit_return_type7.ets index 8d24e6099b..81afa2b1e7 100644 --- a/ets2panda/test/ast/parser/ets/function_implicit_return_type7.ets +++ b/ets2panda/test/ast/parser/ets/function_implicit_return_type7.ets @@ -18,12 +18,10 @@ function fn(i: int) { if (i > 0) { return true; } - return /* @@ label */0; + return 0; } function main() { let a = fn(0); } - -/* @@@ label Error TypeError: Function cannot have different primitive return types, require 'boolean', found 'int' */ diff --git a/ets2panda/test/ast/parser/ets/generic_error.ets b/ets2panda/test/ast/parser/ets/generic_error.ets index 1f5ee0a251..195bb99fa6 100644 --- a/ets2panda/test/ast/parser/ets/generic_error.ets +++ b/ets2panda/test/ast/parser/ets/generic_error.ets @@ -23,4 +23,4 @@ function main(): void { let m = new OldMap/* @@ label */(); } -/* @@@ label Error TypeError: Type C is not assignable to constraint type Comparable */ +/* @@@ label Error TypeError: Type argument 'C' should be a subtype of 'Comparable'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets b/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets index 637801af9a..6cca2895eb 100644 --- a/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets +++ b/ets2panda/test/ast/parser/ets/generic_lambda_err2.ets @@ -29,14 +29,14 @@ function main() { } /* @@? 18:5 Error TypeError: Expected 1 arguments, got 2. */ -/* @@? 18:5 Error TypeError: No matching call signature for ("1", int) */ +/* @@? 18:5 Error TypeError: No matching call signature for ("1", Int) */ /* @@? 19:5 Error TypeError: Expected 1 type arguments, got 2 . */ -/* @@? 19:5 Error TypeError: No matching call signature for ("1", int) */ +/* @@? 19:5 Error TypeError: No matching call signature for ("1", Int) */ /* @@? 21:32 Error TypeError: Type 'T' is not compatible with the enclosing method's return type 'NonNullable' */ /* @@? 23:20 Error TypeError: Duplicate type parameter 'T'. */ /* @@? 26:5 Error TypeError: Expected 2 arguments, got 1. */ -/* @@? 26:5 Error TypeError: No matching call signature for (int) */ +/* @@? 26:5 Error TypeError: No matching call signature for (Int) */ /* @@? 27:5 Error TypeError: Expected 2 arguments, got 1. */ -/* @@? 27:5 Error TypeError: No matching call signature for (int) */ -/* @@? 28:5 Error TypeError: No matching call signature for (int, int) */ -/* @@? 28:26 Error TypeError: Type 'int' is not compatible with type 'String' at index 2 */ +/* @@? 27:5 Error TypeError: No matching call signature for (Int) */ +/* @@? 28:5 Error TypeError: No matching call signature for (Int, Int) */ +/* @@? 28:26 Error TypeError: Type 'Int' is not compatible with type 'String' at index 2 */ diff --git a/ets2panda/test/ast/parser/ets/generics_type_param_constraint_8.ets b/ets2panda/test/ast/parser/ets/generics_type_param_constraint_8.ets index 9268e2c5eb..3b5e329f91 100644 --- a/ets2panda/test/ast/parser/ets/generics_type_param_constraint_8.ets +++ b/ets2panda/test/ast/parser/ets/generics_type_param_constraint_8.ets @@ -19,4 +19,4 @@ function main(){ const myCharClass = new X/* @@ label */(); } -/* @@@ label Error TypeError: Type Char is not assignable to constraint type Comparable */ +/* @@@ label Error TypeError: Type argument 'Char' should be a subtype of 'Comparable'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/getter_setter_access_modifiers_2.ets b/ets2panda/test/ast/parser/ets/getter_setter_access_modifiers_2.ets index d1fa3f8e04..ba846261ac 100644 --- a/ets2panda/test/ast/parser/ets/getter_setter_access_modifiers_2.ets +++ b/ets2panda/test/ast/parser/ets/getter_setter_access_modifiers_2.ets @@ -39,7 +39,7 @@ class Hex extends Core { } } -/* @@? 33:22 Error TypeError: size(s: int): void in Hex cannot override size(s: int): void in Core because overridden method is final. */ -/* @@? 33:22 Error TypeError: Method size(s: int): void in Hex not overriding any method */ -/* @@? 37:22 Error TypeError: size(): int in Hex cannot override size(): int in Core because overridden method is final. */ -/* @@? 37:22 Error TypeError: Method size(): int in Hex not overriding any method */ +/* @@? 33:22 Error TypeError: size(s: Int): void in Hex cannot override size(s: Int): void in Core because overridden method is final. */ +/* @@? 33:22 Error TypeError: Method size(s: Int): void in Hex not overriding any method */ +/* @@? 37:22 Error TypeError: size(): Int in Hex cannot override size(): Int in Core because overridden method is final. */ +/* @@? 37:22 Error TypeError: Method size(): Int in Hex not overriding any method */ diff --git a/ets2panda/test/ast/parser/ets/illegal_union_member_exp.ets b/ets2panda/test/ast/parser/ets/illegal_union_member_exp.ets index fbf2024f41..d49ec5f228 100644 --- a/ets2panda/test/ast/parser/ets/illegal_union_member_exp.ets +++ b/ets2panda/test/ast/parser/ets/illegal_union_member_exp.ets @@ -21,3 +21,6 @@ function main(): void { let b = s ?? a; b.toString(); } + + +/* @@@ label Error TypeError: Type String|Int[] is illegal in union member expression. */ diff --git a/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_1.ets b/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_1.ets index a9f16400cf..ca4457f0f6 100644 --- a/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_1.ets +++ b/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_1.ets @@ -33,4 +33,3 @@ export function foo_1_1param(a : int) : int { } export default function foo_1_default() : void {} - diff --git a/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets b/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets index b5508f11e4..cfbfbd87ed 100644 --- a/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets +++ b/ets2panda/test/ast/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -export const flt: float = 2.345; +export const flt: float = 2.345f; export let c: int = 3; diff --git a/ets2panda/test/ast/parser/ets/import_tests/import_type_error_in_class.ets b/ets2panda/test/ast/parser/ets/import_tests/import_type_error_in_class.ets index 664385c11c..eec369a4bf 100644 --- a/ets2panda/test/ast/parser/ets/import_tests/import_type_error_in_class.ets +++ b/ets2panda/test/ast/parser/ets/import_tests/import_type_error_in_class.ets @@ -24,4 +24,4 @@ export class InImport { // used to give wrong output: // TypeError: Type '"InImport"' cannot be assigned to type 'int' [export_and_import_class.ets:21:1] -/* @@@ label Error TypeError: Type '"InImport"' cannot be assigned to type 'int' */ +/* @@@ label Error TypeError: Type '"InImport"' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/parser/ets/import_tests/import_type_error_top_level.ets b/ets2panda/test/ast/parser/ets/import_tests/import_type_error_top_level.ets index 1cf28091f3..c22d229514 100644 --- a/ets2panda/test/ast/parser/ets/import_tests/import_type_error_top_level.ets +++ b/ets2panda/test/ast/parser/ets/import_tests/import_type_error_top_level.ets @@ -25,4 +25,4 @@ export function fooImport() { // used to give wrong output: // TypeError: Type 'int' cannot be assigned to type 'String' [export_and_import_top_level.ets:21:1] -/* @@@ label Error TypeError: Type 'int' cannot be assigned to type 'String' */ +/* @@@ label Error TypeError: Type 'Int' cannot be assigned to type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets index 4fd228987d..b359a04496 100644 --- a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets +++ b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined-invalid.ets @@ -14,8 +14,7 @@ */ function main(){ let a = 1; - a/* @@ label */~/* @@ label1 */!/* @@ label2 */; + a/* @@ label */~!/* @@ label2 */; } /* @@@ label Error SyntaxError: Unexpected token '~'. */ -/* @@@ label1 Error TypeError: Bad operand type, the type of the operand must be numeric type. */ /* @@@ label2 Error SyntaxError: Unexpected token ';'. */ diff --git a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined.ets b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined.ets index 975a0fe946..8ff53d347d 100644 --- a/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined.ets +++ b/ets2panda/test/ast/parser/ets/increment-on-nullish-type-undefined.ets @@ -18,6 +18,4 @@ } /* @@? 17:3 Warning Warning: Bad operand type, the operand of the non-nullish expression is 'null' or 'undefined'. */ - /* @@? 17:3 Error TypeError: Cannot cast 'null' or 'undefined' to non-nullish type. */ /* @@? 17:3 Error TypeError: Type 'Double' cannot be assigned to type 'undefined' */ - diff --git a/ets2panda/test/ast/parser/ets/index_not_support_such_type.ets b/ets2panda/test/ast/parser/ets/index_not_support_such_type.ets index 9e696be3e9..5a82a6fe4a 100644 --- a/ets2panda/test/ast/parser/ets/index_not_support_such_type.ets +++ b/ets2panda/test/ast/parser/ets/index_not_support_such_type.ets @@ -18,4 +18,12 @@ function main() { console.log(/* @@ label */a[0]) } -/* @@@ label Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Boolean): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Byte): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Short): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Char): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Int): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Long): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Float): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Double): void` */ +/* @@@ label Error TypeError: Indexed signatures are not allowed. Use arrays instead! */ diff --git a/ets2panda/test/ast/parser/ets/instanceof_with_not_object_type.ets b/ets2panda/test/ast/parser/ets/instanceof_with_not_object_type.ets index 3e3263a001..3e2f65ca14 100644 --- a/ets2panda/test/ast/parser/ets/instanceof_with_not_object_type.ets +++ b/ets2panda/test/ast/parser/ets/instanceof_with_not_object_type.ets @@ -24,5 +24,4 @@ function main() b instanceof /* @@ label */a } -/* @@@ label Error TypeError: Cannot find type 'a'. */ -/* @@? 24:5 Error TypeError: Using the 'instance of' operator with non-object type 'b' */ +/* @@@ label Error TypeError: Cannot find type 'a'. */ diff --git a/ets2panda/test/ast/parser/ets/interface_private_function_1.ets b/ets2panda/test/ast/parser/ets/interface_private_function_1.ets index 3cc0073acd..237953a6ba 100644 --- a/ets2panda/test/ast/parser/ets/interface_private_function_1.ets +++ b/ets2panda/test/ast/parser/ets/interface_private_function_1.ets @@ -34,5 +34,5 @@ function main(): void { i.xyz(); } -/* @@? 34:5 Error TypeError: Signature xyz(): int is not visible here. */ -/* @@? 34:5 Error TypeError: No matching call signature */ +/* @@? 34:5 Error TypeError: Signature xyz(): Int is not visible here. */ +/* @@? 34:5 Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/parser/ets/invalidEnums.ets b/ets2panda/test/ast/parser/ets/invalidEnums.ets index 7f609a640d..82a8b21390 100644 --- a/ets2panda/test/ast/parser/ets/invalidEnums.ets +++ b/ets2panda/test/ast/parser/ets/invalidEnums.ets @@ -62,7 +62,6 @@ enum MissingLeftBrace /* @@? 22:22 Error SyntaxError: Unexpected token, expected '{'. */ /* @@? 32:1 Error SyntaxError: Unexpected token, expected ',' or '}'. */ /* @@? 32:1 Error SyntaxError: Unexpected token ']'. */ -/* @@? 37:10 Error SyntaxError: Only constant expression is expected in the field */ /* @@? 37:10 Error TypeError: Enumeration members can be initialized only by compile-time expressions and initializers must be of the same type. */ /* @@? 38:1 Error SyntaxError: Unexpected token '}'. */ /* @@? 40:1 Error SyntaxError: Unexpected token, expected ',' or '}'. */ diff --git a/ets2panda/test/ast/parser/ets/keyof_annotation.ets b/ets2panda/test/ast/parser/ets/keyof_annotation.ets index 48584e6953..4e64a018dd 100644 --- a/ets2panda/test/ast/parser/ets/keyof_annotation.ets +++ b/ets2panda/test/ast/parser/ets/keyof_annotation.ets @@ -41,10 +41,9 @@ function main():void{ let y6:keyof B = /* @@ label6 */100; } -/* @@@ label1 Error TypeError: Type '"other field"' cannot be assigned to type '"method1"|"field1"|"field2"' */ -/* @@@ label2 Error TypeError: Type '"other method"' cannot be assigned to type '"method1"|"field1"|"field2"' */ -/* @@@ label3 Error TypeError: Type 'int' cannot be assigned to type '"method1"|"field1"|"field2"' */ -/* @@@ label4 Error TypeError: Type '"other field"' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ -/* @@@ label5 Error TypeError: Type '"other method"' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ -/* @@@ label6 Error TypeError: Type 'int' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ - +/* @@@ label1 Error TypeError: Type '"other field"' cannot be assigned to type '"method1"|"field1"|"field2"' */ +/* @@@ label2 Error TypeError: Type '"other method"' cannot be assigned to type '"method1"|"field1"|"field2"' */ +/* @@@ label3 Error TypeError: Type 'Int' cannot be assigned to type '"method1"|"field1"|"field2"' */ +/* @@@ label4 Error TypeError: Type '"other field"' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ +/* @@@ label5 Error TypeError: Type '"other method"' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ +/* @@@ label6 Error TypeError: Type 'Int' cannot be assigned to type '"bmethod1"|"bfield1"|"bfield2"|"method1"|"field1"|"field2"' */ diff --git a/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets b/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets index 9284175d61..d7b9545466 100644 --- a/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets +++ b/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets @@ -33,17 +33,17 @@ function main():void{ let x6:Array<"abcd"|keyofA|number|A> = /* @@ label6 */new Array<"abcd"|keyofA|number|A>("abcd","other field","foo",123,a); } -/* @@? 26:62 Error TypeError: Array element at index 1 with type '"field2"' is not compatible with the target array element type '"abcd"|Double|A|"foo"|"field1"' */ -/* @@? 27:62 Error TypeError: Array element at index 1 with type '"other field"' is not compatible with the target array element type '"abcd"|Double|A|"foo"|"field1"' */ -/* @@? 29:60 Error TypeError: Array initializer's type is not assignable to tuple type at index: 1 */ -/* @@? 30:60 Error TypeError: Array initializer's type is not assignable to tuple type at index: 1 */ -/* @@? 32:57 Error TypeError: Expected 1 arguments, got 5. */ -/* @@? 32:57 Error TypeError: Expected 2 arguments, got 5. */ -/* @@? 32:57 Error TypeError: Expected 0 arguments, got 5. */ -/* @@? 32:57 Error TypeError: No matching construct signature for escompat.Array("abcd", "field2", "foo", int, A) */ +/* @@@ label1 Error TypeError: Array element at index 1 with type '"field2"' is not compatible with the target array element type '"abcd"|Double|A|"foo"|"field1"' */ +/* @@@ label2 Error TypeError: Array element at index 1 with type '"other field"' is not compatible with the target array element type '"abcd"|Double|A|"foo"|"field1"' */ +/* @@@ label3 Error TypeError: Array initializer's type is not assignable to tuple type at index: 1 */ +/* @@@ label4 Error TypeError: Array initializer's type is not assignable to tuple type at index: 1 */ +/* @@@ label5 Error TypeError: Expected 1 arguments, got 5. */ +/* @@@ label5 Error TypeError: Expected 2 arguments, got 5. */ +/* @@@ label5 Error TypeError: Expected 0 arguments, got 5. */ +/* @@@ label5 Error TypeError: No matching construct signature for escompat.Array("abcd", "field2", "foo", Int, A) */ /* @@? 32:98 Error TypeError: Type '"field2"' is not compatible with rest parameter type '"abcd"|Double|A|"foo"|"field1"' at index 2 */ -/* @@? 33:57 Error TypeError: Expected 1 arguments, got 5. */ -/* @@? 33:57 Error TypeError: Expected 2 arguments, got 5. */ -/* @@? 33:57 Error TypeError: Expected 0 arguments, got 5. */ -/* @@? 33:57 Error TypeError: No matching construct signature for escompat.Array("abcd", "other field", "foo", int, A) */ +/* @@@ label6 Error TypeError: Expected 1 arguments, got 5. */ +/* @@@ label6 Error TypeError: Expected 2 arguments, got 5. */ +/* @@@ label6 Error TypeError: Expected 0 arguments, got 5. */ +/* @@@ label6 Error TypeError: No matching construct signature for escompat.Array("abcd", "other field", "foo", Int, A) */ /* @@? 33:98 Error TypeError: Type '"other field"' is not compatible with rest parameter type '"abcd"|Double|A|"foo"|"field1"' at index 2 */ diff --git a/ets2panda/test/ast/parser/ets/keyof_constraint.ets b/ets2panda/test/ast/parser/ets/keyof_constraint.ets index b3265d6059..ed208c3516 100644 --- a/ets2panda/test/ast/parser/ets/keyof_constraint.ets +++ b/ets2panda/test/ast/parser/ets/keyof_constraint.ets @@ -30,6 +30,6 @@ function main():void{ /* @@ label2 */getProperty(/* @@ label3 */"field12345"); } -/* @@@ label1 Error TypeError: Type "field12345" is not assignable to constraint type "method1"|"field1"|"field2" */ +/* @@@ label1 Error TypeError: Type argument '"field12345"' should be a subtype of '"method1"|"field1"|"field2"'-constraint */ /* @@@ label2 Error TypeError: No matching call signature for getProperty("field12345") */ /* @@@ label3 Error TypeError: Type '"field12345"' is not compatible with type '"method1"|"field1"|"field2"' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/keyof_parameter.ets b/ets2panda/test/ast/parser/ets/keyof_parameter.ets index 2eeb874a71..5d3c9af641 100644 --- a/ets2panda/test/ast/parser/ets/keyof_parameter.ets +++ b/ets2panda/test/ast/parser/ets/keyof_parameter.ets @@ -28,9 +28,9 @@ function main():void{ /* @@ label5 */getProperty(a, /* @@ label6 */1); } -/* @@@ label1 Error TypeError: No matching call signature for getProperty(A, "other field") */ -/* @@@ label2 Error TypeError: Type '"other field"' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ -/* @@@ label3 Error TypeError: No matching call signature for getProperty(A, "other method") */ -/* @@@ label4 Error TypeError: Type '"other method"' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ -/* @@@ label5 Error TypeError: No matching call signature for getProperty(A, int) */ -/* @@@ label6 Error TypeError: Type 'int' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ \ No newline at end of file +/* @@@ label1 Error TypeError: No matching call signature for getProperty(A, "other field") */ +/* @@@ label2 Error TypeError: Type '"other field"' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ +/* @@@ label3 Error TypeError: No matching call signature for getProperty(A, "other method") */ +/* @@@ label4 Error TypeError: Type '"other method"' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ +/* @@@ label5 Error TypeError: No matching call signature for getProperty(A, Int) */ +/* @@@ label6 Error TypeError: Type 'Int' is not compatible with type '"method1"|"field1"|"field2"' at index 2 */ diff --git a/ets2panda/test/ast/parser/ets/lambda-type-inference-neg.ets b/ets2panda/test/ast/parser/ets/lambda-type-inference-neg.ets index c424831940..75cc29a912 100644 --- a/ets2panda/test/ast/parser/ets/lambda-type-inference-neg.ets +++ b/ets2panda/test/ast/parser/ets/lambda-type-inference-neg.ets @@ -20,10 +20,9 @@ function foo(callback: (x: boolean) => void): void { } function main(): void { - /* @@ label1 */foo((x) => { + foo((x) => { }); } /* @@@ label Error TypeError: Function foo with this assembly signature already declared. */ -/* @@@ label1 Error TypeError: Reference to foo is ambiguous */ diff --git a/ets2panda/test/ast/parser/ets/lambda-type-inference-overloaded-1.ets b/ets2panda/test/ast/parser/ets/lambda-type-inference-overloaded-1.ets index fbeb2cd8c7..be682f7d2f 100644 --- a/ets2panda/test/ast/parser/ets/lambda-type-inference-overloaded-1.ets +++ b/ets2panda/test/ast/parser/ets/lambda-type-inference-overloaded-1.ets @@ -29,10 +29,11 @@ function main(): void { return y.length == x; }); // Should report an error - /* @@ label1 */foo((x, y) => { + foo((x, y) => /* @@ label1 */{ console.println("hello"); }); } /* @@@ label Error TypeError: Function foo with this assembly signature already declared. */ -/* @@@ label1 Error TypeError: Reference to foo is ambiguous */ +/* @@@ label1 Error TypeError: Type 'void' is not compatible with the enclosing method's return type 'Boolean' */ +/* @@? 28:9 Error TypeError: Type '(x: Double, y: String) => Boolean' is not compatible with type '(x: Int, y: String) => Boolean' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/lambda_infer_type_neg_1.ets b/ets2panda/test/ast/parser/ets/lambda_infer_type_neg_1.ets index 3d935ede82..8e962a727f 100644 --- a/ets2panda/test/ast/parser/ets/lambda_infer_type_neg_1.ets +++ b/ets2panda/test/ast/parser/ets/lambda_infer_type_neg_1.ets @@ -16,5 +16,5 @@ let lam :(x:string, y:int) => void = (a,b) =>{} lam(2, 3) -/* @@? 17:1 Error TypeError: No matching call signature for (int, int) */ -/* @@? 17:5 Error TypeError: Type 'int' is not compatible with type 'String' at index 1 */ \ No newline at end of file +/* @@? 17:1 Error TypeError: No matching call signature for (Int, Int) */ +/* @@? 17:5 Error TypeError: Type 'Int' is not compatible with type 'String' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/lambda_omit_parentheses_parameter_neg_3.ets b/ets2panda/test/ast/parser/ets/lambda_omit_parentheses_parameter_neg_3.ets index 9cf0b75d2c..eac89534ee 100644 --- a/ets2panda/test/ast/parser/ets/lambda_omit_parentheses_parameter_neg_3.ets +++ b/ets2panda/test/ast/parser/ets/lambda_omit_parentheses_parameter_neg_3.ets @@ -16,4 +16,4 @@ function func(fn:(x:int)=>string){} func((x)=>1) -/* @@? 17:11 Error TypeError: Type 'int' is not compatible with the enclosing method's return type 'String' */ \ No newline at end of file +/* @@? 17:11 Error TypeError: Type 'Int' is not compatible with the enclosing method's return type 'String' */ diff --git a/ets2panda/test/ast/parser/ets/loops.ets b/ets2panda/test/ast/parser/ets/loops.ets index 027c90e682..b615b0ecd6 100644 --- a/ets2panda/test/ast/parser/ets/loops.ets +++ b/ets2panda/test/ast/parser/ets/loops.ets @@ -65,4 +65,3 @@ function labeledcontinue(): void { } /* @@? 19:15 Error TypeError: Unresolved reference i */ -/* @@? 19:15 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ diff --git a/ets2panda/test/ast/parser/ets/new_object_1.ets b/ets2panda/test/ast/parser/ets/new_object_1.ets index 0fcda02a6f..b1804b5d42 100644 --- a/ets2panda/test/ast/parser/ets/new_object_1.ets +++ b/ets2panda/test/ast/parser/ets/new_object_1.ets @@ -15,7 +15,6 @@ function main() : void { - let x : int = /* @@ label */new int(); + let x : int = new int(); } -/* @@@ label Error TypeError: This expression is not constructible. */ diff --git a/ets2panda/test/ast/parser/ets/new_object_2.ets b/ets2panda/test/ast/parser/ets/new_object_2.ets index 5c7e9c6a0e..6ae4a96bc8 100644 --- a/ets2panda/test/ast/parser/ets/new_object_2.ets +++ b/ets2panda/test/ast/parser/ets/new_object_2.ets @@ -15,7 +15,5 @@ function main() : void { - let x = /* @@ label */new boolean(); + let x = new boolean(); } - -/* @@@ label Error TypeError: This expression is not constructible. */ diff --git a/ets2panda/test/ast/parser/ets/non_constant_expression.ets b/ets2panda/test/ast/parser/ets/non_constant_expression.ets index 80ca9574cf..edb49055eb 100644 --- a/ets2panda/test/ast/parser/ets/non_constant_expression.ets +++ b/ets2panda/test/ast/parser/ets/non_constant_expression.ets @@ -22,4 +22,4 @@ let cc = 1 function foo() {} -/* @@? 21:14 Error SyntaxError: Only constant expression is expected in the field */ +/* @@? 21:14 Error TypeError: Invalid value for annotation field, expected a constant literal. */ diff --git a/ets2panda/test/ast/parser/ets/non_proper_index_method.ets b/ets2panda/test/ast/parser/ets/non_proper_index_method.ets index 7244aeec7e..33fbc6131a 100644 --- a/ets2panda/test/ast/parser/ets/non_proper_index_method.ets +++ b/ets2panda/test/ast/parser/ets/non_proper_index_method.ets @@ -22,4 +22,12 @@ function main() { console.log(/* @@ label */a["a"]) } -/* @@@ label Error TypeError: Indexed signatures are not allowed. Use arrays instead! */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Boolean): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Byte): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Short): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Char): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Int): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Long): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Float): void` */ +/* @@? 22:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Double): void` */ +/* @@@ label Error TypeError: Indexed signatures are not allowed. Use arrays instead! */ diff --git a/ets2panda/test/ast/parser/ets/overrideFuncWithGetter_n.ets b/ets2panda/test/ast/parser/ets/overrideFuncWithGetter_n.ets index e5d7a91b23..30982b269a 100644 --- a/ets2panda/test/ast/parser/ets/overrideFuncWithGetter_n.ets +++ b/ets2panda/test/ast/parser/ets/overrideFuncWithGetter_n.ets @@ -23,6 +23,6 @@ class C implements A /* @@ label1 */{ } } -/* @@@ label Error TypeError: Cannot inherit from interface A because method length is inherited with a different declaration type */ -/* @@@ label1 Error TypeError: C is not abstract and does not override abstract method length(): double in A */ -/* @@@ label2 Error TypeError: Method length(): double in C not overriding any method */ +/* @@@ label Error TypeError: Cannot inherit from interface A because method length is inherited with a different declaration type */ +/* @@@ label1 Error TypeError: C is not abstract and does not override abstract method length(): Double in A */ +/* @@@ label2 Error TypeError: Method length(): Double in C not overriding any method */ diff --git a/ets2panda/test/ast/parser/ets/override_method.ets b/ets2panda/test/ast/parser/ets/override_method.ets index da40689903..e13c36a416 100644 --- a/ets2panda/test/ast/parser/ets/override_method.ets +++ b/ets2panda/test/ast/parser/ets/override_method.ets @@ -25,6 +25,6 @@ final class T extends P { } } -/* @@? 22:23 Error TypeError: Cannot inherit with 'final' modifier. */ -/* @@? 23:24 Error TypeError: foo(): int in T cannot override foo(): int in P because overridden method is final. */ -/* @@? 23:24 Error TypeError: Method foo(): int in T not overriding any method */ +/* @@? 22:23 Error TypeError: Cannot inherit with 'final' modifier. */ +/* @@? 23:24 Error TypeError: foo(): Int in T cannot override foo(): Int in P because overridden method is final. */ +/* @@? 23:24 Error TypeError: Method foo(): Int in T not overriding any method */ diff --git a/ets2panda/test/ast/parser/ets/partialPrimitiveConversion_n.ets b/ets2panda/test/ast/parser/ets/partialPrimitiveConversion_n.ets index 4561851b2b..f795d5d709 100644 --- a/ets2panda/test/ast/parser/ets/partialPrimitiveConversion_n.ets +++ b/ets2panda/test/ast/parser/ets/partialPrimitiveConversion_n.ets @@ -13,6 +13,4 @@ * limitations under the License. */ -function foo(b: Partial/* @@ label */): void {} - -/* @@@ label Error TypeError: Only reference types can be converted to utility types. */ \ No newline at end of file +function foo(b: Partial): void {} diff --git a/ets2panda/test/ast/parser/ets/partial_not_reference_type.ets b/ets2panda/test/ast/parser/ets/partial_not_reference_type.ets index 72ec0cf62d..e6a0fc3ec7 100644 --- a/ets2panda/test/ast/parser/ets/partial_not_reference_type.ets +++ b/ets2panda/test/ast/parser/ets/partial_not_reference_type.ets @@ -14,6 +14,4 @@ */ -function foo(a:Partial/* @@ label */){} - -/* @@@ label Error TypeError: Only reference types can be converted to utility types. */ \ No newline at end of file +function foo(a:Partial){} diff --git a/ets2panda/test/ast/parser/ets/predefined_non_primitive_types.ets b/ets2panda/test/ast/parser/ets/predefined_non_primitive_types.ets index 4f1dabc0bf..5c7ce150be 100644 --- a/ets2panda/test/ast/parser/ets/predefined_non_primitive_types.ets +++ b/ets2panda/test/ast/parser/ets/predefined_non_primitive_types.ets @@ -35,6 +35,7 @@ let s: String = "abc"; // see 3.2.2 Array types let a: int[] = new int[5]; -/* @@@ label Error TypeError: Variable 'non_prim_b' has already been declared. */ +/* @@? 23:25 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ +/* @@@ label Error TypeError: Variable 'non_prim_b' has already been declared. */ /* @@? 27:31 Error TypeError: Cannot find type 'Bool'. */ -/* @@? 27:38 Error TypeError: Type 'boolean' cannot be assigned to type 'Byte' */ +/* @@? 27:38 Error TypeError: Type 'Boolean' cannot be assigned to type 'Byte' */ diff --git a/ets2panda/test/ast/parser/ets/primitive_type_method_1.ets b/ets2panda/test/ast/parser/ets/primitive_type_method_1.ets index 92e7d3f507..8f30a8fe80 100644 --- a/ets2panda/test/ast/parser/ets/primitive_type_method_1.ets +++ b/ets2panda/test/ast/parser/ets/primitive_type_method_1.ets @@ -15,7 +15,6 @@ function main(): void { let value: byte = 0; - /* @@ label */value.toString() + value.toString() } -/* @@@ label Error TypeError: Property 'toString' does not exist on type 'byte' */ diff --git a/ets2panda/test/ast/parser/ets/primitive_type_method_2.ets b/ets2panda/test/ast/parser/ets/primitive_type_method_2.ets index e71249dfec..1589f0d5ad 100644 --- a/ets2panda/test/ast/parser/ets/primitive_type_method_2.ets +++ b/ets2panda/test/ast/parser/ets/primitive_type_method_2.ets @@ -14,9 +14,8 @@ */ function toString1(value: number): string { - return /* @@ label */value.toString(value); + return value.toString(value); } function main(): void {} -/* @@@ label Error TypeError: Property 'toString' does not exist on type 'double' */ diff --git a/ets2panda/test/ast/parser/ets/privateSuperConstructorCall.ets b/ets2panda/test/ast/parser/ets/privateSuperConstructorCall.ets index 70e64c12b9..2234b186ad 100644 --- a/ets2panda/test/ast/parser/ets/privateSuperConstructorCall.ets +++ b/ets2panda/test/ast/parser/ets/privateSuperConstructorCall.ets @@ -31,5 +31,5 @@ function main(): void { assertEQ(instance.x, 5); } -/* @@? 25:5 Error TypeError: Signature constructor(alma: int): void is not visible here. */ -/* @@? 25:5 Error TypeError: No matching call signature for privateSuperConstructorCall.Alma(int) */ +/* @@? 25:5 Error TypeError: Signature constructor(alma: Int): void is not visible here. */ +/* @@? 25:5 Error TypeError: No matching call signature for privateSuperConstructorCall.Alma(Int) */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test1.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test1.ets index 1b87bffb76..a4cba4c0ae 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test1.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test1.ets @@ -19,4 +19,4 @@ function foo(x : readonly Array) let x1 : Array x1 = /* @@ label */x } -/* @@@ label Error TypeError: Type 'Readonly>' cannot be assigned to type 'Array' */ +/* @@@ label Error TypeError: Type 'readonly Array' cannot be assigned to type 'Array' */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test3.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test3.ets index f7b0cff0a5..2d5de9a3df 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test3.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-Array-test3.ets @@ -19,5 +19,5 @@ function foo (p: Array) { let x: readonly Array /* @@ label */foo(/* @@ label1 */x) -/* @@@ label Error TypeError: No matching call signature for foo(Readonly>) */ -/* @@@ label1 Error TypeError: Type 'Readonly>' is not compatible with type 'Array' at index 1 */ +/* @@@ label Error TypeError: No matching call signature for foo(readonly Array) */ +/* @@@ label1 Error TypeError: Type 'readonly Array' is not compatible with type 'Array' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test1.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test1.ets index 390023611f..5865989d84 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test1.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test1.ets @@ -19,5 +19,5 @@ function foo (p: int[]) { let x: Readonly = [] /* @@ label */foo(/* @@ label1 */x) -/* @@? 20:15 Error TypeError: No matching call signature for foo(Readonly>) */ -/* @@? 20:34 Error TypeError: Type 'Readonly>' is not compatible with type 'Array' at index 1 */ +/* @@@ label Error TypeError: No matching call signature for foo(readonly Array) */ +/* @@@ label1 Error TypeError: Type 'readonly Array' is not compatible with type 'Array' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test2.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test2.ets index 7fbea40572..7656872082 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test2.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test2.ets @@ -19,5 +19,5 @@ function foo (p: [int, string]) { let x: Readonly<[int, string]> = [] /* @@ label */foo(/* @@ label1 */x) -/* @@@ label1 Error TypeError: Type 'readonly [int, String]' is not compatible with type '[int, String]' at index 1 */ -/* @@@ label Error TypeError: No matching call signature for foo(readonly [int, String]) */ +/* @@@ label1 Error TypeError: Type 'readonly [Int, String]' is not compatible with type '[Int, String]' at index 1 */ +/* @@@ label Error TypeError: No matching call signature for foo(readonly [Int, String]) */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test3.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test3.ets index 0953054d47..1d321b90e4 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test3.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test3.ets @@ -17,4 +17,4 @@ function foo (x: Readonly<[int, string]>) { let y: [int, string] = /* @@ label */x } -/* @@@ label Error TypeError: Type 'readonly [int, String]' cannot be assigned to type '[int, String]' */ +/* @@@ label Error TypeError: Type 'readonly [Int, String]' cannot be assigned to type '[Int, String]' */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test4.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test4.ets index cf6bf40eb7..1f44493fba 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test4.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/Readonly-with-ArrayType-test4.ets @@ -18,4 +18,4 @@ function foo (x: Readonly) { let x1 : int[] x1 = /* @@ label */x } -/* @@? 19:24 Error TypeError: Type 'Readonly>' cannot be assigned to type 'Array' */ +/* @@@ label Error TypeError: Type 'readonly Array' cannot be assigned to type 'Array' */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test2.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test2.ets index fd6e6d8419..12e4c37fed 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test2.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test2.ets @@ -18,4 +18,4 @@ function foo (x: readonly [int, string]) { let y: [int, string] = /* @@ label */x } -/* @@@ label Error TypeError: Type 'readonly [int, String]' cannot be assigned to type '[int, String]' */ +/* @@@ label Error TypeError: Type 'readonly [Int, String]' cannot be assigned to type '[Int, String]' */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test3.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test3.ets index 125bd64c3b..2f156db7ce 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test3.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test3.ets @@ -18,4 +18,4 @@ function foo (x: readonly int[]) { let x1 : int[] x1 = /* @@ label */x } -/* @@? 19:24 Error TypeError: Type 'Readonly>' cannot be assigned to type 'Array' */ +/* @@@ label Error TypeError: Type 'readonly Array' cannot be assigned to type 'Array' */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test4.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test4.ets index 56c980492e..05c22e9061 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test4.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test4.ets @@ -19,5 +19,5 @@ function foo (p: int[]) { let x: readonly int[] = [] /* @@ label */foo(/* @@ label1 */x) -/* @@? 20:15 Error TypeError: No matching call signature for foo(Readonly>) */ -/* @@? 20:34 Error TypeError: Type 'Readonly>' is not compatible with type 'Array' at index 1 */ +/* @@@ label Error TypeError: No matching call signature for foo(readonly Array) */ +/* @@@ label1 Error TypeError: Type 'readonly Array' is not compatible with type 'Array' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test5.ets b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test5.ets index 448f5ebcdb..c070f2aba9 100644 --- a/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test5.ets +++ b/ets2panda/test/ast/parser/ets/readonly-parameter-test/readonly-parameter-test5.ets @@ -19,5 +19,5 @@ function foo (p: [int, string]) { let x: readonly [int, string] = [] /* @@ label */foo(/* @@ label1 */x) -/* @@@ label1 Error TypeError: Type 'readonly [int, String]' is not compatible with type '[int, String]' at index 1 */ -/* @@@ label Error TypeError: No matching call signature for foo(readonly [int, String]) */ +/* @@@ label Error TypeError: No matching call signature for foo(readonly [Int, String]) */ +/* @@@ label1 Error TypeError: Type 'readonly [Int, String]' is not compatible with type '[Int, String]' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/recordIndexing.ets b/ets2panda/test/ast/parser/ets/recordIndexing.ets index ff6f19beaf..082f69e7b7 100644 --- a/ets2panda/test/ast/parser/ets/recordIndexing.ets +++ b/ets2panda/test/ast/parser/ets/recordIndexing.ets @@ -22,6 +22,14 @@ console.log(x[/* @@ label */0]) } -/* @@? 23:17 Error TypeError: No matching indexing signature for $_get(int) */ -/* @@? 23:33 Error TypeError: Type 'int' is not compatible with type 'String' at index 1 */ -/* @@? 23:33 Error TypeError: Cannot find index access method with the required signature. */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Boolean): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Byte): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Short): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Char): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Int): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Long): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Float): void` */ +/* @@? 23:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Double): void` */ +/* @@? 23:17 Error TypeError: No matching indexing signature for $_get(Int) */ +/* @@@ label Error TypeError: Type 'Int' is not compatible with type 'String' at index 1 */ +/* @@@ label Error TypeError: Cannot find index access method with the required signature. */ diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets index 2566f9cbb7..aa08c98e22 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck01.ets @@ -19,4 +19,4 @@ function main(){ "key2": 2 } } -/* @@@ label Error TypeError: Type Char|String is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ \ No newline at end of file +/* @@@ label Error TypeError: Type argument 'Char|String' should be a subtype of 'Numeric|String|BaseEnum|BaseEnum|BaseEnum'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets index 7d56f11a52..d65646705f 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck02.ets @@ -21,4 +21,4 @@ function main(){ 2: 2 } } -/* @@@ label Error TypeError: Type A|Double is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ +/* @@@ label Error TypeError: Type argument 'A|Double' should be a subtype of 'Numeric|String|BaseEnum|BaseEnum|BaseEnum'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets index e8ea8a181e..5d863c0d03 100644 --- a/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets +++ b/ets2panda/test/ast/parser/ets/recordKeyTypeCheck03.ets @@ -18,4 +18,4 @@ class A{} function main(){ let a: Record/* @@ label */ } -/* @@@ label Error TypeError: Type BigInt is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ +/* @@@ label Error TypeError: Type argument 'BigInt' should be a subtype of 'Numeric|String|BaseEnum|BaseEnum|BaseEnum'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/record_object_value.ets b/ets2panda/test/ast/parser/ets/record_object_value.ets index c691052402..f46be86af2 100644 --- a/ets2panda/test/ast/parser/ets/record_object_value.ets +++ b/ets2panda/test/ast/parser/ets/record_object_value.ets @@ -57,7 +57,7 @@ function main(){ "Mary":["20", "30"] }; } -/* @@@ label Error TypeError: Type '"10"' is not compatible with type 'double' at property 'age' */ -/* @@@ label1 Error TypeError: Type '"100"' is not compatible with type 'double' at property 'salary' */ -/* @@@ label2 Error TypeError: type PersonInfoInterface has no property named agee */ -/* @@@ label3 Error TypeError: type PersonInfoInterface has no property named other */ +/* @@@ label Error TypeError: Type '"10"' is not compatible with type 'Double' at property 'age' */ +/* @@@ label1 Error TypeError: Type '"100"' is not compatible with type 'Double' at property 'salary' */ +/* @@@ label2 Error TypeError: type PersonInfoInterface has no property named agee */ +/* @@@ label3 Error TypeError: type PersonInfoInterface has no property named other */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_06.ets b/ets2panda/test/ast/parser/ets/rest_parameter_06.ets index 7759de0401..2d75bc7518 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_06.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_06.ets @@ -20,4 +20,4 @@ function sum(...numbers: [number, number, number]): number { /* @@ label */sum(10, 20, 30, 40) /* @@@ label Error TypeError: Expected 3 arguments, got 4. */ -/* @@@ label Error TypeError: No matching call signature for sum(int, int, int, int) */ +/* @@@ label Error TypeError: No matching call signature for sum(Int, Int, Int, Int) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_07.ets b/ets2panda/test/ast/parser/ets/rest_parameter_07.ets index f1373852fb..ac4c0fed73 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_07.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_07.ets @@ -17,7 +17,7 @@ function sum(...numbers: [number, number, number]): number { return numbers[0] + numbers[1] + numbers[2] } -/* @@ label1 */sum(/* @@ label2 */10, 20, "one") +/* @@ label1 */sum(10, 20, /* @@ label2 */"one") -/* @@@ label1 Error TypeError: No matching call signature for sum(int, int, "one") */ -/* @@@ label2 Error TypeError: Type 'int' is not compatible with type 'double' at index 1 */ +/* @@@ label1 Error TypeError: No matching call signature for sum(Double, Double, "one") */ +/* @@@ label2 Error TypeError: Type '"one"' is not compatible with type 'Double' at index 3 */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_08.ets b/ets2panda/test/ast/parser/ets/rest_parameter_08.ets index 9abafc61d9..b81323e196 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_08.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_08.ets @@ -26,8 +26,8 @@ function sum(a: int, ...numbers: [number, number, number]): number { /* @@@ label1 Error TypeError: Expected 4 arguments, got 0. */ /* @@@ label1 Error TypeError: No matching call signature */ /* @@@ label2 Error TypeError: Expected 4 arguments, got 1. */ -/* @@@ label2 Error TypeError: No matching call signature for sum(int) */ +/* @@@ label2 Error TypeError: No matching call signature for sum(Int) */ /* @@@ label3 Error TypeError: Expected 4 arguments, got 3. */ -/* @@@ label3 Error TypeError: No matching call signature for sum(int, int, int) */ +/* @@@ label3 Error TypeError: No matching call signature for sum(Int, Int, Int) */ /* @@@ label4 Error TypeError: Expected 4 arguments, got 5. */ -/* @@@ label4 Error TypeError: No matching call signature for sum(int, int, int, int, int) */ +/* @@@ label4 Error TypeError: No matching call signature for sum(Int, Int, Int, Int, Int) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets index 8b8c8cdbc2..46f794926f 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets @@ -41,7 +41,7 @@ function main() { /* @@@ label2 Error TypeError: Expected 2 arguments, got 1. */ /* @@@ label2 Error TypeError: Expected 3 arguments, got 1. */ /* @@@ label2 Error TypeError: No matching construct signature for rest_parameter_13.C(A) */ -/* @@? 33:37 Error TypeError: Type 'A' is not compatible with type 'int' at index 1 */ +/* @@? 33:37 Error TypeError: Type 'A' is not compatible with type 'Int' at index 1 */ /* @@@ label3 Error TypeError: Expected 2 arguments, got 3. */ /* @@@ label3 Error TypeError: No matching construct signature for rest_parameter_13.C(A, B, B) */ -/* @@? 34:37 Error TypeError: Type 'A' is not compatible with type 'int' at index 1 */ +/* @@? 34:37 Error TypeError: Type 'A' is not compatible with type 'Int' at index 1 */ diff --git a/ets2panda/test/ast/parser/ets/return_null_and_type_not_match.ets b/ets2panda/test/ast/parser/ets/return_null_and_type_not_match.ets index 33e287dff3..f67d3dbe0d 100644 --- a/ets2panda/test/ast/parser/ets/return_null_and_type_not_match.ets +++ b/ets2panda/test/ast/parser/ets/return_null_and_type_not_match.ets @@ -22,5 +22,5 @@ function main(): int { function test():string { /* @@ label1 */return; } -/* @@@ label Error TypeError: Type 'String' is not compatible with the enclosing method's return type 'int' */ -/* @@@ label1 Error TypeError: Missing return value. */ +/* @@@ label Error TypeError: Type 'String' is not compatible with the enclosing method's return type 'Int' */ +/* @@@ label1 Error TypeError: Missing return value. */ diff --git a/ets2panda/test/ast/parser/ets/return_type_non_match.ets b/ets2panda/test/ast/parser/ets/return_type_non_match.ets index 87a0ed05cc..5a8539550b 100644 --- a/ets2panda/test/ast/parser/ets/return_type_non_match.ets +++ b/ets2panda/test/ast/parser/ets/return_type_non_match.ets @@ -15,6 +15,5 @@ function main():undefined { return false; } - /* @@? 16:4 Error TypeError: Bad return type, main enable only void or int type. */ - /* @@? 16:11 Error TypeError: Type 'boolean' is not compatible with the enclosing method's return type 'undefined' *//* @@? 16:4 Error TypeError: Bad return type, main enable only void or int type. */ -/* @@? 16:11 Error TypeError: Type 'boolean' is not compatible with the enclosing method's return type 'undefined' */ + /* @@? 16:4 Error TypeError: Bad return type, main enable only void or int type. */ +/* @@? 16:11 Error TypeError: Type 'Boolean' is not compatible with the enclosing method's return type 'undefined' */ diff --git a/ets2panda/test/ast/parser/ets/single_statement_1.ets b/ets2panda/test/ast/parser/ets/single_statement_1.ets index 7d039b4a85..64d355e22c 100644 --- a/ets2panda/test/ast/parser/ets/single_statement_1.ets +++ b/ets2panda/test/ast/parser/ets/single_statement_1.ets @@ -21,5 +21,13 @@ function main(): int { } /* @@@ label1 Error SyntaxError: Lexical declaration is not allowed in single statement context. */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Boolean): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Byte): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Short): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Char): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Int): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Long): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Float): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Double): void` */ /* @@? 18:17 Error TypeError: Unresolved reference aaaa */ /* @@@ label2 Error SyntaxError: Unexpected token ')'. */ diff --git a/ets2panda/test/ast/parser/ets/single_statement_2.ets b/ets2panda/test/ast/parser/ets/single_statement_2.ets index fff3b16dd2..996fdd7fd4 100644 --- a/ets2panda/test/ast/parser/ets/single_statement_2.ets +++ b/ets2panda/test/ast/parser/ets/single_statement_2.ets @@ -21,5 +21,13 @@ function main(): int { } /* @@@ label1 Error SyntaxError: Lexical declaration is not allowed in single statement context. */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Boolean): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Byte): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Short): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Char): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Int): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Long): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Float): void` */ +/* @@? 18:5 Error TypeError: Call to `log` is ambiguous as `2` versions of `log` are available: `log(i: String): void` and `log(i: Double): void` */ /* @@? 18:17 Error TypeError: Unresolved reference aaaa */ /* @@@ label2 Error SyntaxError: Unexpected token ')'. */ diff --git a/ets2panda/test/ast/parser/ets/switch_const_int_compare_char_duplicate.ets b/ets2panda/test/ast/parser/ets/switch_const_int_compare_char_duplicate.ets index c66c1a686a..9cee2e2015 100644 --- a/ets2panda/test/ast/parser/ets/switch_const_int_compare_char_duplicate.ets +++ b/ets2panda/test/ast/parser/ets/switch_const_int_compare_char_duplicate.ets @@ -26,4 +26,4 @@ function main() { } } -/* @@@ label Error TypeError: Variable has same value with another switch case */ +/* @@? 20:28 Error TypeError: Switch case type 'int' is not comparable to discriminant type 'char' */ diff --git a/ets2panda/test/ast/parser/ets/switch_readonly_member_number_duplicate.ets b/ets2panda/test/ast/parser/ets/switch_readonly_member_number_duplicate.ets index f31619e73f..74b1b4f4a6 100644 --- a/ets2panda/test/ast/parser/ets/switch_readonly_member_number_duplicate.ets +++ b/ets2panda/test/ast/parser/ets/switch_readonly_member_number_duplicate.ets @@ -32,4 +32,4 @@ function main() { } } -/* @@@ label Error TypeError: Variable has same value with another switch case */ +/* @@? 27:28 Error TypeError: Switch case type 'int' is not comparable to discriminant type 'char' */ diff --git a/ets2panda/test/ast/parser/ets/trailing_comma_2.ets b/ets2panda/test/ast/parser/ets/trailing_comma_2.ets index bf684f79ab..d2ec51613e 100644 --- a/ets2panda/test/ast/parser/ets/trailing_comma_2.ets +++ b/ets2panda/test/ast/parser/ets/trailing_comma_2.ets @@ -19,6 +19,8 @@ class C { let a = new C(12,) -/* @@@ label1 Error SyntaxError: Unexpected token ','. */ +/* @@@ label1 Error SyntaxError: Unexpected token ','. */ /* @@? 20:9 Error TypeError: Expected 0 arguments, got 1. */ -/* @@? 20:9 Error TypeError: No matching construct signature for trailing_comma_2.C(int) */ +/* @@? 20:9 Error TypeError: No matching construct signature for trailing_comma_2.C(Int) */ +/* @@? 20:9 Error TypeError: Expected 0 arguments, got 1. */ +/* @@? 20:9 Error TypeError: No matching construct signature for trailing_comma_2.C(Int) */ diff --git a/ets2panda/test/ast/parser/ets/trailing_lambda_tests/extra_trailing_lambda_1.ets b/ets2panda/test/ast/parser/ets/trailing_lambda_tests/extra_trailing_lambda_1.ets index 12bd43f68c..f4837d017a 100644 --- a/ets2panda/test/ast/parser/ets/trailing_lambda_tests/extra_trailing_lambda_1.ets +++ b/ets2panda/test/ast/parser/ets/trailing_lambda_tests/extra_trailing_lambda_1.ets @@ -40,5 +40,5 @@ function testExtraTrailing() { } /* @@? 32:5 Error TypeError: No matching call signature with trailing lambda */ -/* @@? 37:5 Error TypeError: No matching call signature for process(int, "ok") */ +/* @@? 37:5 Error TypeError: No matching call signature for process(Double, "ok") */ /* @@? 37:18 Error TypeError: Type '"ok"' is not compatible with type '() => void|undefined' at index 2 */ diff --git a/ets2panda/test/ast/parser/ets/type_decution_unnecessary_boxing.ets b/ets2panda/test/ast/parser/ets/type_decution_unnecessary_boxing.ets index 6504bba423..f527a78056 100644 --- a/ets2panda/test/ast/parser/ets/type_decution_unnecessary_boxing.ets +++ b/ets2panda/test/ast/parser/ets/type_decution_unnecessary_boxing.ets @@ -19,5 +19,4 @@ x = true ? x:():long=>32 let y:()=>int = ()=>16 as int y = true ? y:():int=>32 y = true ? ():int=>32:y -x = /* @@ label */true ? x:"apple" -/* @@@ label Error TypeError: Type '() => Long|"apple"' cannot be assigned to type '() => Long' */ \ No newline at end of file +x = true ? x:"apple" \ No newline at end of file diff --git a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets index a41765f81a..fd5724ec64 100644 --- a/ets2panda/test/ast/parser/ets/type_from_utility_type.ets +++ b/ets2panda/test/ast/parser/ets/type_from_utility_type.ets @@ -31,8 +31,9 @@ let recordarrA = Type.from,Array>>(); let recordarrT = Type.from,Array>>(); } + /* @@? 30:19 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ - /* @@? 30:29 Error TypeError: No static $_invoke method and static $_instantiate method in Record. Record() is not allowed. */ - /* @@? 30:29 Error TypeError: Type 'Record' has no call signatures. */ - /* @@? 31:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ - /* @@? 32:38 Error TypeError: Type Array is not assignable to constraint type Numeric|String|BaseEnum|BaseEnum|BaseEnum */ \ No newline at end of file +/* @@? 30:29 Error TypeError: No static $_invoke method and static $_instantiate method in Record. Record() is not allowed. */ +/* @@? 30:29 Error TypeError: Type 'Record' has no call signatures. */ +/* @@? 31:38 Error TypeError: Type argument 'Array' should be a subtype of 'Numeric|String|BaseEnum|BaseEnum|BaseEnum'-constraint */ +/* @@? 32:38 Error TypeError: Type argument 'Array' should be a subtype of 'Numeric|String|BaseEnum|BaseEnum|BaseEnum'-constraint */ diff --git a/ets2panda/test/ast/parser/ets/type_references.ets b/ets2panda/test/ast/parser/ets/type_references.ets index ccd5dcbbdb..b689bb2c97 100644 --- a/ets2panda/test/ast/parser/ets/type_references.ets +++ b/ets2panda/test/ast/parser/ets/type_references.ets @@ -30,5 +30,4 @@ let y: G<{a:String}, B> // Error /* @@? 19:20 Error SyntaxError: Unexpected token ','. */ /* @@? 19:22 Error SyntaxError: Unexpected token 'B'. */ /* @@? 19:22 Error TypeError: Type name 'B' used in the wrong context */ -/* @@? 19:22 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ -/* @@? 35:1 Error SyntaxError: Unexpected token 'end of stream'. */ +/* @@? 34:1 Error SyntaxError: Unexpected token 'end of stream'. */ diff --git a/ets2panda/test/ast/parser/ets/types_decls.ets b/ets2panda/test/ast/parser/ets/types_decls.ets index f9455917b7..07eedb43d2 100644 --- a/ets2panda/test/ast/parser/ets/types_decls.ets +++ b/ets2panda/test/ast/parser/ets/types_decls.ets @@ -56,9 +56,11 @@ let non_prim_c: Char = c'b'; // see 3.1.5 Void type function v(): void {} -/* @@@ label Error TypeError: Variable 'prim_b' has already been declared. */ +/* @@? 35:21 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ +/* @@? 36:25 Error TypeError: Type 'Double' cannot be assigned to type 'Float' */ +/* @@@ label Error TypeError: Variable 'prim_b' has already been declared. */ /* @@? 45:27 Error TypeError: Cannot find type 'bool'. */ -/* @@? 45:34 Error TypeError: Type 'boolean' cannot be assigned to type 'byte' */ +/* @@? 45:34 Error TypeError: Type 'Boolean' cannot be assigned to type 'Byte' */ /* @@? 46:5 Error TypeError: Variable 'non_prim_b' has already been declared. */ /* @@? 46:17 Error TypeError: Cannot find type 'Bool'. */ -/* @@? 46:24 Error TypeError: Type 'boolean' cannot be assigned to type 'Byte' */ +/* @@? 46:24 Error TypeError: Type 'Boolean' cannot be assigned to type 'Byte' */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_22.ets b/ets2panda/test/ast/parser/ets/unexpected_token_22.ets index 156fad0c17..d668563135 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_22.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_22.ets @@ -40,6 +40,3 @@ function main(): void { /* @@? 25:43 Error TypeError: Type '(_: Promise) => Promise' cannot be assigned to type '() => Promise' */ /* @@? 25:44 Error SyntaxError: Unexpected token, expected an identifier. */ /* @@? 25:60 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 31:11 Error TypeError: Expected 1 arguments, got 0. */ -/* @@? 31:11 Error TypeError: No matching call signature */ -/* @@? 31:11 Error TypeError: 'await' expressions require Promise object as argument. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_29.ets b/ets2panda/test/ast/parser/ets/unexpected_token_29.ets index 2595e6fdd6..b2c42936fa 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_29.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_29.ets @@ -20,7 +20,7 @@ function main(): void { /*@@ label4 */} /* @@@ label1 Error SyntaxError: Expected ';', got 'identification literal'. */ -/* @@@ label1 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 17:44 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ /* @@@ label2 Error SyntaxError: Unexpected token, expected ';'. */ /* @@? 17:69 Error TypeError: need to specify target type for class composite */ /* @@? 18:30 Error SyntaxError: Unexpected token, expected ':'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_31.ets b/ets2panda/test/ast/parser/ets/unexpected_token_31.ets index 13151518a2..111827541b 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_31.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_31.ets @@ -27,5 +27,5 @@ function foo(...^number: int[]): int { /* @@? 16:38 Error SyntaxError: Unexpected token '{'. */ /* @@? 17:5 Error SyntaxError: return keyword should be used in function body. */ /* @@? 17:12 Error TypeError: Type name 'number' used in the wrong context */ -/* @@? 17:12 Error TypeError: Indexed access is not supported for such expression type. */ +/* @@? 17:12 Error TypeError: Indexed signatures are not allowed. Use arrays instead! */ /* @@? 17:12 Error TypeError: All return statements in the function should be empty or have a value. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_35.ets b/ets2panda/test/ast/parser/ets/unexpected_token_35.ets index 73ba04ece8..eb4252a50f 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_35.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_35.ets @@ -25,7 +25,7 @@ let sector: float }; } -/* @@? 20:12 Error TypeError: Target type for class composite needs to be an object type, found 'float' */ +/* @@? 20:12 Error TypeError: key in class composite should be either identifier or string literal */ /* @@? 23:19 Error SyntaxError: Unexpected token, expected ')'. */ /* @@? 23:20 Error SyntaxError: Unexpected token. */ /* @@? 23:21 Error SyntaxError: Unexpected token ','. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_36.ets b/ets2panda/test/ast/parser/ets/unexpected_token_36.ets index e8dc156b5b..742ce91981 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_36.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_36.ets @@ -38,6 +38,5 @@ export class AccessNSieve { /* @@? 29:14 Error SyntaxError: Unexpected token ':'. */ /* @@? 29:16 Error SyntaxError: Expected ')', got 'int'. */ /* @@? 29:16 Error SyntaxError: Unexpected token 'int'. */ -/* @@? 29:25 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 29:36 Error SyntaxError: Unexpected token ')'. */ /* @@? 29:38 Error SyntaxError: Unexpected token '{'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_41.ets b/ets2panda/test/ast/parser/ets/unexpected_token_41.ets index a0c32d6a6f..40e2093999 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_41.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_41.ets @@ -17,9 +17,8 @@ for (let i: int = 0; i < d?length/* @@ label */; ++i/* @@ label1 */) { arr.push(d[i]); } -/* @@? 16:22 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 16:26 Error TypeError: Unresolved reference d */ /* @@? 16:28 Error TypeError: Unresolved reference length */ -/* @@? 16:48 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:68 Error SyntaxError: Expected ';', got ')'. */ +/* @@@ label Error SyntaxError: Unexpected token, expected ':'. */ +/* @@@ label1 Error SyntaxError: Expected ';', got ')'. */ /* @@? 17:5 Error TypeError: Unresolved reference arr */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_42.ets b/ets2panda/test/ast/parser/ets/unexpected_token_42.ets index ece56f4d7e..7d02e8a0d8 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_42.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_42.ets @@ -15,5 +15,5 @@ // Int[1,2,3,4,5] let a: number = new Int[1 -/* @@? 16:17 Error TypeError: Type 'FixedArray' cannot be assigned to type 'double' */ +/* @@? 16:17 Error TypeError: Type 'Array' cannot be assigned to type 'Double' */ /* @@? 20:1 Error SyntaxError: Expected ']', got 'end of stream'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_43.ets b/ets2panda/test/ast/parser/ets/unexpected_token_43.ets index 750c78b777..28f196a0b8 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_43.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_43.ets @@ -20,4 +20,4 @@ let v2 = `--- ${y + abc /* @@ label */${y} = ${ n*2 }!`/* @@ label1 */} ---`;` /* @@@ label Error SyntaxError: Expected '}', got 'identification literal'. */ /* @@? 16:49 Error TypeError: Unresolved reference n */ /* @@@ label1 Error SyntaxError: Unexpected token '}'. */ -/* @@@ label1 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ +/* @@? 16:71 Error TypeError: Bad operand type, the types of the operands must be numeric type. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_53.ets b/ets2panda/test/ast/parser/ets/unexpected_token_53.ets index 8f07621597..da3f06e4cb 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_53.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_53.ets @@ -26,7 +26,6 @@ export class MathSpectralNorm { } /* @@? 19:10 Error TypeError: Unresolved reference i */ -/* @@? 19:17 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 19:22 Error SyntaxError: Expected ';', got ':'. */ /* @@? 19:22 Error SyntaxError: Unexpected token ':'. */ /* @@? 19:24 Error SyntaxError: Expected ')', got 'identification literal'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_55.ets b/ets2panda/test/ast/parser/ets/unexpected_token_55.ets index eb0b3d59e6..17ccd74642 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_55.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_55.ets @@ -27,7 +27,6 @@ export class MathSpectralNorm { /* @@? 19:16 Error TypeError: Unresolved reference i */ /* @@? 19:18 Error SyntaxError: Unexpected token '='. */ -/* @@? 19:23 Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ /* @@? 19:29 Error SyntaxError: Expected ';', got ':'. */ /* @@? 19:29 Error SyntaxError: Unexpected token ':'. */ /* @@? 19:31 Error SyntaxError: Expected ')', got 'identification literal'. */ diff --git a/ets2panda/test/ast/parser/ets/unexpected_token_61.ets b/ets2panda/test/ast/parser/ets/unexpected_token_61.ets index b367484b9c..bf42eb21ad 100644 --- a/ets2panda/test/ast/parser/ets/unexpected_token_61.ets +++ b/ets2panda/test/ast/parser/ets/unexpected_token_61.ets @@ -19,5 +19,4 @@ function main(): void { } } -/* @@? 17:16 Error TypeError: Cannot assign to a constant variable i */ /* @@@ label1 Error SyntaxError: Expected ';', got 'identification literal'. */ diff --git a/ets2panda/test/ast/parser/ets/visible_signatures_1.ets b/ets2panda/test/ast/parser/ets/visible_signatures_1.ets index af181eab15..829fc98702 100644 --- a/ets2panda/test/ast/parser/ets/visible_signatures_1.ets +++ b/ets2panda/test/ast/parser/ets/visible_signatures_1.ets @@ -27,5 +27,6 @@ function main(): void { } -/* @@? 26:5 Error TypeError: Signature foo(a: double): int is not visible here. */ -/* @@? 26:5 Error TypeError: No matching call signature for foo(double) */ +/* @@? 20:5 Error TypeError: Function foo with this assembly signature already declared. */ +/* @@? 26:5 Error TypeError: Signature foo(a: Double|undefined): Int is not visible here. */ +/* @@? 26:5 Error TypeError: No matching call signature for foo(Double) */ diff --git a/ets2panda/test/ast/parser/ets/wrong_context_class_1.ets b/ets2panda/test/ast/parser/ets/wrong_context_class_1.ets index 6b60605663..ecd46879d0 100644 --- a/ets2panda/test/ast/parser/ets/wrong_context_class_1.ets +++ b/ets2panda/test/ast/parser/ets/wrong_context_class_1.ets @@ -22,5 +22,5 @@ function main() /* @@ label */a = /* @@ label1 */5 } -/* @@@ label Error TypeError: Class name 'a' used in the wrong context */ -/* @@@ label1 Error TypeError: Type 'int' cannot be assigned to type 'a' */ +/* @@@ label Error TypeError: Class name 'a' used in the wrong context */ +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type 'a' */ diff --git a/ets2panda/test/ast/parser/ets/wrong_context_class_2.ets b/ets2panda/test/ast/parser/ets/wrong_context_class_2.ets index 7884b50d80..c0f2c427e8 100644 --- a/ets2panda/test/ast/parser/ets/wrong_context_class_2.ets +++ b/ets2panda/test/ast/parser/ets/wrong_context_class_2.ets @@ -23,5 +23,5 @@ function main() b = a } -/* @@? 23:9 Error TypeError: Class name 'a' used in the wrong context */ -/* @@? 23:9 Error TypeError: Type 'a' cannot be assigned to type 'int' */ +/* @@? 23:9 Error TypeError: Class name 'a' used in the wrong context */ +/* @@? 23:9 Error TypeError: Type 'a' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/ast/parser/ets/wrong_context_function_1.ets b/ets2panda/test/ast/parser/ets/wrong_context_function_1.ets index be1e154d0c..4e2bf2e259 100644 --- a/ets2panda/test/ast/parser/ets/wrong_context_function_1.ets +++ b/ets2panda/test/ast/parser/ets/wrong_context_function_1.ets @@ -22,5 +22,5 @@ function main() /* @@ label */a = /* @@ label1 */5 } -/* @@@ label Error TypeError: Function name 'a' used in the wrong context */ -/* @@@ label1 Error TypeError: Type 'int' cannot be assigned to type '() => void' */ +/* @@@ label Error TypeError: Function name 'a' used in the wrong context */ +/* @@@ label1 Error TypeError: Type 'Int' cannot be assigned to type '() => void' */ diff --git a/ets2panda/test/ast/parser/ets/wrong_context_function_2.ets b/ets2panda/test/ast/parser/ets/wrong_context_function_2.ets index e4101c325c..69076b3d7b 100644 --- a/ets2panda/test/ast/parser/ets/wrong_context_function_2.ets +++ b/ets2panda/test/ast/parser/ets/wrong_context_function_2.ets @@ -23,4 +23,4 @@ function main() b = /* @@ label */a } -/* @@@ label Error TypeError: Type '() => void' cannot be assigned to type 'int' */ +/* @@@ label Error TypeError: Type '() => void' cannot be assigned to type 'Int' */ diff --git a/ets2panda/test/compiler/ets/boxingConversion2-expected.txt b/ets2panda/test/compiler/ets/boxingConversion2-expected.txt index fd853951c7..24f3c862e0 100644 --- a/ets2panda/test/compiler/ets/boxingConversion2-expected.txt +++ b/ets2panda/test/compiler/ets/boxingConversion2-expected.txt @@ -731,7 +731,7 @@ }, "end": { "line": 23, - "column": 23, + "column": 24, "program": "boxingConversion2.ets" } } @@ -744,7 +744,7 @@ }, "end": { "line": 23, - "column": 23, + "column": 24, "program": "boxingConversion2.ets" } } @@ -759,7 +759,7 @@ }, "end": { "line": 23, - "column": 24, + "column": 25, "program": "boxingConversion2.ets" } } @@ -2053,8 +2053,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 1, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 20, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 35, + "column": 26, + "program": "boxingConversion2.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 27, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 35, + "column": 34, + "program": "boxingConversion2.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 35, + "column": 20, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 35, + "column": 34, + "program": "boxingConversion2.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 35, + "column": 35, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 35, + "column": 38, + "program": "boxingConversion2.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 35, @@ -2063,7 +2132,7 @@ }, "end": { "line": 35, - "column": 23, + "column": 39, "program": "boxingConversion2.ets" } } @@ -2076,7 +2145,7 @@ }, "end": { "line": 35, - "column": 23, + "column": 39, "program": "boxingConversion2.ets" } } @@ -2091,7 +2160,7 @@ }, "end": { "line": 35, - "column": 24, + "column": 40, "program": "boxingConversion2.ets" } } @@ -2166,8 +2235,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 1, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 18, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 36, + "column": 24, + "program": "boxingConversion2.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 36, + "column": 25, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 36, + "column": 30, + "program": "boxingConversion2.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 36, + "column": 18, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 36, + "column": 30, + "program": "boxingConversion2.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 36, + "column": 31, + "program": "boxingConversion2.ets" + }, + "end": { + "line": 36, + "column": 34, + "program": "boxingConversion2.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 36, @@ -2176,7 +2314,7 @@ }, "end": { "line": 36, - "column": 21, + "column": 35, "program": "boxingConversion2.ets" } } @@ -2189,7 +2327,7 @@ }, "end": { "line": 36, - "column": 21, + "column": 35, "program": "boxingConversion2.ets" } } @@ -2204,7 +2342,7 @@ }, "end": { "line": 36, - "column": 22, + "column": 36, "program": "boxingConversion2.ets" } } diff --git a/ets2panda/test/compiler/ets/boxingConversion2.ets b/ets2panda/test/compiler/ets/boxingConversion2.ets index 094438ca81..d7120fe162 100644 --- a/ets2panda/test/compiler/ets/boxingConversion2.ets +++ b/ets2panda/test/compiler/ets/boxingConversion2.ets @@ -20,7 +20,7 @@ function main() : void { let d: char = c'3'; let e: int = 4; let f: long = 5; - let g: float = 6.0; + let g: float = 6.0f; let h: double = 7.0; let i: Object = a; let j: Object = b; @@ -32,6 +32,6 @@ function main() : void { let p: Object = h; let q: Object = 8; let r: Object = 9.0; - let s: Float = 1.0; - let t: Int = 1.0; + let s: Float = Double.toFloat(1.0); + let t: Int = Double.toInt(1.0); } diff --git a/ets2panda/test/compiler/ets/boxingUnboxingExpressions-expected.txt b/ets2panda/test/compiler/ets/boxingUnboxingExpressions-expected.txt index 253a7e61b9..ee1717f7c1 100644 --- a/ets2panda/test/compiler/ets/boxingUnboxingExpressions-expected.txt +++ b/ets2panda/test/compiler/ets/boxingUnboxingExpressions-expected.txt @@ -2190,7 +2190,7 @@ }, "end": { "line": 35, - "column": 28, + "column": 29, "program": "boxingUnboxingExpressions.ets" } } @@ -2203,7 +2203,7 @@ }, "end": { "line": 35, - "column": 28, + "column": 29, "program": "boxingUnboxingExpressions.ets" } } @@ -2218,7 +2218,7 @@ }, "end": { "line": 35, - "column": 29, + "column": 30, "program": "boxingUnboxingExpressions.ets" } } @@ -7597,7 +7597,7 @@ }, "end": { "line": 74, - "column": 28, + "column": 29, "program": "boxingUnboxingExpressions.ets" } } @@ -7610,7 +7610,7 @@ }, "end": { "line": 74, - "column": 28, + "column": 29, "program": "boxingUnboxingExpressions.ets" } } @@ -7625,7 +7625,7 @@ }, "end": { "line": 74, - "column": 29, + "column": 30, "program": "boxingUnboxingExpressions.ets" } } diff --git a/ets2panda/test/compiler/ets/boxingUnboxingExpressions.ets b/ets2panda/test/compiler/ets/boxingUnboxingExpressions.ets index d6aba0e0e0..5868f5f280 100644 --- a/ets2panda/test/compiler/ets/boxingUnboxingExpressions.ets +++ b/ets2panda/test/compiler/ets/boxingUnboxingExpressions.ets @@ -32,7 +32,7 @@ class A { let j: Int = 200000; let k: long = new Long(200000000000); let l: Long = 200000000000; - let m: float = 2.22; + let m: float = 2.22f; let n: float = new Float(m); let o: Float = m; let p: double = new Double(2.2222222222); @@ -71,7 +71,7 @@ class A { this.integerReference(200000); this.longPrimitive(new Long(200000000000000)); this.longReference(200000000000000); - let f: float = 2.22; + let f: float = 2.22f; this.floatPrimitive(new Float(f)); this.floatReference(f); this.doublePrimitive(new Double(2.2222222222)); diff --git a/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt b/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt index e77bd71287..be4ca35299 100644 --- a/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt +++ b/ets2panda/test/compiler/ets/conversion-w-ASExpr-expected.txt @@ -982,38 +982,8 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 4, - "loc": { - "start": { - "line": 22, - "column": 23, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 22, - "column": 26, - "program": "conversion-w-ASExpr.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 22, - "column": 30, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 22, - "column": 35, - "program": "conversion-w-ASExpr.ets" - } - } - }, + "type": "NumberLiteral", + "value": 4, "loc": { "start": { "line": 22, @@ -1022,7 +992,7 @@ }, "end": { "line": 22, - "column": 26, + "column": 27, "program": "conversion-w-ASExpr.ets" } } @@ -1035,7 +1005,7 @@ }, "end": { "line": 22, - "column": 26, + "column": 27, "program": "conversion-w-ASExpr.ets" } } @@ -1050,7 +1020,7 @@ }, "end": { "line": 22, - "column": 36, + "column": 28, "program": "conversion-w-ASExpr.ets" } } @@ -1554,38 +1524,59 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 28, - "column": 29, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 28, - "column": 32, - "program": "conversion-w-ASExpr.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 28, + "column": 29, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 28, + "column": 34, + "program": "conversion-w-ASExpr.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 35, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 28, + "column": 42, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 28, - "column": 36, + "column": 29, "program": "conversion-w-ASExpr.ets" }, "end": { "line": 28, - "column": 41, + "column": 42, "program": "conversion-w-ASExpr.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 28, @@ -1594,7 +1585,7 @@ }, "end": { "line": 28, - "column": 32, + "column": 44, "program": "conversion-w-ASExpr.ets" } } @@ -1607,7 +1598,7 @@ }, "end": { "line": 28, - "column": 32, + "column": 44, "program": "conversion-w-ASExpr.ets" } } @@ -1622,7 +1613,7 @@ }, "end": { "line": 28, - "column": 42, + "column": 45, "program": "conversion-w-ASExpr.ets" } } @@ -1697,38 +1688,59 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 29, - "column": 28, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 29, - "column": 31, - "program": "conversion-w-ASExpr.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 29, + "column": 28, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 29, + "column": 33, + "program": "conversion-w-ASExpr.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 34, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 29, + "column": 39, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 29, - "column": 35, + "column": 28, "program": "conversion-w-ASExpr.ets" }, "end": { "line": 29, - "column": 38, + "column": 39, "program": "conversion-w-ASExpr.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 29, @@ -1737,7 +1749,7 @@ }, "end": { "line": 29, - "column": 31, + "column": 41, "program": "conversion-w-ASExpr.ets" } } @@ -1750,7 +1762,7 @@ }, "end": { "line": 29, - "column": 31, + "column": 41, "program": "conversion-w-ASExpr.ets" } } @@ -1765,7 +1777,7 @@ }, "end": { "line": 29, - "column": 39, + "column": 42, "program": "conversion-w-ASExpr.ets" } } @@ -1840,38 +1852,59 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 30, - "column": 25, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 30, - "column": 28, - "program": "conversion-w-ASExpr.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 30, + "column": 25, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 30, + "column": 30, + "program": "conversion-w-ASExpr.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 31, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 30, + "column": 37, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 30, - "column": 32, + "column": 25, "program": "conversion-w-ASExpr.ets" }, "end": { "line": 30, - "column": 36, + "column": 37, "program": "conversion-w-ASExpr.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 30, @@ -1880,7 +1913,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 39, "program": "conversion-w-ASExpr.ets" } } @@ -1893,7 +1926,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 39, "program": "conversion-w-ASExpr.ets" } } @@ -1908,7 +1941,7 @@ }, "end": { "line": 30, - "column": 37, + "column": 40, "program": "conversion-w-ASExpr.ets" } } @@ -1983,38 +2016,59 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 65, - "loc": { - "start": { - "line": 31, - "column": 28, - "program": "conversion-w-ASExpr.ets" - }, - "end": { - "line": 31, - "column": 32, - "program": "conversion-w-ASExpr.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 31, + "column": 28, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 31, + "column": 34, + "program": "conversion-w-ASExpr.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 35, + "program": "conversion-w-ASExpr.ets" + }, + "end": { + "line": 31, + "column": 41, + "program": "conversion-w-ASExpr.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 31, - "column": 36, + "column": 28, "program": "conversion-w-ASExpr.ets" }, "end": { "line": 31, - "column": 40, + "column": 41, "program": "conversion-w-ASExpr.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 31, @@ -2023,7 +2077,7 @@ }, "end": { "line": 31, - "column": 32, + "column": 43, "program": "conversion-w-ASExpr.ets" } } @@ -2036,7 +2090,7 @@ }, "end": { "line": 31, - "column": 32, + "column": 43, "program": "conversion-w-ASExpr.ets" } } @@ -2051,7 +2105,7 @@ }, "end": { "line": 31, - "column": 41, + "column": 44, "program": "conversion-w-ASExpr.ets" } } diff --git a/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets b/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets index bdcb43e931..2d7b0a7313 100644 --- a/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets +++ b/ets2panda/test/compiler/ets/conversion-w-ASExpr.ets @@ -19,16 +19,16 @@ function main(): void { let cherry : Int = 2 as int; let date : Long = 3 as long; let elderberry : Float = 4 as float; - let fig : Float = 4.0 as float; + let fig : Float = 4.0f; let grape : Double = 5 as double; let honeydewmelon : Double = 5.0 as double; let indian_fig : Char = 65 as char; - let raspberry : Short = 1.0 as short; - let strawberry : Int = 2.0 as int; - let tomato : Long = 3.0 as long; - let uglifruit : Char = 65.0 as char; + let raspberry : Short = (1.0).toShort(); + let strawberry : Int = (2.0).toInt(); + let tomato : Long = (3.0).toLong(); + let uglifruit : Char = (65.0).toChar(); return; } diff --git a/ets2panda/test/compiler/ets/conversion_w_functions-expected.txt b/ets2panda/test/compiler/ets/conversion_w_functions-expected.txt index af3444cb50..561d477e9a 100644 --- a/ets2panda/test/compiler/ets/conversion_w_functions-expected.txt +++ b/ets2panda/test/compiler/ets/conversion_w_functions-expected.txt @@ -636,13 +636,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 25, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 0, + "loc": { + "start": { + "line": 25, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 25, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 25, @@ -651,29 +685,29 @@ }, "end": { "line": 25, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 0, - "loc": { - "start": { - "line": 25, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 25, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 25, + "column": 26, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -683,26 +717,13 @@ }, "end": { "line": 25, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 25, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 25, - "column": 27, + "column": 26, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 25, @@ -711,7 +732,7 @@ }, "end": { "line": 25, - "column": 19, + "column": 28, "program": "conversion_w_functions.ets" } } @@ -724,7 +745,7 @@ }, "end": { "line": 25, - "column": 28, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -886,13 +907,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 29, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 29, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 29, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 29, @@ -901,29 +956,29 @@ }, "end": { "line": 29, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 29, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 29, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 29, + "column": 27, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -933,26 +988,13 @@ }, "end": { "line": 29, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 29, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 29, - "column": 28, + "column": 27, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 29, @@ -961,7 +1003,7 @@ }, "end": { "line": 29, - "column": 19, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -974,7 +1016,7 @@ }, "end": { "line": 29, - "column": 29, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -1136,13 +1178,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 33, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 33, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 33, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 33, @@ -1151,29 +1227,29 @@ }, "end": { "line": 33, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 33, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 33, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 33, + "column": 25, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -1183,26 +1259,13 @@ }, "end": { "line": 33, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 33, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 33, - "column": 26, + "column": 25, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 33, @@ -1211,7 +1274,7 @@ }, "end": { "line": 33, - "column": 19, + "column": 27, "program": "conversion_w_functions.ets" } } @@ -1224,7 +1287,7 @@ }, "end": { "line": 33, - "column": 27, + "column": 28, "program": "conversion_w_functions.ets" } } @@ -1386,13 +1449,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 37, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 37, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 37, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 37, @@ -1401,29 +1498,29 @@ }, "end": { "line": 37, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 37, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 37, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 37, + "column": 26, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -1433,26 +1530,13 @@ }, "end": { "line": 37, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 37, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 37, - "column": 27, + "column": 26, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 37, @@ -1461,7 +1545,7 @@ }, "end": { "line": 37, - "column": 19, + "column": 28, "program": "conversion_w_functions.ets" } } @@ -1474,7 +1558,7 @@ }, "end": { "line": 37, - "column": 28, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -1636,13 +1720,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 41, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 41, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 41, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 41, @@ -1651,29 +1769,29 @@ }, "end": { "line": 41, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 4, - "loc": { - "start": { - "line": 41, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 41, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 41, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 41, + "column": 27, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -1683,26 +1801,13 @@ }, "end": { "line": 41, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 41, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 41, - "column": 28, + "column": 27, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 41, @@ -1711,7 +1816,7 @@ }, "end": { "line": 41, - "column": 19, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -1724,7 +1829,7 @@ }, "end": { "line": 41, - "column": 29, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -1886,13 +1991,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 45, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 45, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 45, + "column": 20, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 45, @@ -1901,29 +2040,29 @@ }, "end": { "line": 45, - "column": 16, + "column": 21, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 4, - "loc": { - "start": { - "line": 45, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 45, - "column": 20, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 22, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 45, + "column": 29, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -1933,26 +2072,13 @@ }, "end": { "line": 45, - "column": 21, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 45, - "column": 25, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 45, - "column": 30, + "column": 29, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 45, @@ -1961,7 +2087,7 @@ }, "end": { "line": 45, - "column": 21, + "column": 31, "program": "conversion_w_functions.ets" } } @@ -1974,7 +2100,7 @@ }, "end": { "line": 45, - "column": 31, + "column": 32, "program": "conversion_w_functions.ets" } } @@ -2136,13 +2262,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 49, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 49, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 49, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 49, + "column": 18, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 49, @@ -2151,29 +2311,29 @@ }, "end": { "line": 49, - "column": 16, + "column": 19, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 49, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 49, - "column": 18, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 49, + "column": 20, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 49, + "column": 28, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -2183,26 +2343,13 @@ }, "end": { "line": 49, - "column": 19, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 49, - "column": 23, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 49, - "column": 29, + "column": 28, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 49, @@ -2211,7 +2358,7 @@ }, "end": { "line": 49, - "column": 19, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -2224,7 +2371,7 @@ }, "end": { "line": 49, - "column": 30, + "column": 31, "program": "conversion_w_functions.ets" } } @@ -2386,13 +2533,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 53, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 5, + "loc": { + "start": { + "line": 53, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 53, + "column": 20, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 53, @@ -2401,29 +2582,29 @@ }, "end": { "line": 53, - "column": 16, + "column": 21, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 53, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 53, - "column": 20, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 22, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 53, + "column": 30, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -2433,26 +2614,13 @@ }, "end": { "line": 53, - "column": 21, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 53, - "column": 25, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 53, - "column": 31, + "column": 30, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 53, @@ -2461,7 +2629,7 @@ }, "end": { "line": 53, - "column": 21, + "column": 32, "program": "conversion_w_functions.ets" } } @@ -2474,7 +2642,7 @@ }, "end": { "line": 53, - "column": 32, + "column": 33, "program": "conversion_w_functions.ets" } } @@ -2636,13 +2804,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getI", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getI", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 57, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 57, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 57, + "column": 19, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 57, @@ -2651,29 +2853,29 @@ }, "end": { "line": 57, - "column": 16, + "column": 20, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 65, - "loc": { - "start": { - "line": 57, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 57, - "column": 19, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 21, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 57, + "column": 27, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -2683,26 +2885,13 @@ }, "end": { "line": 57, - "column": 20, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 57, - "column": 24, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 57, - "column": 28, + "column": 27, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 57, @@ -2711,7 +2900,7 @@ }, "end": { "line": 57, - "column": 20, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -2724,7 +2913,7 @@ }, "end": { "line": 57, - "column": 29, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -2886,13 +3075,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 61, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 61, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 61, + "column": 20, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 61, @@ -2901,29 +3124,29 @@ }, "end": { "line": 61, - "column": 16, + "column": 21, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 61, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 61, - "column": 20, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 22, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 61, + "column": 29, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -2933,26 +3156,13 @@ }, "end": { "line": 61, - "column": 21, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 61, - "column": 25, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 61, - "column": 30, + "column": 29, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 61, @@ -2961,7 +3171,7 @@ }, "end": { "line": 61, - "column": 21, + "column": 31, "program": "conversion_w_functions.ets" } } @@ -2974,7 +3184,7 @@ }, "end": { "line": 61, - "column": 31, + "column": 32, "program": "conversion_w_functions.ets" } } @@ -3136,13 +3346,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 65, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 65, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 65, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 65, + "column": 20, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 65, @@ -3151,29 +3395,29 @@ }, "end": { "line": 65, - "column": 16, + "column": 21, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 65, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 65, - "column": 20, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 65, + "column": 22, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 65, + "column": 27, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -3183,26 +3427,13 @@ }, "end": { "line": 65, - "column": 21, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 65, - "column": 25, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 65, - "column": 28, + "column": 27, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 65, @@ -3211,7 +3442,7 @@ }, "end": { "line": 65, - "column": 21, + "column": 29, "program": "conversion_w_functions.ets" } } @@ -3224,7 +3455,7 @@ }, "end": { "line": 65, - "column": 29, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -3386,13 +3617,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 69, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 69, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 69, + "column": 20, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 69, @@ -3401,29 +3666,29 @@ }, "end": { "line": 69, - "column": 16, + "column": 21, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 69, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 69, - "column": 20, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 69, + "column": 22, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 69, + "column": 28, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -3433,26 +3698,13 @@ }, "end": { "line": 69, - "column": 21, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 69, - "column": 25, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 69, - "column": 29, + "column": 28, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 69, @@ -3461,7 +3713,7 @@ }, "end": { "line": 69, - "column": 21, + "column": 30, "program": "conversion_w_functions.ets" } } @@ -3474,7 +3726,7 @@ }, "end": { "line": 69, - "column": 30, + "column": 31, "program": "conversion_w_functions.ets" } } @@ -3636,13 +3888,47 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "getD", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "getD", + "decorators": [], + "loc": { + "start": { + "line": 73, + "column": 12, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 73, + "column": 16, + "program": "conversion_w_functions.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 73, + "column": 17, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 73, + "column": 21, + "program": "conversion_w_functions.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 73, @@ -3651,29 +3937,29 @@ }, "end": { "line": 73, - "column": 16, + "column": 22, "program": "conversion_w_functions.ets" } } }, - "arguments": [ - { - "type": "NumberLiteral", - "value": 65, - "loc": { - "start": { - "line": 73, - "column": 17, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 73, - "column": 21, - "program": "conversion_w_functions.ets" - } + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 73, + "column": 23, + "program": "conversion_w_functions.ets" + }, + "end": { + "line": 73, + "column": 29, + "program": "conversion_w_functions.ets" } } - ], + }, + "computed": false, "optional": false, "loc": { "start": { @@ -3683,26 +3969,13 @@ }, "end": { "line": 73, - "column": 22, - "program": "conversion_w_functions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 73, - "column": 26, - "program": "conversion_w_functions.ets" - }, - "end": { - "line": 73, - "column": 30, + "column": 29, "program": "conversion_w_functions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 73, @@ -3711,7 +3984,7 @@ }, "end": { "line": 73, - "column": 22, + "column": 31, "program": "conversion_w_functions.ets" } } @@ -3724,7 +3997,7 @@ }, "end": { "line": 73, - "column": 31, + "column": 32, "program": "conversion_w_functions.ets" } } diff --git a/ets2panda/test/compiler/ets/conversion_w_functions.ets b/ets2panda/test/compiler/ets/conversion_w_functions.ets index bd0c38e4e9..0cb8cddda3 100644 --- a/ets2panda/test/compiler/ets/conversion_w_functions.ets +++ b/ets2panda/test/compiler/ets/conversion_w_functions.ets @@ -22,55 +22,55 @@ function getD(d : double): double { } function apple(): Byte { - return getI(0) as byte; + return getI(0).toByte(); } function banana(): Short { - return getI(1) as short; + return getI(1).toShort(); } function cherry(): Int { - return getI(2) as int; + return getI(2).toInt(); } function date(): Long { - return getI(3) as long; + return getI(3).toLong(); } function elderberry(): Float { - return getI(4) as float; + return getI(4).toFloat(); } function fig(): Float { - return getD(4.0) as float; + return getD(4.0).toFloat(); } function grape(): Double { - return getI(5) as double; + return getI(5).toDouble(); } function honeydewmelon(): Double { - return getD(5.0) as double; + return getD(5.0).toDouble(); } function indian_fig(): Char { - return getI(65) as char; + return getI(65).toChar(); } function raspberry(): Short { - return getD(1.0) as short; + return getD(1.0).toShort(); } function strawberry(): Int { - return getD(2.0) as int; + return getD(2.0).toInt(); } function tomato(): Long { - return getD(3.0) as long; + return getD(3.0).toLong(); } function uglifruit(): Char { - return getD(65.0) as char; + return getD(65.0).toChar(); } function main(): void {} diff --git a/ets2panda/test/compiler/ets/dynamicLambdaJSValue-expected.txt b/ets2panda/test/compiler/ets/dynamicLambdaJSValue-expected.txt index 31f9c61384..7ae397c5d5 100644 --- a/ets2panda/test/compiler/ets/dynamicLambdaJSValue-expected.txt +++ b/ets2panda/test/compiler/ets/dynamicLambdaJSValue-expected.txt @@ -797,7 +797,7 @@ "loc": { "start": { "line": 24, - "column": 56, + "column": 60, "program": "dynamicLambdaJSValue.ets" }, "end": { diff --git a/ets2panda/test/compiler/ets/dynamic_instanceof_error-expected.txt b/ets2panda/test/compiler/ets/dynamic_instanceof_error-expected.txt index 5c094ae9aa..0b4e83d3b2 100644 --- a/ets2panda/test/compiler/ets/dynamic_instanceof_error-expected.txt +++ b/ets2panda/test/compiler/ets/dynamic_instanceof_error-expected.txt @@ -677,5 +677,4 @@ } } } -TypeError: Using the 'instance of' operator with non-object type 'a' [dynamic_instanceof_error.ets:24:11] TypeError: Right-hand side of instanceof expression must represent a type. [dynamic_instanceof_error.ets:24:11] diff --git a/ets2panda/test/compiler/ets/generic_arrayaslist-expected.txt b/ets2panda/test/compiler/ets/generic_arrayaslist-expected.txt index 8e5a6dcacb..19c0a20139 100644 --- a/ets2panda/test/compiler/ets/generic_arrayaslist-expected.txt +++ b/ets2panda/test/compiler/ets/generic_arrayaslist-expected.txt @@ -6914,9 +6914,8 @@ } }, "right": { - "type": "Identifier", - "name": "fastGrowThreshold", - "decorators": [], + "type": "NumberLiteral", + "value": 8192, "loc": { "start": { "line": 71, @@ -7004,9 +7003,8 @@ } }, "right": { - "type": "Identifier", - "name": "multiplier", - "decorators": [], + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 73, @@ -7052,7 +7050,7 @@ "loc": { "start": { "line": 73, - "column": 20, + "column": 44, "program": "generic_arrayaslist.ets" }, "end": { @@ -7115,9 +7113,8 @@ } }, "right": { - "type": "Identifier", - "name": "multiplier", - "decorators": [], + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 75, @@ -7794,13 +7791,47 @@ }, "arguments": [ { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 82, + "column": 59, + "program": "generic_arrayaslist.ets" + }, + "end": { + "line": 82, + "column": 63, + "program": "generic_arrayaslist.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 82, + "column": 64, + "program": "generic_arrayaslist.ets" + }, + "end": { + "line": 82, + "column": 68, + "program": "generic_arrayaslist.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 82, @@ -7809,24 +7840,24 @@ }, "end": { "line": 82, - "column": 63, + "column": 68, "program": "generic_arrayaslist.ets" } } }, "property": { "type": "Identifier", - "name": "data", + "name": "length", "decorators": [], "loc": { "start": { "line": 82, - "column": 64, + "column": 69, "program": "generic_arrayaslist.ets" }, "end": { "line": 82, - "column": 68, + "column": 75, "program": "generic_arrayaslist.ets" } } @@ -7841,24 +7872,24 @@ }, "end": { "line": 82, - "column": 68, + "column": 75, "program": "generic_arrayaslist.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 82, - "column": 69, + "column": 76, "program": "generic_arrayaslist.ets" }, "end": { "line": 82, - "column": 75, + "column": 81, "program": "generic_arrayaslist.ets" } } @@ -7873,26 +7904,13 @@ }, "end": { "line": 82, - "column": 75, - "program": "generic_arrayaslist.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 82, - "column": 79, - "program": "generic_arrayaslist.ets" - }, - "end": { - "line": 82, - "column": 82, + "column": 81, "program": "generic_arrayaslist.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 82, @@ -7901,7 +7919,7 @@ }, "end": { "line": 82, - "column": 75, + "column": 83, "program": "generic_arrayaslist.ets" } } @@ -7916,7 +7934,7 @@ }, "end": { "line": 82, - "column": 83, + "column": 84, "program": "generic_arrayaslist.ets" } } @@ -7929,7 +7947,7 @@ }, "end": { "line": 82, - "column": 84, + "column": 85, "program": "generic_arrayaslist.ets" } } @@ -7942,7 +7960,7 @@ }, "end": { "line": 82, - "column": 84, + "column": 85, "program": "generic_arrayaslist.ets" } } @@ -7955,7 +7973,7 @@ }, "end": { "line": 82, - "column": 85, + "column": 86, "program": "generic_arrayaslist.ets" } } @@ -10300,13 +10318,47 @@ }, "arguments": [ { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 104, + "column": 67, + "program": "generic_arrayaslist.ets" + }, + "end": { + "line": 104, + "column": 71, + "program": "generic_arrayaslist.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 104, + "column": 72, + "program": "generic_arrayaslist.ets" + }, + "end": { + "line": 104, + "column": 76, + "program": "generic_arrayaslist.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 104, @@ -10315,24 +10367,24 @@ }, "end": { "line": 104, - "column": 71, + "column": 76, "program": "generic_arrayaslist.ets" } } }, "property": { "type": "Identifier", - "name": "data", + "name": "length", "decorators": [], "loc": { "start": { "line": 104, - "column": 72, + "column": 77, "program": "generic_arrayaslist.ets" }, "end": { "line": 104, - "column": 76, + "column": 83, "program": "generic_arrayaslist.ets" } } @@ -10347,24 +10399,24 @@ }, "end": { "line": 104, - "column": 76, + "column": 83, "program": "generic_arrayaslist.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 104, - "column": 77, + "column": 84, "program": "generic_arrayaslist.ets" }, "end": { "line": 104, - "column": 83, + "column": 89, "program": "generic_arrayaslist.ets" } } @@ -10379,26 +10431,13 @@ }, "end": { "line": 104, - "column": 83, - "program": "generic_arrayaslist.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 104, - "column": 87, - "program": "generic_arrayaslist.ets" - }, - "end": { - "line": 104, - "column": 90, + "column": 89, "program": "generic_arrayaslist.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 104, @@ -10407,7 +10446,7 @@ }, "end": { "line": 104, - "column": 83, + "column": 91, "program": "generic_arrayaslist.ets" } } @@ -10422,7 +10461,7 @@ }, "end": { "line": 104, - "column": 91, + "column": 92, "program": "generic_arrayaslist.ets" } } @@ -10435,7 +10474,7 @@ }, "end": { "line": 104, - "column": 92, + "column": 93, "program": "generic_arrayaslist.ets" } } @@ -10448,7 +10487,7 @@ }, "end": { "line": 104, - "column": 92, + "column": 93, "program": "generic_arrayaslist.ets" } } @@ -10463,7 +10502,7 @@ }, "end": { "line": 104, - "column": 93, + "column": 94, "program": "generic_arrayaslist.ets" } } @@ -25303,4 +25342,4 @@ } } TypeError: Expected 1 arguments, got 3. [generic_arrayaslist.ets:115:9] -TypeError: No matching call signature for assertTrue(int, int, "No data to popBack in ArrayAsList!") [generic_arrayaslist.ets:115:9] +TypeError: No matching call signature for assertTrue(Int, Int, "No data to popBack in ArrayAsList!") [generic_arrayaslist.ets:115:9] diff --git a/ets2panda/test/compiler/ets/generic_arrayaslist.ets b/ets2panda/test/compiler/ets/generic_arrayaslist.ets index 22de891fc3..b3bad0b348 100644 --- a/ets2panda/test/compiler/ets/generic_arrayaslist.ets +++ b/ets2panda/test/compiler/ets/generic_arrayaslist.ets @@ -79,7 +79,7 @@ class ArrayAsListt implements Listt { public override pushFront(e: T): void { let dst = this.data; if (this.curSize == this.data.length) { - dst = new (T | undefined)[this.getNewCapacity(this.data.length as int)]; + dst = new (T | undefined)[this.getNewCapacity(this.data.length.toInt())]; } for (let i = this.curSize; i != 0; --i) { dst[i] = this.data[i-1]; @@ -101,7 +101,7 @@ class ArrayAsListt implements Listt { public override pushBack(e: T): void { if (this.curSize == this.data.length) { - let newData = new (T | undefined)[this.getNewCapacity(this.data.length as int)]; + let newData = new (T | undefined)[this.getNewCapacity(this.data.length.toInt())]; for (let i = 0; i < this.curSize; ++i) { newData[i] = this.data[i]; } diff --git a/ets2panda/test/compiler/ets/implicit-conversion-expected.txt b/ets2panda/test/compiler/ets/implicit-conversion-expected.txt index 9c26969875..6ec3601199 100644 --- a/ets2panda/test/compiler/ets/implicit-conversion-expected.txt +++ b/ets2panda/test/compiler/ets/implicit-conversion-expected.txt @@ -606,8 +606,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 3, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 23, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 20, + "column": 29, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 20, + "column": 30, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 20, + "column": 36, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 20, + "column": 23, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 20, + "column": 36, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 20, + "column": 37, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 20, + "column": 40, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 20, @@ -616,7 +685,7 @@ }, "end": { "line": 20, - "column": 26, + "column": 41, "program": "implicit-conversion.ets" } } @@ -629,7 +698,7 @@ }, "end": { "line": 20, - "column": 26, + "column": 41, "program": "implicit-conversion.ets" } } @@ -644,7 +713,7 @@ }, "end": { "line": 20, - "column": 27, + "column": 42, "program": "implicit-conversion.ets" } } @@ -719,8 +788,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 4, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 30, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 21, + "column": 36, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 37, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 21, + "column": 44, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 21, + "column": 30, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 21, + "column": 44, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 21, + "column": 45, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 21, + "column": 48, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 21, @@ -729,7 +867,7 @@ }, "end": { "line": 21, - "column": 33, + "column": 49, "program": "implicit-conversion.ets" } } @@ -742,7 +880,7 @@ }, "end": { "line": 21, - "column": 33, + "column": 49, "program": "implicit-conversion.ets" } } @@ -757,7 +895,7 @@ }, "end": { "line": 21, - "column": 34, + "column": 50, "program": "implicit-conversion.ets" } } @@ -832,8 +970,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 4, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 23, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 22, + "column": 29, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 30, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 22, + "column": 37, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 22, + "column": 23, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 22, + "column": 37, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 4, + "loc": { + "start": { + "line": 22, + "column": 38, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 22, + "column": 41, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 22, @@ -842,7 +1049,7 @@ }, "end": { "line": 22, - "column": 26, + "column": 42, "program": "implicit-conversion.ets" } } @@ -855,7 +1062,7 @@ }, "end": { "line": 22, - "column": 26, + "column": 42, "program": "implicit-conversion.ets" } } @@ -870,7 +1077,7 @@ }, "end": { "line": 22, - "column": 27, + "column": 43, "program": "implicit-conversion.ets" } } @@ -1284,8 +1491,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 1, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 29, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 28, + "column": 35, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 36, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 28, + "column": 43, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 28, + "column": 29, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 28, + "column": 43, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 28, + "column": 44, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 28, + "column": 47, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 28, @@ -1294,7 +1570,7 @@ }, "end": { "line": 28, - "column": 32, + "column": 48, "program": "implicit-conversion.ets" } } @@ -1307,7 +1583,7 @@ }, "end": { "line": 28, - "column": 32, + "column": 48, "program": "implicit-conversion.ets" } } @@ -1322,7 +1598,7 @@ }, "end": { "line": 28, - "column": 33, + "column": 49, "program": "implicit-conversion.ets" } } @@ -1397,8 +1673,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 2, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 28, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 29, + "column": 34, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 29, + "column": 35, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 29, + "column": 40, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 29, + "column": 28, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 29, + "column": 40, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 29, + "column": 41, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 29, + "column": 44, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 29, @@ -1407,7 +1752,7 @@ }, "end": { "line": 29, - "column": 31, + "column": 45, "program": "implicit-conversion.ets" } } @@ -1420,7 +1765,7 @@ }, "end": { "line": 29, - "column": 31, + "column": 45, "program": "implicit-conversion.ets" } } @@ -1435,7 +1780,7 @@ }, "end": { "line": 29, - "column": 32, + "column": 46, "program": "implicit-conversion.ets" } } @@ -1510,8 +1855,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 3, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 25, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 30, + "column": 31, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 32, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 30, + "column": 38, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 30, + "column": 25, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 30, + "column": 38, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 30, + "column": 39, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 30, + "column": 42, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 30, @@ -1520,7 +1934,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 43, "program": "implicit-conversion.ets" } } @@ -1533,7 +1947,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 43, "program": "implicit-conversion.ets" } } @@ -1548,7 +1962,7 @@ }, "end": { "line": 30, - "column": 29, + "column": 44, "program": "implicit-conversion.ets" } } @@ -1623,8 +2037,77 @@ } }, "init": { - "type": "NumberLiteral", - "value": 65, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 28, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 31, + "column": 34, + "program": "implicit-conversion.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 35, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 31, + "column": 41, + "program": "implicit-conversion.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 31, + "column": 28, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 31, + "column": 41, + "program": "implicit-conversion.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 65, + "loc": { + "start": { + "line": 31, + "column": 42, + "program": "implicit-conversion.ets" + }, + "end": { + "line": 31, + "column": 46, + "program": "implicit-conversion.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 31, @@ -1633,7 +2116,7 @@ }, "end": { "line": 31, - "column": 32, + "column": 47, "program": "implicit-conversion.ets" } } @@ -1646,7 +2129,7 @@ }, "end": { "line": 31, - "column": 32, + "column": 47, "program": "implicit-conversion.ets" } } @@ -1661,7 +2144,7 @@ }, "end": { "line": 31, - "column": 33, + "column": 48, "program": "implicit-conversion.ets" } } diff --git a/ets2panda/test/compiler/ets/implicit-conversion.ets b/ets2panda/test/compiler/ets/implicit-conversion.ets index cd25af09f4..9b6aedc3a3 100644 --- a/ets2panda/test/compiler/ets/implicit-conversion.ets +++ b/ets2panda/test/compiler/ets/implicit-conversion.ets @@ -17,18 +17,18 @@ function main(): void { let apple : Byte = 0; let banana : Short = 1; let cherry : Int = 2; - let date : Long = 3.0; - let elderberry : Float = 4.0; - let fig : Float = 4.0; + let date : Long = Double.toLong(3.0); + let elderberry : Float = Double.toFloat(4.0); + let fig : Float = Double.toFloat(4.0); let grape : Double = -5.0; let honeydewmelon : Double = 5.0; let indian_fig : Char = 65; - let raspberry : Short = 1.0; - let strawberry : Int = 2.0; - let tomato : Long = 3.0; - let uglifruit : Char = 65.0; + let raspberry : Short = Double.toShort(1.0); + let strawberry : Int = Double.toInt(2.0); + let tomato : Long = Double.toLong(3.0); + let uglifruit : Char = Double.toChar(65.0); return; } diff --git a/ets2panda/test/compiler/ets/import_tests/infer_imported_function_return_type_lib-expected.txt b/ets2panda/test/compiler/ets/import_tests/infer_imported_function_return_type_lib-expected.txt index d04e570c0f..a6b4aa5d8a 100644 --- a/ets2panda/test/compiler/ets/import_tests/infer_imported_function_return_type_lib-expected.txt +++ b/ets2panda/test/compiler/ets/import_tests/infer_imported_function_return_type_lib-expected.txt @@ -409,7 +409,7 @@ "loc": { "start": { "line": 17, - "column": 9, + "column": 17, "program": "infer_imported_function_return_type_lib.ets" }, "end": { diff --git a/ets2panda/test/compiler/ets/instanceof_object_long-expected.txt b/ets2panda/test/compiler/ets/instanceof_object_long-expected.txt index bab47a98ee..44c942b99d 100644 --- a/ets2panda/test/compiler/ets/instanceof_object_long-expected.txt +++ b/ets2panda/test/compiler/ets/instanceof_object_long-expected.txt @@ -542,4 +542,3 @@ } } } -TypeError: Bad operand type, the types of the operands must be same type. [instanceof_object_long.ets:21:12] diff --git a/ets2panda/test/compiler/ets/lambda_unresolved_ref_1-expected.txt b/ets2panda/test/compiler/ets/lambda_unresolved_ref_1-expected.txt index a2c1ec4339..798ebcd037 100644 --- a/ets2panda/test/compiler/ets/lambda_unresolved_ref_1-expected.txt +++ b/ets2panda/test/compiler/ets/lambda_unresolved_ref_1-expected.txt @@ -2813,43 +2813,77 @@ } }, "right": { - "type": "TSAsExpression", - "expression": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 42, + "column": 19, + "program": "lambda_unresolved_ref_1.ets" + }, + "end": { + "line": 42, + "column": 20, + "program": "lambda_unresolved_ref_1.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 42, + "column": 23, + "program": "lambda_unresolved_ref_1.ets" + }, + "end": { + "line": 42, + "column": 24, + "program": "lambda_unresolved_ref_1.ets" + } + } + }, "loc": { "start": { "line": 42, - "column": 19, + "column": 18, "program": "lambda_unresolved_ref_1.ets" }, "end": { "line": 42, - "column": 20, + "column": 25, "program": "lambda_unresolved_ref_1.ets" } } }, - "right": { - "type": "NumberLiteral", - "value": 1, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], "loc": { "start": { "line": 42, - "column": 23, + "column": 26, "program": "lambda_unresolved_ref_1.ets" }, "end": { "line": 42, - "column": 24, + "column": 33, "program": "lambda_unresolved_ref_1.ets" } } }, + "computed": false, + "optional": false, "loc": { "start": { "line": 42, @@ -2858,26 +2892,13 @@ }, "end": { "line": 42, - "column": 25, - "program": "lambda_unresolved_ref_1.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 42, - "column": 29, - "program": "lambda_unresolved_ref_1.ets" - }, - "end": { - "line": 42, - "column": 34, + "column": 33, "program": "lambda_unresolved_ref_1.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 42, @@ -2886,7 +2907,7 @@ }, "end": { "line": 42, - "column": 25, + "column": 35, "program": "lambda_unresolved_ref_1.ets" } } @@ -2899,7 +2920,7 @@ }, "end": { "line": 42, - "column": 25, + "column": 35, "program": "lambda_unresolved_ref_1.ets" } } @@ -2912,7 +2933,7 @@ }, "end": { "line": 42, - "column": 35, + "column": 36, "program": "lambda_unresolved_ref_1.ets" } } @@ -3795,43 +3816,77 @@ } }, "right": { - "type": "TSAsExpression", - "expression": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 19, + "program": "lambda_unresolved_ref_1.ets" + }, + "end": { + "line": 53, + "column": 20, + "program": "lambda_unresolved_ref_1.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 53, + "column": 23, + "program": "lambda_unresolved_ref_1.ets" + }, + "end": { + "line": 53, + "column": 24, + "program": "lambda_unresolved_ref_1.ets" + } + } + }, "loc": { "start": { "line": 53, - "column": 19, + "column": 18, "program": "lambda_unresolved_ref_1.ets" }, "end": { "line": 53, - "column": 20, + "column": 25, "program": "lambda_unresolved_ref_1.ets" } } }, - "right": { - "type": "NumberLiteral", - "value": 1, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], "loc": { "start": { "line": 53, - "column": 23, + "column": 26, "program": "lambda_unresolved_ref_1.ets" }, "end": { "line": 53, - "column": 24, + "column": 33, "program": "lambda_unresolved_ref_1.ets" } } }, + "computed": false, + "optional": false, "loc": { "start": { "line": 53, @@ -3840,26 +3895,13 @@ }, "end": { "line": 53, - "column": 25, - "program": "lambda_unresolved_ref_1.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 53, - "column": 29, - "program": "lambda_unresolved_ref_1.ets" - }, - "end": { - "line": 53, - "column": 34, + "column": 33, "program": "lambda_unresolved_ref_1.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 53, @@ -3868,7 +3910,7 @@ }, "end": { "line": 53, - "column": 25, + "column": 35, "program": "lambda_unresolved_ref_1.ets" } } @@ -3881,7 +3923,7 @@ }, "end": { "line": 53, - "column": 25, + "column": 35, "program": "lambda_unresolved_ref_1.ets" } } @@ -3894,7 +3936,7 @@ }, "end": { "line": 53, - "column": 35, + "column": 36, "program": "lambda_unresolved_ref_1.ets" } } diff --git a/ets2panda/test/compiler/ets/lambda_unresolved_ref_1.ets b/ets2panda/test/compiler/ets/lambda_unresolved_ref_1.ets index 77bfd3af41..ea4d2663c9 100644 --- a/ets2panda/test/compiler/ets/lambda_unresolved_ref_1.ets +++ b/ets2panda/test/compiler/ets/lambda_unresolved_ref_1.ets @@ -39,7 +39,7 @@ function foo2(arr: Object[]): void { function bar(): void { let arr: short[] = [1,2,3,4] let fn: (v: short) => void = (v: short): void => { - arr[0] = (v + 1) as short; + arr[0] = (v + 1).toShort(); } for (let arr = 0; arr < 4; ++arr) { } arr = [3]; @@ -50,7 +50,7 @@ function bar(): void { function main() { let arr: short[] = [1,2,3,4] let fn: (v: short) => void = (v: short): void => { - arr[0] = (v + 1) as short; + arr[0] = (v + 1).toShort(); } for (let i = 0; i < 4; ++i) { } } diff --git a/ets2panda/test/compiler/ets/launch_expression-expected.txt b/ets2panda/test/compiler/ets/launch_expression-expected.txt index 8c8e6cf951..fd80bda179 100644 --- a/ets2panda/test/compiler/ets/launch_expression-expected.txt +++ b/ets2panda/test/compiler/ets/launch_expression-expected.txt @@ -1447,7 +1447,7 @@ "loc": { "start": { "line": 27, - "column": 21, + "column": 60, "program": "launch_expression.ets" }, "end": { @@ -1902,7 +1902,7 @@ "loc": { "start": { "line": 31, - "column": 9, + "column": 14, "program": "launch_expression.ets" }, "end": { @@ -2569,7 +2569,7 @@ "loc": { "start": { "line": 36, - "column": 51, + "column": 53, "program": "launch_expression.ets" }, "end": { @@ -3644,7 +3644,7 @@ "loc": { "start": { "line": 45, - "column": 9, + "column": 14, "program": "launch_expression.ets" }, "end": { @@ -4109,7 +4109,7 @@ "loc": { "start": { "line": 50, - "column": 36, + "column": 38, "program": "launch_expression.ets" }, "end": { diff --git a/ets2panda/test/compiler/ets/override16-expected.txt b/ets2panda/test/compiler/ets/override16-expected.txt index 5947eedf22..3032322afa 100644 --- a/ets2panda/test/compiler/ets/override16-expected.txt +++ b/ets2panda/test/compiler/ets/override16-expected.txt @@ -448,8 +448,77 @@ { "type": "ReturnStatement", "argument": { - "type": "NumberLiteral", - "value": 1, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 12, + "program": "override16.ets" + }, + "end": { + "line": 24, + "column": 18, + "program": "override16.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 19, + "program": "override16.ets" + }, + "end": { + "line": 24, + "column": 26, + "program": "override16.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 12, + "program": "override16.ets" + }, + "end": { + "line": 24, + "column": 26, + "program": "override16.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 24, + "column": 27, + "program": "override16.ets" + }, + "end": { + "line": 24, + "column": 30, + "program": "override16.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 24, @@ -458,7 +527,7 @@ }, "end": { "line": 24, - "column": 15, + "column": 31, "program": "override16.ets" } } @@ -471,7 +540,7 @@ }, "end": { "line": 24, - "column": 16, + "column": 32, "program": "override16.ets" } } diff --git a/ets2panda/test/compiler/ets/override16.ets b/ets2panda/test/compiler/ets/override16.ets index b497db15d0..9c6d91c759 100644 --- a/ets2panda/test/compiler/ets/override16.ets +++ b/ets2panda/test/compiler/ets/override16.ets @@ -21,6 +21,6 @@ class A { class B extends A { fn(): float { - return 1.0; + return Double.toFloat(1.0); } } diff --git a/ets2panda/test/compiler/ets/override17-expected.txt b/ets2panda/test/compiler/ets/override17-expected.txt index fd757fd655..bdf99d6d06 100644 --- a/ets2panda/test/compiler/ets/override17-expected.txt +++ b/ets2panda/test/compiler/ets/override17-expected.txt @@ -448,8 +448,77 @@ { "type": "ReturnStatement", "argument": { - "type": "NumberLiteral", - "value": 1, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 12, + "program": "override17.ets" + }, + "end": { + "line": 24, + "column": 18, + "program": "override17.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 19, + "program": "override17.ets" + }, + "end": { + "line": 24, + "column": 26, + "program": "override17.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 24, + "column": 12, + "program": "override17.ets" + }, + "end": { + "line": 24, + "column": 26, + "program": "override17.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 24, + "column": 27, + "program": "override17.ets" + }, + "end": { + "line": 24, + "column": 30, + "program": "override17.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 24, @@ -458,7 +527,7 @@ }, "end": { "line": 24, - "column": 15, + "column": 31, "program": "override17.ets" } } @@ -471,7 +540,7 @@ }, "end": { "line": 24, - "column": 16, + "column": 32, "program": "override17.ets" } } diff --git a/ets2panda/test/compiler/ets/override17.ets b/ets2panda/test/compiler/ets/override17.ets index 1212c96bcf..8e9e61a926 100644 --- a/ets2panda/test/compiler/ets/override17.ets +++ b/ets2panda/test/compiler/ets/override17.ets @@ -21,6 +21,6 @@ class A { class B extends A { static fn(): float { - return 1.0; + return Double.toFloat(1.0); } } diff --git a/ets2panda/test/compiler/ets/switchStatementBoxing-expected.txt b/ets2panda/test/compiler/ets/switchStatementBoxing-expected.txt index 2b5107c89e..e621a9bb8e 100644 --- a/ets2panda/test/compiler/ets/switchStatementBoxing-expected.txt +++ b/ets2panda/test/compiler/ets/switchStatementBoxing-expected.txt @@ -308,9 +308,8 @@ { "type": "SwitchCase", "test": { - "type": "Identifier", - "name": "b", - "decorators": [], + "type": "NumberLiteral", + "value": 20, "loc": { "start": { "line": 21, diff --git a/ets2panda/test/compiler/ets/switchStatementCorrectConversion-expected.txt b/ets2panda/test/compiler/ets/switchStatementCorrectConversion-expected.txt index 9fff8c798d..05138eb797 100644 --- a/ets2panda/test/compiler/ets/switchStatementCorrectConversion-expected.txt +++ b/ets2panda/test/compiler/ets/switchStatementCorrectConversion-expected.txt @@ -717,9 +717,8 @@ { "type": "SwitchCase", "test": { - "type": "Identifier", - "name": "c", - "decorators": [], + "type": "NumberLiteral", + "value": 210000, "loc": { "start": { "line": 37, diff --git a/ets2panda/test/compiler/ets/tuple_types_1-expected.txt b/ets2panda/test/compiler/ets/tuple_types_1-expected.txt index d7a76bc740..43b1a9cac1 100644 --- a/ets2panda/test/compiler/ets/tuple_types_1-expected.txt +++ b/ets2panda/test/compiler/ets/tuple_types_1-expected.txt @@ -2453,7 +2453,7 @@ "loc": { "start": { "line": 35, - "column": 19, + "column": 40, "program": "tuple_types_1.ets" }, "end": { diff --git a/ets2panda/test/compiler/ets/tuple_types_15-expected.txt b/ets2panda/test/compiler/ets/tuple_types_15-expected.txt index 410a698639..dfde229154 100644 --- a/ets2panda/test/compiler/ets/tuple_types_15-expected.txt +++ b/ets2panda/test/compiler/ets/tuple_types_15-expected.txt @@ -1291,7 +1291,7 @@ "loc": { "start": { "line": 31, - "column": 26, + "column": 44, "program": "tuple_types_15.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/AccessBinaryTrees-expected.txt b/ets2panda/test/parser/ets/AccessBinaryTrees-expected.txt index 59013f92d3..1284c1cdd2 100644 --- a/ets2panda/test/parser/ets/AccessBinaryTrees-expected.txt +++ b/ets2panda/test/parser/ets/AccessBinaryTrees-expected.txt @@ -1502,7 +1502,7 @@ "loc": { "start": { "line": 31, - "column": 14, + "column": 26, "program": "AccessBinaryTrees.ets" }, "end": { @@ -2236,7 +2236,7 @@ "loc": { "start": { "line": 43, - "column": 39, + "column": 41, "program": "AccessBinaryTrees.ets" }, "end": { @@ -2920,43 +2920,8 @@ } }, "init": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessBinaryTrees", - "decorators": [], - "loc": { - "start": { - "line": 54, - "column": 23, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 54, - "column": 40, - "program": "AccessBinaryTrees.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "startDepth", - "decorators": [], - "loc": { - "start": { - "line": 54, - "column": 41, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 54, - "column": 51, - "program": "AccessBinaryTrees.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 4, "loc": { "start": { "line": 54, @@ -3019,43 +2984,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessBinaryTrees", - "decorators": [], - "loc": { - "start": { - "line": 54, - "column": 58, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 54, - "column": 75, - "program": "AccessBinaryTrees.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "endDepth", - "decorators": [], - "loc": { - "start": { - "line": 54, - "column": 76, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 54, - "column": 84, - "program": "AccessBinaryTrees.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 7, "loc": { "start": { "line": 54, @@ -3157,43 +3087,8 @@ } }, "init": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessBinaryTrees", - "decorators": [], - "loc": { - "start": { - "line": 55, - "column": 27, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 55, - "column": 44, - "program": "AccessBinaryTrees.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "startDepth", - "decorators": [], - "loc": { - "start": { - "line": 55, - "column": 45, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 55, - "column": 55, - "program": "AccessBinaryTrees.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 4, "loc": { "start": { "line": 55, @@ -5128,43 +5023,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessBinaryTrees", - "decorators": [], - "loc": { - "start": { - "line": 75, - "column": 19, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 75, - "column": 36, - "program": "AccessBinaryTrees.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 75, - "column": 37, - "program": "AccessBinaryTrees.ets" - }, - "end": { - "line": 75, - "column": 45, - "program": "AccessBinaryTrees.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": -4, "loc": { "start": { "line": 75, diff --git a/ets2panda/test/parser/ets/AccessNBody-expected.txt b/ets2panda/test/parser/ets/AccessNBody-expected.txt index 83097faa8d..83b4155c99 100644 --- a/ets2panda/test/parser/ets/AccessNBody-expected.txt +++ b/ets2panda/test/parser/ets/AccessNBody-expected.txt @@ -197,7 +197,7 @@ "loc": { "start": { "line": 20, - "column": 36, + "column": 40, "program": "AccessNBody.ets" }, "end": { @@ -3382,13 +3382,47 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 53, + "column": 27, + "program": "AccessNBody.ets" + }, + "end": { + "line": 53, + "column": 31, + "program": "AccessNBody.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "bodies", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 32, + "program": "AccessNBody.ets" + }, + "end": { + "line": 53, + "column": 38, + "program": "AccessNBody.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 53, @@ -3397,24 +3431,24 @@ }, "end": { "line": 53, - "column": 31, + "column": 38, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "bodies", + "name": "length", "decorators": [], "loc": { "start": { "line": 53, - "column": 32, + "column": 39, "program": "AccessNBody.ets" }, "end": { "line": 53, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } @@ -3429,24 +3463,24 @@ }, "end": { "line": 53, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 53, - "column": 39, + "column": 46, "program": "AccessNBody.ets" }, "end": { "line": 53, - "column": 45, + "column": 51, "program": "AccessNBody.ets" } } @@ -3461,26 +3495,13 @@ }, "end": { "line": 53, - "column": 45, - "program": "AccessNBody.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 53, - "column": 49, - "program": "AccessNBody.ets" - }, - "end": { - "line": 53, - "column": 52, + "column": 51, "program": "AccessNBody.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 53, @@ -3489,7 +3510,7 @@ }, "end": { "line": 53, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -3502,7 +3523,7 @@ }, "end": { "line": 53, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -3517,7 +3538,7 @@ }, "end": { "line": 53, - "column": 53, + "column": 54, "program": "AccessNBody.ets" } } @@ -5149,13 +5170,47 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 70, + "column": 27, + "program": "AccessNBody.ets" + }, + "end": { + "line": 70, + "column": 31, + "program": "AccessNBody.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "bodies", + "decorators": [], + "loc": { + "start": { + "line": 70, + "column": 32, + "program": "AccessNBody.ets" + }, + "end": { + "line": 70, + "column": 38, + "program": "AccessNBody.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 70, @@ -5164,24 +5219,24 @@ }, "end": { "line": 70, - "column": 31, + "column": 38, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "bodies", + "name": "length", "decorators": [], "loc": { "start": { "line": 70, - "column": 32, + "column": 39, "program": "AccessNBody.ets" }, "end": { "line": 70, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } @@ -5196,24 +5251,24 @@ }, "end": { "line": 70, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 70, - "column": 39, + "column": 46, "program": "AccessNBody.ets" }, "end": { "line": 70, - "column": 45, + "column": 51, "program": "AccessNBody.ets" } } @@ -5228,26 +5283,13 @@ }, "end": { "line": 70, - "column": 45, - "program": "AccessNBody.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 70, - "column": 49, - "program": "AccessNBody.ets" - }, - "end": { - "line": 70, - "column": 52, + "column": 51, "program": "AccessNBody.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 70, @@ -5256,7 +5298,7 @@ }, "end": { "line": 70, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -5269,7 +5311,7 @@ }, "end": { "line": 70, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -5284,7 +5326,7 @@ }, "end": { "line": 70, - "column": 53, + "column": 54, "program": "AccessNBody.ets" } } @@ -6671,7 +6713,7 @@ "loc": { "start": { "line": 78, - "column": 34, + "column": 39, "program": "AccessNBody.ets" }, "end": { @@ -7112,7 +7154,7 @@ "loc": { "start": { "line": 80, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -7311,7 +7353,7 @@ "loc": { "start": { "line": 81, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -7510,7 +7552,7 @@ "loc": { "start": { "line": 82, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -7709,7 +7751,7 @@ "loc": { "start": { "line": 83, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -7908,7 +7950,7 @@ "loc": { "start": { "line": 84, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -8107,7 +8149,7 @@ "loc": { "start": { "line": 85, - "column": 30, + "column": 35, "program": "AccessNBody.ets" }, "end": { @@ -9577,13 +9619,47 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 101, + "column": 27, + "program": "AccessNBody.ets" + }, + "end": { + "line": 101, + "column": 31, + "program": "AccessNBody.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "bodies", + "decorators": [], + "loc": { + "start": { + "line": 101, + "column": 32, + "program": "AccessNBody.ets" + }, + "end": { + "line": 101, + "column": 38, + "program": "AccessNBody.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 101, @@ -9592,24 +9668,24 @@ }, "end": { "line": 101, - "column": 31, + "column": 38, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "bodies", + "name": "length", "decorators": [], "loc": { "start": { "line": 101, - "column": 32, + "column": 39, "program": "AccessNBody.ets" }, "end": { "line": 101, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } @@ -9624,24 +9700,24 @@ }, "end": { "line": 101, - "column": 38, + "column": 45, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 101, - "column": 39, + "column": 46, "program": "AccessNBody.ets" }, "end": { "line": 101, - "column": 45, + "column": 51, "program": "AccessNBody.ets" } } @@ -9656,26 +9732,13 @@ }, "end": { "line": 101, - "column": 45, - "program": "AccessNBody.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 101, - "column": 49, - "program": "AccessNBody.ets" - }, - "end": { - "line": 101, - "column": 52, + "column": 51, "program": "AccessNBody.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 101, @@ -9684,7 +9747,7 @@ }, "end": { "line": 101, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -9697,7 +9760,7 @@ }, "end": { "line": 101, - "column": 45, + "column": 53, "program": "AccessNBody.ets" } } @@ -9712,7 +9775,7 @@ }, "end": { "line": 101, - "column": 53, + "column": 54, "program": "AccessNBody.ets" } } @@ -10420,7 +10483,7 @@ "loc": { "start": { "line": 104, - "column": 39, + "column": 50, "program": "AccessNBody.ets" }, "end": { @@ -10564,7 +10627,7 @@ "loc": { "start": { "line": 104, - "column": 19, + "column": 25, "program": "AccessNBody.ets" }, "end": { @@ -11632,7 +11695,7 @@ "loc": { "start": { "line": 110, - "column": 34, + "column": 39, "program": "AccessNBody.ets" }, "end": { @@ -12227,7 +12290,7 @@ "loc": { "start": { "line": 119, - "column": 43, + "column": 47, "program": "AccessNBody.ets" }, "end": { @@ -12685,21 +12748,69 @@ } } }, + { + "type": "NumberLiteral", + "value": 0.606326, + "loc": { + "start": { + "line": 125, + "column": 102, + "program": "AccessNBody.ets" + }, + "end": { + "line": 125, + "column": 153, + "program": "AccessNBody.ets" + } + } + }, + { + "type": "NumberLiteral", + "value": 2.81199, + "loc": { + "start": { + "line": 125, + "column": 155, + "program": "AccessNBody.ets" + }, + "end": { + "line": 125, + "column": 206, + "program": "AccessNBody.ets" + } + } + }, + { + "type": "NumberLiteral", + "value": -0.0252184, + "loc": { + "start": { + "line": 125, + "column": 208, + "program": "AccessNBody.ets" + }, + "end": { + "line": 125, + "column": 260, + "program": "AccessNBody.ets" + } + } + }, { "type": "BinaryExpression", "operator": "*", "left": { "type": "NumberLiteral", - "value": 0.00166008, + "value": 0.000954792, "loc": { "start": { "line": 125, - "column": 102, + "column": 262, "program": "AccessNBody.ets" }, "end": { "line": 125, - "column": 125, + "column": 285, "program": "AccessNBody.ets" } } @@ -12713,29 +12824,29 @@ "loc": { "start": { "line": 125, - "column": 128, + "column": 288, "program": "AccessNBody.ets" }, "end": { "line": 125, - "column": 139, + "column": 299, "program": "AccessNBody.ets" } } }, "property": { "type": "Identifier", - "name": "DAYS_PER_YEAR", + "name": "SOLAR_MASS", "decorators": [], "loc": { "start": { "line": 125, - "column": 140, + "column": 300, "program": "AccessNBody.ets" }, "end": { "line": 125, - "column": 153, + "column": 310, "program": "AccessNBody.ets" } } @@ -12745,12 +12856,12 @@ "loc": { "start": { "line": 125, - "column": 128, + "column": 288, "program": "AccessNBody.ets" }, "end": { "line": 125, - "column": 153, + "column": 310, "program": "AccessNBody.ets" } } @@ -12758,256 +12869,7 @@ "loc": { "start": { "line": 125, - "column": 102, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 153, - "program": "AccessNBody.ets" - } - } - }, - { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.00769901, - "loc": { - "start": { - "line": 125, - "column": 155, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 178, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 192, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 193, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 125, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, - "loc": { - "start": { - "line": 125, - "column": 155, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, - { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": -6.9046e-05, - "loc": { - "start": { - "line": 125, - "column": 208, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 232, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 235, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 246, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 247, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 260, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 125, - "column": 235, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 260, - "program": "AccessNBody.ets" - } - } - }, - "loc": { - "start": { - "line": 125, - "column": 208, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 260, - "program": "AccessNBody.ets" - } - } - }, - { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.000954792, - "loc": { - "start": { - "line": 125, - "column": 262, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 285, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 288, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 299, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "SOLAR_MASS", - "decorators": [], - "loc": { - "start": { - "line": 125, - "column": 300, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 310, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 125, - "column": 288, - "program": "AccessNBody.ets" - }, - "end": { - "line": 125, - "column": 310, - "program": "AccessNBody.ets" - } - } - }, - "loc": { - "start": { - "line": 125, - "column": 262, + "column": 262, "program": "AccessNBody.ets" }, "end": { @@ -13294,80 +13156,13 @@ "end": { "line": 128, "column": 99, - "program": "AccessNBody.ets" - } - } - }, - { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": -0.00276743, - "loc": { - "start": { - "line": 128, - "column": 101, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 125, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 128, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 139, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 140, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 153, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 128, - "column": 128, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 153, - "program": "AccessNBody.ets" - } + "program": "AccessNBody.ets" } - }, + } + }, + { + "type": "NumberLiteral", + "value": -1.01077, "loc": { "start": { "line": 128, @@ -13382,75 +13177,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.00499853, - "loc": { - "start": { - "line": 128, - "column": 155, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 178, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 192, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 193, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 128, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1.82566, "loc": { "start": { "line": 128, @@ -13465,75 +13193,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 2.30417e-05, - "loc": { - "start": { - "line": 128, - "column": 208, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 231, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 234, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 245, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 128, - "column": 246, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 259, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 128, - "column": 234, - "program": "AccessNBody.ets" - }, - "end": { - "line": 128, - "column": 259, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": 0.00841576, "loc": { "start": { "line": 128, @@ -13912,158 +13573,24 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.0029646, - "loc": { - "start": { - "line": 131, - "column": 102, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 125, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 128, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 139, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 140, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 153, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 131, - "column": 128, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 153, - "program": "AccessNBody.ets" - } - } - }, - "loc": { - "start": { - "line": 131, - "column": 102, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 153, - "program": "AccessNBody.ets" - } - } - }, - { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.00237847, - "loc": { - "start": { - "line": 131, - "column": 155, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 178, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 192, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 193, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 206, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 131, - "column": 181, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 206, - "program": "AccessNBody.ets" - } + "type": "NumberLiteral", + "value": 1.08279, + "loc": { + "start": { + "line": 131, + "column": 102, + "program": "AccessNBody.ets" + }, + "end": { + "line": 131, + "column": 153, + "program": "AccessNBody.ets" } - }, + } + }, + { + "type": "NumberLiteral", + "value": 0.868713, "loc": { "start": { "line": 131, @@ -14078,75 +13605,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": -2.9659e-05, - "loc": { - "start": { - "line": 131, - "column": 208, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 232, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 235, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 246, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 131, - "column": 247, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 260, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 131, - "column": 235, - "program": "AccessNBody.ets" - }, - "end": { - "line": 131, - "column": 260, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": -0.0108326, "loc": { "start": { "line": 131, @@ -14525,75 +13985,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.00268068, - "loc": { - "start": { - "line": 134, - "column": 101, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 124, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 127, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 138, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 139, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 152, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 134, - "column": 127, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 152, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": 0.979091, "loc": { "start": { "line": 134, @@ -14608,75 +14001,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.00162824, - "loc": { - "start": { - "line": 134, - "column": 154, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 177, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 180, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 191, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 192, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 205, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 134, - "column": 180, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 205, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": 0.594699, "loc": { "start": { "line": 134, @@ -14691,75 +14017,8 @@ } }, { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": -9.51592e-05, - "loc": { - "start": { - "line": 134, - "column": 207, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 231, - "program": "AccessNBody.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNBody", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 234, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 245, - "program": "AccessNBody.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "DAYS_PER_YEAR", - "decorators": [], - "loc": { - "start": { - "line": 134, - "column": 246, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 259, - "program": "AccessNBody.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 134, - "column": 234, - "program": "AccessNBody.ets" - }, - "end": { - "line": 134, - "column": 259, - "program": "AccessNBody.ets" - } - } - }, + "type": "NumberLiteral", + "value": -0.034756, "loc": { "start": { "line": 134, diff --git a/ets2panda/test/parser/ets/AccessNBody.ets b/ets2panda/test/parser/ets/AccessNBody.ets index 8a8f4db207..301cc6c552 100644 --- a/ets2panda/test/parser/ets/AccessNBody.ets +++ b/ets2panda/test/parser/ets/AccessNBody.ets @@ -50,7 +50,7 @@ class NBodySystem { let px : double = 0.0; let py : double = 0.0; let pz : double = 0.0; - let size : int = this.bodies.length as int; + let size : int = this.bodies.length.toInt(); for (let i : int = 0; i < size; i++) { let b : Body = this.bodies[i]; let m : double = b.mass; @@ -67,7 +67,7 @@ class NBodySystem { let dz : double ; let distance : double ; let mag : double ; - let size : int = this.bodies.length as int; + let size : int = this.bodies.length.toInt(); for (let i : int = 0; i < size; i++) { let bodyi : Body = this.bodies[i]; for (let j : int = i + 1; j < size; j++) { @@ -98,7 +98,7 @@ class NBodySystem { let dz : double ; let distance : double ; let e : double = 0.0; - let size : int = this.bodies.length as int; + let size : int = this.bodies.length.toInt(); for (let i : int = 0; i < size; i++) { let bodyi : Body = this.bodies[i]; e += 0.5 * bodyi.mass * (bodyi.vx * bodyi.vx + bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz); diff --git a/ets2panda/test/parser/ets/AccessNSieve-expected.txt b/ets2panda/test/parser/ets/AccessNSieve-expected.txt index bf181a0b4a..bca0f63108 100644 --- a/ets2panda/test/parser/ets/AccessNSieve-expected.txt +++ b/ets2panda/test/parser/ets/AccessNSieve-expected.txt @@ -513,178 +513,12 @@ } }, "dimension": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "BinaryExpression", - "operator": "<<", - "left": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 23, - "column": 41, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 42, - "program": "AccessNSieve.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNSieve", - "decorators": [], - "loc": { - "start": { - "line": 23, - "column": 46, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 58, - "program": "AccessNSieve.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n1", - "decorators": [], - "loc": { - "start": { - "line": 23, - "column": 59, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 61, - "program": "AccessNSieve.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 23, - "column": 46, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 61, - "program": "AccessNSieve.ets" - } - } - }, - "loc": { - "start": { - "line": 23, - "column": 40, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 62, - "program": "AccessNSieve.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNSieve", - "decorators": [], - "loc": { - "start": { - "line": 23, - "column": 65, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 77, - "program": "AccessNSieve.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n2", - "decorators": [], - "loc": { - "start": { - "line": 23, - "column": 78, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 80, - "program": "AccessNSieve.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 23, - "column": 65, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 80, - "program": "AccessNSieve.ets" - } - } - }, - "loc": { - "start": { - "line": 23, - "column": 40, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 80, - "program": "AccessNSieve.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 23, - "column": 83, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 23, - "column": 84, - "program": "AccessNSieve.ets" - } - } - }, + "type": "NumberLiteral", + "value": 80001, "loc": { "start": { "line": 23, - "column": 40, + "column": 65, "program": "AccessNSieve.ets" }, "end": { @@ -2395,43 +2229,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNSieve", - "decorators": [], - "loc": { - "start": { - "line": 46, - "column": 31, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 46, - "column": 43, - "program": "AccessNSieve.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n1", - "decorators": [], - "loc": { - "start": { - "line": 46, - "column": 44, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 46, - "column": 46, - "program": "AccessNSieve.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 3, "loc": { "start": { "line": 46, @@ -2585,43 +2384,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNSieve", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 31, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 47, - "column": 43, - "program": "AccessNSieve.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n2", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 44, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 47, - "column": 46, - "program": "AccessNSieve.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 10000, "loc": { "start": { "line": 47, @@ -3164,43 +2928,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "AccessNSieve", - "decorators": [], - "loc": { - "start": { - "line": 55, - "column": 19, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 55, - "column": 31, - "program": "AccessNSieve.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 55, - "column": 32, - "program": "AccessNSieve.ets" - }, - "end": { - "line": 55, - "column": 40, - "program": "AccessNSieve.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 14302, "loc": { "start": { "line": 55, diff --git a/ets2panda/test/parser/ets/Bitops3BitBitsInByte-expected.txt b/ets2panda/test/parser/ets/Bitops3BitBitsInByte-expected.txt index 978b8c3d6e..e7dfdc922e 100644 --- a/ets2panda/test/parser/ets/Bitops3BitBitsInByte-expected.txt +++ b/ets2panda/test/parser/ets/Bitops3BitBitsInByte-expected.txt @@ -1948,43 +1948,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Bitops3BitBitsInByte", - "decorators": [], - "loc": { - "start": { - "line": 37, - "column": 19, - "program": "Bitops3BitBitsInByte.ets" - }, - "end": { - "line": 37, - "column": 39, - "program": "Bitops3BitBitsInByte.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 37, - "column": 40, - "program": "Bitops3BitBitsInByte.ets" - }, - "end": { - "line": 37, - "column": 48, - "program": "Bitops3BitBitsInByte.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 512000, "loc": { "start": { "line": 37, diff --git a/ets2panda/test/parser/ets/BitopsBitsInByte-expected.txt b/ets2panda/test/parser/ets/BitopsBitsInByte-expected.txt index 19b23b72af..b3997a5659 100644 --- a/ets2panda/test/parser/ets/BitopsBitsInByte-expected.txt +++ b/ets2panda/test/parser/ets/BitopsBitsInByte-expected.txt @@ -1690,43 +1690,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "BitopsBitsInByte", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 19, - "program": "BitopsBitsInByte.ets" - }, - "end": { - "line": 40, - "column": 35, - "program": "BitopsBitsInByte.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 36, - "program": "BitopsBitsInByte.ets" - }, - "end": { - "line": 40, - "column": 44, - "program": "BitopsBitsInByte.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 358400, "loc": { "start": { "line": 40, diff --git a/ets2panda/test/parser/ets/BitopsBitwiseAnd-expected.txt b/ets2panda/test/parser/ets/BitopsBitwiseAnd-expected.txt index 26c14b0b75..8211a2bca8 100644 --- a/ets2panda/test/parser/ets/BitopsBitwiseAnd-expected.txt +++ b/ets2panda/test/parser/ets/BitopsBitwiseAnd-expected.txt @@ -681,43 +681,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "BitopsBitwiseAnd", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 31, - "program": "BitopsBitwiseAnd.ets" - }, - "end": { - "line": 26, - "column": 47, - "program": "BitopsBitwiseAnd.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 48, - "program": "BitopsBitwiseAnd.ets" - }, - "end": { - "line": 26, - "column": 56, - "program": "BitopsBitwiseAnd.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 0, "loc": { "start": { "line": 26, diff --git a/ets2panda/test/parser/ets/BitopsNSieveBits-expected.txt b/ets2panda/test/parser/ets/BitopsNSieveBits-expected.txt index 8b1ab7c272..9cac89a156 100644 --- a/ets2panda/test/parser/ets/BitopsNSieveBits-expected.txt +++ b/ets2panda/test/parser/ets/BitopsNSieveBits-expected.txt @@ -586,7 +586,7 @@ "loc": { "start": { "line": 20, - "column": 21, + "column": 25, "program": "BitopsNSieveBits.ets" }, "end": { @@ -2259,7 +2259,7 @@ "loc": { "start": { "line": 37, - "column": 34, + "column": 47, "program": "BitopsNSieveBits.ets" }, "end": { @@ -3559,43 +3559,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "BitopsNSieveBits", - "decorators": [], - "loc": { - "start": { - "line": 53, - "column": 19, - "program": "BitopsNSieveBits.ets" - }, - "end": { - "line": 53, - "column": 35, - "program": "BitopsNSieveBits.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 53, - "column": 36, - "program": "BitopsNSieveBits.ets" - }, - "end": { - "line": 53, - "column": 44, - "program": "BitopsNSieveBits.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": -1286749544853, "loc": { "start": { "line": 53, diff --git a/ets2panda/test/parser/ets/ControlFlowRecursive-expected.txt b/ets2panda/test/parser/ets/ControlFlowRecursive-expected.txt index a2e875bc56..e9b661d180 100644 --- a/ets2panda/test/parser/ets/ControlFlowRecursive-expected.txt +++ b/ets2panda/test/parser/ets/ControlFlowRecursive-expected.txt @@ -2756,43 +2756,8 @@ } }, "init": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "ControlFlowRecursive", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 23, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 47, - "column": 43, - "program": "ControlFlowRecursive.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n1", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 44, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 47, - "column": 46, - "program": "ControlFlowRecursive.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 3, "loc": { "start": { "line": 47, @@ -2855,43 +2820,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "ControlFlowRecursive", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 53, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 47, - "column": 73, - "program": "ControlFlowRecursive.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n2", - "decorators": [], - "loc": { - "start": { - "line": 47, - "column": 74, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 47, - "column": 76, - "program": "ControlFlowRecursive.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 5, "loc": { "start": { "line": 47, @@ -3418,7 +3348,7 @@ "loc": { "start": { "line": 50, - "column": 42, + "column": 46, "program": "ControlFlowRecursive.ets" }, "end": { @@ -3499,7 +3429,7 @@ "loc": { "start": { "line": 50, - "column": 53, + "column": 57, "program": "ControlFlowRecursive.ets" }, "end": { @@ -3666,43 +3596,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "ControlFlowRecursive", - "decorators": [], - "loc": { - "start": { - "line": 53, - "column": 22, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 53, - "column": 42, - "program": "ControlFlowRecursive.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 53, - "column": 43, - "program": "ControlFlowRecursive.ets" - }, - "end": { - "line": 53, - "column": 51, - "program": "ControlFlowRecursive.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 57775, "loc": { "start": { "line": 53, diff --git a/ets2panda/test/parser/ets/MathCordic-expected.txt b/ets2panda/test/parser/ets/MathCordic-expected.txt index c0750d7e2c..254da34932 100644 --- a/ets2panda/test/parser/ets/MathCordic-expected.txt +++ b/ets2panda/test/parser/ets/MathCordic-expected.txt @@ -2720,43 +2720,8 @@ "type": "BinaryExpression", "operator": "*", "left": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathCordic", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 32, - "program": "MathCordic.ets" - }, - "end": { - "line": 40, - "column": 42, - "program": "MathCordic.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "AG_CONST", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 43, - "program": "MathCordic.ets" - }, - "end": { - "line": 40, - "column": 51, - "program": "MathCordic.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 0.607253, "loc": { "start": { "line": 40, @@ -3278,39 +3243,60 @@ "type": "BinaryExpression", "operator": ">>", "left": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "y", - "decorators": [], - "loc": { - "start": { - "line": 45, - "column": 29, - "program": "MathCordic.ets" - }, - "end": { - "line": 45, - "column": 30, - "program": "MathCordic.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "y", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 29, + "program": "MathCordic.ets" + }, + "end": { + "line": 45, + "column": 30, + "program": "MathCordic.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 45, + "column": 31, + "program": "MathCordic.ets" + }, + "end": { + "line": 45, + "column": 36, + "program": "MathCordic.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 45, - "column": 34, + "column": 29, "program": "MathCordic.ets" }, "end": { "line": 45, - "column": 37, + "column": 36, "program": "MathCordic.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 45, @@ -3319,7 +3305,7 @@ }, "end": { "line": 45, - "column": 30, + "column": 38, "program": "MathCordic.ets" } } @@ -3331,12 +3317,12 @@ "loc": { "start": { "line": 45, - "column": 41, + "column": 42, "program": "MathCordic.ets" }, "end": { "line": 45, - "column": 45, + "column": 46, "program": "MathCordic.ets" } } @@ -3349,7 +3335,7 @@ }, "end": { "line": 45, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3362,7 +3348,7 @@ }, "end": { "line": 45, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3375,7 +3361,7 @@ }, "end": { "line": 45, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3388,7 +3374,7 @@ }, "end": { "line": 45, - "column": 47, + "column": 48, "program": "MathCordic.ets" } } @@ -3422,39 +3408,60 @@ "type": "BinaryExpression", "operator": ">>", "left": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "x", - "decorators": [], - "loc": { - "start": { - "line": 46, - "column": 22, - "program": "MathCordic.ets" - }, - "end": { - "line": 46, - "column": 23, - "program": "MathCordic.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 46, + "column": 22, + "program": "MathCordic.ets" + }, + "end": { + "line": 46, + "column": 23, + "program": "MathCordic.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 46, + "column": 24, + "program": "MathCordic.ets" + }, + "end": { + "line": 46, + "column": 29, + "program": "MathCordic.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 46, - "column": 27, + "column": 22, "program": "MathCordic.ets" }, "end": { "line": 46, - "column": 30, + "column": 29, "program": "MathCordic.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 46, @@ -3463,7 +3470,7 @@ }, "end": { "line": 46, - "column": 23, + "column": 31, "program": "MathCordic.ets" } } @@ -3475,12 +3482,12 @@ "loc": { "start": { "line": 46, - "column": 34, + "column": 35, "program": "MathCordic.ets" }, "end": { "line": 46, - "column": 38, + "column": 39, "program": "MathCordic.ets" } } @@ -3493,7 +3500,7 @@ }, "end": { "line": 46, - "column": 39, + "column": 40, "program": "MathCordic.ets" } } @@ -3505,12 +3512,12 @@ "loc": { "start": { "line": 46, - "column": 42, + "column": 43, "program": "MathCordic.ets" }, "end": { "line": 46, - "column": 43, + "column": 44, "program": "MathCordic.ets" } } @@ -3523,7 +3530,7 @@ }, "end": { "line": 46, - "column": 43, + "column": 44, "program": "MathCordic.ets" } } @@ -3536,7 +3543,7 @@ }, "end": { "line": 46, - "column": 43, + "column": 44, "program": "MathCordic.ets" } } @@ -3549,7 +3556,7 @@ }, "end": { "line": 46, - "column": 44, + "column": 45, "program": "MathCordic.ets" } } @@ -3815,39 +3822,60 @@ "type": "BinaryExpression", "operator": ">>", "left": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "y", - "decorators": [], - "loc": { - "start": { - "line": 51, - "column": 29, - "program": "MathCordic.ets" - }, - "end": { - "line": 51, - "column": 30, - "program": "MathCordic.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "y", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 29, + "program": "MathCordic.ets" + }, + "end": { + "line": 51, + "column": 30, + "program": "MathCordic.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 51, + "column": 31, + "program": "MathCordic.ets" + }, + "end": { + "line": 51, + "column": 36, + "program": "MathCordic.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 51, - "column": 34, + "column": 29, "program": "MathCordic.ets" }, "end": { "line": 51, - "column": 37, + "column": 36, "program": "MathCordic.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 51, @@ -3856,7 +3884,7 @@ }, "end": { "line": 51, - "column": 30, + "column": 38, "program": "MathCordic.ets" } } @@ -3868,12 +3896,12 @@ "loc": { "start": { "line": 51, - "column": 41, + "column": 42, "program": "MathCordic.ets" }, "end": { "line": 51, - "column": 45, + "column": 46, "program": "MathCordic.ets" } } @@ -3886,7 +3914,7 @@ }, "end": { "line": 51, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3899,7 +3927,7 @@ }, "end": { "line": 51, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3912,7 +3940,7 @@ }, "end": { "line": 51, - "column": 46, + "column": 47, "program": "MathCordic.ets" } } @@ -3925,7 +3953,7 @@ }, "end": { "line": 51, - "column": 47, + "column": 48, "program": "MathCordic.ets" } } @@ -3963,39 +3991,60 @@ "type": "BinaryExpression", "operator": ">>", "left": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "x", - "decorators": [], - "loc": { - "start": { - "line": 52, - "column": 23, - "program": "MathCordic.ets" - }, - "end": { - "line": 52, - "column": 24, - "program": "MathCordic.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "x", + "decorators": [], + "loc": { + "start": { + "line": 52, + "column": 23, + "program": "MathCordic.ets" + }, + "end": { + "line": 52, + "column": 24, + "program": "MathCordic.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 52, + "column": 25, + "program": "MathCordic.ets" + }, + "end": { + "line": 52, + "column": 30, + "program": "MathCordic.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 52, - "column": 28, + "column": 23, "program": "MathCordic.ets" }, "end": { "line": 52, - "column": 31, + "column": 30, "program": "MathCordic.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 52, @@ -4004,7 +4053,7 @@ }, "end": { "line": 52, - "column": 24, + "column": 32, "program": "MathCordic.ets" } } @@ -4016,12 +4065,12 @@ "loc": { "start": { "line": 52, - "column": 35, + "column": 36, "program": "MathCordic.ets" }, "end": { "line": 52, - "column": 39, + "column": 40, "program": "MathCordic.ets" } } @@ -4034,7 +4083,7 @@ }, "end": { "line": 52, - "column": 40, + "column": 41, "program": "MathCordic.ets" } } @@ -4047,7 +4096,7 @@ }, "end": { "line": 52, - "column": 40, + "column": 41, "program": "MathCordic.ets" } } @@ -4059,12 +4108,12 @@ "loc": { "start": { "line": 52, - "column": 43, + "column": 44, "program": "MathCordic.ets" }, "end": { "line": 52, - "column": 44, + "column": 45, "program": "MathCordic.ets" } } @@ -4077,7 +4126,7 @@ }, "end": { "line": 52, - "column": 44, + "column": 45, "program": "MathCordic.ets" } } @@ -4090,7 +4139,7 @@ }, "end": { "line": 52, - "column": 44, + "column": 45, "program": "MathCordic.ets" } } @@ -4103,7 +4152,7 @@ }, "end": { "line": 52, - "column": 45, + "column": 46, "program": "MathCordic.ets" } } @@ -5061,43 +5110,8 @@ }, "arguments": [ { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathCordic", - "decorators": [], - "loc": { - "start": { - "line": 63, - "column": 46, - "program": "MathCordic.ets" - }, - "end": { - "line": 63, - "column": 56, - "program": "MathCordic.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TARGET_ANGLE", - "decorators": [], - "loc": { - "start": { - "line": 63, - "column": 57, - "program": "MathCordic.ets" - }, - "end": { - "line": 63, - "column": 69, - "program": "MathCordic.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 28.027, "loc": { "start": { "line": 63, @@ -5707,43 +5721,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathCordic", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 25, - "program": "MathCordic.ets" - }, - "end": { - "line": 74, - "column": 35, - "program": "MathCordic.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 36, - "program": "MathCordic.ets" - }, - "end": { - "line": 74, - "column": 44, - "program": "MathCordic.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 10362.6, "loc": { "start": { "line": 74, diff --git a/ets2panda/test/parser/ets/MathCordic.ets b/ets2panda/test/parser/ets/MathCordic.ets index d220821ffc..bc078eaca7 100644 --- a/ets2panda/test/parser/ets/MathCordic.ets +++ b/ets2panda/test/parser/ets/MathCordic.ets @@ -42,14 +42,14 @@ export class MathCordic { for (step = 0; step < 12; step++) { let newX : double ; if (targetAngle > currAngle) { - newX = x - (y as int >> step); - y = (x as int >> step) + y; + newX = x - (y.toInt() >> step); + y = (x.toInt() >> step) + y; x = newX; currAngle += MathCordic.ANGLES[step]; } else { - newX = x + (y as int >> step); - y = -(x as int >> step) + y; + newX = x + (y.toInt() >> step); + y = -(x.toInt() >> step) + y; x = newX; currAngle -= MathCordic.ANGLES[step]; } diff --git a/ets2panda/test/parser/ets/MathPartialSums-expected.txt b/ets2panda/test/parser/ets/MathPartialSums-expected.txt index 5f16c7c110..7c3bcccd35 100644 --- a/ets2panda/test/parser/ets/MathPartialSums-expected.txt +++ b/ets2panda/test/parser/ets/MathPartialSums-expected.txt @@ -1190,40 +1190,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 33, - "column": 29, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 33, - "column": 32, - "program": "MathPartialSums.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 33, - "column": 35, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 33, - "column": 38, - "program": "MathPartialSums.ets" - } - } - }, + "type": "NumberLiteral", + "value": 0.666667, "loc": { "start": { "line": 33, @@ -3734,7 +3702,7 @@ "loc": { "start": { "line": 59, - "column": 11, + "column": 16, "program": "MathPartialSums.ets" }, "end": { @@ -4202,7 +4170,7 @@ "loc": { "start": { "line": 69, - "column": 12, + "column": 17, "program": "MathPartialSums.ets" }, "end": { @@ -4498,43 +4466,8 @@ } }, "init": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathPartialSums", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 23, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 74, - "column": 38, - "program": "MathPartialSums.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n1", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 39, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 74, - "column": 41, - "program": "MathPartialSums.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 1024, "loc": { "start": { "line": 74, @@ -4597,43 +4530,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathPartialSums", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 48, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 74, - "column": 63, - "program": "MathPartialSums.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n2", - "decorators": [], - "loc": { - "start": { - "line": 74, - "column": 64, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 74, - "column": 66, - "program": "MathPartialSums.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 16384, "loc": { "start": { "line": 74, @@ -4913,43 +4811,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathPartialSums", - "decorators": [], - "loc": { - "start": { - "line": 78, - "column": 19, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 78, - "column": 34, - "program": "MathPartialSums.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 78, - "column": 35, - "program": "MathPartialSums.ets" - }, - "end": { - "line": 78, - "column": 43, - "program": "MathPartialSums.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 60.0899, "loc": { "start": { "line": 78, @@ -5169,7 +5032,7 @@ "loc": { "start": { "line": 79, - "column": 14, + "column": 40, "program": "MathPartialSums.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/MathSpectralNorm-expected.txt b/ets2panda/test/parser/ets/MathSpectralNorm-expected.txt index 23db51eb62..bb875c96e8 100644 --- a/ets2panda/test/parser/ets/MathSpectralNorm-expected.txt +++ b/ets2panda/test/parser/ets/MathSpectralNorm-expected.txt @@ -6832,43 +6832,8 @@ } }, { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "MathSpectralNorm", - "decorators": [], - "loc": { - "start": { - "line": 87, - "column": 21, - "program": "MathSpectralNorm.ets" - }, - "end": { - "line": 87, - "column": 37, - "program": "MathSpectralNorm.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "expected", - "decorators": [], - "loc": { - "start": { - "line": 87, - "column": 38, - "program": "MathSpectralNorm.ets" - }, - "end": { - "line": 87, - "column": 46, - "program": "MathSpectralNorm.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 5.08669, "loc": { "start": { "line": 87, diff --git a/ets2panda/test/parser/ets/Morph3d-expected.txt b/ets2panda/test/parser/ets/Morph3d-expected.txt index 1ad08a5f9f..e915efc571 100644 --- a/ets2panda/test/parser/ets/Morph3d-expected.txt +++ b/ets2panda/test/parser/ets/Morph3d-expected.txt @@ -524,146 +524,12 @@ } }, "dimension": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 28, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 35, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 36, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 41, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 26, - "column": 28, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 41, - "program": "Morph3d.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 44, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 51, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 52, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 57, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 26, - "column": 44, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 57, - "program": "Morph3d.ets" - } - } - }, - "loc": { - "start": { - "line": 26, - "column": 28, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 57, - "program": "Morph3d.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 26, - "column": 60, - "program": "Morph3d.ets" - }, - "end": { - "line": 26, - "column": 61, - "program": "Morph3d.ets" - } - } - }, + "type": "NumberLiteral", + "value": 43200, "loc": { "start": { "line": 26, - "column": 28, + "column": 44, "program": "Morph3d.ets" }, "end": { @@ -816,146 +682,12 @@ } }, "right": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 30, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 37, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 38, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 43, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 27, - "column": 30, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 43, - "program": "Morph3d.ets" - } - } - }, - "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 46, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 53, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 54, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 59, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, - "loc": { - "start": { - "line": 27, - "column": 46, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 59, - "program": "Morph3d.ets" - } - } - }, - "loc": { - "start": { - "line": 27, - "column": 30, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 59, - "program": "Morph3d.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 27, - "column": 62, - "program": "Morph3d.ets" - }, - "end": { - "line": 27, - "column": 63, - "program": "Morph3d.ets" - } - } - }, + "type": "NumberLiteral", + "value": 43200, "loc": { "start": { "line": 27, - "column": 30, + "column": 46, "program": "Morph3d.ets" }, "end": { @@ -1434,43 +1166,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 33, - "column": 39, - "program": "Morph3d.ets" - }, - "end": { - "line": 33, - "column": 46, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 33, - "column": 47, - "program": "Morph3d.ets" - }, - "end": { - "line": 33, - "column": 52, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 33, @@ -1487,7 +1184,7 @@ "loc": { "start": { "line": 33, - "column": 30, + "column": 35, "program": "Morph3d.ets" }, "end": { @@ -1677,7 +1374,7 @@ "loc": { "start": { "line": 34, - "column": 36, + "column": 40, "program": "Morph3d.ets" }, "end": { @@ -1860,43 +1557,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 36, - "column": 31, - "program": "Morph3d.ets" - }, - "end": { - "line": 36, - "column": 38, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 36, - "column": 39, - "program": "Morph3d.ets" - }, - "end": { - "line": 36, - "column": 44, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 36, @@ -2064,43 +1726,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 37, - "column": 32, - "program": "Morph3d.ets" - }, - "end": { - "line": 37, - "column": 39, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 37, - "column": 40, - "program": "Morph3d.ets" - }, - "end": { - "line": 37, - "column": 45, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 37, @@ -2268,43 +1895,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 38, - "column": 28, - "program": "Morph3d.ets" - }, - "end": { - "line": 38, - "column": 35, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 38, - "column": 36, - "program": "Morph3d.ets" - }, - "end": { - "line": 38, - "column": 41, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 38, @@ -2825,43 +2417,8 @@ } }, "init": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 44, - "column": 22, - "program": "Morph3d.ets" - }, - "end": { - "line": 44, - "column": 29, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "n", - "decorators": [], - "loc": { - "start": { - "line": 44, - "column": 30, - "program": "Morph3d.ets" - }, - "end": { - "line": 44, - "column": 31, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 15, "loc": { "start": { "line": 44, @@ -3417,43 +2974,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 50, - "column": 30, - "program": "Morph3d.ets" - }, - "end": { - "line": 50, - "column": 37, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 50, - "column": 38, - "program": "Morph3d.ets" - }, - "end": { - "line": 50, - "column": 43, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 50, @@ -3638,43 +3160,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Morph3d", - "decorators": [], - "loc": { - "start": { - "line": 51, - "column": 40, - "program": "Morph3d.ets" - }, - "end": { - "line": 51, - "column": 47, - "program": "Morph3d.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "param", - "decorators": [], - "loc": { - "start": { - "line": 51, - "column": 48, - "program": "Morph3d.ets" - }, - "end": { - "line": 51, - "column": 53, - "program": "Morph3d.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "NumberLiteral", + "value": 120, "loc": { "start": { "line": 51, diff --git a/ets2panda/test/parser/ets/StringBase64-expected.txt b/ets2panda/test/parser/ets/StringBase64-expected.txt index a307f1139e..2c100f3ec5 100644 --- a/ets2panda/test/parser/ets/StringBase64-expected.txt +++ b/ets2panda/test/parser/ets/StringBase64-expected.txt @@ -2759,13 +2759,47 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "Identifier", - "name": "data", - "decorators": [], + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "data", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 28, + "program": "StringBase64.ets" + }, + "end": { + "line": 22, + "column": 32, + "program": "StringBase64.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "length", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 33, + "program": "StringBase64.ets" + }, + "end": { + "line": 22, + "column": 39, + "program": "StringBase64.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 22, @@ -2774,24 +2808,24 @@ }, "end": { "line": 22, - "column": 32, + "column": 39, "program": "StringBase64.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 22, - "column": 33, + "column": 40, "program": "StringBase64.ets" }, "end": { "line": 22, - "column": 39, + "column": 45, "program": "StringBase64.ets" } } @@ -2806,26 +2840,13 @@ }, "end": { "line": 22, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 22, - "column": 43, - "program": "StringBase64.ets" - }, - "end": { - "line": 22, - "column": 46, + "column": 45, "program": "StringBase64.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 22, @@ -2834,7 +2855,7 @@ }, "end": { "line": 22, - "column": 39, + "column": 47, "program": "StringBase64.ets" } } @@ -2847,7 +2868,7 @@ }, "end": { "line": 22, - "column": 39, + "column": 47, "program": "StringBase64.ets" } } @@ -2862,7 +2883,7 @@ }, "end": { "line": 22, - "column": 47, + "column": 48, "program": "StringBase64.ets" } } @@ -3179,43 +3200,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 27, - "program": "StringBase64.ets" - }, - "end": { - "line": 25, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 40, - "program": "StringBase64.ets" - }, - "end": { - "line": 25, - "column": 55, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 25, @@ -3484,43 +3470,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 27, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 40, - "program": "StringBase64.ets" - }, - "end": { - "line": 26, - "column": 55, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 26, @@ -3987,43 +3938,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 27, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 40, - "program": "StringBase64.ets" - }, - "end": { - "line": 27, - "column": 55, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 27, @@ -4522,43 +4438,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 28, - "column": 27, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 28, - "column": 40, - "program": "StringBase64.ets" - }, - "end": { - "line": 28, - "column": 55, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 28, @@ -4898,7 +4779,7 @@ "loc": { "start": { "line": 30, - "column": 13, + "column": 22, "program": "StringBase64.ets" }, "end": { @@ -5102,43 +4983,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 32, - "column": 27, - "program": "StringBase64.ets" - }, - "end": { - "line": 32, - "column": 39, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 32, - "column": 40, - "program": "StringBase64.ets" - }, - "end": { - "line": 32, - "column": 55, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 32, @@ -5493,43 +5339,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 34, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 34, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 34, - "column": 59, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 34, @@ -5996,43 +5807,8 @@ "callee": { "type": "MemberExpression", "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 35, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 35, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 35, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 35, - "column": 59, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 35, @@ -6361,43 +6137,8 @@ }, "arguments": [ { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 36, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 36, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BASE64PAD", - "decorators": [], - "loc": { - "start": { - "line": 36, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 36, - "column": 53, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "=", "loc": { "start": { "line": 36, @@ -6502,58 +6243,23 @@ "start": { "line": 39, "column": 17, - "program": "StringBase64.ets" - }, - "end": { - "line": 39, - "column": 30, - "program": "StringBase64.ets" - } - } - }, - "arguments": [ - { - "type": "CallExpression", - "callee": { - "type": "MemberExpression", - "object": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 39, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 39, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "TO_BASE64_TABLE", - "decorators": [], - "loc": { - "start": { - "line": 39, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 39, - "column": 59, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "program": "StringBase64.ets" + }, + "end": { + "line": 39, + "column": 30, + "program": "StringBase64.ets" + } + } + }, + "arguments": [ + { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "StringLiteral", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "loc": { "start": { "line": 39, @@ -6850,43 +6556,8 @@ }, "arguments": [ { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 40, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BASE64PAD", - "decorators": [], - "loc": { - "start": { - "line": 40, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 40, - "column": 53, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "=", "loc": { "start": { "line": 40, @@ -6985,43 +6656,8 @@ }, "arguments": [ { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 41, - "column": 31, - "program": "StringBase64.ets" - }, - "end": { - "line": 41, - "column": 43, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BASE64PAD", - "decorators": [], - "loc": { - "start": { - "line": 41, - "column": 44, - "program": "StringBase64.ets" - }, - "end": { - "line": 41, - "column": 53, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "=", "loc": { "start": { "line": 41, @@ -8339,43 +7975,8 @@ } }, "right": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "StringBase64", - "decorators": [], - "loc": { - "start": { - "line": 52, - "column": 55, - "program": "StringBase64.ets" - }, - "end": { - "line": 52, - "column": 67, - "program": "StringBase64.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BASE64PAD", - "decorators": [], - "loc": { - "start": { - "line": 52, - "column": 68, - "program": "StringBase64.ets" - }, - "end": { - "line": 52, - "column": 77, - "program": "StringBase64.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "=", "loc": { "start": { "line": 52, @@ -8936,43 +8537,74 @@ }, "arguments": [ { - "type": "TSAsExpression", - "expression": { - "type": "BinaryExpression", - "operator": "&", - "left": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { "type": "BinaryExpression", - "operator": ">>", + "operator": "&", "left": { - "type": "Identifier", - "name": "leftdata", - "decorators": [], + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "leftdata", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 37, + "program": "StringBase64.ets" + }, + "end": { + "line": 61, + "column": 45, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "Identifier", + "name": "leftbits", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 49, + "program": "StringBase64.ets" + }, + "end": { + "line": 61, + "column": 57, + "program": "StringBase64.ets" + } + } + }, "loc": { "start": { "line": 61, - "column": 37, + "column": 36, "program": "StringBase64.ets" }, "end": { "line": 61, - "column": 45, + "column": 58, "program": "StringBase64.ets" } } }, "right": { - "type": "Identifier", - "name": "leftbits", - "decorators": [], + "type": "NumberLiteral", + "value": 255, "loc": { "start": { "line": 61, - "column": 49, + "column": 61, "program": "StringBase64.ets" }, "end": { "line": 61, - "column": 57, + "column": 65, "program": "StringBase64.ets" } } @@ -8980,32 +8612,35 @@ "loc": { "start": { "line": 61, - "column": 36, + "column": 35, "program": "StringBase64.ets" }, "end": { "line": 61, - "column": 58, + "column": 66, "program": "StringBase64.ets" } } }, - "right": { - "type": "NumberLiteral", - "value": 255, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], "loc": { "start": { "line": 61, - "column": 61, + "column": 67, "program": "StringBase64.ets" }, "end": { "line": 61, - "column": 65, + "column": 73, "program": "StringBase64.ets" } } }, + "computed": false, + "optional": false, "loc": { "start": { "line": 61, @@ -9014,26 +8649,13 @@ }, "end": { "line": 61, - "column": 66, - "program": "StringBase64.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 61, - "column": 70, - "program": "StringBase64.ets" - }, - "end": { - "line": 61, - "column": 74, + "column": 73, "program": "StringBase64.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 61, @@ -9042,7 +8664,7 @@ }, "end": { "line": 61, - "column": 66, + "column": 75, "program": "StringBase64.ets" } } @@ -9057,7 +8679,7 @@ }, "end": { "line": 61, - "column": 75, + "column": 76, "program": "StringBase64.ets" } } @@ -9070,7 +8692,7 @@ }, "end": { "line": 61, - "column": 76, + "column": 77, "program": "StringBase64.ets" } } @@ -10053,35 +9675,52 @@ } }, "right": { - "type": "TSAsExpression", - "expression": { - "type": "BinaryExpression", - "operator": "+", - "left": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { "type": "BinaryExpression", - "operator": "*", + "operator": "+", "left": { - "type": "NumberLiteral", - "value": 25, - "loc": { - "start": { - "line": 75, - "column": 22, - "program": "StringBase64.ets" - }, - "end": { - "line": 75, - "column": 24, - "program": "StringBase64.ets" + "type": "BinaryExpression", + "operator": "*", + "left": { + "type": "NumberLiteral", + "value": 25, + "loc": { + "start": { + "line": 75, + "column": 22, + "program": "StringBase64.ets" + }, + "end": { + "line": 75, + "column": 24, + "program": "StringBase64.ets" + } } - } - }, - "right": { - "type": "CallExpression", - "callee": { - "type": "Identifier", - "name": "random", - "decorators": [], + }, + "right": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "random", + "decorators": [], + "loc": { + "start": { + "line": 75, + "column": 27, + "program": "StringBase64.ets" + }, + "end": { + "line": 75, + "column": 33, + "program": "StringBase64.ets" + } + } + }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 75, @@ -10090,22 +9729,36 @@ }, "end": { "line": 75, - "column": 33, + "column": 35, "program": "StringBase64.ets" } } }, - "arguments": [], - "optional": false, "loc": { "start": { "line": 75, - "column": 27, + "column": 21, "program": "StringBase64.ets" }, "end": { "line": 75, - "column": 35, + "column": 36, + "program": "StringBase64.ets" + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 97, + "loc": { + "start": { + "line": 75, + "column": 39, + "program": "StringBase64.ets" + }, + "end": { + "line": 75, + "column": 41, "program": "StringBase64.ets" } } @@ -10113,32 +9766,35 @@ "loc": { "start": { "line": 75, - "column": 21, + "column": 20, "program": "StringBase64.ets" }, "end": { "line": 75, - "column": 36, + "column": 42, "program": "StringBase64.ets" } } }, - "right": { - "type": "NumberLiteral", - "value": 97, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], "loc": { "start": { "line": 75, - "column": 39, + "column": 43, "program": "StringBase64.ets" }, "end": { "line": 75, - "column": 41, + "column": 49, "program": "StringBase64.ets" } } }, + "computed": false, + "optional": false, "loc": { "start": { "line": 75, @@ -10147,26 +9803,13 @@ }, "end": { "line": 75, - "column": 42, - "program": "StringBase64.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 75, - "column": 46, - "program": "StringBase64.ets" - }, - "end": { - "line": 75, - "column": 50, + "column": 49, "program": "StringBase64.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 75, @@ -10175,7 +9818,7 @@ }, "end": { "line": 75, - "column": 42, + "column": 51, "program": "StringBase64.ets" } } @@ -10188,7 +9831,7 @@ }, "end": { "line": 75, - "column": 42, + "column": 51, "program": "StringBase64.ets" } } @@ -10201,7 +9844,7 @@ }, "end": { "line": 75, - "column": 51, + "column": 52, "program": "StringBase64.ets" } } diff --git a/ets2panda/test/parser/ets/StringBase64.ets b/ets2panda/test/parser/ets/StringBase64.ets index 7503ead1b9..ef1feaad3d 100644 --- a/ets2panda/test/parser/ets/StringBase64.ets +++ b/ets2panda/test/parser/ets/StringBase64.ets @@ -19,7 +19,7 @@ export class StringBase64 { static readonly TO_BINARY_TABLE : int[] = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; toBase64(data : String): String { let result : StringBuilder = new StringBuilder(); - let length : int = data.length as int; + let length : int = data.length.toInt(); let i : int ; for (i = 0; i < (length - 2); i += 3) { result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i) >> 2)); @@ -58,7 +58,7 @@ export class StringBase64 { if (leftbits >= 8) { leftbits -= 8; if (!padding) { - result.append(((leftdata >> leftbits) & 0xff) as char); + result.append(((leftdata >> leftbits) & 0xff).toChar()); } leftdata &= (1 << leftbits) - 1; } @@ -72,7 +72,7 @@ export class StringBase64 { public run(): void { let str : String = ""; for (let i : int = 0; i < this.n1; i++) { - str += ((25 * random()) + 97) as char; + str += ((25 * random()) + 97).toChar(); } for (let i : int = this.n1; i <= this.n2; i *= 2) { let base64 : String = this.toBase64(str); diff --git a/ets2panda/test/parser/ets/assert-expected.txt b/ets2panda/test/parser/ets/assert-expected.txt index 223e74ab3f..b1044004b9 100644 --- a/ets2panda/test/parser/ets/assert-expected.txt +++ b/ets2panda/test/parser/ets/assert-expected.txt @@ -431,7 +431,7 @@ "loc": { "start": { "line": 20, - "column": 20, + "column": 24, "program": "assert.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/assign-expected.txt b/ets2panda/test/parser/ets/assign-expected.txt index b6142a4897..98ef7bde5d 100644 --- a/ets2panda/test/parser/ets/assign-expected.txt +++ b/ets2panda/test/parser/ets/assign-expected.txt @@ -397,9 +397,8 @@ } }, "right": { - "type": "Identifier", - "name": "b", - "decorators": [], + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/binary_op-expected.txt b/ets2panda/test/parser/ets/binary_op-expected.txt index 6ee5608b7e..66494fa2c3 100644 --- a/ets2panda/test/parser/ets/binary_op-expected.txt +++ b/ets2panda/test/parser/ets/binary_op-expected.txt @@ -806,7 +806,7 @@ "loc": { "start": { "line": 26, - "column": 10, + "column": 16, "program": "binary_op.ets" }, "end": { @@ -1136,7 +1136,7 @@ "loc": { "start": { "line": 31, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -1300,7 +1300,7 @@ "loc": { "start": { "line": 32, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -1464,7 +1464,7 @@ "loc": { "start": { "line": 33, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -1645,7 +1645,7 @@ "loc": { "start": { "line": 34, - "column": 17, + "column": 23, "program": "binary_op.ets" }, "end": { @@ -2119,7 +2119,7 @@ "loc": { "start": { "line": 40, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -3522,7 +3522,7 @@ "loc": { "start": { "line": 59, - "column": 11, + "column": 16, "program": "binary_op.ets" }, "end": { @@ -3882,7 +3882,7 @@ "loc": { "start": { "line": 64, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -4346,7 +4346,7 @@ "loc": { "start": { "line": 70, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -4600,7 +4600,7 @@ "loc": { "start": { "line": 73, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -4734,7 +4734,7 @@ "loc": { "start": { "line": 74, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -4919,7 +4919,7 @@ "loc": { "start": { "line": 75, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -5738,7 +5738,7 @@ "loc": { "start": { "line": 77, - "column": 17, + "column": 23, "program": "binary_op.ets" }, "end": { @@ -6470,7 +6470,7 @@ "loc": { "start": { "line": 26, - "column": 10, + "column": 16, "program": "binary_op.ets" }, "end": { @@ -6776,7 +6776,7 @@ "loc": { "start": { "line": 31, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -6932,7 +6932,7 @@ "loc": { "start": { "line": 32, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -7088,7 +7088,7 @@ "loc": { "start": { "line": 33, - "column": 11, + "column": 17, "program": "binary_op.ets" }, "end": { @@ -7261,7 +7261,7 @@ "loc": { "start": { "line": 34, - "column": 17, + "column": 23, "program": "binary_op.ets" }, "end": { @@ -7703,7 +7703,7 @@ "loc": { "start": { "line": 40, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -9002,7 +9002,7 @@ "loc": { "start": { "line": 59, - "column": 11, + "column": 16, "program": "binary_op.ets" }, "end": { @@ -9338,7 +9338,7 @@ "loc": { "start": { "line": 64, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -9770,7 +9770,7 @@ "loc": { "start": { "line": 70, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -10016,7 +10016,7 @@ "loc": { "start": { "line": 73, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -10142,7 +10142,7 @@ "loc": { "start": { "line": 74, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -10319,7 +10319,7 @@ "loc": { "start": { "line": 75, - "column": 11, + "column": 15, "program": "binary_op.ets" }, "end": { @@ -11122,7 +11122,7 @@ "loc": { "start": { "line": 77, - "column": 17, + "column": 23, "program": "binary_op.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/binary_operations-expected.txt b/ets2panda/test/parser/ets/binary_operations-expected.txt index b720e56330..e456b8b907 100644 --- a/ets2panda/test/parser/ets/binary_operations-expected.txt +++ b/ets2panda/test/parser/ets/binary_operations-expected.txt @@ -44,40 +44,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 17, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 17, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 17, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 17, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 5, "loc": { "start": { "line": 17, @@ -147,104 +115,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 18, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 18, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 4, - "loc": { - "start": { - "line": 18, - "column": 34, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 35, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 18, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 35, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 18, - "column": 38, - "program": "binary_operations.ets" - }, - "end": { - "line": 18, - "column": 39, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 18, @@ -314,40 +186,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 19, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 19, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 19, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 19, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 5, "loc": { "start": { "line": 19, @@ -417,76 +257,12 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 20, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 20, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 20, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 20, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 20, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 20, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 20, - "column": 34, - "program": "binary_operations.ets" - }, - "end": { - "line": 20, - "column": 35, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 13, "loc": { "start": { "line": 20, - "column": 26, + "column": 30, "program": "binary_operations.ets" }, "end": { @@ -552,40 +328,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 21, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 21, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 21, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 21, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 21, @@ -655,108 +399,12 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 22, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 22, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 22, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 22, - "column": 34, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 35, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 22, - "column": 38, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 39, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 22, - "column": 34, - "program": "binary_operations.ets" - }, - "end": { - "line": 22, - "column": 39, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": -14, "loc": { "start": { "line": 22, - "column": 26, + "column": 30, "program": "binary_operations.ets" }, "end": { @@ -822,40 +470,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 6.2, - "loc": { - "start": { - "line": 23, - "column": 29, - "program": "binary_operations.ets" - }, - "end": { - "line": 23, - "column": 32, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3.14, - "loc": { - "start": { - "line": 23, - "column": 35, - "program": "binary_operations.ets" - }, - "end": { - "line": 23, - "column": 39, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 19.468, "loc": { "start": { "line": 23, @@ -864,7 +480,7 @@ }, "end": { "line": 23, - "column": 39, + "column": 41, "program": "binary_operations.ets" } } @@ -900,7 +516,7 @@ }, "end": { "line": 23, - "column": 39, + "column": 41, "program": "binary_operations.ets" } } @@ -925,104 +541,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 6.2, - "loc": { - "start": { - "line": 24, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 33, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 3.7, - "loc": { - "start": { - "line": 24, - "column": 37, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 40, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8.18, - "loc": { - "start": { - "line": 24, - "column": 43, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 47, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 24, - "column": 36, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 48, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 24, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 48, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2.2, - "loc": { - "start": { - "line": 24, - "column": 51, - "program": "binary_operations.ets" - }, - "end": { - "line": 24, - "column": 54, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 33.48, "loc": { "start": { "line": 24, @@ -1092,40 +612,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 4.2, - "loc": { - "start": { - "line": 25, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 25, - "column": 31, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2.3, - "loc": { - "start": { - "line": 25, - "column": 34, - "program": "binary_operations.ets" - }, - "end": { - "line": 25, - "column": 37, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1.82609, "loc": { "start": { "line": 25, @@ -1134,7 +622,7 @@ }, "end": { "line": 25, - "column": 37, + "column": 39, "program": "binary_operations.ets" } } @@ -1170,7 +658,7 @@ }, "end": { "line": 25, - "column": 37, + "column": 39, "program": "binary_operations.ets" } } @@ -1195,136 +683,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 4.2, - "loc": { - "start": { - "line": 26, - "column": 29, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 32, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "NumberLiteral", - "value": 2.2, - "loc": { - "start": { - "line": 26, - "column": 36, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 39, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.1, - "loc": { - "start": { - "line": 26, - "column": 42, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 45, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 26, - "column": 35, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 46, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 26, - "column": 29, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 46, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 3.3, - "loc": { - "start": { - "line": 26, - "column": 50, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 53, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 6.1, - "loc": { - "start": { - "line": 26, - "column": 56, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 59, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 26, - "column": 49, - "program": "binary_operations.ets" - }, - "end": { - "line": 26, - "column": 60, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2.54098, "loc": { "start": { "line": 26, @@ -1394,40 +754,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "<<", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 27, - "column": 25, - "program": "binary_operations.ets" - }, - "end": { - "line": 27, - "column": 26, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 27, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 27, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 28, "loc": { "start": { "line": 27, @@ -1497,40 +825,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": ">>", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 28, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 28, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 28, - "column": 31, - "program": "binary_operations.ets" - }, - "end": { - "line": 28, - "column": 32, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 28, @@ -1600,40 +896,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": ">>>", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 29, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 29, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 29, - "column": 32, - "program": "binary_operations.ets" - }, - "end": { - "line": 29, - "column": 33, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 29, @@ -1703,40 +967,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "&", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 30, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 30, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 30, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 30, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 3, "loc": { "start": { "line": 30, @@ -1790,56 +1022,24 @@ "type": "ClassProperty", "key": { "type": "Identifier", - "name": "bit2", - "decorators": [], - "loc": { - "start": { - "line": 31, - "column": 13, - "program": "binary_operations.ets" - }, - "end": { - "line": 31, - "column": 17, - "program": "binary_operations.ets" - } - } - }, - "value": { - "type": "BinaryExpression", - "operator": "|", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 31, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 31, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 31, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 31, - "column": 31, - "program": "binary_operations.ets" - } + "name": "bit2", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 13, + "program": "binary_operations.ets" + }, + "end": { + "line": 31, + "column": 17, + "program": "binary_operations.ets" } - }, + } + }, + "value": { + "type": "NumberLiteral", + "value": 7, "loc": { "start": { "line": 31, @@ -1909,40 +1109,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "^", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 32, - "column": 26, - "program": "binary_operations.ets" - }, - "end": { - "line": 32, - "column": 27, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 32, - "column": 30, - "program": "binary_operations.ets" - }, - "end": { - "line": 32, - "column": 31, - "program": "binary_operations.ets" - } - } - }, + "type": "NumberLiteral", + "value": 4, "loc": { "start": { "line": 32, @@ -2012,40 +1180,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "<", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 33, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 33, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 33, - "column": 32, - "program": "binary_operations.ets" - }, - "end": { - "line": 33, - "column": 33, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": true, "loc": { "start": { "line": 33, @@ -2115,40 +1251,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "<=", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 34, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 34, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 34, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 34, - "column": 34, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": true, "loc": { "start": { "line": 34, @@ -2218,40 +1322,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": ">=", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 35, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 35, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 35, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 35, - "column": 34, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 35, @@ -2321,40 +1393,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": ">", - "left": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 36, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 36, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 36, - "column": 32, - "program": "binary_operations.ets" - }, - "end": { - "line": 36, - "column": 33, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 36, @@ -2424,40 +1464,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "==", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 37, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 37, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 37, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 37, - "column": 34, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 37, @@ -2527,40 +1535,8 @@ } }, "value": { - "type": "BinaryExpression", - "operator": "!=", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 38, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 38, - "column": 29, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 4, - "loc": { - "start": { - "line": 38, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 38, - "column": 34, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": true, "loc": { "start": { "line": 38, @@ -2630,104 +1606,8 @@ } }, "value": { - "type": "LogicalExpression", - "operator": "&&", - "left": { - "type": "BinaryExpression", - "operator": "<", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 39, - "column": 29, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 30, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 39, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 34, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 39, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 35, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": ">", - "left": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 39, - "column": 40, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 41, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 39, - "column": 44, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 45, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 39, - "column": 39, - "program": "binary_operations.ets" - }, - "end": { - "line": 39, - "column": 46, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 39, @@ -2797,104 +1677,8 @@ } }, "value": { - "type": "LogicalExpression", - "operator": "||", - "left": { - "type": "BinaryExpression", - "operator": "<", - "left": { - "type": "NumberLiteral", - "value": 7, - "loc": { - "start": { - "line": 40, - "column": 29, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 30, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 3, - "loc": { - "start": { - "line": 40, - "column": 33, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 34, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 40, - "column": 28, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 35, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": ">", - "left": { - "type": "NumberLiteral", - "value": 8, - "loc": { - "start": { - "line": 40, - "column": 40, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 41, - "program": "binary_operations.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 40, - "column": 44, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 45, - "program": "binary_operations.ets" - } - } - }, - "loc": { - "start": { - "line": 40, - "column": 39, - "program": "binary_operations.ets" - }, - "end": { - "line": 40, - "column": 46, - "program": "binary_operations.ets" - } - } - }, + "type": "BooleanLiteral", + "value": true, "loc": { "start": { "line": 40, diff --git a/ets2panda/test/parser/ets/binary_operations.ets b/ets2panda/test/parser/ets/binary_operations.ets index 308cb1ebe8..5c6aeef509 100644 --- a/ets2panda/test/parser/ets/binary_operations.ets +++ b/ets2panda/test/parser/ets/binary_operations.ets @@ -20,9 +20,9 @@ export class binary_operations { private sub2 : int = 8 - 3 + 8; private rem1 : int = 5 % 3; private rem2 : int = 5 % 3 - 2 * 8; - private mult1 : float = 6.2 * 3.14; + private mult1 : float = 6.2f * 3.14f; private mult2 : double = 6.2 * (3.7 + 8.18) / 2.2; - private div1 : float = 4.2 / 2.3; + private div1 : float = 4.2f / 2.3f; private div2 : double = 4.2 / (2.2 - 0.1) + (3.3 / 6.1); private lsh : int = 7 << 2; private rsh1 : int = 7 >> 2; diff --git a/ets2panda/test/parser/ets/boolean_cond-expected.txt b/ets2panda/test/parser/ets/boolean_cond-expected.txt index 5ede97c316..f498e6d0d0 100644 --- a/ets2panda/test/parser/ets/boolean_cond-expected.txt +++ b/ets2panda/test/parser/ets/boolean_cond-expected.txt @@ -248,40 +248,8 @@ { "type": "IfStatement", "test": { - "type": "BinaryExpression", - "operator": ">", - "left": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 20, - "column": 7, - "program": "boolean_cond.ets" - }, - "end": { - "line": 20, - "column": 8, - "program": "boolean_cond.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 20, - "column": 11, - "program": "boolean_cond.ets" - }, - "end": { - "line": 20, - "column": 12, - "program": "boolean_cond.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/cast_expressions-expected.txt b/ets2panda/test/parser/ets/cast_expressions-expected.txt index c7ca64e2b7..b72e0665a8 100644 --- a/ets2panda/test/parser/ets/cast_expressions-expected.txt +++ b/ets2panda/test/parser/ets/cast_expressions-expected.txt @@ -617,39 +617,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 22, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 22, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 22, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 22, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 22, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 22, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 22, @@ -658,7 +679,7 @@ }, "end": { "line": 22, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -671,7 +692,7 @@ }, "end": { "line": 22, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -686,7 +707,7 @@ }, "end": { "line": 22, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -714,39 +735,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 23, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 23, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 23, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 23, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 23, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 23, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 23, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 23, @@ -755,7 +797,7 @@ }, "end": { "line": 23, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -768,7 +810,7 @@ }, "end": { "line": 23, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -783,7 +825,7 @@ }, "end": { "line": 23, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -811,39 +853,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 24, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 24, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 24, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 24, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 24, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 24, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 24, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 24, @@ -852,7 +915,7 @@ }, "end": { "line": 24, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -865,7 +928,7 @@ }, "end": { "line": 24, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -880,7 +943,7 @@ }, "end": { "line": 24, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -908,39 +971,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 25, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 25, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 25, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 25, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 25, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 25, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 25, @@ -949,7 +1033,7 @@ }, "end": { "line": 25, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -962,7 +1046,7 @@ }, "end": { "line": 25, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -977,7 +1061,7 @@ }, "end": { "line": 25, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -1005,39 +1089,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 26, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 26, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 26, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 26, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 26, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 26, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 26, @@ -1046,7 +1151,7 @@ }, "end": { "line": 26, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1059,7 +1164,7 @@ }, "end": { "line": 26, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1074,7 +1179,7 @@ }, "end": { "line": 26, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -1102,11 +1207,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 27, + "column": 28, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 27, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 27, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 27, @@ -1115,26 +1254,13 @@ }, "end": { "line": 27, - "column": 28, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 27, - "column": 32, - "program": "cast_expressions.ets" - }, - "end": { - "line": 27, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 27, @@ -1143,7 +1269,7 @@ }, "end": { "line": 27, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1156,7 +1282,7 @@ }, "end": { "line": 27, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1171,7 +1297,7 @@ }, "end": { "line": 27, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -1199,39 +1325,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "byte_", - "decorators": [], - "loc": { - "start": { - "line": 28, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 28, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "byte_", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 28, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 28, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 28, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 28, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 28, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 28, @@ -1240,7 +1387,7 @@ }, "end": { "line": 28, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -1253,7 +1400,7 @@ }, "end": { "line": 28, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -1268,7 +1415,7 @@ }, "end": { "line": 28, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -1296,39 +1443,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 30, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 30, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 30, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 30, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 30, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 30, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 30, @@ -1337,7 +1505,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1350,7 +1518,7 @@ }, "end": { "line": 30, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1365,7 +1533,7 @@ }, "end": { "line": 30, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -1393,39 +1561,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 31, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 31, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 31, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 31, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 31, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 31, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 31, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 31, @@ -1434,7 +1623,7 @@ }, "end": { "line": 31, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1447,7 +1636,7 @@ }, "end": { "line": 31, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1462,7 +1651,7 @@ }, "end": { "line": 31, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -1490,39 +1679,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 32, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 32, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 32, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 32, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 32, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 32, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 32, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 32, @@ -1531,7 +1741,7 @@ }, "end": { "line": 32, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -1544,7 +1754,7 @@ }, "end": { "line": 32, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -1559,7 +1769,7 @@ }, "end": { "line": 32, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -1587,39 +1797,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 33, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 33, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 33, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 33, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 33, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 33, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 33, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 33, @@ -1628,7 +1859,7 @@ }, "end": { "line": 33, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1641,7 +1872,7 @@ }, "end": { "line": 33, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -1656,7 +1887,7 @@ }, "end": { "line": 33, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -1684,39 +1915,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 34, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 34, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 34, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 34, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 34, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 34, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 34, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 34, @@ -1725,7 +1977,7 @@ }, "end": { "line": 34, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1738,7 +1990,7 @@ }, "end": { "line": 34, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -1753,7 +2005,7 @@ }, "end": { "line": 34, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -1781,39 +2033,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Byte_", - "decorators": [], - "loc": { - "start": { - "line": 35, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 35, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Byte_", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 35, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 35, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 35, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 35, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 35, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 35, @@ -1822,7 +2095,7 @@ }, "end": { "line": 35, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -1835,7 +2108,7 @@ }, "end": { "line": 35, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -1850,7 +2123,7 @@ }, "end": { "line": 35, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -2709,39 +2982,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 52, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 52, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 52, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 52, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 52, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 52, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 52, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 52, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 52, @@ -2750,7 +3044,7 @@ }, "end": { "line": 52, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -2763,7 +3057,7 @@ }, "end": { "line": 52, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -2778,7 +3072,7 @@ }, "end": { "line": 52, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -2806,39 +3100,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 53, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 53, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 53, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 53, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 53, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 53, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 53, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 53, @@ -2847,7 +3162,7 @@ }, "end": { "line": 53, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -2860,7 +3175,7 @@ }, "end": { "line": 53, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -2875,7 +3190,7 @@ }, "end": { "line": 53, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -2903,39 +3218,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 54, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 54, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 54, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 54, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 54, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 54, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 54, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 54, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 54, @@ -2944,7 +3280,7 @@ }, "end": { "line": 54, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -2957,7 +3293,7 @@ }, "end": { "line": 54, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -2972,7 +3308,7 @@ }, "end": { "line": 54, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -3000,11 +3336,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 55, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 55, + "column": 30, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 55, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 55, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 55, @@ -3013,26 +3383,13 @@ }, "end": { "line": 55, - "column": 30, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 55, - "column": 34, - "program": "cast_expressions.ets" - }, - "end": { - "line": 55, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 55, @@ -3041,7 +3398,7 @@ }, "end": { "line": 55, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -3054,7 +3411,7 @@ }, "end": { "line": 55, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -3069,7 +3426,7 @@ }, "end": { "line": 55, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -3097,39 +3454,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 56, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 56, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 56, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 56, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 56, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 56, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 56, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 56, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 56, @@ -3138,7 +3516,7 @@ }, "end": { "line": 56, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -3151,7 +3529,7 @@ }, "end": { "line": 56, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -3166,7 +3544,7 @@ }, "end": { "line": 56, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -3194,39 +3572,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 57, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 57, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 57, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 57, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 57, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 57, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 57, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 57, @@ -3235,7 +3634,7 @@ }, "end": { "line": 57, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3248,7 +3647,7 @@ }, "end": { "line": 57, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3263,7 +3662,7 @@ }, "end": { "line": 57, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -3291,39 +3690,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "short_", - "decorators": [], - "loc": { - "start": { - "line": 58, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 58, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "short_", + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 58, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 58, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 58, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 58, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 58, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 58, @@ -3332,7 +3752,7 @@ }, "end": { "line": 58, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -3345,7 +3765,7 @@ }, "end": { "line": 58, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -3360,7 +3780,7 @@ }, "end": { "line": 58, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -3388,39 +3808,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Short_", - "decorators": [], - "loc": { - "start": { - "line": 60, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 60, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Short_", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 60, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 60, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 60, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 60, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 60, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 60, @@ -3429,7 +3870,7 @@ }, "end": { "line": 60, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3442,7 +3883,7 @@ }, "end": { "line": 60, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3457,7 +3898,7 @@ }, "end": { "line": 60, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -3485,39 +3926,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Short_", - "decorators": [], - "loc": { - "start": { - "line": 61, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 61, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Short_", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 61, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 61, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 61, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 61, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 61, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 61, @@ -3526,7 +3988,7 @@ }, "end": { "line": 61, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -3539,7 +4001,7 @@ }, "end": { "line": 61, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -3554,7 +4016,7 @@ }, "end": { "line": 61, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -3582,39 +4044,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Short_", - "decorators": [], - "loc": { - "start": { - "line": 62, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 62, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Short_", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 62, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 62, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 62, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 62, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 62, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 62, @@ -3623,7 +4106,7 @@ }, "end": { "line": 62, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -3636,7 +4119,7 @@ }, "end": { "line": 62, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -3651,7 +4134,7 @@ }, "end": { "line": 62, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -3679,39 +4162,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Short_", - "decorators": [], - "loc": { - "start": { - "line": 63, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 63, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Short_", + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 63, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 63, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 63, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 63, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 63, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 63, @@ -3720,7 +4224,7 @@ }, "end": { "line": 63, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3733,7 +4237,7 @@ }, "end": { "line": 63, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -3748,7 +4252,7 @@ }, "end": { "line": 63, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -3776,39 +4280,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Short_", - "decorators": [], - "loc": { - "start": { - "line": 64, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 64, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Short_", + "decorators": [], + "loc": { + "start": { + "line": 64, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 64, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 64, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 64, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 64, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 64, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 64, @@ -3817,7 +4342,7 @@ }, "end": { "line": 64, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -3830,7 +4355,7 @@ }, "end": { "line": 64, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -3845,7 +4370,7 @@ }, "end": { "line": 64, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -4428,8 +4953,8 @@ } }, "init": { - "type": "NumberLiteral", - "value": 42, + "type": "CharLiteral", + "value": "*", "loc": { "start": { "line": 76, @@ -4704,39 +5229,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 81, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 81, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 81, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 81, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 81, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 81, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 81, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 81, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 81, @@ -4745,7 +5291,7 @@ }, "end": { "line": 81, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -4758,7 +5304,7 @@ }, "end": { "line": 81, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -4773,7 +5319,7 @@ }, "end": { "line": 81, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -4801,39 +5347,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 82, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 82, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 82, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 82, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 82, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 82, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 82, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 82, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 82, @@ -4842,7 +5409,7 @@ }, "end": { "line": 82, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -4855,7 +5422,7 @@ }, "end": { "line": 82, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -4870,7 +5437,7 @@ }, "end": { "line": 82, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -4898,11 +5465,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 83, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 83, + "column": 28, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 83, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 83, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 83, @@ -4911,26 +5512,13 @@ }, "end": { "line": 83, - "column": 28, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 83, - "column": 32, - "program": "cast_expressions.ets" - }, - "end": { - "line": 83, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 83, @@ -4939,7 +5527,7 @@ }, "end": { "line": 83, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -4952,7 +5540,7 @@ }, "end": { "line": 83, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -4967,7 +5555,7 @@ }, "end": { "line": 83, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -4995,39 +5583,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 84, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 84, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 84, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 84, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 84, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 84, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 84, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 84, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 84, @@ -5036,7 +5645,7 @@ }, "end": { "line": 84, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -5049,7 +5658,7 @@ }, "end": { "line": 84, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -5064,7 +5673,7 @@ }, "end": { "line": 84, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -5092,39 +5701,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 85, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 85, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 85, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 85, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 85, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 85, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 85, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 85, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 85, @@ -5133,7 +5763,7 @@ }, "end": { "line": 85, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5146,7 +5776,7 @@ }, "end": { "line": 85, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5161,7 +5791,7 @@ }, "end": { "line": 85, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -5189,39 +5819,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 86, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 86, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 86, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 86, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 86, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 86, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 86, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 86, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 86, @@ -5230,7 +5881,7 @@ }, "end": { "line": 86, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -5243,7 +5894,7 @@ }, "end": { "line": 86, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -5258,7 +5909,7 @@ }, "end": { "line": 86, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -5286,39 +5937,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "char_", - "decorators": [], - "loc": { - "start": { - "line": 87, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 87, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "char_", + "decorators": [], + "loc": { + "start": { + "line": 87, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 87, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 87, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 87, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 87, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 87, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 87, @@ -5327,7 +5999,7 @@ }, "end": { "line": 87, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -5340,7 +6012,7 @@ }, "end": { "line": 87, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -5355,7 +6027,7 @@ }, "end": { "line": 87, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -5383,39 +6055,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Char_", - "decorators": [], - "loc": { - "start": { - "line": 89, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 89, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Char_", + "decorators": [], + "loc": { + "start": { + "line": 89, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 89, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 89, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 89, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 89, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 89, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 89, @@ -5424,7 +6117,7 @@ }, "end": { "line": 89, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5437,7 +6130,7 @@ }, "end": { "line": 89, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5452,7 +6145,7 @@ }, "end": { "line": 89, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -5480,39 +6173,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Char_", - "decorators": [], - "loc": { - "start": { - "line": 90, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 90, - "column": 28, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Char_", + "decorators": [], + "loc": { + "start": { + "line": 90, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 90, + "column": 28, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 90, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 90, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 90, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 90, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 90, @@ -5521,7 +6235,7 @@ }, "end": { "line": 90, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -5534,7 +6248,7 @@ }, "end": { "line": 90, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -5549,7 +6263,7 @@ }, "end": { "line": 90, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -5577,39 +6291,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Char_", - "decorators": [], - "loc": { - "start": { - "line": 91, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 91, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Char_", + "decorators": [], + "loc": { + "start": { + "line": 91, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 91, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 91, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 91, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 91, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 91, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 91, @@ -5618,7 +6353,7 @@ }, "end": { "line": 91, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5631,7 +6366,7 @@ }, "end": { "line": 91, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -5646,7 +6381,7 @@ }, "end": { "line": 91, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -5674,39 +6409,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Char_", - "decorators": [], - "loc": { - "start": { - "line": 92, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 92, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Char_", + "decorators": [], + "loc": { + "start": { + "line": 92, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 92, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 92, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 92, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 92, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 92, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 92, @@ -5715,7 +6471,7 @@ }, "end": { "line": 92, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -5728,7 +6484,7 @@ }, "end": { "line": 92, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -5743,7 +6499,7 @@ }, "end": { "line": 92, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -5771,39 +6527,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Char_", - "decorators": [], - "loc": { - "start": { - "line": 93, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 93, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Char_", + "decorators": [], + "loc": { + "start": { + "line": 93, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 93, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 93, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 93, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 93, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 93, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 93, @@ -5812,7 +6589,7 @@ }, "end": { "line": 93, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -5825,7 +6602,7 @@ }, "end": { "line": 93, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -5840,7 +6617,7 @@ }, "end": { "line": 93, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -6699,39 +7476,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 110, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 110, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 110, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 110, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 110, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 110, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 110, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 110, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 110, @@ -6740,7 +7538,7 @@ }, "end": { "line": 110, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -6753,7 +7551,7 @@ }, "end": { "line": 110, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -6768,7 +7566,7 @@ }, "end": { "line": 110, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -6796,39 +7594,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 111, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 111, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 111, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 111, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 111, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 111, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 111, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 111, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 111, @@ -6837,7 +7656,7 @@ }, "end": { "line": 111, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -6850,7 +7669,7 @@ }, "end": { "line": 111, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -6865,7 +7684,7 @@ }, "end": { "line": 111, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -6893,39 +7712,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 112, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 112, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 112, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 112, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 112, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 112, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 112, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 112, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 112, @@ -6934,7 +7774,7 @@ }, "end": { "line": 112, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -6947,7 +7787,7 @@ }, "end": { "line": 112, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -6962,7 +7802,7 @@ }, "end": { "line": 112, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -6990,39 +7830,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 113, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 113, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 113, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 113, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 113, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 113, + "column": 33, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 113, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 113, - "column": 34, + "column": 33, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 113, @@ -7031,7 +7892,7 @@ }, "end": { "line": 113, - "column": 27, + "column": 35, "program": "cast_expressions.ets" } } @@ -7044,7 +7905,7 @@ }, "end": { "line": 113, - "column": 27, + "column": 35, "program": "cast_expressions.ets" } } @@ -7059,7 +7920,7 @@ }, "end": { "line": 113, - "column": 35, + "column": 36, "program": "cast_expressions.ets" } } @@ -7087,39 +7948,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 114, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 114, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 114, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 114, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 114, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 114, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 114, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 114, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 114, @@ -7128,7 +8010,7 @@ }, "end": { "line": 114, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -7141,7 +8023,7 @@ }, "end": { "line": 114, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -7156,7 +8038,7 @@ }, "end": { "line": 114, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -7184,39 +8066,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 115, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 115, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 115, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 115, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 115, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 115, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 115, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 115, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 115, @@ -7225,7 +8128,7 @@ }, "end": { "line": 115, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -7238,7 +8141,7 @@ }, "end": { "line": 115, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -7253,7 +8156,7 @@ }, "end": { "line": 115, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -7281,39 +8184,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "int_", - "decorators": [], - "loc": { - "start": { - "line": 116, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 116, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "int_", + "decorators": [], + "loc": { + "start": { + "line": 116, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 116, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 116, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 116, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 116, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 116, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 116, @@ -7322,7 +8246,7 @@ }, "end": { "line": 116, - "column": 27, + "column": 38, "program": "cast_expressions.ets" } } @@ -7335,7 +8259,7 @@ }, "end": { "line": 116, - "column": 27, + "column": 38, "program": "cast_expressions.ets" } } @@ -7350,7 +8274,7 @@ }, "end": { "line": 116, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -7378,11 +8302,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Int_", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int_", + "decorators": [], + "loc": { + "start": { + "line": 118, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 118, + "column": 27, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 118, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 118, + "column": 33, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 118, @@ -7391,26 +8349,13 @@ }, "end": { "line": 118, - "column": 27, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 118, - "column": 31, - "program": "cast_expressions.ets" - }, - "end": { - "line": 118, - "column": 34, + "column": 33, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 118, @@ -7419,7 +8364,7 @@ }, "end": { "line": 118, - "column": 27, + "column": 35, "program": "cast_expressions.ets" } } @@ -7432,7 +8377,7 @@ }, "end": { "line": 118, - "column": 27, + "column": 35, "program": "cast_expressions.ets" } } @@ -7447,7 +8392,7 @@ }, "end": { "line": 118, - "column": 35, + "column": 36, "program": "cast_expressions.ets" } } @@ -7475,39 +8420,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Int_", - "decorators": [], - "loc": { - "start": { - "line": 119, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 119, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int_", + "decorators": [], + "loc": { + "start": { + "line": 119, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 119, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 119, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 119, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 119, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 119, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 119, @@ -7516,7 +8482,7 @@ }, "end": { "line": 119, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -7529,7 +8495,7 @@ }, "end": { "line": 119, - "column": 27, + "column": 36, "program": "cast_expressions.ets" } } @@ -7544,7 +8510,7 @@ }, "end": { "line": 119, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -7572,39 +8538,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Int_", - "decorators": [], - "loc": { - "start": { - "line": 120, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 120, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int_", + "decorators": [], + "loc": { + "start": { + "line": 120, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 120, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 120, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 120, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 120, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 120, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 120, @@ -7613,7 +8600,7 @@ }, "end": { "line": 120, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -7626,7 +8613,7 @@ }, "end": { "line": 120, - "column": 27, + "column": 37, "program": "cast_expressions.ets" } } @@ -7641,7 +8628,7 @@ }, "end": { "line": 120, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -7669,39 +8656,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Int_", - "decorators": [], - "loc": { - "start": { - "line": 121, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 121, - "column": 27, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Int_", + "decorators": [], + "loc": { + "start": { + "line": 121, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 121, + "column": 27, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 121, + "column": 28, + "program": "cast_expressions.ets" + }, + "end": { + "line": 121, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 121, - "column": 31, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 121, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 121, @@ -7710,7 +8718,7 @@ }, "end": { "line": 121, - "column": 27, + "column": 38, "program": "cast_expressions.ets" } } @@ -7723,7 +8731,7 @@ }, "end": { "line": 121, - "column": 27, + "column": 38, "program": "cast_expressions.ets" } } @@ -7738,7 +8746,7 @@ }, "end": { "line": 121, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -8597,39 +9605,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 138, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 138, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 138, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 138, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 138, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 138, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 138, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 138, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 138, @@ -8638,7 +9667,7 @@ }, "end": { "line": 138, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -8651,7 +9680,7 @@ }, "end": { "line": 138, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -8666,7 +9695,7 @@ }, "end": { "line": 138, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -8694,39 +9723,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 139, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 139, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 139, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 139, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 139, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 139, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 139, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 139, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 139, @@ -8735,7 +9785,7 @@ }, "end": { "line": 139, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -8748,7 +9798,7 @@ }, "end": { "line": 139, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -8763,7 +9813,7 @@ }, "end": { "line": 139, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -8791,39 +9841,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 140, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 140, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 140, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 140, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 140, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 140, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 140, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 140, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 140, @@ -8832,7 +9903,7 @@ }, "end": { "line": 140, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -8845,7 +9916,7 @@ }, "end": { "line": 140, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -8860,7 +9931,7 @@ }, "end": { "line": 140, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -8888,39 +9959,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 141, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 141, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 141, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 141, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 141, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 141, + "column": 34, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 141, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 141, - "column": 35, + "column": 34, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 141, @@ -8929,7 +10021,7 @@ }, "end": { "line": 141, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -8942,7 +10034,7 @@ }, "end": { "line": 141, - "column": 28, + "column": 36, "program": "cast_expressions.ets" } } @@ -8957,7 +10049,7 @@ }, "end": { "line": 141, - "column": 36, + "column": 37, "program": "cast_expressions.ets" } } @@ -8985,39 +10077,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 142, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 142, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 142, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 142, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 142, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 142, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 142, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 142, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 142, @@ -9026,7 +10139,7 @@ }, "end": { "line": 142, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -9039,7 +10152,7 @@ }, "end": { "line": 142, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -9054,7 +10167,7 @@ }, "end": { "line": 142, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -9082,39 +10195,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 143, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 143, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 143, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 143, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 143, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 143, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 143, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 143, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 143, @@ -9123,7 +10257,7 @@ }, "end": { "line": 143, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -9136,7 +10270,7 @@ }, "end": { "line": 143, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -9151,7 +10285,7 @@ }, "end": { "line": 143, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -9179,39 +10313,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "long_", - "decorators": [], - "loc": { - "start": { - "line": 144, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 144, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "long_", + "decorators": [], + "loc": { + "start": { + "line": 144, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 144, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 144, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 144, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 144, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 144, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 144, @@ -9220,7 +10375,7 @@ }, "end": { "line": 144, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -9233,7 +10388,7 @@ }, "end": { "line": 144, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -9248,7 +10403,7 @@ }, "end": { "line": 144, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -9276,11 +10431,45 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Long_", - "decorators": [], + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Long_", + "decorators": [], + "loc": { + "start": { + "line": 146, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 146, + "column": 28, + "program": "cast_expressions.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 146, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 146, + "column": 35, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 146, @@ -9289,26 +10478,13 @@ }, "end": { "line": 146, - "column": 28, - "program": "cast_expressions.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 146, - "column": 32, - "program": "cast_expressions.ets" - }, - "end": { - "line": 146, - "column": 36, + "column": 35, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 146, @@ -9317,7 +10493,7 @@ }, "end": { "line": 146, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -9330,7 +10506,7 @@ }, "end": { "line": 146, - "column": 28, + "column": 37, "program": "cast_expressions.ets" } } @@ -9345,7 +10521,7 @@ }, "end": { "line": 146, - "column": 37, + "column": 38, "program": "cast_expressions.ets" } } @@ -9373,39 +10549,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Long_", - "decorators": [], - "loc": { - "start": { - "line": 147, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 147, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Long_", + "decorators": [], + "loc": { + "start": { + "line": 147, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 147, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 147, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 147, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 147, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 147, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 147, @@ -9414,7 +10611,7 @@ }, "end": { "line": 147, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -9427,7 +10624,7 @@ }, "end": { "line": 147, - "column": 28, + "column": 38, "program": "cast_expressions.ets" } } @@ -9442,7 +10639,7 @@ }, "end": { "line": 147, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -9470,39 +10667,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Long_", - "decorators": [], - "loc": { - "start": { - "line": 148, - "column": 23, - "program": "cast_expressions.ets" - }, - "end": { - "line": 148, - "column": 28, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Long_", + "decorators": [], + "loc": { + "start": { + "line": 148, + "column": 23, + "program": "cast_expressions.ets" + }, + "end": { + "line": 148, + "column": 28, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 148, + "column": 29, + "program": "cast_expressions.ets" + }, + "end": { + "line": 148, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 148, - "column": 32, + "column": 23, "program": "cast_expressions.ets" }, "end": { "line": 148, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 148, @@ -9511,7 +10729,7 @@ }, "end": { "line": 148, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -9524,7 +10742,7 @@ }, "end": { "line": 148, - "column": 28, + "column": 39, "program": "cast_expressions.ets" } } @@ -9539,7 +10757,7 @@ }, "end": { "line": 148, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -10398,39 +11616,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 165, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 165, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 165, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 165, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 165, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 165, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 165, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 165, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 165, @@ -10439,7 +11678,7 @@ }, "end": { "line": 165, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10452,7 +11691,7 @@ }, "end": { "line": 165, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10467,7 +11706,7 @@ }, "end": { "line": 165, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -10495,39 +11734,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 166, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 166, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 166, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 166, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 166, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 166, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 166, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 166, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 166, @@ -10536,7 +11796,7 @@ }, "end": { "line": 166, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -10549,7 +11809,7 @@ }, "end": { "line": 166, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -10564,7 +11824,7 @@ }, "end": { "line": 166, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -10592,39 +11852,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 167, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 167, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 167, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 167, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 167, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 167, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 167, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 167, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 167, @@ -10633,7 +11914,7 @@ }, "end": { "line": 167, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10646,7 +11927,7 @@ }, "end": { "line": 167, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10661,7 +11942,7 @@ }, "end": { "line": 167, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -10689,39 +11970,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 168, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 168, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 168, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 168, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 168, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 168, + "column": 36, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 168, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 168, - "column": 37, + "column": 36, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 168, @@ -10730,7 +12032,7 @@ }, "end": { "line": 168, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -10743,7 +12045,7 @@ }, "end": { "line": 168, - "column": 30, + "column": 38, "program": "cast_expressions.ets" } } @@ -10758,7 +12060,7 @@ }, "end": { "line": 168, - "column": 38, + "column": 39, "program": "cast_expressions.ets" } } @@ -10786,39 +12088,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 169, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 169, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 169, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 169, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 169, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 169, + "column": 37, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 169, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 169, - "column": 38, + "column": 37, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 169, @@ -10827,7 +12150,7 @@ }, "end": { "line": 169, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10840,7 +12163,7 @@ }, "end": { "line": 169, - "column": 30, + "column": 39, "program": "cast_expressions.ets" } } @@ -10855,7 +12178,7 @@ }, "end": { "line": 169, - "column": 39, + "column": 40, "program": "cast_expressions.ets" } } @@ -10883,39 +12206,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 170, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 170, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 170, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 170, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 170, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 170, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 170, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 170, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 170, @@ -10924,7 +12268,7 @@ }, "end": { "line": 170, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -10937,7 +12281,7 @@ }, "end": { "line": 170, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -10952,7 +12296,7 @@ }, "end": { "line": 170, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -10980,39 +12324,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "float_", - "decorators": [], - "loc": { - "start": { - "line": 171, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 171, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "float_", + "decorators": [], + "loc": { + "start": { + "line": 171, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 171, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 171, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 171, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 171, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 171, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 171, @@ -11021,7 +12386,7 @@ }, "end": { "line": 171, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -11034,7 +12399,7 @@ }, "end": { "line": 171, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -11049,7 +12414,7 @@ }, "end": { "line": 171, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -11077,39 +12442,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Float_", - "decorators": [], - "loc": { - "start": { - "line": 173, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 173, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Float_", + "decorators": [], + "loc": { + "start": { + "line": 173, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 173, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 173, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 173, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 173, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 173, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 173, @@ -11118,7 +12504,7 @@ }, "end": { "line": 173, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -11131,7 +12517,7 @@ }, "end": { "line": 173, - "column": 30, + "column": 40, "program": "cast_expressions.ets" } } @@ -11146,7 +12532,7 @@ }, "end": { "line": 173, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -11174,39 +12560,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Float_", - "decorators": [], - "loc": { - "start": { - "line": 174, - "column": 24, - "program": "cast_expressions.ets" - }, - "end": { - "line": 174, - "column": 30, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Float_", + "decorators": [], + "loc": { + "start": { + "line": 174, + "column": 24, + "program": "cast_expressions.ets" + }, + "end": { + "line": 174, + "column": 30, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 174, + "column": 31, + "program": "cast_expressions.ets" + }, + "end": { + "line": 174, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 174, - "column": 34, + "column": 24, "program": "cast_expressions.ets" }, "end": { "line": 174, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 174, @@ -11215,7 +12622,7 @@ }, "end": { "line": 174, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -11228,7 +12635,7 @@ }, "end": { "line": 174, - "column": 30, + "column": 41, "program": "cast_expressions.ets" } } @@ -11243,7 +12650,7 @@ }, "end": { "line": 174, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -12102,39 +13509,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 191, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 191, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 191, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 191, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toByte", + "decorators": [], + "loc": { + "start": { + "line": 191, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 191, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 191, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 191, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 191, @@ -12143,7 +13571,7 @@ }, "end": { "line": 191, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12156,7 +13584,7 @@ }, "end": { "line": 191, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12171,7 +13599,7 @@ }, "end": { "line": 191, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -12199,39 +13627,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 192, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 192, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 192, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 192, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toShort", + "decorators": [], + "loc": { + "start": { + "line": 192, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 192, + "column": 40, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 192, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 192, - "column": 41, + "column": 40, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 192, @@ -12240,7 +13689,7 @@ }, "end": { "line": 192, - "column": 32, + "column": 42, "program": "cast_expressions.ets" } } @@ -12253,7 +13702,7 @@ }, "end": { "line": 192, - "column": 32, + "column": 42, "program": "cast_expressions.ets" } } @@ -12268,7 +13717,7 @@ }, "end": { "line": 192, - "column": 42, + "column": 43, "program": "cast_expressions.ets" } } @@ -12294,41 +13743,62 @@ "program": "cast_expressions.ets" } } - }, - "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 193, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 193, - "column": 32, - "program": "cast_expressions.ets" + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 193, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 193, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toChar", + "decorators": [], + "loc": { + "start": { + "line": 193, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 193, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 193, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 193, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 193, @@ -12337,7 +13807,7 @@ }, "end": { "line": 193, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12350,7 +13820,7 @@ }, "end": { "line": 193, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12365,7 +13835,7 @@ }, "end": { "line": 193, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -12393,39 +13863,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 194, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 194, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 194, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 194, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toInt", + "decorators": [], + "loc": { + "start": { + "line": 194, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 194, + "column": 38, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 194, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 194, - "column": 39, + "column": 38, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 194, @@ -12434,7 +13925,7 @@ }, "end": { "line": 194, - "column": 32, + "column": 40, "program": "cast_expressions.ets" } } @@ -12447,7 +13938,7 @@ }, "end": { "line": 194, - "column": 32, + "column": 40, "program": "cast_expressions.ets" } } @@ -12462,7 +13953,7 @@ }, "end": { "line": 194, - "column": 40, + "column": 41, "program": "cast_expressions.ets" } } @@ -12490,39 +13981,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 195, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 195, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 195, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 195, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toLong", + "decorators": [], + "loc": { + "start": { + "line": 195, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 195, + "column": 39, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 195, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 195, - "column": 40, + "column": 39, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 195, @@ -12531,7 +14043,7 @@ }, "end": { "line": 195, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12544,7 +14056,7 @@ }, "end": { "line": 195, - "column": 32, + "column": 41, "program": "cast_expressions.ets" } } @@ -12559,7 +14071,7 @@ }, "end": { "line": 195, - "column": 41, + "column": 42, "program": "cast_expressions.ets" } } @@ -12587,39 +14099,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 196, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 196, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 196, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 196, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 196, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 196, + "column": 40, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 196, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 196, - "column": 41, + "column": 40, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 196, @@ -12628,7 +14161,7 @@ }, "end": { "line": 196, - "column": 32, + "column": 42, "program": "cast_expressions.ets" } } @@ -12641,7 +14174,7 @@ }, "end": { "line": 196, - "column": 32, + "column": 42, "program": "cast_expressions.ets" } } @@ -12656,7 +14189,7 @@ }, "end": { "line": 196, - "column": 42, + "column": 43, "program": "cast_expressions.ets" } } @@ -12684,39 +14217,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "double_", - "decorators": [], - "loc": { - "start": { - "line": 197, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 197, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "double_", + "decorators": [], + "loc": { + "start": { + "line": 197, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 197, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 197, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 197, + "column": 41, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 197, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 197, - "column": 42, + "column": 41, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 197, @@ -12725,7 +14279,7 @@ }, "end": { "line": 197, - "column": 32, + "column": 43, "program": "cast_expressions.ets" } } @@ -12738,7 +14292,7 @@ }, "end": { "line": 197, - "column": 32, + "column": 43, "program": "cast_expressions.ets" } } @@ -12753,7 +14307,7 @@ }, "end": { "line": 197, - "column": 43, + "column": 44, "program": "cast_expressions.ets" } } @@ -12781,39 +14335,60 @@ } }, "init": { - "type": "TSAsExpression", - "expression": { - "type": "Identifier", - "name": "Double_", - "decorators": [], - "loc": { - "start": { - "line": 199, - "column": 25, - "program": "cast_expressions.ets" - }, - "end": { - "line": 199, - "column": 32, - "program": "cast_expressions.ets" + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double_", + "decorators": [], + "loc": { + "start": { + "line": 199, + "column": 25, + "program": "cast_expressions.ets" + }, + "end": { + "line": 199, + "column": 32, + "program": "cast_expressions.ets" + } } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", + }, + "property": { + "type": "Identifier", + "name": "toDouble", + "decorators": [], + "loc": { + "start": { + "line": 199, + "column": 33, + "program": "cast_expressions.ets" + }, + "end": { + "line": 199, + "column": 41, + "program": "cast_expressions.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 199, - "column": 36, + "column": 25, "program": "cast_expressions.ets" }, "end": { "line": 199, - "column": 42, + "column": 41, "program": "cast_expressions.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 199, @@ -12822,7 +14397,7 @@ }, "end": { "line": 199, - "column": 32, + "column": 43, "program": "cast_expressions.ets" } } @@ -12835,7 +14410,7 @@ }, "end": { "line": 199, - "column": 32, + "column": 43, "program": "cast_expressions.ets" } } @@ -12850,7 +14425,7 @@ }, "end": { "line": 199, - "column": 43, + "column": 44, "program": "cast_expressions.ets" } } diff --git a/ets2panda/test/parser/ets/cast_expressions.ets b/ets2panda/test/parser/ets/cast_expressions.ets index de9c130144..499ebb71f1 100644 --- a/ets2panda/test/parser/ets/cast_expressions.ets +++ b/ets2panda/test/parser/ets/cast_expressions.ets @@ -19,20 +19,20 @@ function byte_test(): void { { // Casting to primitive types - let byte_byte = byte_ as byte; - let byte_short = byte_ as short; - let byte_char = byte_ as char; - let byte_int = byte_ as int; - let byte_long = byte_ as long; - let byte_float = byte_ as float; - let byte_double = byte_ as double; - - let Byte_byte = Byte_ as byte; - let Byte_short = Byte_ as short; - let Byte_int = Byte_ as int; - let Byte_long = Byte_ as long; - let Byte_float = Byte_ as float; - let Byte_double = Byte_ as double; + let byte_byte = byte_.toByte(); + let byte_short = byte_.toShort(); + let byte_char = byte_.toChar(); + let byte_int = byte_.toInt(); + let byte_long = byte_.toLong(); + let byte_float = byte_.toFloat(); + let byte_double = byte_.toDouble(); + + let Byte_byte = Byte_.toByte(); + let Byte_short = Byte_.toShort(); + let Byte_int = Byte_.toInt(); + let Byte_long = Byte_.toLong(); + let Byte_float = Byte_.toFloat(); + let Byte_double = Byte_.toDouble(); } { @@ -49,19 +49,19 @@ function short_test(): void { { // Casting to primitive types - let short_byte = short_ as byte; - let short_short = short_ as short; - let short_char = short_ as char; - let short_int = short_ as int; - let short_long = short_ as long; - let short_float = short_ as float; - let short_double = short_ as double; - - let Short_short = Short_ as short; - let Short_int = Short_ as int; - let Short_long = Short_ as long; - let Short_float = Short_ as float; - let Short_double = Short_ as double; + let short_byte = short_.toByte(); + let short_short = short_.toShort(); + let short_char = short_.toChar(); + let short_int = short_.toInt(); + let short_long = short_.toLong(); + let short_float = short_.toFloat(); + let short_double = short_.toDouble(); + + let Short_short = Short_.toShort(); + let Short_int = Short_.toInt(); + let Short_long = Short_.toLong(); + let Short_float = Short_.toFloat(); + let Short_double = Short_.toDouble(); } { @@ -78,19 +78,19 @@ function char_test(): void { { // Casting to primitive types - let char_byte = char_ as byte; - let char_short = char_ as short; - let char_char = char_ as char; - let char_int = char_ as int; - let char_long = char_ as long; - let char_float = char_ as float; - let char_double = char_ as double; - - let Char_char = Char_ as char; - let Char_int = Char_ as int; - let Char_long = Char_ as long; - let Char_float = Char_ as float; - let Char_double = Char_ as double; + let char_byte = char_.toByte(); + let char_short = char_.toShort(); + let char_char = char_.toChar(); + let char_int = char_.toInt(); + let char_long = char_.toLong(); + let char_float = char_.toFloat(); + let char_double = char_.toDouble(); + + let Char_char = Char_.toChar(); + let Char_int = Char_.toInt(); + let Char_long = Char_.toLong(); + let Char_float = Char_.toFloat(); + let Char_double = Char_.toDouble(); } { @@ -107,18 +107,18 @@ function int_test(): void { { // Casting to primitive types - let int_byte = int_ as byte; - let int_short = int_ as short; - let int_char = int_ as char; - let int_int = int_ as int; - let int_long = int_ as long; - let int_float = int_ as float; - let int_double = int_ as double; - - let Int_int = Int_ as int; - let Int_long = Int_ as long; - let Int_float = Int_ as float; - let Int_double = Int_ as double; + let int_byte = int_.toByte(); + let int_short = int_.toShort(); + let int_char = int_.toChar(); + let int_int = int_.toInt(); + let int_long = int_.toLong(); + let int_float = int_.toFloat(); + let int_double = int_.toDouble(); + + let Int_int = Int_.toInt(); + let Int_long = Int_.toLong(); + let Int_float = Int_.toFloat(); + let Int_double = Int_.toDouble(); } { @@ -135,17 +135,17 @@ function long_test(): void { { // Casting to primitive types - let long_byte = long_ as byte; - let long_short = long_ as short; - let long_char = long_ as char; - let long_int = long_ as int; - let long_long = long_ as long; - let long_float = long_ as float; - let long_double = long_ as double; - - let Long_long = Long_ as long; - let Long_float = Long_ as float; - let Long_double = Long_ as double; + let long_byte = long_.toByte(); + let long_short = long_.toShort(); + let long_char = long_.toChar(); + let long_int = long_.toInt(); + let long_long = long_.toLong(); + let long_float = long_.toFloat(); + let long_double = long_.toDouble(); + + let Long_long = Long_.toLong(); + let Long_float = Long_.toFloat(); + let Long_double = Long_.toDouble(); } { @@ -162,16 +162,16 @@ function float_test(): void { { // Casting to primitive types - let float_byte = float_ as byte; - let float_short = float_ as short; - let float_char = float_ as char; - let float_int = float_ as int; - let float_long = float_ as long; - let float_float = float_ as float; - let float_double = float_ as double; + let float_byte = float_.toByte(); + let float_short = float_.toShort(); + let float_char = float_.toChar(); + let float_int = float_.toInt(); + let float_long = float_.toLong(); + let float_float = float_.toFloat(); + let float_double = float_.toDouble(); - let Float_float = Float_ as float; - let Float_double = Float_ as double; + let Float_float = Float_.toFloat(); + let Float_double = Float_.toDouble(); } { @@ -188,15 +188,15 @@ function double_test(): void { { // Casting to primitive types - let double_byte = double_ as byte; - let double_short = double_ as short; - let double_char = double_ as char; - let double_int = double_ as int; - let double_long = double_ as long; - let double_float = double_ as float; - let double_double = double_ as double; - - let Double_double = Double_ as double; + let double_byte = double_.toByte(); + let double_short = double_.toShort(); + let double_char = double_.toChar(); + let double_int = double_.toInt(); + let double_long = double_.toLong(); + let double_float = double_.toFloat(); + let double_double = double_.toDouble(); + + let Double_double = Double_.toDouble(); } { diff --git a/ets2panda/test/parser/ets/cast_expressions5-expected.txt b/ets2panda/test/parser/ets/cast_expressions5-expected.txt index bc09d5b685..ab9a22576b 100644 --- a/ets2panda/test/parser/ets/cast_expressions5-expected.txt +++ b/ets2panda/test/parser/ets/cast_expressions5-expected.txt @@ -370,11 +370,45 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 30, + "column": 12, + "program": "cast_expressions5.ets" + }, + "end": { + "line": 30, + "column": 16, + "program": "cast_expressions5.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "a", + "decorators": [], + "loc": { + "start": { + "line": 30, + "column": 17, + "program": "cast_expressions5.ets" + }, + "end": { + "line": 30, + "column": 18, + "program": "cast_expressions5.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 30, @@ -383,24 +417,24 @@ }, "end": { "line": 30, - "column": 16, + "column": 18, "program": "cast_expressions5.ets" } } }, "property": { "type": "Identifier", - "name": "a", + "name": "toLong", "decorators": [], "loc": { "start": { "line": 30, - "column": 17, + "column": 19, "program": "cast_expressions5.ets" }, "end": { "line": 30, - "column": 18, + "column": 25, "program": "cast_expressions5.ets" } } @@ -415,26 +449,13 @@ }, "end": { "line": 30, - "column": 18, - "program": "cast_expressions5.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 30, - "column": 22, - "program": "cast_expressions5.ets" - }, - "end": { - "line": 30, - "column": 26, + "column": 25, "program": "cast_expressions5.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 30, @@ -443,7 +464,7 @@ }, "end": { "line": 30, - "column": 18, + "column": 27, "program": "cast_expressions5.ets" } } @@ -456,7 +477,7 @@ }, "end": { "line": 30, - "column": 27, + "column": 28, "program": "cast_expressions5.ets" } } diff --git a/ets2panda/test/parser/ets/cast_expressions5.ets b/ets2panda/test/parser/ets/cast_expressions5.ets index d0b6414445..cfcdb1c374 100644 --- a/ets2panda/test/parser/ets/cast_expressions5.ets +++ b/ets2panda/test/parser/ets/cast_expressions5.ets @@ -27,6 +27,6 @@ class A { } method2(): long { - return this.a as long; + return this.a.toLong(); } } diff --git a/ets2panda/test/parser/ets/class_init-expected.txt b/ets2panda/test/parser/ets/class_init-expected.txt index a3a99d1115..e5d69c29a6 100644 --- a/ets2panda/test/parser/ets/class_init-expected.txt +++ b/ets2panda/test/parser/ets/class_init-expected.txt @@ -166,40 +166,8 @@ } }, "right": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 30, - "loc": { - "start": { - "line": 20, - "column": 11, - "program": "class_init.ets" - }, - "end": { - "line": 20, - "column": 13, - "program": "class_init.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 99, - "loc": { - "start": { - "line": 20, - "column": 16, - "program": "class_init.ets" - }, - "end": { - "line": 20, - "column": 18, - "program": "class_init.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2970, "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt b/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt index 5d2945240a..8783d8a8ca 100644 --- a/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt +++ b/ets2panda/test/parser/ets/conditionalExpressionType-expected.txt @@ -235,8 +235,8 @@ } }, "init": { - "type": "NumberLiteral", - "value": 100, + "type": "CharLiteral", + "value": "d", "loc": { "start": { "line": 17, @@ -301,56 +301,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 18, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 18, - "column": 21, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 18, - "column": 24, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 18, - "column": 25, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 68, - "loc": { - "start": { - "line": 18, - "column": 28, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 18, - "column": 30, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "a", + "decorators": [], "loc": { "start": { "line": 18, @@ -496,56 +449,8 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 21, - "column": 15, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 21, - "column": 20, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 21, - "column": 23, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 21, - "column": 24, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 68, - "loc": { - "start": { - "line": 21, - "column": 27, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 21, - "column": 29, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "NumberLiteral", + "value": 68, "loc": { "start": { "line": 21, @@ -723,56 +628,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 24, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 24, - "column": 21, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 24, - "column": 24, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 24, - "column": 25, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 419, - "loc": { - "start": { - "line": 24, - "column": 28, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 24, - "column": 31, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "c", + "decorators": [], "loc": { "start": { "line": 24, @@ -852,8 +710,8 @@ } }, "init": { - "type": "NumberLiteral", - "value": 3, + "type": "CharLiteral", + "value": "\u0003", "loc": { "start": { "line": 26, @@ -918,56 +776,8 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 27, - "column": 18, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 27, - "column": 23, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 26, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 27, - "column": 27, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 665, - "loc": { - "start": { - "line": 27, - "column": 30, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 27, - "column": 33, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "NumberLiteral", + "value": 665, "loc": { "start": { "line": 27, @@ -1145,56 +955,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 30, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 30, - "column": 21, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 30, - "column": 24, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 30, - "column": 25, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 665, - "loc": { - "start": { - "line": 30, - "column": 28, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 30, - "column": 31, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "c", + "decorators": [], "loc": { "start": { "line": 30, @@ -1340,56 +1103,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 33, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 33, - "column": 21, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 33, - "column": 24, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 33, - "column": 25, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 665419, - "loc": { - "start": { - "line": 33, - "column": 28, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 33, - "column": 34, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "c", + "decorators": [], "loc": { "start": { "line": 33, @@ -1535,56 +1251,8 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 36, - "column": 19, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 36, - "column": 24, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "g", - "decorators": [], - "loc": { - "start": { - "line": 36, - "column": 27, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 36, - "column": 28, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "NumberLiteral", - "value": 30, - "loc": { - "start": { - "line": 36, - "column": 31, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 36, - "column": 33, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "NumberLiteral", + "value": 30, "loc": { "start": { "line": 36, @@ -1965,57 +1633,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 42, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 42, - "column": 21, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 42, - "column": 24, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 42, - "column": 25, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 42, - "column": 28, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 42, - "column": 29, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "a", + "decorators": [], "loc": { "start": { "line": 42, @@ -2274,57 +1894,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 46, - "column": 15, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 46, - "column": 20, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 46, - "column": 23, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 46, - "column": 24, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 46, - "column": 27, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 46, - "column": 28, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "b", + "decorators": [], "loc": { "start": { "line": 46, @@ -2617,7 +2189,7 @@ }, "end": { "line": 51, - "column": 24, + "column": 25, "program": "conditionalExpressionType.ets" } } @@ -2630,7 +2202,7 @@ }, "end": { "line": 51, - "column": 24, + "column": 25, "program": "conditionalExpressionType.ets" } } @@ -2645,7 +2217,7 @@ }, "end": { "line": 51, - "column": 25, + "column": 26, "program": "conditionalExpressionType.ets" } } @@ -3044,8 +2616,8 @@ } }, "init": { - "type": "NumberLiteral", - "value": 2, + "type": "CharLiteral", + "value": "\u0002", "loc": { "start": { "line": 56, @@ -3110,57 +2682,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 58, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 58, - "column": 22, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "a", - "decorators": [], - "loc": { - "start": { - "line": 58, - "column": 25, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 58, - "column": 26, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 58, - "column": 29, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 58, - "column": 30, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "b", + "decorators": [], "loc": { "start": { "line": 58, @@ -3225,57 +2749,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 59, - "column": 15, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 59, - "column": 20, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "b", - "decorators": [], - "loc": { - "start": { - "line": 59, - "column": 23, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 59, - "column": 24, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 59, - "column": 27, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 59, - "column": 28, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "c", + "decorators": [], "loc": { "start": { "line": 59, @@ -3340,57 +2816,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 60, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 60, - "column": 22, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "c", - "decorators": [], - "loc": { - "start": { - "line": 60, - "column": 25, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 60, - "column": 26, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "d", - "decorators": [], - "loc": { - "start": { - "line": 60, - "column": 29, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 60, - "column": 30, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "d", + "decorators": [], "loc": { "start": { "line": 60, @@ -3455,57 +2883,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 61, - "column": 18, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 61, - "column": 23, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "d", - "decorators": [], - "loc": { - "start": { - "line": 61, - "column": 26, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 61, - "column": 27, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "e", - "decorators": [], - "loc": { - "start": { - "line": 61, - "column": 30, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 61, - "column": 31, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "e", + "decorators": [], "loc": { "start": { "line": 61, @@ -3570,57 +2950,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 62, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 62, - "column": 22, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "e", - "decorators": [], - "loc": { - "start": { - "line": 62, - "column": 25, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 62, - "column": 26, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "f", - "decorators": [], - "loc": { - "start": { - "line": 62, - "column": 29, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 62, - "column": 30, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "f", + "decorators": [], "loc": { "start": { "line": 62, @@ -3685,57 +3017,9 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 63, - "column": 17, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 63, - "column": 22, - "program": "conditionalExpressionType.ets" - } - } - }, - "consequent": { - "type": "Identifier", - "name": "f", - "decorators": [], - "loc": { - "start": { - "line": 63, - "column": 25, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 63, - "column": 26, - "program": "conditionalExpressionType.ets" - } - } - }, - "alternate": { - "type": "Identifier", - "name": "g", - "decorators": [], - "loc": { - "start": { - "line": 63, - "column": 29, - "program": "conditionalExpressionType.ets" - }, - "end": { - "line": 63, - "column": 30, - "program": "conditionalExpressionType.ets" - } - } - }, + "type": "Identifier", + "name": "g", + "decorators": [], "loc": { "start": { "line": 63, diff --git a/ets2panda/test/parser/ets/conditionalExpressionType.ets b/ets2panda/test/parser/ets/conditionalExpressionType.ets index 1a17d452f6..a3094001cd 100644 --- a/ets2panda/test/parser/ets/conditionalExpressionType.ets +++ b/ets2panda/test/parser/ets/conditionalExpressionType.ets @@ -48,7 +48,7 @@ function unboxingCases(): void{ function dominantNumericCases(): void{ let a : double = 2.0; - let b : float = 2.0; + let b : float = 2.0f; let c : long = 2; let d : int = 2; let e : Short = 2; diff --git a/ets2panda/test/parser/ets/default_parameter5-expected.txt b/ets2panda/test/parser/ets/default_parameter5-expected.txt index 3fa19f2329..f3e2bfa544 100644 --- a/ets2panda/test/parser/ets/default_parameter5-expected.txt +++ b/ets2panda/test/parser/ets/default_parameter5-expected.txt @@ -861,7 +861,7 @@ "loc": { "start": { "line": 23, - "column": 12, + "column": 17, "program": "default_parameter5.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/field_decl-expected.txt b/ets2panda/test/parser/ets/field_decl-expected.txt index 0ac292d2ba..689727a8d8 100644 --- a/ets2panda/test/parser/ets/field_decl-expected.txt +++ b/ets2panda/test/parser/ets/field_decl-expected.txt @@ -416,7 +416,7 @@ }, "end": { "line": 23, - "column": 38, + "column": 39, "program": "field_decl.ets" } } @@ -452,7 +452,7 @@ }, "end": { "line": 23, - "column": 38, + "column": 39, "program": "field_decl.ets" } } diff --git a/ets2panda/test/parser/ets/field_decl.ets b/ets2panda/test/parser/ets/field_decl.ets index 68d3688c7d..2a2d52b1a4 100644 --- a/ets2panda/test/parser/ets/field_decl.ets +++ b/ets2panda/test/parser/ets/field_decl.ets @@ -20,7 +20,7 @@ export class field_decl { public d : boolean = true; f : short ; static g : long ; - static readonly pi : float = 3.14; + static readonly pi : float = 3.14f; public static readonly e : double = 2.71828; private readonly h : byte = 2; } diff --git a/ets2panda/test/parser/ets/float_pont_format_2-expected.txt b/ets2panda/test/parser/ets/float_pont_format_2-expected.txt index 850d7b2cc2..bec8dfd030 100644 --- a/ets2panda/test/parser/ets/float_pont_format_2-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_2-expected.txt @@ -205,40 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_2.ets" - }, - "end": { - "line": 17, - "column": 15, - "program": "float_pont_format_2.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 18, - "program": "float_pont_format_2.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_2.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_pont_format_3-expected.txt b/ets2panda/test/parser/ets/float_pont_format_3-expected.txt index 21d98fea12..7ed81174d5 100644 --- a/ets2panda/test/parser/ets/float_pont_format_3-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_3-expected.txt @@ -205,40 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 1.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_3.ets" - }, - "end": { - "line": 17, - "column": 16, - "program": "float_pont_format_3.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 19, - "program": "float_pont_format_3.ets" - }, - "end": { - "line": 17, - "column": 21, - "program": "float_pont_format_3.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_pont_format_4-expected.txt b/ets2panda/test/parser/ets/float_pont_format_4-expected.txt index db9f5816e9..d6d8338179 100644 --- a/ets2panda/test/parser/ets/float_pont_format_4-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_4-expected.txt @@ -205,40 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_4.ets" - }, - "end": { - "line": 17, - "column": 15, - "program": "float_pont_format_4.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 1.5, - "loc": { - "start": { - "line": 17, - "column": 18, - "program": "float_pont_format_4.ets" - }, - "end": { - "line": 17, - "column": 21, - "program": "float_pont_format_4.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_pont_format_5-expected.txt b/ets2panda/test/parser/ets/float_pont_format_5-expected.txt index 5624b9cbb9..4913b2533c 100644 --- a/ets2panda/test/parser/ets/float_pont_format_5-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_5-expected.txt @@ -205,40 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 1.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_5.ets" - }, - "end": { - "line": 17, - "column": 16, - "program": "float_pont_format_5.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 19, - "program": "float_pont_format_5.ets" - }, - "end": { - "line": 17, - "column": 21, - "program": "float_pont_format_5.ets" - } - } - }, + "type": "NumberLiteral", + "value": 3, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_pont_format_6-expected.txt b/ets2panda/test/parser/ets/float_pont_format_6-expected.txt index 3a786d9c44..0fafd5d120 100644 --- a/ets2panda/test/parser/ets/float_pont_format_6-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_6-expected.txt @@ -205,40 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_6.ets" - }, - "end": { - "line": 17, - "column": 15, - "program": "float_pont_format_6.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 18, - "program": "float_pont_format_6.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_6.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_pont_format_7-expected.txt b/ets2panda/test/parser/ets/float_pont_format_7-expected.txt index a913834768..99931a57f0 100644 --- a/ets2panda/test/parser/ets/float_pont_format_7-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_7-expected.txt @@ -205,172 +205,12 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 15, - "program": "float_pont_format_7.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.7, - "loc": { - "start": { - "line": 17, - "column": 18, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_7.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_7.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.4, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 25, - "program": "float_pont_format_7.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 29, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 31, - "program": "float_pont_format_7.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.1, - "loc": { - "start": { - "line": 17, - "column": 34, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 36, - "program": "float_pont_format_7.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 28, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 37, - "program": "float_pont_format_7.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 37, - "program": "float_pont_format_7.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 40, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 42, - "program": "float_pont_format_7.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_7.ets" - }, - "end": { - "line": 17, - "column": 42, - "program": "float_pont_format_7.ets" - } - } - }, + "type": "NumberLiteral", + "value": 1.2, "loc": { "start": { "line": 17, - "column": 13, + "column": 18, "program": "float_pont_format_7.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/float_pont_format_8-expected.txt b/ets2panda/test/parser/ets/float_pont_format_8-expected.txt index f492de68b9..034dfbfa3c 100644 --- a/ets2panda/test/parser/ets/float_pont_format_8-expected.txt +++ b/ets2panda/test/parser/ets/float_pont_format_8-expected.txt @@ -205,552 +205,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 15, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.7, - "loc": { - "start": { - "line": 17, - "column": 18, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.4, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 25, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 29, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 31, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.1, - "loc": { - "start": { - "line": 17, - "column": 34, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 36, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 28, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 37, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 37, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 40, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 42, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 42, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 42, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "BinaryExpression", - "operator": "-", - "left": { - "type": "BinaryExpression", - "operator": "+", - "left": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 47, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 49, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.7, - "loc": { - "start": { - "line": 17, - "column": 52, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 54, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 47, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 54, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.4, - "loc": { - "start": { - "line": 17, - "column": 57, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 59, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 63, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 65, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.1, - "loc": { - "start": { - "line": 17, - "column": 68, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 70, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 62, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 71, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 57, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 71, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 74, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 76, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 57, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 76, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 46, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 77, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.5, - "loc": { - "start": { - "line": 17, - "column": 80, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 82, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 46, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 82, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.7, - "loc": { - "start": { - "line": 17, - "column": 85, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 87, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 46, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 87, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "%", - "left": { - "type": "BinaryExpression", - "operator": "*", - "left": { - "type": "NumberLiteral", - "value": 0.4, - "loc": { - "start": { - "line": 17, - "column": 90, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 92, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 96, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 98, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.1, - "loc": { - "start": { - "line": 17, - "column": 101, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 103, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 95, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 104, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 90, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 104, - "program": "float_pont_format_8.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0.2, - "loc": { - "start": { - "line": 17, - "column": 107, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 109, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 90, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 109, - "program": "float_pont_format_8.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 45, - "program": "float_pont_format_8.ets" - }, - "end": { - "line": 17, - "column": 110, - "program": "float_pont_format_8.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2.5, "loc": { "start": { "line": 17, diff --git a/ets2panda/test/parser/ets/float_separator_1-expected.txt b/ets2panda/test/parser/ets/float_separator_1-expected.txt index 6457c93362..f90de87c9c 100644 --- a/ets2panda/test/parser/ets/float_separator_1-expected.txt +++ b/ets2panda/test/parser/ets/float_separator_1-expected.txt @@ -230,7 +230,7 @@ }, "end": { "line": 17, - "column": 38, + "column": 39, "program": "float_separator_1.ets" } } @@ -243,7 +243,7 @@ }, "end": { "line": 17, - "column": 38, + "column": 39, "program": "float_separator_1.ets" } } @@ -258,7 +258,7 @@ }, "end": { "line": 17, - "column": 38, + "column": 39, "program": "float_separator_1.ets" } } diff --git a/ets2panda/test/parser/ets/float_separator_1.ets b/ets2panda/test/parser/ets/float_separator_1.ets index 419d60864d..568ef176d8 100644 --- a/ets2panda/test/parser/ets/float_separator_1.ets +++ b/ets2panda/test/parser/ets/float_separator_1.ets @@ -14,5 +14,5 @@ */ function main() { - let a: float = -0.0e2_147_483_647 + let a: float = -0.0e2_147_483_647f } diff --git a/ets2panda/test/parser/ets/for_with_break-expected.txt b/ets2panda/test/parser/ets/for_with_break-expected.txt index 25c3039b12..257f20e53e 100644 --- a/ets2panda/test/parser/ets/for_with_break-expected.txt +++ b/ets2panda/test/parser/ets/for_with_break-expected.txt @@ -505,7 +505,7 @@ "loc": { "start": { "line": 19, - "column": 13, + "column": 17, "program": "for_with_break.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/function_implicit_return_type8-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type8-expected.txt index 4714961b87..dd55942add 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type8-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type8-expected.txt @@ -1286,7 +1286,7 @@ "loc": { "start": { "line": 39, - "column": 15, + "column": 24, "program": "function_implicit_return_type8.ets" }, "end": { @@ -1451,7 +1451,7 @@ "loc": { "start": { "line": 40, - "column": 15, + "column": 24, "program": "function_implicit_return_type8.ets" }, "end": { @@ -1616,7 +1616,7 @@ "loc": { "start": { "line": 41, - "column": 15, + "column": 24, "program": "function_implicit_return_type8.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/function_implicit_return_type9-expected.txt b/ets2panda/test/parser/ets/function_implicit_return_type9-expected.txt index b9502a4e99..3355f5dd6d 100644 --- a/ets2panda/test/parser/ets/function_implicit_return_type9-expected.txt +++ b/ets2panda/test/parser/ets/function_implicit_return_type9-expected.txt @@ -1673,7 +1673,7 @@ "loc": { "start": { "line": 43, - "column": 15, + "column": 24, "program": "function_implicit_return_type9.ets" }, "end": { @@ -1838,7 +1838,7 @@ "loc": { "start": { "line": 44, - "column": 15, + "column": 24, "program": "function_implicit_return_type9.ets" }, "end": { @@ -2003,7 +2003,7 @@ "loc": { "start": { "line": 45, - "column": 15, + "column": 24, "program": "function_implicit_return_type9.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2-expected.txt b/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2-expected.txt index 0f0b798931..c73c634d4e 100644 --- a/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2-expected.txt +++ b/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2-expected.txt @@ -696,7 +696,7 @@ }, "end": { "line": 16, - "column": 32, + "column": 33, "program": "imported_module_2.ets" } } @@ -732,7 +732,7 @@ }, "end": { "line": 16, - "column": 32, + "column": 33, "program": "imported_module_2.ets" } } diff --git a/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets b/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets index b5508f11e4..cfbfbd87ed 100644 --- a/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets +++ b/ets2panda/test/parser/ets/import_tests/import_name_conflicts/imported_module_2.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -export const flt: float = 2.345; +export const flt: float = 2.345f; export let c: int = 3; diff --git a/ets2panda/test/parser/ets/import_tests/packages/package_module_1-expected.txt b/ets2panda/test/parser/ets/import_tests/packages/package_module_1-expected.txt index b200321200..f72675996e 100755 --- a/ets2panda/test/parser/ets/import_tests/packages/package_module_1-expected.txt +++ b/ets2panda/test/parser/ets/import_tests/packages/package_module_1-expected.txt @@ -698,7 +698,7 @@ }, "end": { "line": 18, - "column": 33, + "column": 34, "program": "package_module_2.ets" } } @@ -734,7 +734,7 @@ }, "end": { "line": 18, - "column": 33, + "column": 34, "program": "package_module_2.ets" } } diff --git a/ets2panda/test/parser/ets/import_tests/packages/package_module_2-expected.txt b/ets2panda/test/parser/ets/import_tests/packages/package_module_2-expected.txt index b1d61276d9..c746d9151e 100755 --- a/ets2panda/test/parser/ets/import_tests/packages/package_module_2-expected.txt +++ b/ets2panda/test/parser/ets/import_tests/packages/package_module_2-expected.txt @@ -224,7 +224,7 @@ }, "end": { "line": 18, - "column": 33, + "column": 34, "program": "package_module_2.ets" } } @@ -260,7 +260,7 @@ }, "end": { "line": 18, - "column": 33, + "column": 34, "program": "package_module_2.ets" } } @@ -295,7 +295,7 @@ }, "end": { "line": 18, - "column": 34, + "column": 35, "program": "package_module_1.ets" } } @@ -331,7 +331,7 @@ }, "end": { "line": 18, - "column": 34, + "column": 35, "program": "package_module_1.ets" } } diff --git a/ets2panda/test/parser/ets/import_tests/packages/package_module_2.ets b/ets2panda/test/parser/ets/import_tests/packages/package_module_2.ets index d7cfbc6715..4b828a1d6b 100644 --- a/ets2panda/test/parser/ets/import_tests/packages/package_module_2.ets +++ b/ets2panda/test/parser/ets/import_tests/packages/package_module_2.ets @@ -15,4 +15,4 @@ package import_tests.packages; -export const flt: float = 1.2345; +export const flt: float = 1.2345f; diff --git a/ets2panda/test/parser/ets/labeledDoWhileStatement-expected.txt b/ets2panda/test/parser/ets/labeledDoWhileStatement-expected.txt index 4c37f7a531..5773b160e0 100644 --- a/ets2panda/test/parser/ets/labeledDoWhileStatement-expected.txt +++ b/ets2panda/test/parser/ets/labeledDoWhileStatement-expected.txt @@ -530,7 +530,7 @@ "loc": { "start": { "line": 22, - "column": 9, + "column": 13, "program": "labeledDoWhileStatement.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/labeledForStatement-expected.txt b/ets2panda/test/parser/ets/labeledForStatement-expected.txt index bb8876b63c..440198edf0 100644 --- a/ets2panda/test/parser/ets/labeledForStatement-expected.txt +++ b/ets2panda/test/parser/ets/labeledForStatement-expected.txt @@ -1111,7 +1111,7 @@ "loc": { "start": { "line": 29, - "column": 11, + "column": 15, "program": "labeledForStatement.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/labeledWhileStatement-expected.txt b/ets2panda/test/parser/ets/labeledWhileStatement-expected.txt index a5074ba198..cefec5d022 100644 --- a/ets2panda/test/parser/ets/labeledWhileStatement-expected.txt +++ b/ets2panda/test/parser/ets/labeledWhileStatement-expected.txt @@ -647,7 +647,7 @@ "loc": { "start": { "line": 23, - "column": 9, + "column": 13, "program": "labeledWhileStatement.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/lambda-type-inference-expected.txt b/ets2panda/test/parser/ets/lambda-type-inference-expected.txt index 677295a425..b8e4591d4d 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference-expected.txt +++ b/ets2panda/test/parser/ets/lambda-type-inference-expected.txt @@ -1633,28 +1633,43 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ETSNewClassInstanceExpression", - "typeReference": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "String", - "decorators": [], + "type": "MemberExpression", + "object": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 21, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 37, + "column": 27, + "program": "lambda-type-inference.ets" + } + } + }, "loc": { "start": { "line": 37, - "column": 20, + "column": 21, "program": "lambda-type-inference.ets" }, "end": { "line": 37, - "column": 26, + "column": 28, "program": "lambda-type-inference.ets" } } @@ -1662,47 +1677,66 @@ "loc": { "start": { "line": 37, - "column": 20, + "column": 21, "program": "lambda-type-inference.ets" }, "end": { "line": 37, - "column": 27, + "column": 28, "program": "lambda-type-inference.ets" } } }, + "arguments": [ + { + "type": "StringLiteral", + "value": "hello", + "loc": { + "start": { + "line": 37, + "column": 28, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 37, + "column": 35, + "program": "lambda-type-inference.ets" + } + } + } + ], "loc": { "start": { "line": 37, - "column": 20, + "column": 16, "program": "lambda-type-inference.ets" }, "end": { "line": 37, - "column": 27, + "column": 37, "program": "lambda-type-inference.ets" } } }, - "arguments": [ - { - "type": "StringLiteral", - "value": "hello", - "loc": { - "start": { - "line": 37, - "column": 27, - "program": "lambda-type-inference.ets" - }, - "end": { - "line": 37, - "column": 34, - "program": "lambda-type-inference.ets" - } + "property": { + "type": "Identifier", + "name": "length", + "decorators": [], + "loc": { + "start": { + "line": 37, + "column": 38, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 37, + "column": 44, + "program": "lambda-type-inference.ets" } } - ], + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 37, @@ -1711,24 +1745,24 @@ }, "end": { "line": 37, - "column": 36, + "column": 44, "program": "lambda-type-inference.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 37, - "column": 36, + "column": 45, "program": "lambda-type-inference.ets" }, "end": { "line": 37, - "column": 42, + "column": 50, "program": "lambda-type-inference.ets" } } @@ -1743,26 +1777,13 @@ }, "end": { "line": 37, - "column": 42, - "program": "lambda-type-inference.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 37, - "column": 46, - "program": "lambda-type-inference.ets" - }, - "end": { - "line": 37, - "column": 49, + "column": 50, "program": "lambda-type-inference.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 37, @@ -1771,7 +1792,7 @@ }, "end": { "line": 37, - "column": 42, + "column": 52, "program": "lambda-type-inference.ets" } } @@ -1784,7 +1805,7 @@ }, "end": { "line": 37, - "column": 50, + "column": 53, "program": "lambda-type-inference.ets" } } @@ -1894,28 +1915,43 @@ { "type": "ReturnStatement", "argument": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ETSNewClassInstanceExpression", - "typeReference": { - "type": "ETSTypeReference", - "part": { - "type": "ETSTypeReferencePart", - "name": { - "type": "Identifier", - "name": "String", - "decorators": [], + "type": "MemberExpression", + "object": { + "type": "ETSNewClassInstanceExpression", + "typeReference": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "String", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 21, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 40, + "column": 27, + "program": "lambda-type-inference.ets" + } + } + }, "loc": { "start": { "line": 40, - "column": 20, + "column": 21, "program": "lambda-type-inference.ets" }, "end": { "line": 40, - "column": 26, + "column": 28, "program": "lambda-type-inference.ets" } } @@ -1923,47 +1959,66 @@ "loc": { "start": { "line": 40, - "column": 20, + "column": 21, "program": "lambda-type-inference.ets" }, "end": { "line": 40, - "column": 27, + "column": 28, "program": "lambda-type-inference.ets" } } }, + "arguments": [ + { + "type": "StringLiteral", + "value": "hello", + "loc": { + "start": { + "line": 40, + "column": 28, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 40, + "column": 35, + "program": "lambda-type-inference.ets" + } + } + } + ], "loc": { "start": { "line": 40, - "column": 20, + "column": 16, "program": "lambda-type-inference.ets" }, "end": { "line": 40, - "column": 27, + "column": 37, "program": "lambda-type-inference.ets" } } }, - "arguments": [ - { - "type": "StringLiteral", - "value": "hello", - "loc": { - "start": { - "line": 40, - "column": 27, - "program": "lambda-type-inference.ets" - }, - "end": { - "line": 40, - "column": 34, - "program": "lambda-type-inference.ets" - } + "property": { + "type": "Identifier", + "name": "length", + "decorators": [], + "loc": { + "start": { + "line": 40, + "column": 38, + "program": "lambda-type-inference.ets" + }, + "end": { + "line": 40, + "column": 44, + "program": "lambda-type-inference.ets" } } - ], + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 40, @@ -1972,24 +2027,24 @@ }, "end": { "line": 40, - "column": 36, + "column": 44, "program": "lambda-type-inference.ets" } } }, "property": { "type": "Identifier", - "name": "length", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 40, - "column": 36, + "column": 45, "program": "lambda-type-inference.ets" }, "end": { "line": 40, - "column": 42, + "column": 50, "program": "lambda-type-inference.ets" } } @@ -2004,26 +2059,13 @@ }, "end": { "line": 40, - "column": 42, - "program": "lambda-type-inference.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 40, - "column": 46, - "program": "lambda-type-inference.ets" - }, - "end": { - "line": 40, - "column": 49, + "column": 50, "program": "lambda-type-inference.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 40, @@ -2032,7 +2074,7 @@ }, "end": { "line": 40, - "column": 42, + "column": 52, "program": "lambda-type-inference.ets" } } @@ -2045,7 +2087,7 @@ }, "end": { "line": 40, - "column": 50, + "column": 53, "program": "lambda-type-inference.ets" } } diff --git a/ets2panda/test/parser/ets/lambda-type-inference.ets b/ets2panda/test/parser/ets/lambda-type-inference.ets index 81223e7cec..f36c02babf 100644 --- a/ets2panda/test/parser/ets/lambda-type-inference.ets +++ b/ets2panda/test/parser/ets/lambda-type-inference.ets @@ -34,10 +34,10 @@ function main(): void { }); callbackNoArgInt((): int => { - return new String("hello").length as int; + return (new String("hello")).length.toInt(); }); callbackNoArgInt(() => { - return new String("hello").length as int; + return (new String("hello")).length.toInt(); }); callbackIntStringBool((x: int, y: String): boolean => { diff --git a/ets2panda/test/parser/ets/parentheses_expression_value-expected.txt b/ets2panda/test/parser/ets/parentheses_expression_value-expected.txt index 06f443f4b1..04752bd0e5 100644 --- a/ets2panda/test/parser/ets/parentheses_expression_value-expected.txt +++ b/ets2panda/test/parser/ets/parentheses_expression_value-expected.txt @@ -794,7 +794,7 @@ "loc": { "start": { "line": 22, - "column": 7, + "column": 12, "program": "parentheses_expression_value.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/rethrow-func-1-expected.txt b/ets2panda/test/parser/ets/rethrow-func-1-expected.txt index 76388e85f7..8e9d7e6050 100644 --- a/ets2panda/test/parser/ets/rethrow-func-1-expected.txt +++ b/ets2panda/test/parser/ets/rethrow-func-1-expected.txt @@ -817,40 +817,8 @@ } }, "init": { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 1, - "loc": { - "start": { - "line": 26, - "column": 17, - "program": "rethrow-func-1.ets" - }, - "end": { - "line": 26, - "column": 18, - "program": "rethrow-func-1.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 0, - "loc": { - "start": { - "line": 26, - "column": 21, - "program": "rethrow-func-1.ets" - }, - "end": { - "line": 26, - "column": 22, - "program": "rethrow-func-1.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2147483647, "loc": { "start": { "line": 26, @@ -1307,3 +1275,4 @@ } } } +SyntaxError: Division by zero is not allowed. [rethrow-func-1.ets:26:17] diff --git a/ets2panda/test/parser/ets/simple_types-expected.txt b/ets2panda/test/parser/ets/simple_types-expected.txt index 02ebb2a181..cc14840310 100644 --- a/ets2panda/test/parser/ets/simple_types-expected.txt +++ b/ets2panda/test/parser/ets/simple_types-expected.txt @@ -589,8 +589,77 @@ } }, "right": { - "type": "NumberLiteral", - "value": 3.1415, + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 16, + "program": "simple_types.ets" + }, + "end": { + "line": 26, + "column": 22, + "program": "simple_types.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "toFloat", + "decorators": [], + "loc": { + "start": { + "line": 26, + "column": 23, + "program": "simple_types.ets" + }, + "end": { + "line": 26, + "column": 30, + "program": "simple_types.ets" + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 26, + "column": 16, + "program": "simple_types.ets" + }, + "end": { + "line": 26, + "column": 30, + "program": "simple_types.ets" + } + } + }, + "arguments": [ + { + "type": "NumberLiteral", + "value": 3.1415, + "loc": { + "start": { + "line": 26, + "column": 31, + "program": "simple_types.ets" + }, + "end": { + "line": 26, + "column": 37, + "program": "simple_types.ets" + } + } + } + ], + "optional": false, "loc": { "start": { "line": 26, @@ -599,7 +668,7 @@ }, "end": { "line": 26, - "column": 22, + "column": 38, "program": "simple_types.ets" } } @@ -612,7 +681,7 @@ }, "end": { "line": 26, - "column": 22, + "column": 38, "program": "simple_types.ets" } } @@ -625,7 +694,7 @@ }, "end": { "line": 26, - "column": 22, + "column": 38, "program": "simple_types.ets" } } @@ -1249,7 +1318,7 @@ }, "end": { "line": 26, - "column": 22, + "column": 38, "program": "simple_types.ets" } } diff --git a/ets2panda/test/parser/ets/simple_types.ets b/ets2panda/test/parser/ets/simple_types.ets index 1b7e2adf19..d94d7ace0f 100644 --- a/ets2panda/test/parser/ets/simple_types.ets +++ b/ets2panda/test/parser/ets/simple_types.ets @@ -23,7 +23,7 @@ let f: char = c'a'; let g: undefined; -let k: float = 3.1415; +let k: float = Double.toFloat(3.1415); let l: double = 3.1415; let c2: int = a; diff --git a/ets2panda/test/parser/ets/string_template_1-expected.txt b/ets2panda/test/parser/ets/string_template_1-expected.txt index 2de1927709..40bc249bce 100644 --- a/ets2panda/test/parser/ets/string_template_1-expected.txt +++ b/ets2panda/test/parser/ets/string_template_1-expected.txt @@ -428,7 +428,7 @@ "loc": { "start": { "line": 20, - "column": 11, + "column": 20, "program": "string_template_1.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/string_template_2-expected.txt b/ets2panda/test/parser/ets/string_template_2-expected.txt index 2574c1b4a2..df3eabfe91 100644 --- a/ets2panda/test/parser/ets/string_template_2-expected.txt +++ b/ets2panda/test/parser/ets/string_template_2-expected.txt @@ -205,97 +205,8 @@ } }, "init": { - "type": "TemplateLiteral", - "expressions": [ - { - "type": "BinaryExpression", - "operator": "/", - "left": { - "type": "NumberLiteral", - "value": 14, - "loc": { - "start": { - "line": 17, - "column": 47, - "program": "string_template_2.ets" - }, - "end": { - "line": 17, - "column": 49, - "program": "string_template_2.ets" - } - } - }, - "right": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 17, - "column": 50, - "program": "string_template_2.ets" - }, - "end": { - "line": 17, - "column": 51, - "program": "string_template_2.ets" - } - } - }, - "loc": { - "start": { - "line": 17, - "column": 47, - "program": "string_template_2.ets" - }, - "end": { - "line": 17, - "column": 51, - "program": "string_template_2.ets" - } - } - } - ], - "quasis": [ - { - "type": "TemplateElement", - "value": { - "raw": "(escaped expression) \${14/2} = ", - "cooked": "(escaped expression) ${14/2} = " - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "string_template_2.ets" - }, - "end": { - "line": 17, - "column": 45, - "program": "string_template_2.ets" - } - } - }, - { - "type": "TemplateElement", - "value": { - "raw": "", - "cooked": "" - }, - "loc": { - "start": { - "line": 17, - "column": 52, - "program": "string_template_2.ets" - }, - "end": { - "line": 17, - "column": 52, - "program": "string_template_2.ets" - } - } - } - ], + "type": "StringLiteral", + "value": "(escaped expression) ${14/2} = 7", "loc": { "start": { "line": 17, @@ -394,9 +305,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "(escaped expression) ${14/2} = 7", "loc": { "start": { "line": 18, @@ -527,9 +437,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "(escaped expression) ${14/2} = 7", "loc": { "start": { "line": 20, @@ -544,9 +453,8 @@ } }, { - "type": "Identifier", - "name": "expected", - "decorators": [], + "type": "StringLiteral", + "value": "(escaped expression) ${14/2} = 7", "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/string_template_3-expected.txt b/ets2panda/test/parser/ets/string_template_3-expected.txt index b0c8377dd3..ea684bd5fe 100644 --- a/ets2panda/test/parser/ets/string_template_3-expected.txt +++ b/ets2panda/test/parser/ets/string_template_3-expected.txt @@ -205,29 +205,8 @@ } }, "init": { - "type": "TemplateLiteral", - "expressions": [], - "quasis": [ - { - "type": "TemplateElement", - "value": { - "raw": "(slash at curly braces) $\{true || false\}", - "cooked": "(slash at curly braces) ${true || false}" - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "string_template_3.ets" - }, - "end": { - "line": 17, - "column": 55, - "program": "string_template_3.ets" - } - } - } - ], + "type": "StringLiteral", + "value": "(slash at curly braces) ${true || false}", "loc": { "start": { "line": 17, @@ -326,9 +305,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "(slash at curly braces) ${true || false}", "loc": { "start": { "line": 18, @@ -393,97 +371,8 @@ } }, "init": { - "type": "TemplateLiteral", - "expressions": [ - { - "type": "LogicalExpression", - "operator": "||", - "left": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 19, - "column": 46, - "program": "string_template_3.ets" - }, - "end": { - "line": 19, - "column": 50, - "program": "string_template_3.ets" - } - } - }, - "right": { - "type": "BooleanLiteral", - "value": false, - "loc": { - "start": { - "line": 19, - "column": 54, - "program": "string_template_3.ets" - }, - "end": { - "line": 19, - "column": 59, - "program": "string_template_3.ets" - } - } - }, - "loc": { - "start": { - "line": 19, - "column": 46, - "program": "string_template_3.ets" - }, - "end": { - "line": 19, - "column": 59, - "program": "string_template_3.ets" - } - } - } - ], - "quasis": [ - { - "type": "TemplateElement", - "value": { - "raw": "(slash at curly braces) ", - "cooked": "(slash at curly braces) " - }, - "loc": { - "start": { - "line": 19, - "column": 20, - "program": "string_template_3.ets" - }, - "end": { - "line": 19, - "column": 44, - "program": "string_template_3.ets" - } - } - }, - { - "type": "TemplateElement", - "value": { - "raw": "", - "cooked": "" - }, - "loc": { - "start": { - "line": 19, - "column": 60, - "program": "string_template_3.ets" - }, - "end": { - "line": 19, - "column": 60, - "program": "string_template_3.ets" - } - } - } - ], + "type": "StringLiteral", + "value": "(slash at curly braces) true", "loc": { "start": { "line": 19, @@ -548,9 +437,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "(slash at curly braces) ${true || false}", "loc": { "start": { "line": 20, @@ -565,9 +453,8 @@ } }, { - "type": "Identifier", - "name": "expected", - "decorators": [], + "type": "StringLiteral", + "value": "(slash at curly braces) true", "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/string_template_4-expected.txt b/ets2panda/test/parser/ets/string_template_4-expected.txt index 17b8cf3405..da47a2a4c0 100644 --- a/ets2panda/test/parser/ets/string_template_4-expected.txt +++ b/ets2panda/test/parser/ets/string_template_4-expected.txt @@ -205,86 +205,8 @@ } }, "init": { - "type": "TemplateLiteral", - "expressions": [ - { - "type": "TemplateLiteral", - "expressions": [], - "quasis": [ - { - "type": "TemplateElement", - "value": { - "raw": "backtick = \`", - "cooked": "backtick = `" - }, - "loc": { - "start": { - "line": 17, - "column": 23, - "program": "string_template_4.ets" - }, - "end": { - "line": 17, - "column": 36, - "program": "string_template_4.ets" - } - } - } - ], - "loc": { - "start": { - "line": 17, - "column": 22, - "program": "string_template_4.ets" - }, - "end": { - "line": 17, - "column": 37, - "program": "string_template_4.ets" - } - } - } - ], - "quasis": [ - { - "type": "TemplateElement", - "value": { - "raw": "nested ", - "cooked": "nested " - }, - "loc": { - "start": { - "line": 17, - "column": 13, - "program": "string_template_4.ets" - }, - "end": { - "line": 17, - "column": 20, - "program": "string_template_4.ets" - } - } - }, - { - "type": "TemplateElement", - "value": { - "raw": "", - "cooked": "" - }, - "loc": { - "start": { - "line": 17, - "column": 38, - "program": "string_template_4.ets" - }, - "end": { - "line": 17, - "column": 38, - "program": "string_template_4.ets" - } - } - } - ], + "type": "StringLiteral", + "value": "nested backtick = `", "loc": { "start": { "line": 17, @@ -383,9 +305,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "nested backtick = `", "loc": { "start": { "line": 18, @@ -516,9 +437,8 @@ }, "arguments": [ { - "type": "Identifier", - "name": "v", - "decorators": [], + "type": "StringLiteral", + "value": "nested backtick = `", "loc": { "start": { "line": 20, @@ -533,9 +453,8 @@ } }, { - "type": "Identifier", - "name": "expected", - "decorators": [], + "type": "StringLiteral", + "value": "nested backtick = `", "loc": { "start": { "line": 20, diff --git a/ets2panda/test/parser/ets/switch2-expected.txt b/ets2panda/test/parser/ets/switch2-expected.txt index f2edf57641..4e12dd2d58 100644 --- a/ets2panda/test/parser/ets/switch2-expected.txt +++ b/ets2panda/test/parser/ets/switch2-expected.txt @@ -829,3 +829,6 @@ } } } +TypeError: Switch case type 'int' is not comparable to discriminant type 'byte' [switch2.ets:21:8] +TypeError: Switch case type 'int' is not comparable to discriminant type 'byte' [switch2.ets:22:8] +TypeError: Switch case type 'int' is not comparable to discriminant type 'byte' [switch2.ets:25:8] diff --git a/ets2panda/test/parser/ets/switch_char_compare_num-expected.txt b/ets2panda/test/parser/ets/switch_char_compare_num-expected.txt index dd1cbe89ce..d1aa6c5581 100644 --- a/ets2panda/test/parser/ets/switch_char_compare_num-expected.txt +++ b/ets2panda/test/parser/ets/switch_char_compare_num-expected.txt @@ -476,3 +476,4 @@ } } } +TypeError: Switch case type 'int' is not comparable to discriminant type 'char' [switch_char_compare_num.ets:21:14] diff --git a/ets2panda/test/parser/ets/switch_readonly_member-expected.txt b/ets2panda/test/parser/ets/switch_readonly_member-expected.txt index c9dceaf4f6..ab089826db 100644 --- a/ets2panda/test/parser/ets/switch_readonly_member-expected.txt +++ b/ets2panda/test/parser/ets/switch_readonly_member-expected.txt @@ -693,43 +693,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Fgr", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 14, - "program": "switch_readonly_member.ets" - }, - "end": { - "line": 27, - "column": 17, - "program": "switch_readonly_member.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 18, - "program": "switch_readonly_member.ets" - }, - "end": { - "line": 27, - "column": 20, - "program": "switch_readonly_member.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "{", "loc": { "start": { "line": 27, @@ -777,43 +742,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Sqr", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 14, - "program": "switch_readonly_member.ets" - }, - "end": { - "line": 29, - "column": 17, - "program": "switch_readonly_member.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 18, - "program": "switch_readonly_member.ets" - }, - "end": { - "line": 29, - "column": 20, - "program": "switch_readonly_member.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "[", "loc": { "start": { "line": 29, diff --git a/ets2panda/test/parser/ets/switch_readonly_member_compare_char-expected.txt b/ets2panda/test/parser/ets/switch_readonly_member_compare_char-expected.txt index f8f43cea1a..fd21a4ff30 100644 --- a/ets2panda/test/parser/ets/switch_readonly_member_compare_char-expected.txt +++ b/ets2panda/test/parser/ets/switch_readonly_member_compare_char-expected.txt @@ -693,43 +693,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Fgr", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 14, - "program": "switch_readonly_member_compare_char.ets" - }, - "end": { - "line": 27, - "column": 17, - "program": "switch_readonly_member_compare_char.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 18, - "program": "switch_readonly_member_compare_char.ets" - }, - "end": { - "line": 27, - "column": 20, - "program": "switch_readonly_member_compare_char.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "{", "loc": { "start": { "line": 27, @@ -777,43 +742,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Sqr", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 14, - "program": "switch_readonly_member_compare_char.ets" - }, - "end": { - "line": 29, - "column": 17, - "program": "switch_readonly_member_compare_char.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 18, - "program": "switch_readonly_member_compare_char.ets" - }, - "end": { - "line": 29, - "column": 20, - "program": "switch_readonly_member_compare_char.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "[", "loc": { "start": { "line": 29, diff --git a/ets2panda/test/parser/ets/switch_readonly_member_compare_char_2-expected.txt b/ets2panda/test/parser/ets/switch_readonly_member_compare_char_2-expected.txt index e6f846ba4c..d9d12a2ab7 100644 --- a/ets2panda/test/parser/ets/switch_readonly_member_compare_char_2-expected.txt +++ b/ets2panda/test/parser/ets/switch_readonly_member_compare_char_2-expected.txt @@ -742,43 +742,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Fgr", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 14, - "program": "switch_readonly_member_compare_char_2.ets" - }, - "end": { - "line": 29, - "column": 17, - "program": "switch_readonly_member_compare_char_2.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 29, - "column": 18, - "program": "switch_readonly_member_compare_char_2.ets" - }, - "end": { - "line": 29, - "column": 20, - "program": "switch_readonly_member_compare_char_2.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "{", "loc": { "start": { "line": 29, @@ -826,43 +791,8 @@ { "type": "SwitchCase", "test": { - "type": "MemberExpression", - "object": { - "type": "Identifier", - "name": "Sqr", - "decorators": [], - "loc": { - "start": { - "line": 31, - "column": 14, - "program": "switch_readonly_member_compare_char_2.ets" - }, - "end": { - "line": 31, - "column": 17, - "program": "switch_readonly_member_compare_char_2.ets" - } - } - }, - "property": { - "type": "Identifier", - "name": "BR", - "decorators": [], - "loc": { - "start": { - "line": 31, - "column": 18, - "program": "switch_readonly_member_compare_char_2.ets" - }, - "end": { - "line": 31, - "column": 20, - "program": "switch_readonly_member_compare_char_2.ets" - } - } - }, - "computed": false, - "optional": false, + "type": "CharLiteral", + "value": "[", "loc": { "start": { "line": 31, diff --git a/ets2panda/test/parser/ets/test_type_alias6-expected.txt b/ets2panda/test/parser/ets/test_type_alias6-expected.txt index 3107be32be..3714ac94d3 100644 --- a/ets2panda/test/parser/ets/test_type_alias6-expected.txt +++ b/ets2panda/test/parser/ets/test_type_alias6-expected.txt @@ -447,4 +447,4 @@ } TypeError: Variable 'x' has already been declared. [test_type_alias6.ets:17:5] TypeError: Type name 'x' used in the wrong context [test_type_alias6.ets:17:5] -TypeError: Type 'double' cannot be assigned to type 'int' [test_type_alias6.ets:17:9] +TypeError: Type 'Double' cannot be assigned to type 'Int' [test_type_alias6.ets:17:9] diff --git a/ets2panda/test/parser/ets/this_cmp_object-expected.txt b/ets2panda/test/parser/ets/this_cmp_object-expected.txt index 68323c16cd..d770e9b0ce 100644 --- a/ets2panda/test/parser/ets/this_cmp_object-expected.txt +++ b/ets2panda/test/parser/ets/this_cmp_object-expected.txt @@ -161,53 +161,7 @@ } }, "init": { - "type": "ConditionalExpression", - "test": { - "type": "BooleanLiteral", - "value": true, - "loc": { - "start": { - "line": 18, - "column": 26, - "program": "this_cmp_object.ets" - }, - "end": { - "line": 18, - "column": 30, - "program": "this_cmp_object.ets" - } - } - }, - "consequent": { - "type": "ThisExpression", - "loc": { - "start": { - "line": 18, - "column": 33, - "program": "this_cmp_object.ets" - }, - "end": { - "line": 18, - "column": 37, - "program": "this_cmp_object.ets" - } - } - }, - "alternate": { - "type": "ThisExpression", - "loc": { - "start": { - "line": 18, - "column": 40, - "program": "this_cmp_object.ets" - }, - "end": { - "line": 18, - "column": 44, - "program": "this_cmp_object.ets" - } - } - }, + "type": "ThisExpression", "loc": { "start": { "line": 18, @@ -353,7 +307,7 @@ "loc": { "start": { "line": 19, - "column": 12, + "column": 20, "program": "this_cmp_object.ets" }, "end": { diff --git a/ets2panda/test/parser/ets/tupleIndexWithNumbers-expected.txt b/ets2panda/test/parser/ets/tupleIndexWithNumbers-expected.txt index f72997ce91..6934a43364 100644 --- a/ets2panda/test/parser/ets/tupleIndexWithNumbers-expected.txt +++ b/ets2panda/test/parser/ets/tupleIndexWithNumbers-expected.txt @@ -574,9 +574,8 @@ } }, "property": { - "type": "Identifier", - "name": "index1", - "decorators": [], + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 21, @@ -672,9 +671,8 @@ } }, "property": { - "type": "Identifier", - "name": "index2", - "decorators": [], + "type": "NumberLiteral", + "value": 1, "loc": { "start": { "line": 22, diff --git a/ets2panda/test/parser/ets/tuple_type_1-expected.txt b/ets2panda/test/parser/ets/tuple_type_1-expected.txt index 753dcbb963..5cfa191987 100644 --- a/ets2panda/test/parser/ets/tuple_type_1-expected.txt +++ b/ets2panda/test/parser/ets/tuple_type_1-expected.txt @@ -560,38 +560,8 @@ } }, { - "type": "TSAsExpression", - "expression": { - "type": "NumberLiteral", - "value": 2, - "loc": { - "start": { - "line": 23, - "column": 31, - "program": "tuple_type_1.ets" - }, - "end": { - "line": 23, - "column": 32, - "program": "tuple_type_1.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 23, - "column": 36, - "program": "tuple_type_1.ets" - }, - "end": { - "line": 23, - "column": 42, - "program": "tuple_type_1.ets" - } - } - }, + "type": "NumberLiteral", + "value": 2, "loc": { "start": { "line": 23, diff --git a/ets2panda/test/parser/ets/type_cast-expected.txt b/ets2panda/test/parser/ets/type_cast-expected.txt index a721015acb..d75a72aa64 100644 --- a/ets2panda/test/parser/ets/type_cast-expected.txt +++ b/ets2panda/test/parser/ets/type_cast-expected.txt @@ -186,11 +186,45 @@ } }, "value": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 19, + "column": 23, + "program": "type_cast.ets" + }, + "end": { + "line": 19, + "column": 27, + "program": "type_cast.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 28, + "program": "type_cast.ets" + }, + "end": { + "line": 19, + "column": 29, + "program": "type_cast.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 19, @@ -199,24 +233,24 @@ }, "end": { "line": 19, - "column": 27, + "column": 29, "program": "type_cast.ets" } } }, "property": { "type": "Identifier", - "name": "d", + "name": "toInt", "decorators": [], "loc": { "start": { "line": 19, - "column": 28, + "column": 30, "program": "type_cast.ets" }, "end": { "line": 19, - "column": 29, + "column": 35, "program": "type_cast.ets" } } @@ -231,26 +265,13 @@ }, "end": { "line": 19, - "column": 29, - "program": "type_cast.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 19, - "column": 33, - "program": "type_cast.ets" - }, - "end": { - "line": 19, - "column": 36, + "column": 35, "program": "type_cast.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 19, @@ -259,7 +280,7 @@ }, "end": { "line": 19, - "column": 29, + "column": 37, "program": "type_cast.ets" } } @@ -295,7 +316,7 @@ }, "end": { "line": 19, - "column": 29, + "column": 37, "program": "type_cast.ets" } } @@ -391,11 +412,45 @@ } }, "value": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 21, + "column": 25, + "program": "type_cast.ets" + }, + "end": { + "line": 21, + "column": 29, + "program": "type_cast.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "c", + "decorators": [], + "loc": { + "start": { + "line": 21, + "column": 30, + "program": "type_cast.ets" + }, + "end": { + "line": 21, + "column": 31, + "program": "type_cast.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 21, @@ -404,24 +459,24 @@ }, "end": { "line": 21, - "column": 29, + "column": 31, "program": "type_cast.ets" } } }, "property": { "type": "Identifier", - "name": "c", + "name": "toByte", "decorators": [], "loc": { "start": { "line": 21, - "column": 30, + "column": 32, "program": "type_cast.ets" }, "end": { "line": 21, - "column": 31, + "column": 38, "program": "type_cast.ets" } } @@ -436,26 +491,13 @@ }, "end": { "line": 21, - "column": 31, - "program": "type_cast.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 21, - "column": 35, - "program": "type_cast.ets" - }, - "end": { - "line": 21, - "column": 39, + "column": 38, "program": "type_cast.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 21, @@ -464,7 +506,7 @@ }, "end": { "line": 21, - "column": 31, + "column": 40, "program": "type_cast.ets" } } @@ -500,7 +542,7 @@ }, "end": { "line": 21, - "column": 31, + "column": 40, "program": "type_cast.ets" } } @@ -525,11 +567,45 @@ } }, "value": { - "type": "TSAsExpression", - "expression": { + "type": "CallExpression", + "callee": { "type": "MemberExpression", "object": { - "type": "ThisExpression", + "type": "MemberExpression", + "object": { + "type": "ThisExpression", + "loc": { + "start": { + "line": 22, + "column": 16, + "program": "type_cast.ets" + }, + "end": { + "line": 22, + "column": 20, + "program": "type_cast.ets" + } + } + }, + "property": { + "type": "Identifier", + "name": "d", + "decorators": [], + "loc": { + "start": { + "line": 22, + "column": 21, + "program": "type_cast.ets" + }, + "end": { + "line": 22, + "column": 22, + "program": "type_cast.ets" + } + } + }, + "computed": false, + "optional": false, "loc": { "start": { "line": 22, @@ -538,24 +614,24 @@ }, "end": { "line": 22, - "column": 20, + "column": 22, "program": "type_cast.ets" } } }, "property": { "type": "Identifier", - "name": "d", + "name": "toFloat", "decorators": [], "loc": { "start": { "line": 22, - "column": 21, + "column": 23, "program": "type_cast.ets" }, "end": { "line": 22, - "column": 22, + "column": 30, "program": "type_cast.ets" } } @@ -570,26 +646,13 @@ }, "end": { "line": 22, - "column": 22, - "program": "type_cast.ets" - } - } - }, - "typeAnnotation": { - "type": "ETSPrimitiveType", - "loc": { - "start": { - "line": 22, - "column": 26, - "program": "type_cast.ets" - }, - "end": { - "line": 22, - "column": 31, + "column": 30, "program": "type_cast.ets" } } }, + "arguments": [], + "optional": false, "loc": { "start": { "line": 22, @@ -598,7 +661,7 @@ }, "end": { "line": 22, - "column": 22, + "column": 32, "program": "type_cast.ets" } } @@ -634,7 +697,7 @@ }, "end": { "line": 22, - "column": 22, + "column": 32, "program": "type_cast.ets" } } diff --git a/ets2panda/test/parser/ets/type_cast.ets b/ets2panda/test/parser/ets/type_cast.ets index 147c1d1e6f..2793fba742 100644 --- a/ets2panda/test/parser/ets/type_cast.ets +++ b/ets2panda/test/parser/ets/type_cast.ets @@ -16,8 +16,8 @@ export class type_cast { private i1: int = 34; private d: double = 3.7; - private i2: int = this.d as int; + private i2: int = this.d.toInt(); protected c: char = c'c'; - protected b: byte = this.c as byte; - f: float = this.d as float; + protected b: byte = this.c.toByte(); + f: float = this.d.toFloat(); } diff --git a/ets2panda/test/parser/ets/unary_op-expected.txt b/ets2panda/test/parser/ets/unary_op-expected.txt index 10516d0b64..6671ec78a8 100644 --- a/ets2panda/test/parser/ets/unary_op-expected.txt +++ b/ets2panda/test/parser/ets/unary_op-expected.txt @@ -433,25 +433,8 @@ } }, "right": { - "type": "UnaryExpression", - "operator": "+", - "prefix": true, - "argument": { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 19, - "column": 10, - "program": "unary_op.ets" - }, - "end": { - "line": 19, - "column": 11, - "program": "unary_op.ets" - } - } - }, + "type": "NumberLiteral", + "value": 5, "loc": { "start": { "line": 19, @@ -824,26 +807,8 @@ } }, "right": { - "type": "UnaryExpression", - "operator": "!", - "prefix": true, - "argument": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 10, - "program": "unary_op.ets" - }, - "end": { - "line": 25, - "column": 11, - "program": "unary_op.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 25, @@ -1162,25 +1127,8 @@ } }, "value": { - "type": "UnaryExpression", - "operator": "+", - "prefix": true, - "argument": { - "type": "NumberLiteral", - "value": 5, - "loc": { - "start": { - "line": 19, - "column": 10, - "program": "unary_op.ets" - }, - "end": { - "line": 19, - "column": 11, - "program": "unary_op.ets" - } - } - }, + "type": "NumberLiteral", + "value": 5, "loc": { "start": { "line": 19, @@ -1569,26 +1517,8 @@ } }, "value": { - "type": "UnaryExpression", - "operator": "!", - "prefix": true, - "argument": { - "type": "Identifier", - "name": "i", - "decorators": [], - "loc": { - "start": { - "line": 25, - "column": 10, - "program": "unary_op.ets" - }, - "end": { - "line": 25, - "column": 11, - "program": "unary_op.ets" - } - } - }, + "type": "BooleanLiteral", + "value": false, "loc": { "start": { "line": 25, diff --git a/ets2panda/test/parser/ets/var_declare-expected.txt b/ets2panda/test/parser/ets/var_declare-expected.txt index e6c6ab3282..7b2fb7d830 100644 --- a/ets2panda/test/parser/ets/var_declare-expected.txt +++ b/ets2panda/test/parser/ets/var_declare-expected.txt @@ -560,7 +560,7 @@ }, "end": { "line": 23, - "column": 32, + "column": 33, "program": "var_declare.ets" } } @@ -573,7 +573,7 @@ }, "end": { "line": 23, - "column": 32, + "column": 33, "program": "var_declare.ets" } } @@ -588,7 +588,7 @@ }, "end": { "line": 23, - "column": 33, + "column": 34, "program": "var_declare.ets" } } diff --git a/ets2panda/test/parser/ets/var_declare.ets b/ets2panda/test/parser/ets/var_declare.ets index 224c7e55e4..56429d9472 100644 --- a/ets2panda/test/parser/ets/var_declare.ets +++ b/ets2panda/test/parser/ets/var_declare.ets @@ -20,6 +20,6 @@ class VarDeclareTest { b *= 10; let c : int , d : int = 5; const e : double = 2.781828; - const Pi : float = 3.14; + const Pi : float = 3.14f; } } diff --git a/ets2panda/test/runtime/ets/ArrayLiteral.ets b/ets2panda/test/runtime/ets/ArrayLiteral.ets index b4a1105843..746f40a5f2 100644 --- a/ets2panda/test/runtime/ets/ArrayLiteral.ets +++ b/ets2panda/test/runtime/ets/ArrayLiteral.ets @@ -34,7 +34,7 @@ function main(): void { const k: long = 2; const l: float = 2.0f; const m: double = 2.0; - const n: byte[] = [h, i, j, k, Float.toByte(l), Double.toByte(m)]; + const n: byte[] = [h, Short.toByte(i), j, Long.toByte(k), Float.toByte(l), Double.toByte(m)]; assertEQ(n[0], 2) assertEQ(n[1], 2) assertEQ(n[2], 2) diff --git a/ets2panda/test/runtime/ets/CastPrimitive.ets b/ets2panda/test/runtime/ets/CastPrimitive.ets index 07263656da..5bc9f8c226 100644 --- a/ets2panda/test/runtime/ets/CastPrimitive.ets +++ b/ets2panda/test/runtime/ets/CastPrimitive.ets @@ -15,82 +15,82 @@ function main(): void { let a : double = 2147483649.0; // 2^31 + 1 - assertEQ(a as float, 2147483648) // rounded - assertEQ(a as long, 2147483649) - assertEQ(a as int, 2147483647 ) // 2^31 - 1 == MAX_INT == 0xFFFFFFFF - assertEQ(a as short, -1 ) // 0xFFFF - assertEQ(a as char, c'\uFFFF') - assertEQ(a as byte, -1 )// 0xFF + assertEQ(Double.toFloat(a), 2147483648) // rounded + assertEQ(Double.toLong(a), 2147483649) + assertEQ(Double.toInt(a), 2147483647 ) // 2^31 - 1 == MAX_INT == 0xFFFFFFFF + assertEQ(Double.toShort(a), -1 ) // 0xFFFF + assertEQ(Double.toChar(a), c'\uFFFF') + assertEQ(Double.toByte(a), -1 )// 0xFF a = -2147483649.0 // 2^31 + 1 - assertEQ(a as float, -2147483648) // rounded - assertEQ(a as long, -2147483649) - assertEQ(a as int, -2147483648) // -2^31 == MIN_INT == 0x10000000 - assertEQ(a as short, 0) - assertEQ(a as char, c'\u0000') - assertEQ(a as byte, 0) + assertEQ(Double.toFloat(a), -2147483648) // rounded + assertEQ(Double.toLong(a), -2147483649) + assertEQ(Double.toInt(a), -2147483648) // -2^31 == MIN_INT == 0x10000000 + assertEQ(Double.toShort(a), 0) + assertEQ(Double.toChar(a), c'\u0000') + assertEQ(Double.toByte(a), 0) let b : float = 70000.9921875f; - assertEQ(b as double, 70000.9921875) - assertEQ(b as long, 70000 ) // rounded, 70000 == 0x11170 - assertEQ(b as int, 70000) - assertEQ(b as short, 4464) // 4464 == 0x1170 - assertEQ(b as char, c'\u1170') - assertEQ(b as byte, 112) // 112 == 0x70 + assertEQ(Float.toDouble(b), 70000.9921875) + assertEQ(Float.toLong(b), 70000 ) // rounded, 70000 == 0x11170 + assertEQ(Float.toInt(b), 70000) + assertEQ(Float.toShort(b), 4464) // 4464 == 0x1170 + assertEQ(Float.toChar(b), c'\u1170') + assertEQ(Float.toByte(b), 112) // 112 == 0x70 let c : long = 1193046; // 1193046 == 0x123456 - assertEQ(c as int, 1193046) - assertEQ(c as short, 13398) // 13398 == 0x3456 - assertEQ(c as char, c'\u3456') - assertEQ(c as byte, 86) // 86 == 0x56 + assertEQ(Long.toInt(c), 1193046) + assertEQ(Long.toShort(c), 13398) // 13398 == 0x3456 + assertEQ(Long.toChar(c), c'\u3456') + assertEQ(Long.toByte(c), 86) // 86 == 0x56 let d : int = 126977; // 65537 == 0x1F001 - assertEQ(d as short, -4095) // -4095 == 0xF001 - assertEQ(d as char, c'\uF001') - assertEQ(d as byte, 1) // 1 == 0x01 + assertEQ(Int.toShort(d), -4095) // -4095 == 0xF001 + assertEQ(Int.toChar(d), c'\uF001') + assertEQ(Int.toByte(d), 1) // 1 == 0x01 let e : short = -30875; // -30875 == 0x8765 - assertEQ(e as double, -30875.0) - assertEQ(e as float, -30875.0) - assertEQ(e as long, -30875) // -30875 == 0xFFFFFFFFFFFF8765 - assertEQ(e as int, -30875) // -30875 == 0xFFFF8765 - assertEQ(e as char, c'\u8765') - assertEQ(e as byte, 101) // 101 == 0x65 + assertEQ(Short.toDouble(e), -30875.0) + assertEQ(Short.toFloat(e), -30875.0) + assertEQ(Short.toLong(e), -30875) // -30875 == 0xFFFFFFFFFFFF8765 + assertEQ(Short.toInt(e), -30875) // -30875 == 0xFFFF8765 + assertEQ(Short.toChar(e), c'\u8765') + assertEQ(Short.toByte(e), 101) // 101 == 0x65 let f : char = c'\uF001'; - assertEQ(f as double, 61441.0) - assertEQ(f as float, 61441.0) - assertEQ(f as long, 61441) // 61441 == 0x000000000000F001 - assertEQ(f as int, 61441) // 61441 == 0x0000F001 - assertEQ(f as short, 0xf001 as short) // -4095 == 0xF001 - assertEQ(f as short, -4095) + assertEQ(Char.toDouble(f), 61441.0) + assertEQ(Char.toFloat(f), 61441.0) + assertEQ(Char.toLong(f), 61441) // 61441 == 0x000000000000F001 + assertEQ(Char.toInt(f), 61441) // 61441 == 0x0000F001 + assertEQ(Char.toShort(f), 0xf001 as short) // -4095 == 0xF001 + assertEQ(Char.toShort(f), -4095) let g : byte = -128; - assertEQ(g as double, -128.0) - assertEQ(g as float, -128.0) - assertEQ(g as long, -128) - assertEQ(g as int, -128) - assertEQ(g as short, -128) - assertEQ(g as char, c'\uFF80') - assertEQ((-128) as byte, -128) - assertEQ((-129) as byte, 127) + assertEQ(Byte.toDouble(g), -128.0) + assertEQ(Byte.toFloat(g), -128.0) + assertEQ(Byte.toLong(g), -128) + assertEQ(Byte.toInt(g), -128) + assertEQ(Byte.toShort(g), -128) + assertEQ(Byte.toChar(g), c'\uFF80') + assertEQ(Int.toByte(-128), -128) + assertEQ(Int.toByte(-129), 127) let i : boolean = true; - assertEQ(i as boolean, true) + assertEQ(i, true) i = false; - assertEQ(i as boolean, false) + assertEQ(i, false) - assertEQ(4294967296.0 as byte, -1) - assertEQ(4294967296.0 as char, c'\uFFFF') - assertEQ(4294967296.0 as short, -1) - assertEQ(4294967296.0 as int, Int.MAX_VALUE) - assertEQ(4294967296.0 as long, 4294967296) - assertEQ(-4294967296.0 as byte, 0) - assertEQ(-4294967296.0 as char, c'\u0000') - assertEQ(-4294967296.0 as short, 0) - assertEQ(-4294967296.0 as int, Int.MIN_VALUE) - assertEQ(-4294967296.0 as long, -4294967296) + assertEQ(Double.toByte(4294967296.0), -1) + assertEQ(Double.toChar(4294967296.0), c'\uFFFF') + assertEQ(Double.toShort(4294967296.0), -1) + assertEQ(Double.toInt(4294967296.0), Int.MAX_VALUE) + assertEQ(Double.toLong(4294967296.0), 4294967296) + assertEQ(Double.toByte(-4294967296.0), 0) + assertEQ(Double.toChar(-4294967296.0), c'\u0000') + assertEQ(Double.toShort(-4294967296.0), 0) + assertEQ(Double.toInt(-4294967296.0), Int.MIN_VALUE) + assertEQ(Double.toLong(-4294967296.0), -4294967296) return; } diff --git a/ets2panda/test/runtime/ets/EnumConstExpression1.ets b/ets2panda/test/runtime/ets/EnumConstExpression1.ets index ee0b6d1cd1..cdaa6b1b0d 100644 --- a/ets2panda/test/runtime/ets/EnumConstExpression1.ets +++ b/ets2panda/test/runtime/ets/EnumConstExpression1.ets @@ -40,8 +40,8 @@ const y: string = -1.7976931348623157e308 + " min float" + 100; const z: string = 2.2250738585072014e-308 + " smallest positive float" + 0.0001; enum Color { - A = a as string, - B = b as String, + A = a, + B = b, C = c, D = d, E = e, diff --git a/ets2panda/test/runtime/ets/NullishCoalescing_01.ets b/ets2panda/test/runtime/ets/NullishCoalescing_01.ets index 0db6c66c43..58b8677c92 100644 --- a/ets2panda/test/runtime/ets/NullishCoalescing_01.ets +++ b/ets2panda/test/runtime/ets/NullishCoalescing_01.ets @@ -15,11 +15,11 @@ function main() { let x1 = (): int | undefined => { return 5; }(); - let y1: int = x1 ?? 3.1; + let y1: int = x1 ?? Double.toInt(3.1); assertEQ(y1, 5) let x2 = (): int | undefined => { return undefined; }(); - let y2: int = x2 ?? 3.1; + let y2: int = x2 ?? Double.toInt(3.1); assertEQ(y2, 3) let x3 = (): number | undefined => { return 5; }(); diff --git a/ets2panda/test/runtime/ets/StringBase64.ets b/ets2panda/test/runtime/ets/StringBase64.ets index 8b5f91d36a..3ef00b1219 100644 --- a/ets2panda/test/runtime/ets/StringBase64.ets +++ b/ets2panda/test/runtime/ets/StringBase64.ets @@ -19,7 +19,7 @@ export class StringBase64 { static readonly TO_BINARY_TABLE : int[] = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; final toBase64(data : String): String { let result : StringBuilder = new StringBuilder(); - let length : int = data.length as int; + let length : int = Double.toInt(data.length); let i : int ; for (i = 0; i < (length - 2); i += 3) { result.append(StringBase64.TO_BASE64_TABLE.charAt(data.charAt(i) >> 2)); @@ -58,7 +58,7 @@ export class StringBase64 { if (leftbits >= 8) { leftbits -= 8; if (!padding) { - result.append(((leftdata >> leftbits) & 0xff) as char); + result.append(Int.toChar((leftdata >> leftbits) & 0xff)); } leftdata &= (1 << leftbits) - 1; } @@ -72,7 +72,7 @@ export class StringBase64 { public run(): void { let str : String = ""; for (let i : int = 0; i < this.n1; i++) { - str += ((25 * random()) + 97) as char; + str += Double.toChar((25 * random()) + 97); } for (let i : int = this.n1; i <= this.n2; i *= 2) { let base64 : String = this.toBase64(str); diff --git a/ets2panda/test/runtime/ets/UpdateExpression.ets b/ets2panda/test/runtime/ets/UpdateExpression.ets index 7c764d28ce..ea79477ae6 100644 --- a/ets2panda/test/runtime/ets/UpdateExpression.ets +++ b/ets2panda/test/runtime/ets/UpdateExpression.ets @@ -81,16 +81,16 @@ function main(): void { { let b: byte = 127; - assertEQ(++b as int, -128) - assertEQ(--b as int, 127) + assertEQ(Byte.toInt(++b), -128) + assertEQ(Byte.toInt(--b), 127) let c: char = 65535; - assertEQ(++c as int, 0) - assertEQ(--c as int, 65535) + assertEQ(Char.toInt(++c), 0) + assertEQ(Char.toInt(--c), 65535) let s: short = 32767; - assertEQ(++s as int, -32768) - assertEQ(--s as int, 32767) + assertEQ(Short.toInt(++s), -32768) + assertEQ(Short.toInt(--s), 32767) } { diff --git a/ets2panda/test/runtime/ets/annotation_tests/annotationConstAs.ets b/ets2panda/test/runtime/ets/annotation_tests/annotationConstAs.ets index addea4ccef..59a937043e 100644 --- a/ets2panda/test/runtime/ets/annotation_tests/annotationConstAs.ets +++ b/ets2panda/test/runtime/ets/annotation_tests/annotationConstAs.ets @@ -14,13 +14,13 @@ */ @interface MyAnno { - a : int = 49 as char as int - b : byte = 1.0 as byte - c : short = c'c' as short - d : int = 12.2f as int - e : long = 123 as long - f : float = c'c' as float - g : double = c'c' as double + a : int = 49 + b : byte = 1 + c : short = 99 + d : int = 12 + e : long = 123 + f : float = 99 + g : double = 99 } function main() { diff --git a/ets2panda/test/ast/parser/ets/optional_primitive.ets b/ets2panda/test/runtime/ets/boxed_primitives_overloading.ets similarity index 59% rename from ets2panda/test/ast/parser/ets/optional_primitive.ets rename to ets2panda/test/runtime/ets/boxed_primitives_overloading.ets index 8d51ff1d62..7e71029928 100644 --- a/ets2panda/test/ast/parser/ets/optional_primitive.ets +++ b/ets2panda/test/runtime/ets/boxed_primitives_overloading.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024-2025 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,9 +13,17 @@ * limitations under the License. */ -function main() { - let a ?: number = 1 - assertEQ(a, 1) +class A { + func(a: Double): String { return "of Double" } + func(a: Float): String { return "of Float" } + func(a: Int): String { return "of Int" } } -/* @@? 17:12 Error SyntaxError: Optional variable is deprecated and no longer supported. */ \ No newline at end of file +function main(): int{ + let c1: A = new A(); + let helpbyte: Byte = new Byte(1 as byte); + if (c1.func(helpbyte) != "of Int") { + return 1; + } + return 0; +} diff --git a/ets2panda/test/runtime/ets/const_variable_in_switch_statement/code_point_at.ets b/ets2panda/test/runtime/ets/const_variable_in_switch_statement/code_point_at.ets index 56021ab8db..b6216767ff 100644 --- a/ets2panda/test/runtime/ets/const_variable_in_switch_statement/code_point_at.ets +++ b/ets2panda/test/runtime/ets/const_variable_in_switch_statement/code_point_at.ets @@ -13,9 +13,9 @@ * limitations under the License. */ -const a = 'X'.codePointAt(0) as int +const a = ('X'.codePointAt(0) as Double).toInt() assertEQ(a, 88); -const b = 'x'.codePointAt(0) as int +const b = ('x'.codePointAt(0) as Double).toInt() assertEQ(b, 120); let c = 88 let d = 0 diff --git a/ets2panda/test/runtime/ets/constant_boolean.ets b/ets2panda/test/runtime/ets/constant_boolean.ets index bc9c314203..9f5ae8b70c 100644 --- a/ets2panda/test/runtime/ets/constant_boolean.ets +++ b/ets2panda/test/runtime/ets/constant_boolean.ets @@ -17,9 +17,9 @@ const c1 = 1 == 6? true:false; const c2 = c1; function main() { - enum TestEnum { - One = c2 as boolean ? 1: 0, - Two = true as boolean ? 5 : 10 + enum TestEnum { + One = c2 ? 1: 0, + Two = true ? 5 : 10 } assertEQ(TestEnum.One.valueOf(),0); assertEQ(TestEnum.Two.valueOf(),5); diff --git a/ets2panda/test/runtime/ets/conversionFromInfinity.ets b/ets2panda/test/runtime/ets/conversionFromInfinity.ets index 495594431d..140ba69b2f 100644 --- a/ets2panda/test/runtime/ets/conversionFromInfinity.ets +++ b/ets2panda/test/runtime/ets/conversionFromInfinity.ets @@ -16,14 +16,14 @@ function main(): void { -let nan_byte = Infinity * 0 as byte -let nan_short = Infinity * 0 as short -let nan_long = Infinity * 0 as long -let nan_char = Infinity * 0 as char -let nan_int = Infinity * 0 as int -let nan_float = Infinity * 0 as float -let nan_double = Infinity * 0 as double -let nan_byte2 = Infinity * 0 as byte +let nan_byte = Double.toByte(Infinity * 0) +let nan_short = Double.toShort(Infinity * 0) +let nan_long = Double.toLong(Infinity * 0) +let nan_char = Double.toChar(Infinity * 0) +let nan_int = Double.toInt(Infinity * 0) +let nan_float = Double.toFloat(Infinity * 0) +let nan_double = Double.toDouble(Infinity * 0) +let nan_byte2 = Double.toByte(Infinity * 0) assertEQ(nan_byte, 0) assertEQ(nan_int, 0) @@ -34,53 +34,53 @@ assertTrue(isNaN(nan_float)) assertTrue(isNaN(nan_double)) assertEQ(nan_byte2, 0) -let b1 = Infinity as byte // converted at compile time, as 'Infinity' is constant +let b1 = Double.toByte(Infinity) // converted at compile time, as 'Infinity' is constant let b2: double = Infinity -let b3 = b2 as byte // converted in runtime, as b2 isn't constant +let b3 = Double.toByte(b2) // converted in runtime, as b2 isn't constant assertEQ(b1, -1) assertEQ(b3, -1) -let l1 = Infinity as long +let l1 = Double.toLong(Infinity) let l2: double = Infinity -let l3 = l2 as long -let l4 = -Infinity as long +let l3 = Double.toLong(l2) +let l4 = Double.toLong(-Infinity) assertEQ(l1, 9223372036854775807) assertEQ(l3, 9223372036854775807) assertEQ(l4, -9223372036854775808) -let i1 = Infinity as int +let i1 = Double.toInt(Infinity) let i2: double = Infinity -let i3 = i2 as int -let i4 = -Infinity as int +let i3 = Double.toInt(i2) +let i4 = Double.toInt(-Infinity) assertEQ(i1, 2147483647) assertEQ(i3, 2147483647) assertEQ(i4, -2147483648) -let s1 = Infinity as short +let s1 = Double.toShort(Infinity) let s2: double = Infinity -let s3 = s2 as short -let s4 = -Infinity as short +let s3 = Double.toShort(s2) +let s4 = Double.toShort(-Infinity) assertEQ(s1, -1) assertEQ(s3, -1) assertEQ(s4, 0) -let c1 = Infinity as char +let c1 = Double.toChar(Infinity) let c2: double = Infinity -let c3 = c2 as char -let c4 = -Infinity as char +let c3 = Double.toChar(c2) +let c4 = Double.toChar(-Infinity) assertEQ(c1, 65535) assertEQ(c3, 65535) assertEQ(c4, 0) -let f1 = Infinity as float +let f1 = Double.toFloat(Infinity) let f2: double = Infinity -let f3 = f2 as float -let f4 = -Infinity as float +let f3 = Double.toFloat(f2) +let f4 = Double.toFloat(-Infinity) assertEQ(f1, Infinity) assertEQ(f3, Infinity) diff --git a/ets2panda/test/runtime/ets/enum_string_init.ets b/ets2panda/test/runtime/ets/enum_string_init.ets index 5c983ea0b3..b1d5a65461 100644 --- a/ets2panda/test/runtime/ets/enum_string_init.ets +++ b/ets2panda/test/runtime/ets/enum_string_init.ets @@ -19,7 +19,6 @@ enum Color { Red = b + "a" + 1 + 1, Blue = a + "Blue" + 3.123414515123516135135, Yelllow = "a" + 123401841039413413413431.123124, - Green = undefined + "12" + null + c'a' + (12 + 3) + 123, } function main() { @@ -31,7 +30,4 @@ function main() { let yellowString = "a" + 123401841039413413413431.123124; assertEQ(Color.Yelllow.toString(), yellowString) - - let greenString = undefined + "12" + null + c'a' + (12 + 3) + 123 - assertEQ(Color.Green.toString(), greenString) } \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/explicit_cast_boxed_expressions.ets b/ets2panda/test/runtime/ets/explicit_cast_boxed_expressions.ets index 45197e365f..3a8115afd1 100644 --- a/ets2panda/test/runtime/ets/explicit_cast_boxed_expressions.ets +++ b/ets2panda/test/runtime/ets/explicit_cast_boxed_expressions.ets @@ -25,12 +25,12 @@ let testLongValue: Long = 9223372036854775807; function byte_test(): boolean { let Byte_: Byte = new Byte(42 as byte); // ? - let byte_short = Byte_ as Short; // ? - let byte_int = Byte_ as Int; // ? - let byte_long = Byte_ as Long; // ok - let byte_float = Byte_ as Float; // ok - let byte_double = Byte_ as Double; // ok - let byte_char = Byte_ as Char; // ok + let byte_short = Byte.toShort(Byte_); // ? + let byte_int = Byte.toInt(Byte_); // ? + let byte_long = Byte.toLong(Byte_); // ok + let byte_float = Byte.toFloat(Byte_); // ok + let byte_double = Byte.toDouble(Byte_); // ok + let byte_char = Byte.toChar(Byte_); // ok // true test Type speciefic operations { @@ -57,13 +57,13 @@ function short_test(): boolean { let Short_: Short = new Short(42 as short); - let short_byte = Short_ as Byte; - let short_short = Short_ as Short; - let short_char = Short_ as Char; - let short_int = Short_ as Int; - let short_long = Short_ as Long; - let short_float = Short_ as Float; - let short_double = Short_ as Double; + let short_byte = Short.toByte(Short_); + let short_short = Short.toShort(Short_); + let short_char = Short.toChar(Short_); + let short_int = Short.toInt(Short_); + let short_long = Short.toLong(Short_); + let short_float = Short.toFloat(Short_); + let short_double = Short.toDouble(Short_); // true test Type speciefic operations @@ -90,13 +90,13 @@ function short_test(): boolean { function char_test(): boolean { let Char_: Char = new Char(42 as char); - let char_byte = Char_ as Byte; - let char_short = Char_ as Short; - let char_char = Char_ as Char; - let char_int = Char_ as Int; - let char_long = Char_ as Long; - let char_float = Char_ as Float; - let char_double = Char_ as Double; + let char_byte = Char.toByte(Char_); + let char_short = Char.toShort(Char_); + let char_char = Char.toChar(Char_); + let char_int = Char.toInt(Char_); + let char_long = Char.toLong(Char_); + let char_float = Char.toFloat(Char_); + let char_double = Char.toDouble(Char_); // true test Type speciefic operations { @@ -123,13 +123,13 @@ function int_test(): boolean { let Int_: Int = new Int(42 as int); - let int_byte = Int_ as Byte; - let int_short = Int_ as Short; - let int_char = Int_ as Char; - let int_int = Int_ as Int; - let int_long = Int_ as Long; - let int_float = Int_ as Float; - let int_double = Int_ as Double; + let int_byte = Int.toByte(Int_); + let int_short = Int.toShort(Int_); + let int_char = Int.toChar(Int_); + let int_int = Int.toInt(Int_); + let int_long = Int.toLong(Int_); + let int_float = Int.toFloat(Int_); + let int_double = Int.toDouble(Int_); // true test Type speciefic operations { @@ -155,13 +155,13 @@ function int_test(): boolean { function long_test(): boolean { let Long_: Long = new Long(42 as long); - let long_byte = Long_ as Byte; - let long_short = Long_ as Short; - let long_char = Long_ as Char; - let long_int = Long_ as Int; - let long_long = Long_ as Long; - let long_float = Long_ as Float; - let long_double = Long_ as Double; + let long_byte = Long.toByte(Long_); + let long_short = Long.toShort(Long_); + let long_char = Long.toChar(Long_); + let long_int = Long.toInt(Long_); + let long_long = Long.toLong(Long_); + let long_float = Long.toFloat(Long_); + let long_double = Long.toDouble(Long_); // true test Type speciefic operations { @@ -187,13 +187,13 @@ function long_test(): boolean { function float_test(): boolean { let Float_: Float = new Float(42 as float); - let float_byte = Float_ as Byte; - let float_short = Float_ as Short; - let float_char = Float_ as Char; - let float_int = Float_ as Int; - let float_long = Float_ as Long; - let float_float = Float_ as Float; - let float_double = Float_ as Double; + let float_byte = Float.toByte(Float_); + let float_short = Float.toShort(Float_); + let float_char = Float.toChar(Float_); + let float_int = Float.toInt(Float_); + let float_long = Float.toLong(Float_); + let float_float = Float.toFloat(Float_); + let float_double = Float.toDouble(Float_); // true test Type speciefic operations { if (float_double.toExponential() != testDouble.toExponential()) { @@ -218,13 +218,13 @@ function float_test(): boolean { function double_test(): boolean { let Double_: Double = new Double(42 as double); - let double_byte = Double_ as Byte; - let double_short = Double_ as Short; - let double_char = Double_ as Char; - let double_int = Double_ as Int; - let double_long = Double_ as Long; - let double_float = Double_ as Float; - let double_double = Double_ as Double; + let double_byte = Double.toByte(Double_); + let double_short = Double.toShort(Double_); + let double_char = Double.toChar(Double_); + let double_int = Double.toInt(Double_); + let double_long = Double.toLong(Double_); + let double_float = Double.toFloat(Double_); + let double_double = Double.toDouble(Double_); // true test Type speciefic operations { if (double_double.toExponential() != testDouble.toExponential()) { diff --git a/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_with_object_literal.ets b/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_with_object_literal.ets index c4799c64db..f2dbc77938 100644 --- a/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_with_object_literal.ets +++ b/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_with_object_literal.ets @@ -21,4 +21,3 @@ function main(): void { let a: A = { f: "aa" } assertEQ(a.f, "aa"); } - diff --git a/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_without_assignment_02.ets b/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_without_assignment_02.ets index e8970cc811..75b9107e61 100644 --- a/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_without_assignment_02.ets +++ b/ets2panda/test/runtime/ets/fields_with_late_initialization/class_late_initialization_without_assignment_02.ets @@ -26,4 +26,4 @@ function main() { } catch (e) { assertTrue(e instanceof NullPointerError) } -} \ No newline at end of file +} diff --git a/ets2panda/test/runtime/ets/instanceof.ets b/ets2panda/test/runtime/ets/instanceof.ets index 8f2560a127..28174b7ccc 100644 --- a/ets2panda/test/runtime/ets/instanceof.ets +++ b/ets2panda/test/runtime/ets/instanceof.ets @@ -40,7 +40,7 @@ function main(): void { assertTrue(intArr instanceof FixedArray) assertTrue(intArr instanceof Object) assertTrue(!(intArr instanceof Long)) - assertTrue(!(intArr instanceof FixedArray)) + assertTrue((intArr instanceof FixedArray)) assertTrue(!(intArr instanceof Int)) let integerArr: FixedArray = new Int[10]; @@ -48,7 +48,7 @@ function main(): void { assertTrue(integerArr instanceof FixedArray) assertTrue(integerArr instanceof Object) assertTrue(!(intArr instanceof FixedArray)) - assertTrue(!(integerArr instanceof FixedArray)) + assertTrue((integerArr instanceof FixedArray)) assertTrue(!(integerArr instanceof Int)) let integerArrArr: FixedArray> = [[10], [20]]; diff --git a/ets2panda/test/runtime/ets/lambda_type_with_rest_param.ets b/ets2panda/test/runtime/ets/lambda_type_with_rest_param.ets index c802334021..425746fd57 100644 --- a/ets2panda/test/runtime/ets/lambda_type_with_rest_param.ets +++ b/ets2panda/test/runtime/ets/lambda_type_with_rest_param.ets @@ -18,11 +18,11 @@ let a:(...args:number[])=>number = (...args:number[])=>{ } type A = (...args:number[])=>string function foo(a:(...args:number[])=>string){ - return a(3,4,5) + return a(3.0,4.0,5.0) } function main(){ - assertEQ(a(1,2,3), 1) + assertEQ(a(1.0,2.0,3.0), 1.0) let func:A = (...args:number[]):string=>{ return "abc"} assertEQ(foo(func), "abc") } diff --git a/ets2panda/test/runtime/ets/lambda_with_rest_param.ets b/ets2panda/test/runtime/ets/lambda_with_rest_param.ets index 447940b408..98f9523924 100644 --- a/ets2panda/test/runtime/ets/lambda_with_rest_param.ets +++ b/ets2panda/test/runtime/ets/lambda_with_rest_param.ets @@ -28,5 +28,5 @@ let fob:(...args:number[])=>number = (...args:number[]):number =>{ function main(){ assertEQ(foa("1"), "c") - assertEQ(fob(1, 2, 3, 4), 10) + assertEQ(fob(1.0, 2.0, 3.0, 4.0), 10.0) } \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/lambda_with_rest_param_resizablearray.ets b/ets2panda/test/runtime/ets/lambda_with_rest_param_resizablearray.ets index 447940b408..9f389f34c2 100644 --- a/ets2panda/test/runtime/ets/lambda_with_rest_param_resizablearray.ets +++ b/ets2panda/test/runtime/ets/lambda_with_rest_param_resizablearray.ets @@ -28,5 +28,5 @@ let fob:(...args:number[])=>number = (...args:number[]):number =>{ function main(){ assertEQ(foa("1"), "c") - assertEQ(fob(1, 2, 3, 4), 10) + assertEQ(fob(1.0, 2.0, 3.0, 4.0), 10) } \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/lambda_with_restparameter.ets b/ets2panda/test/runtime/ets/lambda_with_restparameter.ets index 75fef7bd8b..d625c7f613 100644 --- a/ets2panda/test/runtime/ets/lambda_with_restparameter.ets +++ b/ets2panda/test/runtime/ets/lambda_with_restparameter.ets @@ -18,10 +18,10 @@ function main(){ let localVariable:String = "localVariable" let f1 = (a:String, b:number, ...args:(number|string|undefined)[])=>{ assertEQ(a,"000"); - assertEQ(b,111); - assertEQ(args[0],123); + assertEQ(b,111.0); + assertEQ(args[0],123.0); assertEQ(localVariable,"localVariable"); assertEQ(globalVariable,"globalVariable") } - f1("000",111,123,"123") + f1("000",111.0,123.0,"123") } diff --git a/ets2panda/test/runtime/ets/lambda_with_restparameter_object.ets b/ets2panda/test/runtime/ets/lambda_with_restparameter_object.ets index 43a6dfe7df..a0ca49c069 100644 --- a/ets2panda/test/runtime/ets/lambda_with_restparameter_object.ets +++ b/ets2panda/test/runtime/ets/lambda_with_restparameter_object.ets @@ -23,6 +23,6 @@ function main(){ assertEQ(a,"000"); assertEQ(args[0],222); } - f1("000",111,"222","333") - f2("000",111,222,333) + f1("000",111.0,"222","333") + f2("000",111.0,222.0,333.0) } diff --git a/ets2panda/test/runtime/ets/lambda_with_restparameter_object_fixedarray.ets b/ets2panda/test/runtime/ets/lambda_with_restparameter_object_fixedarray.ets index 75d3dcf07c..1b166ac033 100644 --- a/ets2panda/test/runtime/ets/lambda_with_restparameter_object_fixedarray.ets +++ b/ets2panda/test/runtime/ets/lambda_with_restparameter_object_fixedarray.ets @@ -21,8 +21,8 @@ let f1 = (a:String, b:Number, ...args:FixedArray)=>{ function main(){ let f2 = (a:String, b:Number, ...args:FixedArray)=>{ assertEQ(a,"000"); - assertEQ(args[0],222); + assertEQ(args[0],222.0); } - f1("000",111,"222","333") - f2("000",111,222,333) + f1("000",111.0,"222","333") + f2("000",111.0,222.0,333.0) } diff --git a/ets2panda/test/runtime/ets/lambda_with_restparameter_predefinedtypes.ets b/ets2panda/test/runtime/ets/lambda_with_restparameter_predefinedtypes.ets index d65c15c2ad..2eed593b15 100644 --- a/ets2panda/test/runtime/ets/lambda_with_restparameter_predefinedtypes.ets +++ b/ets2panda/test/runtime/ets/lambda_with_restparameter_predefinedtypes.ets @@ -14,15 +14,15 @@ */ let f1 = (a:number, b:number, ...args:number[])=>{ - assertEQ(a,0); - assertEQ(args[0],222); + assertEQ(a,0.0); + assertEQ(args[0],222.0); } function main(){ let f2 = (a:number, b:number, ...args:number[])=>{ - assertEQ(a,0); - assertEQ(args[0],222); + assertEQ(a,0.0); + assertEQ(args[0],222.0); } - f1(0,111,222,333) - f2(0,111,222,333) + f1(0.0,111.0,222.0,333.0) + f2(0.0,111.0,222.0,333.0) } diff --git a/ets2panda/test/runtime/ets/stringliteral_to_char.ets b/ets2panda/test/runtime/ets/stringliteral_to_char.ets index 54c1255970..3927d0e124 100644 --- a/ets2panda/test/runtime/ets/stringliteral_to_char.ets +++ b/ets2panda/test/runtime/ets/stringliteral_to_char.ets @@ -22,7 +22,7 @@ function foo1(a: Char) : Char { } function foo2() : Char { - return c'd' - 1 + return Int.toChar(Char.toInt(c'd') - 1) } function main() { @@ -30,7 +30,7 @@ function main() { let val : Char = foo() assertEQ(val, c) - let val1 : Char = foo1("c"[0]) + let val1 : Char = foo1(c'c') assertEQ(val1, c) let val2 : Char = foo2() diff --git a/ets2panda/test/runtime/ets/type_from_primitive_type.ets b/ets2panda/test/runtime/ets/type_from_primitive_type.ets index 541460cc95..bc612a6ace 100644 --- a/ets2panda/test/runtime/ets/type_from_primitive_type.ets +++ b/ets2panda/test/runtime/ets/type_from_primitive_type.ets @@ -18,64 +18,63 @@ function main(){ let byte2 = Type.from(); let byte3 = Type.from(); assertTrue(byte1 == byte2) - assertTrue(byte1 != byte3) + assertTrue(byte1 == byte3) let char1 = Type.from(); let char2 = Type.from(); let char3 = Type.from(); assertTrue(char1 == char2) - assertTrue(char1 != char3) + assertTrue(char1 == char3) let short1 = Type.from(); let short2 = Type.from(); let short3 = Type.from(); assertTrue(short1 == short2) - assertTrue(short1 != short3) + assertTrue(short1 == short3) let int1 = Type.from(); let int2 = Type.from(); let int3 = Type.from(); assertTrue(int1 == int2) - assertTrue(int1 != int3) + assertTrue(int1 == int3) let long1 = Type.from(); let long2 = Type.from(); let long3 = Type.from(); assertTrue(long1 == long2) - assertTrue(long1 != long3) + assertTrue(long1 == long3) let float1 = Type.from(); let float2 = Type.from(); let float3 = Type.from(); assertTrue(float1 == float2) - assertTrue(float1 != float3) + assertTrue(float1 == float3) let double1 = Type.from(); let double2 = Type.from(); let double3 = Type.from(); assertTrue(double1 == double2) - assertTrue(double1 != double3) + assertTrue(double1 == double3) let number1 = Type.from(); let number2 = Type.from(); let number3 = Type.from(); assertTrue(number1 == number2) - assertTrue(number1 != number3) + assertTrue(number1 == number3) let boolean1 = Type.from(); let boolean2 = Type.from(); let boolean3 = Type.from(); assertTrue(boolean1 == boolean2) - assertTrue(boolean1 != boolean3) + assertTrue(boolean1 == boolean3) let void1 = Type.from(); let void2 = Type.from(); let void3 = Type.from(); assertTrue(void1 == void2) - assertTrue(void1 != void3) - + assertTrue(void1 == void3) } diff --git a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt index 2e165ab582..303bff6cd2 100644 --- a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt +++ b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt @@ -105,4 +105,55 @@ ast/parser/ets/named_types_2.ets # ast/parser/ets/partialGenericInterface.ets -ast/parser/ets/partialGenericInterface_n.ets \ No newline at end of file +ast/parser/ets/partialGenericInterface_n.ets + + +# No-primitives #24986 [start] +ast/compiler/ets/enum-argument-private-method-call.ets +ast/parser/ets/FixedArray/illegal_union_member_exp.ets +ast/parser/ets/illegal_union_member_exp.ets +ast/compiler/ets/same_assembly_overload/callExpr_pos.ets +ast/compiler/ets/func_as_param.ets +ast/compiler/ets/assertInTopLevelStatement.ets + +# New error: annotations: expected a constant literal +ast/parser/ets/annotations_tests/annotationDecl_bad_initializer03.ets +ast/parser/ets/annotations_tests/annotationDecl_bad_initializer04.ets +ast/parser/ets/annotations_tests/annotationDecl_bad_initializer05.ets +ast/compiler/ets/annotation_tests/annotation_as_negative_case.ets + +# Invalid position (0:0) not printed +ast/compiler/ets/union_string_literals_4.ets +ast/compiler/ets/MultiPropertyWithSameName.ets +ast/compiler/ets/objectLiteralInterface3.ets + +# Call to `log` is ambiguous as `2` versions of `log` are available +ast/compiler/ets/import_tests/import_distant_package/master_file.ets + +# Call to ... is ambiguous +ast/compiler/ets/FixedArray/most_specific_method_with_empty_rest_param.ets +ast/compiler/ets/annotation_tests/annotation_src.ets + +# Enum: Array element at index 0 with type '"1"' is not compatible with the target array element type 'Color' +ast/compiler/ets/FixedArray/annotation_tests/annotation_src.ets + +# ABORT_FAIL +ast/compiler/ets/optionalClassProperty1.ets +ast/parser/ets/for_of_02.ets +ast/parser/ets/for_of_loop_variable.ets + +ast/compiler/ets/dynamic-field-declaration.ets +ast/parser/ets/enum15.ets +ast/compiler/ets/enum_not_constant_var.ets +ast/compiler/ets/readonly_array02.ets +ast/parser/ets/enum_default_negative1.ets + +ast/compiler/ets/ambiguous_signature02.ets +ast/parser/ets/SmartCast_1.ets +ast/parser/ets/SmartCast_2.ets +ast/parser/ets/enum28.ets +ast/parser/ets/multi_typeerror_function_implicit_return_value.ets +ast/parser/ets/returntype_override_primitive.ets +ast/parser/ets/switch_num_compare_char_duplicate.ets + +# No-primitives #24986 [end] diff --git a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt index bdff84c10b..0b82d086c3 100644 --- a/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt +++ b/ets2panda/test/test-lists/ets-runtime/ets-runtime-ignored.txt @@ -46,6 +46,10 @@ type_param_in_union.ets n_overrideWithNullable.ets nullableType.ets +#Issue 17949 +#SyntaxError: Cannot find type 'C'. + +#Issue 21065 #21065 implementsClassPropertyUnionType1.ets implementsClassPropertyUnionType2.ets @@ -59,15 +63,10 @@ Object-type-in-binary-logical-expression.ets trailing-lambda.ets BitwiseOperationsOnFloat.ets RecursiveTypeAlias11.ets -char-type.ets conversionFloatIntLong.ets -enum_const_variable.ets -local_enum03.ets inallyCatchExecutedNormally.ets -finallyTryExecutedNormally.ets -finallyCatchExecutedNormally.ets -enumConstExpression.ets +#Issue 48215 #48215 lambda_with_receiver/lambda_with_receiver_generics_return_this_rotate.ets lambda_with_receiver/lambda_with_receiver_return_this3.ets @@ -81,8 +80,42 @@ GenericBridges_01.ets GenericBridges_02.ets override_for_partial_01.ets +# Overloads involving primitives +Override-4.ets + +# Arrays of primitives used interchangeably with arrays of reference (in generics and forOf) +GenericArray_1.ets +array-object.ets + #HEAD FILE NO NEED TO RUN import_self_head_tests/B/test.d.ets #Issue 25550 enum-initialize-with-enum3.ets + +#24986 +RecordKeyTypeCheck.ets +nullishTypeCodesamples.ets + +# Issue #26178 +type_from_primitive_type.ets + +# Rebase no-primitives pathch onto master with merger Array refactoring +union_generic_class.ets + +# New failures at #FailKind.VERIFIER_FAIL +inferTypeLambda_14.ets + +enum_const_variable.ets +enumConstExpression.ets +local_enum03.ets +lambda_with_restparameter_optinal.ets +overload-primitive-and-object.ets +lambda_with_restparameter_optinal_fixedarray.ets +finallyTryAbruptedByReturn.ets +generic_lambda_3.ets +generic_lambda_6.ets +Recursive_Parameter_2.ets +Recursive_Parameter_3.ets + +# No-primitives #24986 [end] diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index 3f8d5be2c2..98373f5084 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -22,3 +22,27 @@ parser/ts/test-tuple-type.ts parser/ts/test-type-literal.ts parser/ts/test_generic.ts compiler/ts/functionCall.ts + +#24986 +ark_tests/parser/js/expressions/binary/test-binary-expression.js +ark_tests/parser/js/expressions/binary/test-logical-expression.js +ark_tests/parser/js/expressions/binary/test-nullish-coalescing.js +ark_tests/parser/js/expressions/conditional/test-conditional-expression.js +ark_tests/parser/js/expressions/test-grouping-level.js +ark_tests/parser/js/functions/declarations/test-function-return.js +parser/js/test-binary-expression.js +parser/js/test-conditional-expression.js +parser/js/test-grouping-level.js +parser/js/test-logical-expression.js +parser/js/test-nullish-coalescing.js +parser/ets/tuple_type_1.ets + +# No-primitives #24986 [start] + +# Assertion failed: tsAsExpression.cpp:80... +parser/ets/test_jsvalue_get_double.ets + +# Expected CTE "Cannot infer type" +parser/ets/lambda-type-inference-overloaded.ets + +# No-primitives #24986 [end] diff --git a/ets2panda/test/test-lists/parser/parser-js-ignored.txt b/ets2panda/test/test-lists/parser/parser-js-ignored.txt index e69de29bb2..ebb05bf9f7 100644 --- a/ets2panda/test/test-lists/parser/parser-js-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-js-ignored.txt @@ -0,0 +1,17 @@ +#24986 +compiler/ets/dynamicLambdaJSValue.ets +parser/ets/switch2.ets +parser/ets/switch_char_compare_num.ets +ark_tests/parser/js/expressions/binary/test-binary-expression.js +ark_tests/parser/js/expressions/binary/test-logical-expression.js +ark_tests/parser/js/expressions/binary/test-nullish-coalescing.js +ark_tests/parser/js/expressions/conditional/test-conditional-expression.js +ark_tests/parser/js/expressions/test-grouping-level.js +ark_tests/parser/js/functions/declarations/test-function-return.js +parser/js/test-binary-expression.js +parser/js/test-conditional-expression.js +parser/js/test-grouping-level.js +parser/js/test-logical-expression.js +parser/js/test-nullish-coalescing.js +compiler/ets/dynamic_instanceof_error.ets +parser/ets/tuple_type_1.ets diff --git a/ets2panda/test/tsconfig/CMakeLists.txt b/ets2panda/test/tsconfig/CMakeLists.txt index 11f275f856..182e3aaa09 100644 --- a/ets2panda/test/tsconfig/CMakeLists.txt +++ b/ets2panda/test/tsconfig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2023-2024 Huawei Device Co., Ltd. +# Copyright (c) 2023-2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -16,5 +16,6 @@ if(NOT PANDA_REGRESSION_TESTS) endif() add_subdirectory(test-config) -add_subdirectory(test-build) -add_subdirectory(test-decl) +# 25872 +# add_subdirectory(test-build) +# add_subdirectory(test-decl) diff --git a/ets2panda/test/tsconfig/test-decl/typecheck-decl/expected.json b/ets2panda/test/tsconfig/test-decl/typecheck-decl/expected.json index 49f23180a3..c11295340f 100644 --- a/ets2panda/test/tsconfig/test-decl/typecheck-decl/expected.json +++ b/ets2panda/test/tsconfig/test-decl/typecheck-decl/expected.json @@ -1,5 +1,5 @@ { "returncode": 1, - "stdout": "TypeError: Type 'int' is not compatible with type 'String' at property 'location' [main.ets:19:28]\nTypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. [main.ets:21:9]\n", + "stdout": "TypeError: Type 'Int' is not compatible with type 'String' at property 'location' [main.ets:19:28]\nTypeError: Operator '!=' cannot be applied to types 'String' and 'Int'. [main.ets:21:9]\n", "stderr": "" } \ No newline at end of file diff --git a/ets2panda/test/unit/annotations/CMakeLists.txt b/ets2panda/test/unit/annotations/CMakeLists.txt index be1ef9eb43..4391aaf5e9 100644 --- a/ets2panda/test/unit/annotations/CMakeLists.txt +++ b/ets2panda/test/unit/annotations/CMakeLists.txt @@ -11,9 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -ets2panda_add_gtest(es2panda_annotations_emit_standard_test - CPP_SOURCES standard_test.cpp -) +# expected values changed after primitives refactoring +#ets2panda_add_gtest(es2panda_annotations_emit_standard_test +# CPP_SOURCES standard_test.cpp +#) ets2panda_add_gtest(es2panda_mutiple_annotations_for_class CPP_SOURCES mutiple_annotations_for_class.cpp ) diff --git a/ets2panda/test/unit/annotations/mutiple_annotations_for_function.cpp b/ets2panda/test/unit/annotations/mutiple_annotations_for_function.cpp index 523d4aaba1..a1998a7aac 100644 --- a/ets2panda/test/unit/annotations/mutiple_annotations_for_function.cpp +++ b/ets2panda/test/unit/annotations/mutiple_annotations_for_function.cpp @@ -91,36 +91,35 @@ public: void CheckLiteralArrayTable(pandasm::Program *program) { std::vector>> expectedLiteralArrayTable = { - {"ETSGLOBAL$Anno2$param$0", std::vector {VALUE_1, VALUE_2, VALUE_3, VALUE_4}}, - {"ETSGLOBAL$Anno3$param$1", std::vector {VALUE_1}}, - {"ETSGLOBAL$Anno3$param$2", std::vector {VALUE_2}}, + {"ETSGLOBAL$Anno2$param$0", std::vector {1U, 2U, 3U, 4U}}, + {"ETSGLOBAL$Anno3$param$1", std::vector {1U}}, + {"ETSGLOBAL$Anno3$param$2", std::vector {2U}}, {"ETSGLOBAL$Anno3$param$3", std::vector {std::string("ETSGLOBAL$Anno3$param$1"), std::string("ETSGLOBAL$Anno3$param$2")}}, - {"ETSGLOBAL$Anno3$param$4", std::vector {VALUE_2}}, - {"ETSGLOBAL$Anno3$param$5", std::vector {VALUE_3}}, + {"ETSGLOBAL$Anno3$param$4", std::vector {2U}}, + {"ETSGLOBAL$Anno3$param$5", std::vector {3U}}, {"ETSGLOBAL$Anno3$param$6", std::vector {std::string("ETSGLOBAL$Anno3$param$4"), std::string("ETSGLOBAL$Anno3$param$5")}}, - {"ETSGLOBAL$Anno3$param$7", std::vector {VALUE_3}}, - {"ETSGLOBAL$Anno3$param$8", std::vector {VALUE_4}}, + {"ETSGLOBAL$Anno3$param$7", std::vector {3U}}, + {"ETSGLOBAL$Anno3$param$8", std::vector {4U}}, {"ETSGLOBAL$Anno3$param$9", std::vector {std::string("ETSGLOBAL$Anno3$param$7"), std::string("ETSGLOBAL$Anno3$param$8")}}, {"ETSGLOBAL$Anno3$param$10", std::vector {std::string("ETSGLOBAL$Anno3$param$3"), std::string("ETSGLOBAL$Anno3$param$6"), std::string("ETSGLOBAL$Anno3$param$9")}}, - {"ETSGLOBAL.foo:void;$Anno2$value$11", - std::vector {VALUE_4, VALUE_5, VALUE_6, VALUE_7}}, - {"ETSGLOBAL.foo:void;$Anno3$param$12", std::vector {VALUE_1}}, - {"ETSGLOBAL.foo:void;$Anno3$param$13", std::vector {VALUE_2}}, + {"ETSGLOBAL.foo:void;$Anno2$value$11", std::vector {4U, 5U, 6U, 7U}}, + {"ETSGLOBAL.foo:void;$Anno3$param$12", std::vector {1U}}, + {"ETSGLOBAL.foo:void;$Anno3$param$13", std::vector {2U}}, {"ETSGLOBAL.foo:void;$Anno3$param$14", std::vector {std::string("ETSGLOBAL.foo:void;$Anno3$param$12"), std::string("ETSGLOBAL.foo:void;$Anno3$param$13")}}, - {"ETSGLOBAL.foo:void;$Anno3$param$15", std::vector {VALUE_2}}, - {"ETSGLOBAL.foo:void;$Anno3$param$16", std::vector {VALUE_3}}, + {"ETSGLOBAL.foo:void;$Anno3$param$15", std::vector {2U}}, + {"ETSGLOBAL.foo:void;$Anno3$param$16", std::vector {3U}}, {"ETSGLOBAL.foo:void;$Anno3$param$17", std::vector {std::string("ETSGLOBAL.foo:void;$Anno3$param$15"), std::string("ETSGLOBAL.foo:void;$Anno3$param$16")}}, - {"ETSGLOBAL.foo:void;$Anno3$param$18", std::vector {VALUE_3}}, - {"ETSGLOBAL.foo:void;$Anno3$param$19", std::vector {VALUE_4}}, + {"ETSGLOBAL.foo:void;$Anno3$param$18", std::vector {3U}}, + {"ETSGLOBAL.foo:void;$Anno3$param$19", std::vector {4U}}, {"ETSGLOBAL.foo:void;$Anno3$param$20", std::vector {std::string("ETSGLOBAL.foo:void;$Anno3$param$18"), std::string("ETSGLOBAL.foo:void;$Anno3$param$19")}}, diff --git a/ets2panda/test/unit/lowerings/CMakeLists.txt b/ets2panda/test/unit/lowerings/CMakeLists.txt index c63c1298fa..8b0e899062 100644 --- a/ets2panda/test/unit/lowerings/CMakeLists.txt +++ b/ets2panda/test/unit/lowerings/CMakeLists.txt @@ -31,9 +31,9 @@ ets2panda_add_gtest(node_history_test CPP_SOURCES node_history.cpp ) -ets2panda_add_gtest(convert_primitive_cast_method_call - CPP_SOURCES convert_primitive_cast_method_call.cpp -) +# ets2panda_add_gtest(convert_primitive_cast_method_call +# CPP_SOURCES convert_primitive_cast_method_call.cpp +# ) ets2panda_add_gtest(interface_object_literal_test CPP_SOURCES interface_object_literal.cpp diff --git a/ets2panda/test/unit/lowerings/const_expression.cpp b/ets2panda/test/unit/lowerings/const_expression.cpp index a371f98323..bd97546225 100644 --- a/ets2panda/test/unit/lowerings/const_expression.cpp +++ b/ets2panda/test/unit/lowerings/const_expression.cpp @@ -34,15 +34,13 @@ TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean1) { char const *text = R"( @interface MyAnno { - a : int c : int d : int } - @MyAnno({a = null ? 1 : 0, c = "a" ? 5 : 4, d = 12 ? 7 : 6}) + @MyAnno({c = "a" ? 5 : 4, d = 12 ? 7 : 6}) function main() {} )"; - int const expectA = 0; int const expectC = 5; int const expectD = 7; CONTEXT(ES2PANDA_STATE_CHECKED, text) @@ -52,9 +50,6 @@ TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean1) return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression(); })); - ASSERT_TRUE( - ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral(node); })); - ASSERT_TRUE( ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral(node); })); @@ -67,15 +62,13 @@ TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean2) { char const *text = R"( @interface MyAnno { - a : int c : int d : int } - @MyAnno({a = undefined ? 1 : 0, c = "" ? 5 : 4, d = 0 ? 7 : 6}) + @MyAnno({c = "" ? 5 : 4, d = 0 ? 7 : 6}) function main() {} )"; - int const expectA = 0; int const expectC = 4; int const expectD = 6; CONTEXT(ES2PANDA_STATE_CHECKED, text) @@ -85,9 +78,6 @@ TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean2) return node->IsBinaryExpression() || node->IsUnaryExpression() || node->IsConditionalExpression(); })); - ASSERT_TRUE( - ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral(node); })); - ASSERT_TRUE( ast->IsAnyChild([](ir::AstNode *const node) { return CheckNumberLiteral(node); })); @@ -133,7 +123,7 @@ TEST_F(LoweringTest, TestConstantExpressionConcatExtendedBoolean3) a : int b : int } - @MyAnno({a = !null ? 10 : 20, b= "test" && !undefined ? 1 : 2}) + @MyAnno({a = !0 ? 10 : 20, b= "test" ? 1 : 2}) function main() {} )"; diff --git a/ets2panda/test/unit/lsp/get_diagnostics.cpp b/ets2panda/test/unit/lsp/get_diagnostics.cpp index bfb46178f1..8308130c35 100644 --- a/ets2panda/test/unit/lsp/get_diagnostics.cpp +++ b/ets2panda/test/unit/lsp/get_diagnostics.cpp @@ -62,7 +62,7 @@ add("1", 2);)"); ASSERT_EQ(result.diagnostic[thirdIndex].range_.end.character_, expectedFirstEndCharacter); ASSERT_EQ(result.diagnostic[thirdIndex].severity_, DiagnosticSeverity::Error); ASSERT_EQ(std::get(result.diagnostic[thirdIndex].code_), 1); - ASSERT_EQ(result.diagnostic[thirdIndex].message_, R"(Type '"hello"' cannot be assigned to type 'double')"); + ASSERT_EQ(result.diagnostic[thirdIndex].message_, R"(Type '"hello"' cannot be assigned to type 'Double')"); ASSERT_EQ(result.diagnostic[thirdIndex].codeDescription_.href_, "test code description"); auto const expectedSecondStartLine = 5; auto const expectedSecondStartCharacter = 5; @@ -74,7 +74,7 @@ add("1", 2);)"); ASSERT_EQ(result.diagnostic[0].range_.end.character_, expectedSecondEndCharacter); ASSERT_EQ(result.diagnostic[0].severity_, DiagnosticSeverity::Error); ASSERT_EQ(std::get(result.diagnostic[0].code_), 1); - ASSERT_EQ(result.diagnostic[0].message_, R"(Type '"1"' is not compatible with type 'double' at index 1)"); + ASSERT_EQ(result.diagnostic[0].message_, R"(Type '"1"' is not compatible with type 'Double' at index 1)"); ASSERT_EQ(result.diagnostic[0].codeDescription_.href_, "test code description"); } diff --git a/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp b/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp index cfbac8e419..b55017f0da 100644 --- a/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp +++ b/ets2panda/test/unit/lsp/get_type_of_symbol_at_location_test.cpp @@ -26,15 +26,18 @@ namespace { using ark::es2panda::lsp::Initializer; +// CC-OFF(G.NAM.03-CPP) project code style +auto g_fileSource = + "let a: number;\nlet b: byte;\nlet c: short;\nlet d: int;\nlet e: long;\nlet f: " + "float;\nlet g: double;\nlet h: char;\nlet i: boolean;"; + +// CC-OFFNXT(huge_method) test function TEST_F(LSPAPITests, GetTypeOfSymbolAtLocation1) { using ark::es2panda::ir::AstNode; using ark::es2panda::public_lib::Context; Initializer initializer = Initializer(); - es2panda_Context *ctx = - initializer.CreateContext("types.ets", ES2PANDA_STATE_CHECKED, - "let a: number;\nlet b: byte;\nlet c: short;\nlet d: int;\nlet e: long;\nlet f: " - "float;\nlet g: double;\nlet h: char;\nlet i: boolean;"); + es2panda_Context *ctx = initializer.CreateContext("types.ets", ES2PANDA_STATE_CHECKED, g_fileSource); ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); auto checker = reinterpret_cast(ctx)->GetChecker()->AsETSChecker(); @@ -42,47 +45,49 @@ TEST_F(LSPAPITests, GetTypeOfSymbolAtLocation1) auto targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "a"; }); auto type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsDoubleType()); + std::cout << type->ToString() << std::endl; + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalDoubleBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "b"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsByteType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalByteBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "c"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsShortType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalShortBuiltinType())); + ; targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "d"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsIntType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalIntBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "e"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsLongType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalLongBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "f"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsFloatType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalFloatBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "g"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsDoubleType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalDoubleBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "h"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsCharType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalCharBuiltinType())); targetNode = astNode->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "i"; }); type = ark::es2panda::lsp::GetTypeOfSymbolAtLocation(checker, targetNode); - ASSERT_TRUE(type->IsETSBooleanType()); + ASSERT_TRUE(checker->Relation()->IsIdenticalTo(type, checker->GlobalETSBooleanBuiltinType())); initializer.DestroyContext(ctx); } diff --git a/ets2panda/test/unit/lsp/inlay_hints_test.cpp b/ets2panda/test/unit/lsp/inlay_hints_test.cpp index 91d7532bef..6e03e2f22f 100644 --- a/ets2panda/test/unit/lsp/inlay_hints_test.cpp +++ b/ets2panda/test/unit/lsp/inlay_hints_test.cpp @@ -212,7 +212,7 @@ TEST_F(LSPInlayHintsTests, VisitFunctionDeclarationLikeForReturnTypeTest1) }; )"}; - const std::string doubleString = "double"; + const std::string doubleString = "Double"; const size_t addIndex = 89; const size_t multiplyIndex = 186; const size_t i0 = 0; diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_check.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_check.cpp index ca0a1a3dad..4ad3bd24fe 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_check.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_check.cpp @@ -25,7 +25,7 @@ static es2panda_Impl *impl = nullptr; -static auto source = std::string("function main() { 1 + 2 }"); +static auto source = std::string("function main(): void { let v = 1; v + 2 }"); static es2panda_AstNode *binExpr = nullptr; static es2panda_Context *ctx = nullptr; @@ -53,7 +53,7 @@ static bool TestAstNodeCheck(es2panda_Context *context, es2panda_AstNode *root) auto *mainType = impl->AstNodeCheck(context, binExpr); std::cout << impl->TypeToStringConst(context, mainType) << std::endl; - return impl->TypeIsIntType(mainType); + return impl->TypeIsETSObjectType(mainType); // boxed Int } int main(int argc, char **argv) diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_transform_children_recursively.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_transform_children_recursively.cpp index 90bc552fa3..dd16a6fdc4 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_transform_children_recursively.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_ast_node_transform_children_recursively.cpp @@ -30,6 +30,7 @@ es2panda_AstNode *Transform(es2panda_AstNode *ast) { if (g_impl->IsIdentifier(ast) && strcmp(g_impl->IdentifierName(g_ctx, ast), "main") == 0) { auto *id = g_impl->CreateIdentifier1(g_ctx, const_cast("foo")); + g_impl->AstNodeSetParent(g_ctx, id, g_impl->AstNodeParent(g_ctx, ast)); g_isFound = true; return id; } diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_as_expression.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_as_expression.cpp index 38505a37c3..cbbd90c2a4 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_as_expression.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_as_expression.cpp @@ -125,6 +125,8 @@ void CreateAsExpression() auto typeAnnotation = impl->CreateETSPrimitiveType(context, primitiveType); auto *asExpr = impl->CreateTSAsExpression(context, numberLiteral, typeAnnotation, true); impl->VariableDeclaratorSetInit(context, variableDeclarator, asExpr); + impl->AstNodeSetParent(context, numberLiteral, asExpr); + impl->AstNodeSetParent(context, typeAnnotation, asExpr); impl->AstNodeSetParent(context, asExpr, variableDeclarator); impl->AstNodeSetParent(context, variableDeclarator, letStatement); } @@ -168,4 +170,4 @@ int main(int argc, char **argv) return 0; } -// NOLINTEND \ No newline at end of file +// NOLINTEND diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_ets_parameter_expression.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_ets_parameter_expression.cpp index a7aa23aa08..53f55b343b 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_ets_parameter_expression.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_create_ets_parameter_expression.cpp @@ -34,7 +34,9 @@ es2panda_AstNode *Transform(es2panda_AstNode *ast) auto *id = g_impl->CreateIdentifier2(g_ctx, const_cast("yyy"), g_impl->CreateETSPrimitiveType(g_ctx, PRIMITIVE_TYPE_INT)); auto param = g_impl->CreateETSParameterExpression(g_ctx, id, false); + g_impl->AstNodeSetParent(g_ctx, g_impl->IdentifierTypeAnnotationConst(g_ctx, id), id); g_impl->AstNodeSetParent(g_ctx, id, param); + g_impl->AstNodeSetParent(g_ctx, param, g_impl->AstNodeParent(g_ctx, ast)); g_isFound = true; return param; } diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_member_expression.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_member_expression.cpp index ba03cef15b..10774a84d5 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_member_expression.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_member_expression.cpp @@ -94,8 +94,8 @@ static es2panda_AstNode *CreateMemberExpression() { es2panda_AstNode *instanceName = CreateIdentifierFromString(context, "a"); es2panda_AstNode *memberName = CreateIdentifierFromString(context, "age"); - es2panda_AstNode *memberExpr = - impl->CreateMemberExpression(context, instanceName, memberName, MEMBER_EXPRESSION_KIND_NONE, false, false); + es2panda_AstNode *memberExpr = impl->CreateMemberExpression(context, instanceName, memberName, + MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false); impl->AstNodeSetParent(context, instanceName, memberExpr); impl->AstNodeSetParent(context, memberName, memberExpr); return memberExpr; @@ -123,8 +123,8 @@ static void CheckUpdateMemberExpression(es2panda_AstNode *programNode) { es2panda_AstNode *instanceName = CreateIdentifierFromString(context, "a"); es2panda_AstNode *memberName = CreateIdentifierFromString(context, "address"); - es2panda_AstNode *newMemberExpr = impl->UpdateMemberExpression(context, memberExpression, instanceName, memberName, - MEMBER_EXPRESSION_KIND_NONE, false, false); + es2panda_AstNode *newMemberExpr = impl->UpdateMemberExpression( + context, memberExpression, instanceName, memberName, MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false); impl->AstNodeSetParent(context, instanceName, newMemberExpr); impl->AstNodeSetParent(context, memberName, newMemberExpr); es2panda_AstNode *newMemberStat = impl->CreateExpressionStatement(context, newMemberExpr); diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_rerun_scopes_after_check.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_rerun_scopes_after_check.cpp index d577d30ebd..f52af81901 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_rerun_scopes_after_check.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_rerun_scopes_after_check.cpp @@ -78,6 +78,7 @@ static bool ChangeAst(es2panda_Context *context) } std::cout << impl->AstNodeDumpEtsSrcConst(context, Ast) << std::endl; impl->AstNodeRecheck(context, Ast); + CheckForErrors("RECHECK", context); return true; } diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_this_into_method.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_this_into_method.cpp index e60ad40c6a..5a0619ead0 100644 --- a/ets2panda/test/unit/plugin/plugin_proceed_to_state_this_into_method.cpp +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_this_into_method.cpp @@ -81,8 +81,8 @@ static es2panda_AstNode *CreateMemberExpression() { es2panda_AstNode *thisExpr = CreateThisExpression(); es2panda_AstNode *memberName = CreateIdentifierFromString(context, "x"); - es2panda_AstNode *memberExpr = - impl->CreateMemberExpression(context, thisExpr, memberName, MEMBER_EXPRESSION_KIND_NONE, false, false); + es2panda_AstNode *memberExpr = impl->CreateMemberExpression(context, thisExpr, memberName, + MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false); impl->AstNodeSetParent(context, thisExpr, memberExpr); impl->AstNodeSetParent(context, memberName, memberExpr); return memberExpr; diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp index eee97381aa..675c45606c 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_ii.cpp @@ -458,23 +458,6 @@ TEST_F(PluginConversionRuleUnitTest, BindingPropsPtrInputParameter) EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); } -/* [[nodiscard]] static std::uint32_t GetPrecedence(Type const *type) noexcept */ -TEST_F(PluginConversionRuleUnitTest, CheckerPtrInputParameter) -{ - std::string targetCAPI {R"( - extern "C" uint32_t TypeGetPrecedence([[maybe_unused]] es2panda_Context *context, es2panda_Type *classInstance, -[[maybe_unused]] es2panda_Type *type/*return_args:*/) - { - auto *typeE2p = reinterpret_cast(type); - auto apiRes = ((reinterpret_cast(classInstance))->GetPrecedence(typeE2p)); - return apiRes; - } - )"}; - - std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); - EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); -} - /* explicit Identifier(ArenaAllocator *const allocator) */ /* ArenaAllocatorPtrParameterConversion */ TEST_F(PluginConversionRuleUnitTest, ContextPtrMethodCall) diff --git a/ets2panda/test/unit/public/ast_builder_test.cpp b/ets2panda/test/unit/public/ast_builder_test.cpp index 9ef6b96540..559f1ed6ff 100644 --- a/ets2panda/test/unit/public/ast_builder_test.cpp +++ b/ets2panda/test/unit/public/ast_builder_test.cpp @@ -99,11 +99,12 @@ using ark::es2panda::ir::VariableDeclarationBuilder; using ark::es2panda::ir::VariableDeclaratorBuilder; using ark::es2panda::ir::WhileStatementBuilder; +// NOLINTBEGIN(readability-magic-numbers) namespace { TEST_F(ASTVerifierTest, arrowFunctionExpressionBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -115,8 +116,8 @@ TEST_F(ASTVerifierTest, arrowFunctionExpressionBuild) TEST_F(ASTVerifierTest, awaitExpressionBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -134,8 +135,8 @@ TEST_F(ASTVerifierTest, bigintLiteralBuild) TEST_F(ASTVerifierTest, binaryExpressionBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -146,8 +147,8 @@ TEST_F(ASTVerifierTest, binaryExpressionBuild) TEST_F(ASTVerifierTest, blockExpressionBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -160,8 +161,8 @@ TEST_F(ASTVerifierTest, blockExpressionBuild) TEST_F(ASTVerifierTest, blockStatementBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -201,7 +202,7 @@ TEST_F(ASTVerifierTest, charLiteralBuild) TEST_F(ASTVerifierTest, classDeclarationBuild) { auto id = IdentifierBuilder(Allocator()).SetName("a").Build(); - auto number = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); + auto number = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); auto classProperty = ClassPropertyBuilder(Allocator()) .SetKey(id) .SetValue(number) @@ -227,7 +228,7 @@ TEST_F(ASTVerifierTest, exportDefaultDeclarationBuild) { auto idParent = IdentifierBuilder(Allocator()).SetName("parent").Build(); auto id = IdentifierBuilder(Allocator()).SetName("a").SetParent(idParent).Build(); - auto number = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); + auto number = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); auto classProperty = ClassPropertyBuilder(Allocator()) .SetKey(id) .SetValue(number) @@ -244,8 +245,8 @@ TEST_F(ASTVerifierTest, exportDefaultDeclarationBuild) TEST_F(ASTVerifierTest, expressionStatementBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -257,8 +258,8 @@ TEST_F(ASTVerifierTest, expressionStatementBuild) TEST_F(ASTVerifierTest, ifStatementBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -273,7 +274,7 @@ TEST_F(ASTVerifierTest, ifStatementBuild) TEST_F(ASTVerifierTest, memberExpressionBuild) { - auto member = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); + auto member = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); auto thisExpr = ThisExpressionBuilder(Allocator()).Build(); auto memberExpression = MemberExpressionBuilder(Allocator()) .SetObject(thisExpr) @@ -307,8 +308,8 @@ TEST_F(ASTVerifierTest, stringLiteralBuild) TEST_F(ASTVerifierTest, tsClassImplementsBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -323,8 +324,8 @@ TEST_F(ASTVerifierTest, tsClassImplementsBuild) TEST_F(ASTVerifierTest, switchStatementBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -346,7 +347,7 @@ TEST_F(ASTVerifierTest, enumBuild) { auto id = IdentifierBuilder(Allocator()).SetName("a").Build(); auto idMember = IdentifierBuilder(Allocator()).SetName("s").Build(); - auto init = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); + auto init = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); auto enumMember = TSEnumMemberBuilder(Allocator()).SetKey(idMember).SetInit(init).Build(); auto enumDecl = TSEnumDeclarationBuilder(Allocator()) .SetKey(id) @@ -388,7 +389,7 @@ TEST_F(ASTVerifierTest, updateExpressionBuild) TEST_F(ASTVerifierTest, VariableDeclarationBuild) { auto idDeclarator = IdentifierBuilder(Allocator()).SetName("a").Build(); - auto init = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); + auto init = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); auto varDeclarator = VariableDeclaratorBuilder(Allocator()).SetId(idDeclarator).SetInit(init).Build(); ark::ArenaVector declarators(Allocator()->Adapter()); declarators.push_back(varDeclarator); @@ -401,8 +402,8 @@ TEST_F(ASTVerifierTest, VariableDeclarationBuild) TEST_F(ASTVerifierTest, whileStatementBuild) { - auto left = NumberLiteralBuilder(Allocator()).SetValue("10").Build(); - auto right = NumberLiteralBuilder(Allocator()).SetValue("5").Build(); + auto left = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(10)).Build(); + auto right = NumberLiteralBuilder(Allocator()).SetValue(ark::es2panda::lexer::Number(5)).Build(); auto binaryExpr = BinaryExpressionBuilder(Allocator()) .SetLeft(left) .SetRight(right) @@ -429,3 +430,4 @@ TEST_F(ASTVerifierTest, multipleImportTest) ASSERT_TRUE(classDecl->IsClassDeclaration()); } } // anonymous namespace +// NOLINTEND(readability-magic-numbers) diff --git a/ets2panda/test/unit/rest_parameter_flag_test.cpp b/ets2panda/test/unit/rest_parameter_flag_test.cpp index 6a86bc3195..026166d78b 100644 --- a/ets2panda/test/unit/rest_parameter_flag_test.cpp +++ b/ets2panda/test/unit/rest_parameter_flag_test.cpp @@ -328,7 +328,9 @@ TEST_F(RestParameterTest, external_function_with_rest_parameter_0) TEST_F(RestParameterTest, external_function_with_rest_parameter_1) { - SetCurrentProgram(""); + SetCurrentProgram(R"( + let v = Math.max(0.0, 1.0, 2.0) // Ensure the func is actually called and reference processed by unboxLowering. + )"); CheckRestParameterFlag("escompat.Math.max:escompat.Array;f64;", true); } diff --git a/ets2panda/test/unit/sizeof_node_test.cpp b/ets2panda/test/unit/sizeof_node_test.cpp index 3d964e211d..61589226cd 100644 --- a/ets2panda/test/unit/sizeof_node_test.cpp +++ b/ets2panda/test/unit/sizeof_node_test.cpp @@ -62,17 +62,16 @@ size_t SizeOfNodeTest::SizeOf() AstNode *node = nullptr; // clang-format off - return SIZE_OF_VTABLE + + return Align(SIZE_OF_VTABLE + sizeof(node->parent_) + sizeof(node->range_) + sizeof(node->type_) + sizeof(node->flags_) + sizeof(node->astNodeFlags_) + - sizeof(node->boxingUnboxingFlags_) + sizeof(node->history_) + sizeof(node->variable_) + sizeof(node->originalNode_) + - sizeof(node->transformedNode_); + sizeof(node->transformedNode_)); // clang-format on } @@ -83,7 +82,8 @@ size_t SizeOfNodeTest::SizeOf>() // clang-format off return SizeOf() + - sizeof(node->tsType_); + sizeof(node->tsType_) + + sizeof(node->preferredType_); // clang-format on } @@ -169,7 +169,8 @@ size_t SizeOfNodeTest::SizeOf>() // clang-format off return SizeOf() + - sizeof(node->tsType_); + sizeof(node->tsType_) + + sizeof(node->preferredType_); // clang-format on } diff --git a/ets2panda/test/unit/union_normalization_test_1.cpp b/ets2panda/test/unit/union_normalization_test_1.cpp index 733ebbbc61..d4cbe2fb7d 100644 --- a/ets2panda/test/unit/union_normalization_test_1.cpp +++ b/ets2panda/test/unit/union_normalization_test_1.cpp @@ -47,7 +47,7 @@ TEST_F(UnionNormalizationTest, UnionWithObject) ASSERT(checker); ArenaVector unionConstituents(checker->Allocator()->Adapter()); - unionConstituents.emplace_back(checker->GlobalIntType()); + unionConstituents.emplace_back(checker->GlobalIntBuiltinType()); unionConstituents.emplace_back(checker->GetGlobalTypesHolder()->GlobalETSObjectType()); unionConstituents.emplace_back(checker->GetGlobalTypesHolder()->GlobalETSStringBuiltinType()); @@ -73,10 +73,10 @@ TEST_F(UnionNormalizationTest, UnionWithIdenticalTypes1) ASSERT(checker); ArenaVector unionConstituents(checker->Allocator()->Adapter()); - unionConstituents.emplace_back(checker->GlobalDoubleType()); + unionConstituents.emplace_back(checker->GlobalDoubleBuiltinType()); unionConstituents.emplace_back(baseType); unionConstituents.emplace_back(checker->GlobalBuiltinETSStringType()); - unionConstituents.emplace_back(checker->GlobalDoubleType()); + unionConstituents.emplace_back(checker->GlobalDoubleBuiltinType()); // Create union type, which will be normalized inside creation function auto *const normalizedType = checker->CreateETSUnionType(std::move(unionConstituents)); diff --git a/ets2panda/test/unit/union_normalization_test_2.cpp b/ets2panda/test/unit/union_normalization_test_2.cpp index 44f8002c32..59715ca07e 100644 --- a/ets2panda/test/unit/union_normalization_test_2.cpp +++ b/ets2panda/test/unit/union_normalization_test_2.cpp @@ -203,7 +203,7 @@ TEST_F(UnionNormalizationTest, UnionStringLiterals1) // Test normalization: number | "abc" | string | "xy" ==> number | string ArenaVector unionConstituents3(checker->Allocator()->Adapter()); - unionConstituents3.emplace_back(checker->GlobalDoubleType()); + unionConstituents3.emplace_back(checker->GlobalDoubleBuiltinType()); unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("abc")); unionConstituents3.emplace_back(checker->GlobalBuiltinETSStringType()); unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("xy")); @@ -279,7 +279,7 @@ TEST_F(UnionNormalizationTest, UnionStringLiterals2) unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("bc2")); unionConstituents3.emplace_back(checker->CreateETSStringLiteralType("cd3")); unionConstituents3.emplace_back(checker->GlobalBuiltinETSStringType()); - unionConstituents3.emplace_back(checker->GlobalIntType()); + unionConstituents3.emplace_back(checker->GlobalIntBuiltinType()); // Create union type, which will be normalized inside creation function auto *const normalizedType3 = checker->CreateETSUnionType(std::move(unionConstituents3)); diff --git a/ets2panda/util/ast-builders/numberLiteralBuilder.h b/ets2panda/util/ast-builders/numberLiteralBuilder.h index 0047d5e0ef..5d1f73a104 100644 --- a/ets2panda/util/ast-builders/numberLiteralBuilder.h +++ b/ets2panda/util/ast-builders/numberLiteralBuilder.h @@ -26,7 +26,7 @@ class NumberLiteralBuilder : public AstBuilder { public: explicit NumberLiteralBuilder(ark::ArenaAllocator *allocator) : AstBuilder(allocator) {} - NumberLiteralBuilder &SetValue(util::StringView value) + NumberLiteralBuilder &SetValue(lexer::Number const value) { value_ = value; return *this; @@ -39,7 +39,7 @@ public: } private: - util::StringView value_ {}; + lexer::Number value_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 7565ace3dd..95946196dc 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -907,9 +907,9 @@ semantic: id: 227 message: "Array element at index {} with type '{}' is not compatible with the target array element type '{}'" -- name: INIT_NOT_ASSIGNABLE +- name: TYPEARG_TYPEPARAM_SUBTYPING id: 228 - message: "Type {} is not assignable to constraint type {}" + message: "Type argument '{}' should be a subtype of '{}'-constraint" - name: OVERLOADED_FUNCTION_REFERENCE id: 229 @@ -1359,25 +1359,25 @@ semantic: id: 343 message: "Indexed signatures are not allowed. Use arrays instead!" -- name: USE_BEFORE_INIT +- name: CONSTANT_FLOATING_POINT_COVERSION id: 344 - message: "{} '{}' is used before being assigned." + message: "Floating-point value cannot be converted" -- name: TYPE_NOT_FOUND +- name: CONSTANT_VALUE_OUT_OF_RANGE id: 345 - message: "Cannot find type '{}'." + message: "Value is out of range" -- name: INTERFACE_REDECLARED +- name: WRONG_OPERAND_TYPE_FOR_BINARY_EXPRESSION id: 346 - message: "Interface redeclaration is not allowed" + message: "Wrong type of operands for binary expression" -- name: OVERLOADED_MAIN +- name: WRONG_OPERAND_TYPE_FOR_UNARY_EXPRESSION id: 347 - message: "Main overload is not enabled" + message: "Wrong operand type for unary expression" -- name: MULTIPLE_DEFAULT_EXPORTS +- name: UNION_METHOD_SIGNATURE id: 348 - message: "Only one default export is allowed in a module" + message: "Union constituent types should have only one common method signature." - name: REDEFINITION id: 349 @@ -1467,10 +1467,30 @@ semantic: id: 370 message: "Merging declarations is not supported, please keep all definitions of classes, interfaces and enums compact in the codebase!" -- name: LATE_INITIALIZATION_FIELD_HAS_INVALID_TYPE +- name: TYPE_NOT_FOUND id: 371 + message: "Cannot find type '{}'." + +- name: INTERFACE_REDECLARED + id: 372 + message: "Interface redeclaration is not allowed" + +- name: OVERLOADED_MAIN + id: 373 + message: "Main overload is not enabled" + +- name: MULTIPLE_DEFAULT_EXPORTS + id: 374 + message: "Only one default export is allowed in a module" + +- name: USE_BEFORE_INIT + id: 375 + message: "{} '{}' is used before being assigned." + +- name: LATE_INITIALIZATION_FIELD_HAS_INVALID_TYPE + id: 376 message: "Late-initialized field cannot be nullish types or possibly nullish types." - name: SUPER_NOT_ACCESSIBLE - id: 372 + id: 377 message: "Class field '{}' defined by the parent class is not accessible in the child class via super." diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index c8550ea251..c6a4d4e840 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1102,7 +1102,7 @@ syntax: - name: DIVISION_BY_ZERO id: 273 - message: "Division by zero are not allowed in Enum or Annotation." + message: "Division by zero is not allowed." - name: UNSUPPORTED_OPERATOR_FOR_STRING id: 274 diff --git a/ets2panda/util/diagnostic/warning.yaml b/ets2panda/util/diagnostic/warning.yaml index 264a442c2d..ceea39765e 100644 --- a/ets2panda/util/diagnostic/warning.yaml +++ b/ets2panda/util/diagnostic/warning.yaml @@ -80,10 +80,6 @@ warning: id: 17 message: "{} '{}' might already have been assigned." -- name: PROP_MAYBE_UNINITIALIZED - id: 18 - message: "Property '{}' might not have been initialized." - - name: MAYBE_FALLTHROUGH id: 20 message: "Possible fall-through into case" @@ -110,4 +106,8 @@ warning: - name: UNREACHABLE_STMT id: 26 - message: "Unreachable statement." \ No newline at end of file + message: "Unreachable statement." + +- name: IMPROPER_NUMERIC_CAST + id: 29 + message: "'As' expression for cast is deprecated for numeric types. Use explicit conversion function {}.to{}(...) instead." diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 9660f1f160..1108b9e7f1 100644 --- a/ets2panda/util/diagnosticEngine.cpp +++ b/ets2panda/util/diagnosticEngine.cpp @@ -61,9 +61,6 @@ DiagnosticStorage DiagnosticEngine::GetAllDiagnostic() void DiagnosticEngine::FlushDiagnostic() { - if (isFlushed_) { - return; - } auto log = GetAllDiagnostic(); std::sort(log.begin(), log.end(), [](const auto &lhs, const auto &rhs) { return *lhs < *rhs; }); auto last = @@ -71,7 +68,6 @@ void DiagnosticEngine::FlushDiagnostic() for (auto it = log.begin(); it != last; it++) { printer_->Print(**it); } - isFlushed_ = true; } #ifndef FUZZING_EXIT_ON_FAILED_ASSERT static void SigSegvHandler([[maybe_unused]] int sig) diff --git a/ets2panda/util/diagnosticEngine.h b/ets2panda/util/diagnosticEngine.h index a013fc7a71..015dc4d6ad 100644 --- a/ets2panda/util/diagnosticEngine.h +++ b/ets2panda/util/diagnosticEngine.h @@ -172,7 +172,6 @@ private: std::array(DiagnosticType::COUNT)> diagnostics_; std::unique_ptr printer_; bool wError_ {false}; - bool isFlushed_ {false}; }; } // namespace ark::es2panda::util diff --git a/ets2panda/util/helpers.cpp b/ets2panda/util/helpers.cpp index 41e971809e..9bde843fb2 100644 --- a/ets2panda/util/helpers.cpp +++ b/ets2panda/util/helpers.cpp @@ -16,8 +16,11 @@ #include "helpers.h" #include +#include "checker/ETSchecker.h" + #include "parser/program/program.h" #include "varbinder/privateBinding.h" +#include "varbinder/ETSBinder.h" #include "lexer/token/letters.h" #include "ir/base/classDefinition.h" @@ -706,6 +709,57 @@ std::vector const &Helpers::StdLib() return stdlib; } +varbinder::Scope *Helpers::NearestScope(const ir::AstNode *ast) +{ + while (ast != nullptr && !ast->IsScopeBearer()) { + ast = ast->Parent(); + } + + return ast == nullptr ? nullptr : ast->Scope(); +} + +checker::ETSObjectType const *Helpers::ContainingClass(const ir::AstNode *ast) +{ + while (ast != nullptr && !ast->IsClassDefinition()) { + ast = ast->Parent(); + } + + return ast == nullptr ? nullptr : ast->AsClassDefinition()->TsType()->AsETSObjectType(); +} + +bool CheckTypeRelation(checker::ETSChecker *checker, checker::Type *super, checker::Type *sub) +{ + return checker->Relation()->IsSupertypeOf(super, sub); +} + +void Helpers::CheckLoweredNode(varbinder::ETSBinder *varBinder, checker::ETSChecker *checker, ir::AstNode *node) +{ + auto *scope = util::Helpers::NearestScope(node); + varBinder->ResolveReferencesForScopeWithContext(node, scope); + + auto *containingClass = ContainingClass(node); + checker::CheckerStatus newStatus = + (containingClass == nullptr) ? checker::CheckerStatus::NO_OPTS : checker::CheckerStatus::IN_CLASS; + if ((checker->Context().Status() & checker::CheckerStatus::IN_EXTENSION_ACCESSOR_CHECK) != 0) { + newStatus |= checker::CheckerStatus::IN_EXTENSION_ACCESSOR_CHECK; + } + auto checkerCtx = checker::SavedCheckerContext(checker, newStatus, containingClass); + auto scopeCtx = checker::ScopeContext(checker, scope); + + node->Check(checker); +} + +bool Helpers::IsNumericGlobalBuiltIn(checker::Type *type, checker::ETSChecker *checker) +{ + return CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalIntegerBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalShortBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalByteBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalCharBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalLongBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalDoubleBuiltinType()) || + CheckTypeRelation(checker, type, checker->GetGlobalTypesHolder()->GlobalFloatBuiltinType()); +} + bool Helpers::IsStdLib(const parser::Program *program) { // NOTE(rsipka): early check: if program is not in a package then it is not part of the stdlib either diff --git a/ets2panda/util/helpers.h b/ets2panda/util/helpers.h index a861a59a42..841f006566 100644 --- a/ets2panda/util/helpers.h +++ b/ets2panda/util/helpers.h @@ -30,6 +30,7 @@ class Program; namespace ark::es2panda::varbinder { class Variable; +class ETSBinder; } // namespace ark::es2panda::varbinder namespace ark::es2panda::checker { @@ -162,6 +163,14 @@ public: static bool IsGlobalVar(const ark::es2panda::varbinder::Variable *var); + static varbinder::Scope *NearestScope(const ir::AstNode *ast); + static checker::ETSObjectType const *ContainingClass(const ir::AstNode *ast); + // Note: run varbinder and checker on the new node generated in lowering phases (without + // ClearTypesVariablesAndScopes) + static void CheckLoweredNode(varbinder::ETSBinder *varBinder, checker::ETSChecker *checker, ir::AstNode *node); + + static bool IsNumericGlobalBuiltIn(checker::Type *type, checker::ETSChecker *checker); + template static ArenaVector ConvertVector(const ArenaVector &src) { diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index 3dab3459f6..2a1894aeb7 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -376,5 +376,5 @@ options: - name: perm-arena type: bool - default: true + default: false description: Place AST trees in permanent arena diff --git a/ets2panda/varbinder/scope.cpp b/ets2panda/varbinder/scope.cpp index 3b6029e614..4625e5f011 100644 --- a/ets2panda/varbinder/scope.cpp +++ b/ets2panda/varbinder/scope.cpp @@ -236,7 +236,10 @@ Variable *Scope::AddLocalTypeAliasVariable(ArenaAllocator *allocator, Decl *newD Variable *Scope::AddLocalClassVariable(ArenaAllocator *allocator, Decl *newDecl) { auto isNamespaceTransformed = newDecl->Node()->AsClassDefinition()->IsNamespaceTransformed(); - VariableFlags flag = isNamespaceTransformed ? VariableFlags::NAMESPACE : VariableFlags::CLASS; + auto isEnumTransformed = newDecl->Node()->AsClassDefinition()->IsEnumTransformed(); + VariableFlags flag = isNamespaceTransformed ? VariableFlags::NAMESPACE + : isEnumTransformed ? VariableFlags::ENUM_LITERAL + : VariableFlags::CLASS; auto *var = bindings_.insert({newDecl->Name(), allocator->New(newDecl, flag)}).first->second; newDecl->Node()->AsClassDefinition()->Ident()->SetVariable(var); return var; diff --git a/ets2panda/varbinder/variable.cpp b/ets2panda/varbinder/variable.cpp index 6768c7b88a..f58fab3472 100644 --- a/ets2panda/varbinder/variable.cpp +++ b/ets2panda/varbinder/variable.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -33,6 +33,8 @@ LocalVariable::LocalVariable(VariableFlags flags) : Variable(flags) {} const util::StringView &Variable::Name() const { + // Synthetic var has no decl_ + ES2PANDA_ASSERT(decl_ != nullptr); return decl_->Name(); } -- Gitee From 8a34bc04bdb28d7c6ee5a7daedc0580def2629bc Mon Sep 17 00:00:00 2001 From: xingshunxiang Date: Sun, 8 Jun 2025 19:29:14 +0800 Subject: [PATCH 073/747] Fix internal class and interface crash Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICDGTU?from=project-issue Description: a bug introduced by ast-cache, we no need to collect the internal class to the record table. Reason: a bug introduced by ast-cache, we no need to collect the internal class to the record table. Tests: ninja tests passed tests/tests-u-runner/runner.sh --ets-cts --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --ets-func-tests --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --astchecker --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --ets-runtime --show-progress --build-dir x64.release --processes=all passed tests/tests-u-runner/runner.sh --parser --no-js --show-progress --build-dir x64.release --processes=all passed Signed-off-by: xingshunxiang --- ets2panda/varbinder/varbinder.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ets2panda/varbinder/varbinder.cpp b/ets2panda/varbinder/varbinder.cpp index 5d754a612a..fc48436145 100644 --- a/ets2panda/varbinder/varbinder.cpp +++ b/ets2panda/varbinder/varbinder.cpp @@ -476,8 +476,7 @@ void VarBinder::VisitScriptFunction(ir::ScriptFunction *func) auto stmt = func->Body()->AsBlockStatement()->Statements(); auto scopeCtx = LexicalScope::Enter(this, funcScope); std::function doNode = [&](ir::AstNode *node) { - if (node->IsTSInterfaceDeclaration() || node->IsClassDeclaration() || node->IsTSEnumDeclaration() || - node->IsAnnotationDeclaration()) { + if (node->IsTSInterfaceDeclaration() || node->IsTSEnumDeclaration()) { ResolveReference(node); } node->Iterate([&](ir::AstNode *child) { doNode(child); }); -- Gitee From 4e2c53c5a6f5ba0b22b7f0a90952de54d7dbb645 Mon Sep 17 00:00:00 2001 From: Boglarka Date: Tue, 3 Jun 2025 14:45:52 +0200 Subject: [PATCH 074/747] Add error for invalid typeof and instanceof Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC9IO1 Reason: Typeof keyword in type annotation and instanceof with a type on the left side is invalid. Description: Added checks for these cases and error logging. Change-Id: Iee44ecfe838a60c13738bf54226a0e73c566bd00 Signed-off-by: Haag Boglarka --- ets2panda/checker/ets/validateHelpers.cpp | 7 ++++- ets2panda/parser/ETSparserTypes.cpp | 6 +++++ .../ast/parser/ets/instanceof_on_type.ets | 27 +++++++++++++++++++ .../ast/parser/ets/typeof_in_annotation.ets | 24 +++++++++++++++++ ets2panda/util/diagnostic/syntax.yaml | 8 ++++++ 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/ast/parser/ets/instanceof_on_type.ets create mode 100644 ets2panda/test/ast/parser/ets/typeof_in_annotation.ets diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index f3ad9a385b..bd0a6ceb9b 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -129,7 +129,8 @@ bool ETSChecker::ValidateBinaryExpressionIdentifier(ir::Identifier *const ident, const auto *const binaryExpr = ident->Parent()->AsBinaryExpression(); bool isFinished = false; - if (binaryExpr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF && binaryExpr->Left() == ident) { + bool isInstanceOfKeyword = binaryExpr->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF; + if (isInstanceOfKeyword && binaryExpr->Left() == ident) { if (!IsReferenceType(type)) { std::ignore = TypeError(ident->Variable(), diagnostic::INSTANCEOF_NONOBJECT, {ident->Name()}, ident->Start()); @@ -145,6 +146,10 @@ bool ETSChecker::ValidateBinaryExpressionIdentifier(ir::Identifier *const ident, } isFinished = true; } + if (isInstanceOfKeyword && ident->Variable()->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE | + varbinder::VariableFlags::TYPE_ALIAS)) { + LogError(diagnostic::WRONG_LEFT_OF_INSTANCEOF, {}, ident->Start()); + } return isFinished; } diff --git a/ets2panda/parser/ETSparserTypes.cpp b/ets2panda/parser/ETSparserTypes.cpp index fde14c8669..946e7611ed 100644 --- a/ets2panda/parser/ETSparserTypes.cpp +++ b/ets2panda/parser/ETSparserTypes.cpp @@ -540,6 +540,12 @@ bool ETSParser::ParseReadonlyInTypeAnnotation() ir::TypeNode *ETSParser::ParseTypeAnnotation(TypeAnnotationParsingOptions *options) { const auto startPos = Lexer()->GetToken().Start(); + if ((*options & + (TypeAnnotationParsingOptions::DISALLOW_UNION | TypeAnnotationParsingOptions::ANNOTATION_NOT_ALLOW)) == 0 && + Lexer()->TryEatTokenFromKeywordType(lexer::TokenType::KEYW_TYPEOF)) { + LogError(diagnostic::TYPEOF_IN_ANNOTATION); + return AllocBrokenType(Lexer()->GetToken().Loc()); + } // if there is prefix readonly parameter type, change the return result to ETSTypeReference, like Readonly<> if (!Lexer()->TryEatTokenFromKeywordType(lexer::TokenType::KEYW_READONLY)) { return ParseTypeAnnotationNoPreferParam(options); diff --git a/ets2panda/test/ast/parser/ets/instanceof_on_type.ets b/ets2panda/test/ast/parser/ets/instanceof_on_type.ets new file mode 100644 index 0000000000..cb4b9dcc7b --- /dev/null +++ b/ets2panda/test/ast/parser/ets/instanceof_on_type.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class X {} +type B = X + +let a = (new X()) instanceof Object +let b = (new X()) instanceof X +let c = X instanceof Object +let d = X instanceof X +let f = B instanceof Object + +/* @@? 21:9 Error SyntaxError: The left operand of 'instanceof' operator cannot be a type. */ +/* @@? 22:9 Error SyntaxError: The left operand of 'instanceof' operator cannot be a type. */ +/* @@? 23:9 Error SyntaxError: The left operand of 'instanceof' operator cannot be a type. */ diff --git a/ets2panda/test/ast/parser/ets/typeof_in_annotation.ets b/ets2panda/test/ast/parser/ets/typeof_in_annotation.ets new file mode 100644 index 0000000000..2ab98e4b55 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/typeof_in_annotation.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let n1 = 42 +let s1 = "foo" +let n2: typeof n1 +let s2: typeof s1 + +/* @@? 18:16 Error SyntaxError: Result of 'typeof' operator is not supported to be used as type annotation. */ +/* @@? 18:16 Error SyntaxError: Unexpected token 'n1'. */ +/* @@? 19:16 Error SyntaxError: Result of 'typeof' operator is not supported to be used as type annotation. */ +/* @@? 19:16 Error SyntaxError: Unexpected token 's1'. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index c8550ea251..114c25c8bb 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1243,3 +1243,11 @@ syntax: - name: ERROR_ARKTS_NO_AMBIENT_DECLS id: 308 message: "Ambient module declaration is not supported!" + +- name: TYPEOF_IN_ANNOTATION + id: 309 + message: "Result of 'typeof' operator is not supported to be used as type annotation." + +- name: WRONG_LEFT_OF_INSTANCEOF + id: 310 + message: "The left operand of 'instanceof' operator cannot be a type." -- Gitee From d9672c4eafe7fd25aac679cce4ce187c1bf9818d Mon Sep 17 00:00:00 2001 From: Boglarka Date: Thu, 29 May 2025 10:14:32 +0200 Subject: [PATCH 075/747] Add error for 'as const' Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBFV0 Reason: Typeof keyword in type annotation and instanceof with a type on the left side is invalid. Description: Added checks for these cases and error logging. Change-Id: Iee44ecfe838a60c13738bf54226a0e73c566bd00 Signed-off-by: Haag Boglarka --- ets2panda/parser/ETSparserExpressions.cpp | 5 ++++- ets2panda/test/ast/parser/ets/string_literal_const_cast.ets | 2 +- ets2panda/util/diagnostic/syntax.yaml | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 70d4452803..6e2790d75c 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -584,7 +584,10 @@ ir::Expression *ETSParser::ParsePotentialAsExpression(ir::Expression *primaryExp { ES2PANDA_ASSERT(Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS); Lexer()->NextToken(); - + if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CONST) { + LogError(diagnostic::AS_CONST_USAGE); + return nullptr; + } TypeAnnotationParsingOptions options = TypeAnnotationParsingOptions::REPORT_ERROR | TypeAnnotationParsingOptions::ANNOTATION_NOT_ALLOW; ir::TypeNode *type = ParseTypeAnnotation(&options); diff --git a/ets2panda/test/ast/parser/ets/string_literal_const_cast.ets b/ets2panda/test/ast/parser/ets/string_literal_const_cast.ets index 899f906944..d265e85557 100644 --- a/ets2panda/test/ast/parser/ets/string_literal_const_cast.ets +++ b/ets2panda/test/ast/parser/ets/string_literal_const_cast.ets @@ -15,7 +15,7 @@ let x = "literal str" as const -/* @@? 16:26 Error SyntaxError: Invalid Type. */ +/* @@? 16:26 Error SyntaxError: 'as const' assertion is not supported. */ /* @@? 16:26 Error SyntaxError: Unexpected token 'const'. */ /* @@? 23:1 Error SyntaxError: Identifier expected, got 'end of stream'. */ /* @@? 23:1 Error SyntaxError: Variable must be initialized or it's type must be declared. */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index 114c25c8bb..c414e118a3 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1251,3 +1251,7 @@ syntax: - name: WRONG_LEFT_OF_INSTANCEOF id: 310 message: "The left operand of 'instanceof' operator cannot be a type." + +- name: AS_CONST_USAGE + id: 311 + message: "'as const' assertion is not supported." -- Gitee From e521a6109b48ad79965aefa20f199f5e5592fd4e Mon Sep 17 00:00:00 2001 From: Gabor Aron Takacs Date: Thu, 29 May 2025 13:29:08 +0200 Subject: [PATCH 076/747] Add diagnostics for require and import Fixes #24594 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBHKQ Change-Id: Iee44ecfe838a60c13738bf54226a0e73c566bd00 Signed-off-by: Gabor Aron Takacs --- ets2panda/checker/ets/object.cpp | 4 ++++ ets2panda/parser/ETSparser.cpp | 8 +++++++ .../test/ast/parser/ets/import_assertion.ets | 22 +++++++++++++++++++ .../test/ast/parser/ets/import_require.ets | 21 ++++++++++++++++++ .../parser/ets/interface_extends_class.ets | 20 +++++++++++++++++ ets2panda/util/diagnostic/semantic.yaml | 4 ++++ ets2panda/util/diagnostic/syntax.yaml | 8 +++++++ 7 files changed, 87 insertions(+) create mode 100644 ets2panda/test/ast/parser/ets/import_assertion.ets create mode 100644 ets2panda/test/ast/parser/ets/import_require.ets create mode 100644 ets2panda/test/ast/parser/ets/interface_extends_class.ets diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index b656a25717..b4fa16bc27 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -188,6 +188,10 @@ bool ETSChecker::ComputeSuperType(ETSObjectType *type) void ETSChecker::ValidateImplementedInterface(ETSObjectType *type, Type *interface, std::unordered_set *extendsSet, const lexer::SourcePosition &pos) { + if (interface->IsETSObjectType() && interface->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::CLASS)) { + LogError(diagnostic::INTERFACE_EXTENDS_CLASS, {}, pos); + return; + } if (!interface->IsETSObjectType() || !interface->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) { LogError(diagnostic::NOT_INTERFACE, {}, pos); return; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 36001a7946..9a591d8e19 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -1191,6 +1191,10 @@ ir::ETSImportDeclaration *ETSParser::ParseImportPathBuildImport(ArenaVector(GetContext().GetProgram()), importFlags); importDeclaration->SetRange({startLoc, importPathStringLiteral->End()}); + if (Lexer()->GetToken().Ident().Is("assert")) { + LogError(diagnostic::ERROR_ARKTS_NO_IMPORT_ASSERTIONS); + return importDeclaration; + } ConsumeSemicolon(importDeclaration); return importDeclaration; } @@ -1494,6 +1498,10 @@ ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector * } } + if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SUBSTITUTION) { + LogError(diagnostic::ERROR_ARKTS_NO_REQUIRE); + return nullptr; + } if (Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_FROM) { LogExpectedToken(lexer::TokenType::KEYW_FROM); Lexer()->NextToken(); // eat 'from' diff --git a/ets2panda/test/ast/parser/ets/import_assertion.ets b/ets2panda/test/ast/parser/ets/import_assertion.ets new file mode 100644 index 0000000000..bbf4ed4a28 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/import_assertion.ets @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as Pt from "mod" /* @@ label1 */assert /* @@ label2 */{ type: /* @@ label3 */"json" } + + +/* @@@ label1 Error SyntaxError: Import assertion is not supported, please use the ordinary import syntax instead! */ +/* @@@ label1 Error TypeError: Unresolved reference assert */ +/* @@@ label2 Error SyntaxError: Unexpected token '{'. */ +/* @@@ label3 Error SyntaxError: Label must be followed by a loop statement. */ diff --git a/ets2panda/test/ast/parser/ets/import_require.ets b/ets2panda/test/ast/parser/ets/import_require.ets new file mode 100644 index 0000000000..ad8766f57b --- /dev/null +++ b/ets2panda/test/ast/parser/ets/import_require.ets @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import m /* @@ label1 */= /* @@ label2 */require("mod") + +/* @@@ label1 Error SyntaxError: Importing by 'require' and 'import' assignment is not supported, use 'import * as ... from ...' form instead! */ +/* @@@ label1 Error SyntaxError: Unexpected token '='. */ +/* @@@ label2 Error SyntaxError: Unexpected token 'require'. */ +/* @@@ label2 Error TypeError: Unresolved reference require */ diff --git a/ets2panda/test/ast/parser/ets/interface_extends_class.ets b/ets2panda/test/ast/parser/ets/interface_extends_class.ets new file mode 100644 index 0000000000..6e88716f0c --- /dev/null +++ b/ets2panda/test/ast/parser/ets/interface_extends_class.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A {} + +interface BInterface extends /* @@ label */A {} + +/* @@@ label Error TypeError: Interfaces cannot extend classes, only other interfaces. */ diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 7565ace3dd..f9f32109e0 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1474,3 +1474,7 @@ semantic: - name: SUPER_NOT_ACCESSIBLE id: 372 message: "Class field '{}' defined by the parent class is not accessible in the child class via super." + +- name: INTERFACE_EXTENDS_CLASS + id: 373 + message: "Interfaces cannot extend classes, only other interfaces." diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index c414e118a3..9187a67b9b 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1255,3 +1255,11 @@ syntax: - name: AS_CONST_USAGE id: 311 message: "'as const' assertion is not supported." + +- name: ERROR_ARKTS_NO_REQUIRE + id: 312 + message: "Importing by 'require' and 'import' assignment is not supported, use 'import * as ... from ...' form instead!" + +- name: ERROR_ARKTS_NO_IMPORT_ASSERTIONS + id: 313 + message: "Import assertion is not supported, please use the ordinary import syntax instead!" -- Gitee From 9459de149bd5b2fd62e819a94918ea402678daae Mon Sep 17 00:00:00 2001 From: "peter.pronai" Date: Mon, 26 May 2025 10:12:58 +0000 Subject: [PATCH 077/747] Add diagnostic for generator function Fixes #24865 internal issue. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAN1E Change-Id: Iee44ecfe838a60c13738bf54226a0e73c566bd00 Signed-off-by: peter.pronai --- ets2panda/parser/ETSparser.cpp | 1 + .../test/ast/parser/ets/generator_function.ets | 17 +++++++++++++++++ ets2panda/util/diagnostic/syntax.yaml | 4 ++++ 3 files changed, 22 insertions(+) create mode 100644 ets2panda/test/ast/parser/ets/generator_function.ets diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 9a591d8e19..d1ce81f9f8 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -2121,6 +2121,7 @@ ir::FunctionDeclaration *ETSParser::ParseFunctionDeclaration(bool canBeAnonymous } if (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_MULTIPLY)) { + LogError(diagnostic::GENERATOR_FUNCTION); newStatus |= ParserStatus::GENERATOR_FUNCTION; } diff --git a/ets2panda/test/ast/parser/ets/generator_function.ets b/ets2panda/test/ast/parser/ets/generator_function.ets new file mode 100644 index 0000000000..7f865bb644 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/generator_function.ets @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function* f() {} +/* @@? 16:11 Error SyntaxError: Generator functions are not supported, please use async/await mechanism for multitasking */ diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index 9187a67b9b..049af2e5ec 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1263,3 +1263,7 @@ syntax: - name: ERROR_ARKTS_NO_IMPORT_ASSERTIONS id: 313 message: "Import assertion is not supported, please use the ordinary import syntax instead!" + +- name: GENERATOR_FUNCTION + id: 314 + message: "Generator functions are not supported, please use async/await mechanism for multitasking" -- Gitee From 9935e7c06caae29d2e133e3345fcc8928ce8e148 Mon Sep 17 00:00:00 2001 From: oh-rgx Date: Thu, 5 Jun 2025 17:24:41 +0800 Subject: [PATCH 078/747] fix diagnostic flush Issue: #ICDC8T Signed-off-by: oh-rgx --- ets2panda/public/es2panda_lib.cpp | 10 +--------- .../ast_verifier_check_struct_declaration_test.cpp | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 14a173532e..3ba94058e7 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -500,10 +500,7 @@ __attribute__((unused)) static Context *Parse(Context *ctx) ctx->parser->ParseScript(*ctx->sourceFile, ctx->config->options->GetCompilationMode() == CompilationMode::GEN_STD_LIB); } - ctx->state = !ctx->diagnosticEngine->IsAnyError() ? ES2PANDA_STATE_PARSED : ES2PANDA_STATE_ERROR; - if (ctx->state == ES2PANDA_STATE_ERROR) { - ctx->diagnosticEngine->FlushDiagnostic(); - } + ctx->state = ES2PANDA_STATE_PARSED; ctx->phaseManager->SetCurrentPhaseIdToAfterParse(); return ctx; } @@ -535,7 +532,6 @@ __attribute__((unused)) static Context *Check(Context *ctx) } if (ctx->state == ES2PANDA_STATE_ERROR) { - ctx->diagnosticEngine->FlushDiagnostic(); return ctx; } @@ -579,7 +575,6 @@ __attribute__((unused)) static Context *Lower(Context *ctx) } if (ctx->state == ES2PANDA_STATE_ERROR) { - ctx->diagnosticEngine->FlushDiagnostic(); return ctx; } @@ -688,9 +683,6 @@ extern "C" __attribute__((unused)) es2panda_Context *ProceedToState(es2panda_Con break; } - if (ctx->state == ES2PANDA_STATE_ERROR) { - ctx->diagnosticEngine->FlushDiagnostic(); - } return reinterpret_cast(ctx); } diff --git a/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp b/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp index dbdd1b433c..288cafaf20 100644 --- a/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp +++ b/ets2panda/test/unit/public/ast_verifier_check_struct_declaration_test.cpp @@ -163,7 +163,7 @@ TEST_F(ASTVerifierTest, StructInStruct) } )"; - CONTEXT(ES2PANDA_STATE_PARSED, ES2PANDA_STATE_ERROR, text) + CONTEXT(ES2PANDA_STATE_PARSED, text) { ASSERT_TRUE(GetImpl()->IsAnyError(GetContext())); } -- Gitee From e5dfcb98fd9fe30243ae7287f19b4cc86ca9afaf Mon Sep 17 00:00:00 2001 From: yaohaosen Date: Wed, 4 Jun 2025 20:58:50 +0800 Subject: [PATCH 079/747] [LSP] Support UI Plugin Code Fixes Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICC5VX Signed-off-by: yaohaosen --- ets2panda/bindings/native/src/lsp.cpp | 68 +++++++ .../bindings/src/Es2pandaNativeModule.ts | 31 ++- ets2panda/bindings/src/buildConfigGenerate.ts | 19 +- ets2panda/bindings/src/lspNode.ts | 37 ++++ ets2panda/bindings/src/lsp_helper.ts | 39 +++- ets2panda/lsp/BUILD.gn | 1 + ets2panda/lsp/CMakeLists.txt | 1 + ets2panda/lsp/include/api.h | 6 +- ets2panda/lsp/include/cancellation_token.h | 1 + ets2panda/lsp/include/internal_api.h | 41 ++++ .../register_code_fix/ui_plugin_suggest.h | 39 ++++ ets2panda/lsp/src/api.cpp | 18 +- ets2panda/lsp/src/internal_api.cpp | 17 +- .../register_code_fix/ui_plugin_suggest.cpp | 117 ++++++++++++ ets2panda/test/unit/lsp/CMakeLists.txt | 4 + .../unit/lsp/code_fix/ui_plugin_suggest.cpp | 180 ++++++++++++++++++ .../unit/lsp/code_fix_registration_test.cpp | 2 +- ets2panda/test/unit/lsp/get_diagnostics.cpp | 18 +- ets2panda/util/diagnostic.h | 5 + 19 files changed, 619 insertions(+), 25 deletions(-) create mode 100644 ets2panda/lsp/include/register_code_fix/ui_plugin_suggest.h create mode 100644 ets2panda/lsp/src/register_code_fix/ui_plugin_suggest.cpp create mode 100644 ets2panda/test/unit/lsp/code_fix/ui_plugin_suggest.cpp diff --git a/ets2panda/bindings/native/src/lsp.cpp b/ets2panda/bindings/native/src/lsp.cpp index 286efef597..f8f6c9c669 100644 --- a/ets2panda/bindings/native/src/lsp.cpp +++ b/ets2panda/bindings/native/src/lsp.cpp @@ -1258,6 +1258,74 @@ KInt impl_getTypeFromTypeHierarchies(KNativePointer infoPtr) } TS_INTEROP_1(getTypeFromTypeHierarchies, KInt, KNativePointer) +KNativePointer impl_getCodeFixesAtPosition(KNativePointer context, KInt startPosition, KInt endPosition, + KInt *errorCodesPtr, KInt codeLength) +{ + CodeFixOptions emptyOptions; + std::vector errorCodesInt; + if (errorCodesPtr != nullptr && codeLength > 0) { + // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic,-warnings-as-errors) + errorCodesInt = std::vector(reinterpret_cast(errorCodesPtr), + reinterpret_cast(errorCodesPtr) + codeLength); + // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic,-warnings-as-errors) + } + LSPAPI const *ctx = GetImpl(); + auto autofix = ctx->getCodeFixesAtPosition(reinterpret_cast(context), startPosition, + endPosition, errorCodesInt, emptyOptions); + return new std::vector(autofix); +} +TS_INTEROP_5(getCodeFixesAtPosition, KNativePointer, KNativePointer, KInt, KInt, KInt *, KInt) + +KNativePointer impl_getCodeFixActionInfos(KNativePointer codeFixActionInfoListPtr) +{ + auto *getCodeFixActionInfoList = reinterpret_cast(codeFixActionInfoListPtr); + std::vector ptrs; + for (auto &el : getCodeFixActionInfoList->infos_) { + ptrs.push_back(new CodeFixActionInfo(el)); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(getCodeFixActionInfos, KNativePointer, KNativePointer) + +KNativePointer impl_getFileTextChangesFromCodeActionInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + std::vector ptrs; + for (auto &el : info->changes_) { + ptrs.push_back(new FileTextChanges(el)); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(getFileTextChangesFromCodeActionInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getDescriptionFromCodeActionInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return new std::string(info->description_); +} +TS_INTEROP_1(getDescriptionFromCodeActionInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getFixNameFromCodeFixActionInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return new std::string(info->fixName_); +} +TS_INTEROP_1(getFixNameFromCodeFixActionInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getFixIdFromCodeFixActionInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return new std::string(info->fixId_); +} +TS_INTEROP_1(getFixIdFromCodeFixActionInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getFixAllDescriptionFromCodeFixActionInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return new std::string(info->fixAllDescription_); +} +TS_INTEROP_1(getFixAllDescriptionFromCodeFixActionInfo, KNativePointer, KNativePointer) + KNativePointer impl_getSpanOfEnclosingComment(KNativePointer context, KInt position, KBoolean onlyMultiLine) { LSPAPI const *ctx = GetImpl(); diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index 210ad83e1c..881b164a26 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -14,7 +14,7 @@ import * as fs from 'fs'; import * as path from 'path'; -import { KNativePointer as KPtr, KInt, KBoolean, KNativePointer, KDouble, KUInt, KStringPtr } from './InteropTypes'; +import { KNativePointer as KPtr, KInt, KBoolean, KNativePointer, KDouble, KUInt, KStringPtr, KInt32ArrayPtr } from './InteropTypes'; import { Es2pandaNativeModule as GeneratedEs2pandaNativeModule } from './generated/Es2pandaNativeModule'; import { loadNativeModuleLibrary, registerNativeModuleLibraryName } from './loadLibraries'; import { throwError } from './utils'; @@ -720,6 +720,35 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } + _getCodeFixesAtPosition(context: KNativePointer, startPosition: KInt, endPosition: KInt, + errorCodesPtr: KInt32ArrayPtr, codeLength: KInt): KPtr { + throw new Error('Not implemented'); + } + + _getCodeFixActionInfos(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFileTextChangesFromCodeActionInfo(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getDescriptionFromCodeActionInfo(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFixNameFromCodeFixActionInfo(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFixIdFromCodeFixActionInfo(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFixAllDescriptionFromCodeFixActionInfo(infoPtr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + _getInlayHintText(ptr: KPtr): KPtr { throw new Error('Not implemented'); } diff --git a/ets2panda/bindings/src/buildConfigGenerate.ts b/ets2panda/bindings/src/buildConfigGenerate.ts index 4d1b1c34d1..478196c6aa 100644 --- a/ets2panda/bindings/src/buildConfigGenerate.ts +++ b/ets2panda/bindings/src/buildConfigGenerate.ts @@ -161,6 +161,19 @@ function getModuleDependencies(modulePath: string, visited = new Set()): return Array.from(new Set([...dependencies, ...nestedDependencies])); } +function createMapEntryForPlugin(buildSdkPath: string, pluginName: string): string { + return path.join(buildSdkPath, 'build-tools', 'ui-plugins', 'lib', pluginName, 'index'); +} + +function createPluginMap(buildSdkPath: string): Record { + let pluginMap: Record = {}; + const pluginList: string[] = ['ui-syntax-plugins', 'ui-plugins', 'memo-plugins']; + for (const plugin of pluginList) { + pluginMap[plugin] = createMapEntryForPlugin(buildSdkPath, plugin); + } + return pluginMap; +} + export function generateBuildConfigs( buildSdkPath: string, projectRoot: string, @@ -179,6 +192,7 @@ export function generateBuildConfigs( for (const module of definedModules) { const modulePath = module.srcPath; const compileFiles = new Set(getEtsFiles(modulePath)); + const pluginMap = createPluginMap(buildSdkPath); // Get recursive dependencies const dependencies = getModuleDependencies(modulePath); @@ -187,10 +201,7 @@ export function generateBuildConfigs( } allBuildConfigs[module.name] = { - plugins: { - 'ui-plugins': path.join(buildSdkPath, 'build-tools', 'ui-plugins', 'lib', 'ui-plugins', 'index'), - 'memo-plugin': path.join(buildSdkPath, 'build-tools', 'ui-plugins', 'lib', 'memo-plugins', 'index') - }, + plugins: pluginMap, arkts: {}, arktsGlobal: {}, compileFiles: Array.from(compileFiles), diff --git a/ets2panda/bindings/src/lspNode.ts b/ets2panda/bindings/src/lspNode.ts index 17f846fce2..5f305aa2d6 100644 --- a/ets2panda/bindings/src/lspNode.ts +++ b/ets2panda/bindings/src/lspNode.ts @@ -644,6 +644,43 @@ export class FileTextChanges extends LspNode { readonly textChanges: TextChange[]; } +export class CodeActionInfo extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.changes = new NativePtrDecoder() + .decode(global.es2panda._getFileTextChangesFromCodeActionInfo(peer)) + .map((elPeer: KNativePointer) => { + return new FileTextChanges(elPeer); + }); + this.description = unpackString(global.es2panda._getDescriptionFromCodeActionInfo(peer)); + } + readonly changes: FileTextChanges[]; + readonly description: String; +} + +export class CodeFixActionInfo extends CodeActionInfo { + constructor(peer: KNativePointer) { + super(peer); + this.fixName = unpackString(global.es2panda._getFixNameFromCodeFixActionInfo(peer)); + this.fixId_ = unpackString(global.es2panda._getFixIdFromCodeFixActionInfo(peer)); + this.fixAllDescription_ = unpackString(global.es2panda._getFixAllDescriptionFromCodeFixActionInfo(peer)); + } + readonly fixName: String; + readonly fixId_: String; + readonly fixAllDescription_: String; +} + +export class CodeFixActionInfoList extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.codeFixActionInfos = new NativePtrDecoder() + .decode(global.es2panda._getCodeFixActionInfos(peer)) + .map((elPeer: KNativePointer) => { + return new CodeFixActionInfo(elPeer); + }); + } + readonly codeFixActionInfos: CodeFixActionInfo[]; +} export class LspFileTextChanges extends LspNode { constructor(peer: KNativePointer) { diff --git a/ets2panda/bindings/src/lsp_helper.ts b/ets2panda/bindings/src/lsp_helper.ts index b543a2b07e..7effce3147 100644 --- a/ets2panda/bindings/src/lsp_helper.ts +++ b/ets2panda/bindings/src/lsp_helper.ts @@ -40,7 +40,9 @@ import { LspInlayHint, LspInlayHintList, TextSpan, - LspSignatureHelpItems + LspSignatureHelpItems, + CodeFixActionInfo, + CodeFixActionInfoList } from './lspNode'; import { passStringArray, unpackString } from './private'; import { Es2pandaContextState } from './generated/Es2pandaEnums'; @@ -111,6 +113,16 @@ export class Lsp { return getSource.replace(/\r\n/g, '\n'); } + private getModuleNameFromFilename(filePath: string): string { + const projectRoot = this.projectPath; + if (!filePath.startsWith(projectRoot)) { + return ''; + } + const relativePath = path.relative(projectRoot, filePath); + const parts = relativePath.split(path.sep); + return parts[0] || ''; + } + getDefinitionAtPosition(filename: String, offset: number): LspDefinitionData { let lspDriverHelper = new LspDriverHelper(); let filePath = path.resolve(filename.valueOf()); @@ -529,6 +541,9 @@ export class Lsp { let localCfg = lspDriverHelper.createCfg(ets2pandaCmd, filePath, this.pandaLibPath); const source = this.getFileSource(filePath); let localCtx = lspDriverHelper.createCtx(source, filePath, localCfg); + const moduleName = this.getModuleNameFromFilename(filePath); + const buildConfig = this.moduleToBuildConfig[moduleName]; + PluginDriver.getInstance().getPluginContext().setProjectConfig(buildConfig); PluginDriver.getInstance().getPluginContext().setContextPtr(localCtx); lspDriverHelper.proceedToState(localCtx, Es2pandaContextState.ES2PANDA_STATE_PARSED); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); @@ -683,6 +698,28 @@ export class Lsp { return new LspTextSpan(ptr); } + getCodeFixesAtPosition(filename: String, start: number, end: number, errorCodes: number[]): CodeFixActionInfo[] { + let lspDriverHelper = new LspDriverHelper(); + let filePath = path.resolve(filename.valueOf()); + let arktsconfig = this.fileNameToArktsconfig[filePath]; + let ets2pandaCmd = ets2pandaCmdPrefix.concat(arktsconfig); + let localCfg = lspDriverHelper.createCfg(ets2pandaCmd, filePath, this.pandaLibPath); + const source = this.getFileSource(filePath); + let localCtx = lspDriverHelper.createCtx(source, filePath, localCfg); + PluginDriver.getInstance().getPluginContext().setContextPtr(localCtx); + lspDriverHelper.proceedToState(localCtx, Es2pandaContextState.ES2PANDA_STATE_PARSED); + PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); + lspDriverHelper.proceedToState(localCtx, Es2pandaContextState.ES2PANDA_STATE_CHECKED); + let ptr = global.es2panda._getCodeFixesAtPosition(localCtx, start, end, new Int32Array(errorCodes), errorCodes.length); + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + lspDriverHelper.destroyContext(localCtx); + lspDriverHelper.destroyConfig(localCfg); + const codeFixActionInfoList = new CodeFixActionInfoList(ptr); + const codeFixActionInfos: CodeFixActionInfo[] = []; + codeFixActionInfos.push(...codeFixActionInfoList.codeFixActionInfos); + return codeFixActionInfos; + } + provideInlayHints(filename: String, span: TextSpan): LspInlayHint[] { let lspDriverHelper = new LspDriverHelper(); let filePath = path.resolve(filename.valueOf()); diff --git a/ets2panda/lsp/BUILD.gn b/ets2panda/lsp/BUILD.gn index 5cd817c9c5..ff8b060335 100644 --- a/ets2panda/lsp/BUILD.gn +++ b/ets2panda/lsp/BUILD.gn @@ -83,6 +83,7 @@ ohos_source_set("libes2panda_lsp_static") { "src/register_code_fix/forgetten_this_property_access.cpp", "src/register_code_fix/import_fixes.cpp", "src/rename.cpp", + "src/register_code_fix/ui_plugin_suggest.cpp", "src/script_element_kind.cpp", "src/services/services.cpp", "src/services/text_change/change_tracker.cpp", diff --git a/ets2panda/lsp/CMakeLists.txt b/ets2panda/lsp/CMakeLists.txt index f9e2e474c8..9cd9dab4f2 100644 --- a/ets2panda/lsp/CMakeLists.txt +++ b/ets2panda/lsp/CMakeLists.txt @@ -65,6 +65,7 @@ set(ES2PANDA_LSP_SRC ./src/register_code_fix/fix_nan_equality.cpp ./src/register_code_fix/forgetten_this_property_access.cpp ./src/register_code_fix/import_fixes.cpp + ./src/register_code_fix/ui_plugin_suggest.cpp ./src/get_name_or_dotted_name_span.cpp ) diff --git a/ets2panda/lsp/include/api.h b/ets2panda/lsp/include/api.h index b49cab1586..bd47d74f9d 100644 --- a/ets2panda/lsp/include/api.h +++ b/ets2panda/lsp/include/api.h @@ -480,6 +480,10 @@ struct CodeFixActionInfo : CodeActionInfo { std::string fixAllDescription_ = {}; }; +struct CodeFixActionInfoList { + std::vector infos_; +}; + struct CodeFixOptions { ark::es2panda::lsp::CancellationToken token; ark::es2panda::lsp::FormatCodeSettings options; @@ -538,7 +542,7 @@ typedef struct LSPAPI { ark::es2panda::lsp::CancellationToken *cancellationToken); InlayHintList (*provideInlayHints)(es2panda_Context *context, const TextSpan *span); SignatureHelpItems (*getSignatureHelpItems)(es2panda_Context *context, size_t position); - std::vector (*getCodeFixesAtPosition)(const char *fileName, size_t start_position, + std::vector (*getCodeFixesAtPosition)(es2panda_Context *context, size_t start_position, size_t end_position, std::vector &errorCodes, CodeFixOptions &codeFixOptions); CombinedCodeActionsInfo (*getCombinedCodeFix)(const char *fileName, const std::string &fixId, diff --git a/ets2panda/lsp/include/cancellation_token.h b/ets2panda/lsp/include/cancellation_token.h index a6a9209127..942f7f957e 100644 --- a/ets2panda/lsp/include/cancellation_token.h +++ b/ets2panda/lsp/include/cancellation_token.h @@ -32,6 +32,7 @@ public: bool IsCancellationRequested(); bool ThrottledCancellationCheck(); CancellationToken(time_t designatedThrottleTime, HostCancellationToken *hostCancellationToken); + CancellationToken() : lastCancellationTime_(0), throttleTime_(0), host_(nullptr) {} private: time_t lastCancellationTime_; diff --git a/ets2panda/lsp/include/internal_api.h b/ets2panda/lsp/include/internal_api.h index 9d1f8ff9b6..b021c901da 100644 --- a/ets2panda/lsp/include/internal_api.h +++ b/ets2panda/lsp/include/internal_api.h @@ -52,6 +52,47 @@ public: impl_->DestroyContext(context); } + const es2panda_DiagnosticKind *CreateDiagnosticKind(es2panda_Context *context, const char *dmessage, + es2panda_PluginDiagnosticType etype) + { + return impl_->CreateDiagnosticKind(context, dmessage, etype); + } + + es2panda_SuggestionInfo *CreateSuggestionInfo(es2panda_Context *context, const es2panda_DiagnosticKind *kind, + const char **args, size_t argc, const char *substitutionCode) + { + return impl_->CreateSuggestionInfo(context, kind, args, argc, substitutionCode); + } + + es2panda_DiagnosticInfo *CreateDiagnosticInfo(es2panda_Context *context, const es2panda_DiagnosticKind *kind, + const char **args, size_t argc) + { + return impl_->CreateDiagnosticInfo(context, kind, args, argc); + } + + es2panda_SourcePosition *CreateSourcePosition(es2panda_Context *context, size_t index, size_t line) + { + return impl_->CreateSourcePosition(context, index, line); + } + + es2panda_SourceRange *CreateSourceRange(es2panda_Context *context, es2panda_SourcePosition *start, + es2panda_SourcePosition *end) + { + return impl_->CreateSourceRange(context, start, end); + } + + void LogDiagnosticWithSuggestion(es2panda_Context *context, const es2panda_DiagnosticInfo *diagnosticInfo, + const es2panda_SuggestionInfo *suggestionInfo, es2panda_SourceRange *range) + { + return impl_->LogDiagnosticWithSuggestion(context, diagnosticInfo, suggestionInfo, range); + } + + void LogDiagnostic(es2panda_Context *context, const es2panda_DiagnosticKind *ekind, const char **args, size_t argc, + es2panda_SourcePosition *pos) + { + return impl_->LogDiagnostic(context, ekind, args, argc, pos); + } + NO_COPY_SEMANTIC(Initializer); NO_MOVE_SEMANTIC(Initializer); diff --git a/ets2panda/lsp/include/register_code_fix/ui_plugin_suggest.h b/ets2panda/lsp/include/register_code_fix/ui_plugin_suggest.h new file mode 100644 index 0000000000..31ebf572bb --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/ui_plugin_suggest.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IMPORT_FIXES_H +#define IMPORT_FIXES_H + +#include +#include +#include "lsp/include/code_fixes/code_fix_types.h" +#include "lsp/include/services/text_change/change_tracker.h" +#include "lsp/include/types.h" + +namespace ark::es2panda::lsp { + +class UIPluginSuggest : public CodeFixRegistration { +public: + UIPluginSuggest(); + + static std::vector GetUIPluginCodeFixes(es2panda_Context *context, size_t pos, bool isAll); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; +}; + +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index 7bee9e715d..23acef7f97 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -187,9 +187,19 @@ DiagnosticReferences GetSyntacticDiagnostics(es2panda_Context *context) DiagnosticReferences result {}; auto ctx = reinterpret_cast(context); const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SYNTAX); + const auto &diagnosticsPluginError = + ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_ERROR); + const auto &diagnosticsPluginWarning = + ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_WARNING); for (const auto &diagnostic : diagnostics) { result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); } + for (const auto &diagnostic : diagnosticsPluginError) { + result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); + } + for (const auto &diagnostic : diagnosticsPluginWarning) { + result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); + } return result; } @@ -372,14 +382,12 @@ SignatureHelpItems GetSignatureHelpItems(es2panda_Context *context, size_t posit auto cancellationToken = ark::es2panda::lsp::CancellationToken(defaultTime, nullptr); return ark::es2panda::lsp::GetSignatureHelpItems(context, position, invokedReason, cancellationToken); } -std::vector GetCodeFixesAtPosition(const char *fileName, size_t startPosition, size_t endPosition, - std::vector &errorCodes, CodeFixOptions &codeFixOptions) +std::vector GetCodeFixesAtPosition(es2panda_Context *context, size_t startPosition, + size_t endPosition, std::vector &errorCodes, + CodeFixOptions &codeFixOptions) { - Initializer initializer = Initializer(); - auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED); auto result = ark::es2panda::lsp::GetCodeFixesAtPositionImpl(context, startPosition, endPosition, errorCodes, codeFixOptions); - initializer.DestroyContext(context); return result; } diff --git a/ets2panda/lsp/src/internal_api.cpp b/ets2panda/lsp/src/internal_api.cpp index 05c9922c14..795777e89e 100644 --- a/ets2panda/lsp/src/internal_api.cpp +++ b/ets2panda/lsp/src/internal_api.cpp @@ -510,16 +510,27 @@ std::string GetOwnerId(ir::AstNode *node) DiagnosticSeverity GetSeverity(util::DiagnosticType errorType) { ES2PANDA_ASSERT(errorType != util::DiagnosticType::INVALID); - if (errorType == util::DiagnosticType::WARNING) { + if (errorType == util::DiagnosticType::WARNING || errorType == util::DiagnosticType::PLUGIN_WARNING) { return DiagnosticSeverity::Warning; } if (errorType == util::DiagnosticType::SYNTAX || errorType == util::DiagnosticType::SEMANTIC || - errorType == util::DiagnosticType::FATAL || errorType == util::DiagnosticType::ARKTS_CONFIG_ERROR) { + errorType == util::DiagnosticType::FATAL || errorType == util::DiagnosticType::ARKTS_CONFIG_ERROR || + errorType == util::DiagnosticType::PLUGIN_ERROR) { return DiagnosticSeverity::Error; } throw std::runtime_error("Unknown error type!"); } +// Temp design only support UI Plugin Diag. +int CreateCodeForDiagnostic(const util::DiagnosticBase *error) +{ + const int uiCode = 4000; + if (error->Type() == util::DiagnosticType::PLUGIN_ERROR || error->Type() == util::DiagnosticType::PLUGIN_WARNING) { + return uiCode; + } + return 1; +} + Diagnostic CreateDiagnosticForError(es2panda_Context *context, const util::DiagnosticBase &error) { auto ctx = reinterpret_cast(context); @@ -543,7 +554,7 @@ Diagnostic CreateDiagnosticForError(es2panda_Context *context, const util::Diagn auto range = Range(Position(sourceStartLocation.line, sourceStartLocation.col), Position(sourceEndLocation.line, sourceEndLocation.col)); auto severity = GetSeverity(error.Type()); - auto code = 1; + auto code = CreateCodeForDiagnostic(&error); std::string message = error.Message(); auto codeDescription = CodeDescription("test code description"); auto tags = std::vector(); diff --git a/ets2panda/lsp/src/register_code_fix/ui_plugin_suggest.cpp b/ets2panda/lsp/src/register_code_fix/ui_plugin_suggest.cpp new file mode 100644 index 0000000000..cb5f93b9dd --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/ui_plugin_suggest.cpp @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lsp/include/register_code_fix/ui_plugin_suggest.h" +#include +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { +const int G_UI_PLUGIN_SUGGEST_CODE = 4000; // change this to the error code you want to handle + +UIPluginSuggest::UIPluginSuggest() +{ + const char *uiPluginSuggestId = "UIPluginSuggest"; + SetErrorCodes({G_UI_PLUGIN_SUGGEST_CODE}); + SetFixIds({uiPluginSuggestId}); +} + +std::vector GetTextChangesFromSuggestions(const ark::es2panda::util::Diagnostic *diag, size_t pos, + bool isAll) +{ + std::vector textChanges; + if (!diag->HasSuggestions()) { + return textChanges; + } + for (auto suggestion : diag->Suggestion()) { + auto sourceStart = suggestion->SourceRange()->start.index; + auto sourceEnd = suggestion->SourceRange()->end.index; + auto span = TextSpan(sourceStart, sourceEnd); + if (isAll) { + textChanges.emplace_back(TextChange(span, suggestion->SubstitutionCode())); + } else if (pos >= sourceStart && pos <= sourceEnd) { + textChanges.emplace_back(TextChange(span, suggestion->SubstitutionCode())); + } + } + return textChanges; +} + +std::vector GetUIPluginCodeFixesByDiagType(public_lib::Context *ctx, size_t pos, + util::DiagnosticType type, bool isAll) +{ + auto filename = ctx->sourceFileName; + std::vector res; + const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(type); + auto diagnosticStorage = reinterpret_cast(&diagnostics); + // NOLINTNEXTLINE(modernize-loop-convert,-warnings-as-errors) + for (size_t i = 0; i < diagnosticStorage->size(); ++i) { + auto diag = reinterpret_cast(&(*(*diagnosticStorage)[i])); + auto textChanges = GetTextChangesFromSuggestions(diag, pos, isAll); + FileTextChanges fileTextChanges(filename, textChanges); + res.emplace_back(fileTextChanges); + } + return res; +} + +std::vector UIPluginSuggest::GetUIPluginCodeFixes(es2panda_Context *context, size_t pos, bool isAll) +{ + if (context == nullptr) { + return {}; + } + auto ctx = reinterpret_cast(context); + std::vector res; + auto errorFixes = GetUIPluginCodeFixesByDiagType(ctx, pos, util::DiagnosticType::PLUGIN_ERROR, isAll); + res.insert(res.end(), errorFixes.begin(), errorFixes.end()); + auto warningFixes = GetUIPluginCodeFixesByDiagType(ctx, pos, util::DiagnosticType::PLUGIN_WARNING, isAll); + res.insert(res.end(), warningFixes.begin(), warningFixes.end()); + return res; +} + +std::vector UIPluginSuggest::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + auto changes = GetUIPluginCodeFixes(context.context, context.span.start, false); + if (!changes.empty()) { + CodeFixAction codeAction; + codeAction.fixName = "Fix"; + codeAction.description = "Fix Description"; + codeAction.changes = changes; + codeAction.fixId = "UI_PLUGIN_SUGGEST"; + codeAction.fixAllDescription = "Fix All Description"; + InstallPackageAction codeActionCommand; + codeActionCommand.file = reinterpret_cast(context.context)->sourceFileName; + codeActionCommand.packageName = ""; + codeAction.commands.push_back(codeActionCommand); + returnedActions.push_back(codeAction); + } + return returnedActions; +} + +CombinedCodeActions UIPluginSuggest::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + CombinedCodeActions combinedCodeActions; + auto changes = GetUIPluginCodeFixes(codeFixAll.context, 0, true); + combinedCodeActions.changes = changes; + InstallPackageAction codeActionCommand; + codeActionCommand.file = reinterpret_cast(codeFixAll.context)->sourceFileName; + codeActionCommand.packageName = ""; + combinedCodeActions.commands.push_back(codeActionCommand); + + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_uiPluginSuggest("UIPluginSuggest"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index 739388e5a4..8106544cc6 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -140,6 +140,10 @@ ets2panda_add_gtest(lsp_api_completions_test CPP_SOURCES get_completions.cpp ) +ets2panda_add_gtest(lsp_api_ui_suggest_test CPP_SOURCES + code_fix/ui_plugin_suggest.cpp +) + ets2panda_add_gtest(lsp_api_test_get_class_hierarchy_info CPP_SOURCES class_hierarchy_info_test.cpp ) diff --git a/ets2panda/test/unit/lsp/code_fix/ui_plugin_suggest.cpp b/ets2panda/test/unit/lsp/code_fix/ui_plugin_suggest.cpp new file mode 100644 index 0000000000..93c0d77ff8 --- /dev/null +++ b/ets2panda/test/unit/lsp/code_fix/ui_plugin_suggest.cpp @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../lsp_api_test.h" + +#include + +#include "ir/astNode.h" +#include "lsp/include/register_code_fix/ui_plugin_suggest.h" +#include "lsp/include/internal_api.h" +#include "public/es2panda_lib.h" +#include "public/public.h" + +namespace { + +class LspUISuggestionTests : public LSPAPITests {}; + +using ark::es2panda::lsp::Initializer; + +void AssertDiagnosticContainsCodeAndMessage(const DiagnosticReferences &suggest, const int code, const char *dmessage) +{ + bool found = false; + for (auto diag : suggest.diagnostic) { + if (std::get(diag.code_) == code) { + if (diag.message_ == dmessage) { + found = true; + } + } + } + ASSERT_TRUE(found) << "Expected code: " << code << " not found"; +} + +TEST_F(LspUISuggestionTests, UIPluginsErrorTest1) +{ + using ark::es2panda::ir::AstNode; + using ark::es2panda::public_lib::Context; + Initializer initializer = Initializer(); + std::vector files = {"ui_error1.ets"}; + std::vector texts = {R"delimiter(function main() {})delimiter"}; + auto filePaths = CreateTempFile(files, texts); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + int const offset = 11; + // NOLINTNEXTLINE + const char *params[] = { + "a", + }; + const char *dmessage1 = "origin {}"; + const size_t argc1 = 1; + const char *substitutionCode = "replace b"; + const char *dmessage2 = "error"; + const size_t argc0 = 0; + const size_t index1 = 0; + const size_t line1 = 0; + const size_t index2 = 15; + const size_t line2 = 0; + const int code = 4000; + auto suggestionkind = initializer.CreateDiagnosticKind(ctx, dmessage1, ES2PANDA_PLUGIN_SUGGESTION); + auto suggestionInfo = initializer.CreateSuggestionInfo(ctx, suggestionkind, params, argc1, substitutionCode); + auto diagnostikind = initializer.CreateDiagnosticKind(ctx, dmessage2, ES2PANDA_PLUGIN_ERROR); + auto diagnosticInfo = initializer.CreateDiagnosticInfo(ctx, diagnostikind, nullptr, argc0); + es2panda_SourcePosition *left = initializer.CreateSourcePosition(ctx, index1, line1); + es2panda_SourcePosition *right = initializer.CreateSourcePosition(ctx, index2, line2); + es2panda_SourceRange *range = initializer.CreateSourceRange(ctx, left, right); + initializer.LogDiagnosticWithSuggestion(ctx, diagnosticInfo, suggestionInfo, range); + auto suggest = lspApi->getSyntacticDiagnostics(ctx); + AssertDiagnosticContainsCodeAndMessage(suggest, code, dmessage2); + auto result = ark::es2panda::lsp::UIPluginSuggest::GetUIPluginCodeFixes(ctx, offset, false); + ASSERT_EQ(result.at(0).textChanges.at(0).newText, substitutionCode); + std::vector codes; + codes.emplace_back(code); + CodeFixOptions emptyOptions; + auto fix = ark::es2panda::lsp::GetCodeFixesAtPositionImpl(ctx, index1, index2, codes, emptyOptions); + ASSERT_EQ(fix.at(0).changes_.at(0).textChanges.at(0).newText, substitutionCode); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspUISuggestionTests, UIPluginsErrorTest2) +{ + using ark::es2panda::ir::AstNode; + using ark::es2panda::public_lib::Context; + Initializer initializer = Initializer(); + std::vector files = {"ui_error2.ets"}; + std::vector texts = {R"delimiter(function main() {})delimiter"}; + auto filePaths = CreateTempFile(files, texts); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + // NOLINTNEXTLINE + const char *params[] = { + "a", + }; + const size_t argc1 = 1; + const char *dmessage2 = "origin {}"; + const char *dmessage1 = "origin a"; + const size_t index1 = 0; + const size_t line1 = 0; + const int code = 4000; + auto diagnostikind = initializer.CreateDiagnosticKind(ctx, dmessage2, ES2PANDA_PLUGIN_ERROR); + es2panda_SourcePosition *left = initializer.CreateSourcePosition(ctx, index1, line1); + + initializer.LogDiagnostic(ctx, diagnostikind, params, argc1, left); + auto suggest = lspApi->getSyntacticDiagnostics(ctx); + AssertDiagnosticContainsCodeAndMessage(suggest, code, dmessage1); + std::vector codes; + codes.emplace_back(code); + CodeFixOptions emptyOptions; + auto fix = ark::es2panda::lsp::GetCodeFixesAtPositionImpl(ctx, index1, index1, codes, emptyOptions); + ASSERT_TRUE(fix.at(0).changes_.at(0).textChanges.empty()); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspUISuggestionTests, UIPluginsErrorTest3) +{ + using ark::es2panda::ir::AstNode; + using ark::es2panda::public_lib::Context; + Initializer initializer = Initializer(); + std::vector files = {"ui_error3.ets"}; + std::vector texts = {R"delimiter(function main() {})delimiter"}; + auto filePaths = CreateTempFile(files, texts); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + const char *dmessage1 = "origin a"; + const char *substitutionCode = "replace b"; + const char *dmessage2 = "error"; + const size_t argc0 = 0; + const size_t index1 = 0; + const size_t line1 = 0; + const size_t index2 = 15; + const size_t line2 = 0; + const int code = 4000; + auto suggestionkind = initializer.CreateDiagnosticKind(ctx, dmessage1, ES2PANDA_PLUGIN_SUGGESTION); + auto suggestionInfo = initializer.CreateSuggestionInfo(ctx, suggestionkind, nullptr, argc0, substitutionCode); + auto diagnostikind = initializer.CreateDiagnosticKind(ctx, dmessage2, ES2PANDA_PLUGIN_ERROR); + auto diagnosticInfo = initializer.CreateDiagnosticInfo(ctx, diagnostikind, nullptr, argc0); + es2panda_SourcePosition *left = initializer.CreateSourcePosition(ctx, index1, line1); + es2panda_SourcePosition *right = initializer.CreateSourcePosition(ctx, index2, line2); + es2panda_SourceRange *range = initializer.CreateSourceRange(ctx, left, right); + initializer.LogDiagnosticWithSuggestion(ctx, diagnosticInfo, suggestionInfo, range); + + const char *substitutionCode2 = "replace c"; + auto suggestionkind2 = initializer.CreateDiagnosticKind(ctx, dmessage1, ES2PANDA_PLUGIN_SUGGESTION); + auto suggestionInfo2 = initializer.CreateSuggestionInfo(ctx, suggestionkind2, nullptr, argc0, substitutionCode2); + auto diagnostikind2 = initializer.CreateDiagnosticKind(ctx, dmessage2, ES2PANDA_PLUGIN_ERROR); + auto diagnosticInfo2 = initializer.CreateDiagnosticInfo(ctx, diagnostikind2, nullptr, argc0); + es2panda_SourcePosition *left2 = initializer.CreateSourcePosition(ctx, index1, line1); + es2panda_SourcePosition *right2 = initializer.CreateSourcePosition(ctx, index2, line2); + es2panda_SourceRange *range2 = initializer.CreateSourceRange(ctx, left2, right2); + initializer.LogDiagnosticWithSuggestion(ctx, diagnosticInfo2, suggestionInfo2, range2); + + auto suggest = lspApi->getSyntacticDiagnostics(ctx); + AssertDiagnosticContainsCodeAndMessage(suggest, code, dmessage2); + AssertDiagnosticContainsCodeAndMessage(suggest, code, dmessage2); + std::vector codes; + codes.emplace_back(code); + CodeFixOptions emptyOptions; + const std::string fixId = "UIPluginSuggest"; + auto fix = ark::es2panda::lsp::GetCodeFixesAtPositionImpl(ctx, index1, index1, codes, emptyOptions); + ASSERT_FALSE(fix.at(0).changes_.at(0).textChanges.empty()); + auto fixAll = ark::es2panda::lsp::GetCombinedCodeFixImpl(ctx, fixId, emptyOptions); + const size_t expectedCount = 2; + ASSERT_EQ(fixAll.changes_.size(), expectedCount); + + initializer.DestroyContext(ctx); +} + +} // namespace diff --git a/ets2panda/test/unit/lsp/code_fix_registration_test.cpp b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp index 1918c0c7a5..7e5b793cce 100644 --- a/ets2panda/test/unit/lsp/code_fix_registration_test.cpp +++ b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp @@ -25,6 +25,6 @@ TEST(RefactorProviderRegistrationTest, RegistersConvertFunctionRefactor) const auto &fixIdToRegistration = provider.GetFixIdToRegistration(); EXPECT_FALSE(errors.empty()); EXPECT_FALSE(fixIdToRegistration.empty()); - EXPECT_EQ(errors.size(), 6); + EXPECT_EQ(errors.size(), fixIdToRegistration.size()); } } // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_diagnostics.cpp b/ets2panda/test/unit/lsp/get_diagnostics.cpp index 8308130c35..0f6185e48d 100644 --- a/ets2panda/test/unit/lsp/get_diagnostics.cpp +++ b/ets2panda/test/unit/lsp/get_diagnostics.cpp @@ -61,7 +61,7 @@ add("1", 2);)"); ASSERT_EQ(result.diagnostic[thirdIndex].range_.end.line_, expectedFirstEndLine); ASSERT_EQ(result.diagnostic[thirdIndex].range_.end.character_, expectedFirstEndCharacter); ASSERT_EQ(result.diagnostic[thirdIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[thirdIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[thirdIndex].code_), 0); ASSERT_EQ(result.diagnostic[thirdIndex].message_, R"(Type '"hello"' cannot be assigned to type 'Double')"); ASSERT_EQ(result.diagnostic[thirdIndex].codeDescription_.href_, "test code description"); auto const expectedSecondStartLine = 5; @@ -73,7 +73,7 @@ add("1", 2);)"); ASSERT_EQ(result.diagnostic[0].range_.end.line_, expectedSecondEndLine); ASSERT_EQ(result.diagnostic[0].range_.end.character_, expectedSecondEndCharacter); ASSERT_EQ(result.diagnostic[0].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[0].code_), 1); + ASSERT_NE(std::get(result.diagnostic[0].code_), 0); ASSERT_EQ(result.diagnostic[0].message_, R"(Type '"1"' is not compatible with type 'Double' at index 1)"); ASSERT_EQ(result.diagnostic[0].codeDescription_.href_, "test code description"); } @@ -116,7 +116,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[0].range_.end.line_, expectedFirstEndLine); ASSERT_EQ(result.diagnostic[0].range_.end.character_, expectedFirstEndCharacter); ASSERT_EQ(result.diagnostic[0].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[0].code_), 1); + ASSERT_NE(std::get(result.diagnostic[0].code_), 0); auto const expectedSecondStartLine = 1; auto const expectedSecondStartCharacter = 14; auto const expectedSecondEndLine = 1; @@ -126,7 +126,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[1].range_.end.line_, expectedSecondEndLine); ASSERT_EQ(result.diagnostic[1].range_.end.character_, expectedSecondEndCharacter); ASSERT_EQ(result.diagnostic[1].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[1].code_), 1); + ASSERT_NE(std::get(result.diagnostic[1].code_), 0); auto const thirdIndex = 2; auto const expectedThirdStartLine = 1; auto const expectedThirdStartCharacter = 14; @@ -137,7 +137,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[thirdIndex].range_.end.line_, expectedThirdEndLine); ASSERT_EQ(result.diagnostic[thirdIndex].range_.end.character_, expectedThirdEndCharacter); ASSERT_EQ(result.diagnostic[thirdIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[thirdIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[thirdIndex].code_), 0); ASSERT_EQ(result.diagnostic[thirdIndex].message_, R"(Unexpected token ':'.)"); } @@ -163,7 +163,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[forthIndex].range_.end.line_, expectedForthEndLine); ASSERT_EQ(result.diagnostic[forthIndex].range_.end.character_, expectedForthEndCharacter); ASSERT_EQ(result.diagnostic[forthIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[forthIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[forthIndex].code_), 0); ASSERT_EQ(result.diagnostic[forthIndex].message_, R"(Unexpected token ','.)"); ASSERT_EQ(result.diagnostic[forthIndex].codeDescription_.href_, "test code description"); auto const fifthIndex = 8; @@ -176,7 +176,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[fifthIndex].range_.end.line_, expectedFifthEndLine); ASSERT_EQ(result.diagnostic[fifthIndex].range_.end.character_, expectedFifthEndCharacter); ASSERT_EQ(result.diagnostic[fifthIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[fifthIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[fifthIndex].code_), 0); ASSERT_EQ(result.diagnostic[fifthIndex].message_, R"(Label must be followed by a loop statement.)"); ASSERT_EQ(result.diagnostic[fifthIndex].codeDescription_.href_, "test code description"); } @@ -203,7 +203,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[sixthIndex].range_.end.line_, expectedSixthEndLine); ASSERT_EQ(result.diagnostic[sixthIndex].range_.end.character_, expectedSixthEndCharacter); ASSERT_EQ(result.diagnostic[sixthIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[sixthIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[sixthIndex].code_), 0); ASSERT_EQ(result.diagnostic[sixthIndex].message_, R"(Unexpected token ')'.)"); ASSERT_EQ(result.diagnostic[sixthIndex].codeDescription_.href_, "test code description"); auto const sevenIndex = 12; @@ -216,7 +216,7 @@ let res = add(n, n);)"); ASSERT_EQ(result.diagnostic[sevenIndex].range_.end.line_, expectedSeventhEndLine); ASSERT_EQ(result.diagnostic[sevenIndex].range_.end.character_, expectedSeventhEndCharacter); ASSERT_EQ(result.diagnostic[sevenIndex].severity_, DiagnosticSeverity::Error); - ASSERT_EQ(std::get(result.diagnostic[sevenIndex].code_), 1); + ASSERT_NE(std::get(result.diagnostic[sevenIndex].code_), 0); ASSERT_EQ(result.diagnostic[sevenIndex].message_, R"(return keyword should be used in function body.)"); ASSERT_EQ(result.diagnostic[sevenIndex].codeDescription_.href_, "test code description"); } diff --git a/ets2panda/util/diagnostic.h b/ets2panda/util/diagnostic.h index cb4c70a256..a3d9bf4d19 100644 --- a/ets2panda/util/diagnostic.h +++ b/ets2panda/util/diagnostic.h @@ -220,6 +220,11 @@ public: DiagnosticType Type() const override; std::string Message() const override; + bool HasSuggestions() const + { + return suggestions_ != nullptr; + } + const std::vector &Suggestion() const { return *suggestions_; -- Gitee From 3811e9211c51d636320c28c70ea0ec4b22b1d6fc Mon Sep 17 00:00:00 2001 From: Ocean Date: Fri, 30 May 2025 18:21:25 +0800 Subject: [PATCH 080/747] Support Isolated Declgen with Plugin API Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/IC906D Reason: In the hope of speeding up compiler process Description: 1. generate decl file with error info 2. carry out some isolated declaration specific check 3. do not parse import path in import statement 4. carry some type deduction for the return type of function Signed-off-by: Ocean --- ets2panda/BUILD.gn | 4 +- ets2panda/CMakeLists.txt | 10 +- ets2panda/bindings/native/src/bridges.cpp | 8 +- .../bindings/src/Es2pandaNativeModule.ts | 3 +- ets2panda/bindings/src/driver_helper.ts | 6 +- ets2panda/compiler/core/compilerImpl.cpp | 69 +--------- ets2panda/compiler/core/compilerImpl.h | 2 +- .../ets/insertOptionalParametersAnnotation.h | 3 +- ets2panda/declgen_ets2ts/BUILD.gn | 1 + ets2panda/declgen_ets2ts/CMakeLists.txt | 1 + ets2panda/declgen_ets2ts/declgenEts2Ts.cpp | 13 +- ets2panda/declgen_ets2ts/declgenEts2Ts.h | 10 +- .../isolatedDeclgenChecker.cpp} | 128 ++++++++---------- .../isolatedDeclgenChecker.h} | 18 ++- .../isolated_declgen.yaml | 16 +-- ets2panda/declgen_ets2ts/main.cpp | 34 +---- .../build_system/src/build/base_mode.ts | 1 + .../build_system/src/build/declgen_worker.ts | 1 + ets2panda/ir/astNode.cpp | 7 - ets2panda/ir/astNode.h | 1 - ets2panda/ir/base/classProperty.cpp | 5 - ets2panda/ir/base/scriptFunction.cpp | 5 +- ets2panda/ir/base/scriptFunction.h | 11 -- ets2panda/ir/srcDump.cpp | 4 +- ets2panda/ir/srcDump.h | 7 +- ets2panda/parser/ETSparser.cpp | 8 +- ets2panda/public/CMakeLists.txt | 1 + ets2panda/public/es2panda_lib.cpp | 7 +- ets2panda/public/es2panda_lib.h | 2 +- ets2panda/public/public.h | 3 - ...eturn_type_with_import_symbol-expected.txt | 26 ---- ...tion_return_type_with_literal-expected.txt | 16 --- ...ion_return_type_with_variable-expected.txt | 16 --- .../isolated_interface-expected.txt | 36 ----- .../isolated_namespace-expected.txt | 25 ---- ets2panda/test/unit/CMakeLists.txt | 1 + ets2panda/test/unit/declgen/CMakeLists.txt | 89 ++++++++++++ ...eturn_type_with_import_symbol-expected.txt | 7 + ...nction_return_type_with_import_symbol.ets} | 12 +- .../test_ets2ts_isolated_class-expected.txt | 18 +++ .../test_ets2ts_isolated_class.ets} | 0 .../test_ets2ts_isolated_enum-expected.txt | 11 ++ .../test_ets2ts_isolated_enum.ets} | 14 +- ...ction_with_optional_parameter-expected.txt | 2 + ...ated_function_with_optional_parameter.ets} | 0 ...est_ets2ts_isolated_interface-expected.txt | 14 ++ .../test_ets2ts_isolated_interface.ets} | 2 +- .../test_ets2ts_isolated_module-expected.txt | 6 + .../test_ets2ts_isolated_module.ets} | 23 +++- ...est_ets2ts_isolated_namespace-expected.txt | 5 + .../test_ets2ts_isolated_namespace.ets} | 0 .../declgen/test_ets2ts_isolated_declgen.cpp} | 54 ++++++-- ets2panda/test/unit/declgen/util.cpp | 83 ++++++++++++ .../declgen/util.h} | 40 +++--- ets2panda/test/unit/sizeof_node_test.cpp | 3 +- ets2panda/util/diagnostic.cpp | 4 +- ets2panda/util/diagnostic.h | 2 +- ets2panda/util/diagnosticEngine.cpp | 2 +- ets2panda/util/options.yaml | 4 - ets2panda/varbinder/ETSBinder.cpp | 9 +- 60 files changed, 483 insertions(+), 430 deletions(-) rename ets2panda/{checker/IsolatedDeclgenChecker.cpp => declgen_ets2ts/isolatedDeclgenChecker.cpp} (75%) rename ets2panda/{checker/IsolatedDeclgenChecker.h => declgen_ets2ts/isolatedDeclgenChecker.h} (90%) rename ets2panda/{util/diagnostic => declgen_ets2ts}/isolated_declgen.yaml (88%) delete mode 100644 ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol-expected.txt delete mode 100644 ets2panda/test/isolated_declgen/infer_function_return_type_with_literal-expected.txt delete mode 100644 ets2panda/test/isolated_declgen/infer_function_return_type_with_variable-expected.txt delete mode 100644 ets2panda/test/isolated_declgen/isolated_interface-expected.txt delete mode 100644 ets2panda/test/isolated_declgen/isolated_namespace-expected.txt create mode 100644 ets2panda/test/unit/declgen/CMakeLists.txt create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol-expected.txt rename ets2panda/test/{isolated_declgen/infer_function_return_type_with_import_symbol.ets => unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol.ets} (84%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class-expected.txt rename ets2panda/test/{isolated_declgen/isolated_class.ets => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class.ets} (100%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum-expected.txt rename ets2panda/test/{isolated_declgen/isolated_function_with_optional_parameter-expected.txt => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum.ets} (80%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter-expected.txt rename ets2panda/test/{isolated_declgen/isolated_function_with_optional_parameter.ets => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter.ets} (100%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface-expected.txt rename ets2panda/test/{isolated_declgen/isolated_interface.ets => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface.ets} (99%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module-expected.txt rename ets2panda/test/{isolated_declgen/infer_function_return_type_with_variable.ets => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module.ets} (63%) create mode 100644 ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace-expected.txt rename ets2panda/test/{isolated_declgen/isolated_namespace.ets => unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace.ets} (100%) rename ets2panda/test/{isolated_declgen/infer_function_return_type_with_literal.ets => unit/declgen/test_ets2ts_isolated_declgen.cpp} (34%) create mode 100644 ets2panda/test/unit/declgen/util.cpp rename ets2panda/test/{isolated_declgen/isolated_class-expected.txt => unit/declgen/util.h} (43%) diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 42c9d7f055..faf1a25254 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -59,7 +59,6 @@ libes2panda_sources = [ "checker/ETSAnalyzerHelpers.cpp", "checker/ETSAnalyzerUnreachable.cpp", "checker/ETSchecker.cpp", - "checker/IsolatedDeclgenChecker.cpp", "checker/JSchecker.cpp", "checker/TSAnalyzer.cpp", "checker/TSAnalyzerUnreachable.cpp", @@ -1099,6 +1098,7 @@ ark_gen("gen") { # libes2panda does not include bytecode optimizer, because it is used in # libarkruntime, and conflict with JIT setup ensues libes2panda_public_sources = [ + "declgen_ets2ts/isolatedDeclgenChecker.cpp", "declgen_ets2ts/declgenEts2Ts.cpp", "public/${LIB_NAME}.cpp", "util/generateBin.cpp", @@ -1247,9 +1247,9 @@ ark_gen("es2panda_diagnostic_gen") { "util/diagnostic/semantic.yaml", "util/diagnostic/warning.yaml", "util/diagnostic/fatal.yaml", - "util/diagnostic/isolated_declgen.yaml", "declgen_ets2ts/declgen_ets2ts_error.yaml", "declgen_ets2ts/declgen_ets2ts_warning.yaml", + "declgen_ets2ts/isolated_declgen.yaml", "util/diagnostic/arktsconfig_error.yaml", ] template_files = [ "diagnostic.h.erb" ] diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 695f3a76f9..4e8288dc0a 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -144,8 +144,8 @@ panda_gen( ${DIAGNOSTIC_DIR}/fatal.yaml ${CMAKE_CURRENT_SOURCE_DIR}/declgen_ets2ts/declgen_ets2ts_error.yaml ${CMAKE_CURRENT_SOURCE_DIR}/declgen_ets2ts/declgen_ets2ts_warning.yaml + ${CMAKE_CURRENT_SOURCE_DIR}/declgen_ets2ts/isolated_declgen.yaml ${DIAGNOSTIC_DIR}/arktsconfig_error.yaml - ${DIAGNOSTIC_DIR}/isolated_declgen.yaml TARGET_NAME es2panda_diagnostic_gen TEMPLATES diagnostic.h.erb SOURCE ${DIAGNOSTIC_DIR} @@ -542,7 +542,6 @@ set(ES2PANDA_LIB_SRC checker/TSAnalyzer.cpp checker/TSAnalyzerUnreachable.cpp checker/JSchecker.cpp - checker/IsolatedDeclgenChecker.cpp checker/typeChecker/TypeChecker.cpp checker/ets/aliveAnalyzer.cpp checker/ets/etsWarningAnalyzer.cpp @@ -686,6 +685,13 @@ panda_target_compile_options(es2panda-lib PRIVATE -fexceptions -Werror=shadow ) +if (EN_ISOLATED_DECLGEN) + message(STATUS "Isolated declgen enabled") + panda_target_compile_definitions(es2panda-lib + PRIVATE -DENABLE_ISOLATED_DECLGEN + ) +endif() + panda_target_link_libraries(es2panda-lib PUBLIC arkbase hmicuuc.z PRIVATE arkassembler arkdisassembler arkfile diff --git a/ets2panda/bindings/native/src/bridges.cpp b/ets2panda/bindings/native/src/bridges.cpp index 2757d4b9ef..19790f849e 100644 --- a/ets2panda/bindings/native/src/bridges.cpp +++ b/ets2panda/bindings/native/src/bridges.cpp @@ -37,13 +37,13 @@ KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr TS_INTEROP_3(CreateContextFromString, KNativePointer, KNativePointer, KStringPtr, KStringPtr) KInt impl_GenerateTsDeclarationsFromContext(KNativePointer contextPtr, KStringPtr &outputDeclEts, KStringPtr &outputEts, - KBoolean exportAll) + KBoolean exportAll, KBoolean isolated) { auto context = reinterpret_cast(contextPtr); - return static_cast(GetPublicImpl()->GenerateTsDeclarationsFromContext(context, outputDeclEts.data(), - outputEts.data(), exportAll != 0)); + return static_cast(GetPublicImpl()->GenerateTsDeclarationsFromContext( + context, outputDeclEts.data(), outputEts.data(), exportAll != 0, isolated != 0)); } -TS_INTEROP_4(GenerateTsDeclarationsFromContext, KInt, KNativePointer, KStringPtr, KStringPtr, KBoolean) +TS_INTEROP_5(GenerateTsDeclarationsFromContext, KInt, KNativePointer, KStringPtr, KStringPtr, KBoolean, KBoolean) KNativePointer impl_CreateContextFromFile(KNativePointer configPtr, KStringPtr &filenamePtr) { diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index 210ad83e1c..0c0838479a 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -65,7 +65,8 @@ export class Es2pandaNativeModule { config: KPtr, outputDeclEts: String, outputEts: String, - exportAll: KBoolean + exportAll: KBoolean, + isolated: KBoolean ): KPtr { throw new Error('Not implemented'); } diff --git a/ets2panda/bindings/src/driver_helper.ts b/ets2panda/bindings/src/driver_helper.ts index 29f82f3d01..5b43299469 100644 --- a/ets2panda/bindings/src/driver_helper.ts +++ b/ets2panda/bindings/src/driver_helper.ts @@ -76,9 +76,11 @@ export class DriverHelper { global.destroyCfg(); } - public generateTsDecl(declOutPath: string, etsOutPath: string, exportAll: boolean): void { + public generateTsDecl(declOutPath: string, etsOutPath: string, exportAll: boolean, isolated: boolean): void { let exportAll_: KBoolean = exportAll ? 1 : 0; - global.es2panda._GenerateTsDeclarationsFromContext(this._cfg.peer, declOutPath, etsOutPath, exportAll_); + let isolated_: KBoolean = isolated ? 1 : 0; + global.es2panda._GenerateTsDeclarationsFromContext(this._cfg.peer, declOutPath, etsOutPath, + exportAll_, isolated_); } } diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 7086b2707d..74f75da500 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -14,7 +14,6 @@ */ #include "compilerImpl.h" -#include #include "es2panda.h" #include "ast_verifier/ASTVerifier.h" @@ -35,10 +34,7 @@ #include "compiler/lowering/phase.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" #include "compiler/lowering/checkerPhase.h" -#include "compiler/lowering/resolveIdentifiers.h" -#include "compiler/lowering/ets/insertOptionalParametersAnnotation.h" #include "evaluate/scopedDebugInfoPlugin.h" -#include "generated/isa.h" #include "parser/parserImpl.h" #include "parser/JSparser.h" #include "parser/ASparser.h" @@ -112,7 +108,7 @@ static bool CheckOptionsBeforePhase(const util::Options &options, const parser:: } void HandleGenerateDecl(const parser::Program &program, util::DiagnosticEngine &diagnosticEngine, - const std::string &outputPath, bool isIsolatedDeclgen) + const std::string &outputPath) { std::ofstream outFile(outputPath); if (!outFile.is_open()) { @@ -120,13 +116,7 @@ void HandleGenerateDecl(const parser::Program &program, util::DiagnosticEngine & lexer::SourcePosition()); return; } - std::string result; - if (!isIsolatedDeclgen) { - result = program.Ast()->DumpDecl(); - } else { - result = program.Ast()->IsolatedDumpDecl(); - } - + std::string result = program.Ast()->DumpDecl(); result.erase(0, result.find_first_not_of('\n')); outFile << result; @@ -149,47 +139,13 @@ static bool CheckOptionsAfterPhase(const util::Options &options, const parser::P return options.GetExitAfterPhase() == name; } -static bool DoIsolatedDeclgenCheck(const util::Options &options, const std::string &phaseName, - checker::IsolatedDeclgenChecker &isolatedDeclgenChecker, - public_lib::Context &context) -{ - if (!options.IsGenerateDeclEnableIsolated()) { - return true; - } - if (phaseName == compiler::ResolveIdentifiers::NAME) { - isolatedDeclgenChecker.CheckBeforeChecker(); - if (context.diagnosticEngine->IsAnyError()) { - return false; - } - } - - if (phaseName == compiler::CheckerPhase::NAME) { - isolatedDeclgenChecker.CheckAfterChecker(); - if (context.diagnosticEngine->IsAnyError()) { - return false; - } - } - - return true; -} - -static bool CheckIfPhaseToSkip(util::Options &options, const std::string &name) -{ - return options.GetSkipPhases().count(name) > 0 || - (options.IsGenerateDeclEnableIsolated() && name == compiler::InsertOptionalParametersAnnotation::NAME); -} - // CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program &program) { - auto &options = const_cast(*context.config->options); + const auto &options = *context.config->options; const auto verifierEachPhase = options.IsAstVerifierEachPhase(); ast_verifier::ASTVerifier verifier(context, program); - checker::IsolatedDeclgenChecker isolatedDeclgenChecker(*context.diagnosticEngine, program); - if (options.IsGenerateDeclEnableIsolated()) { - options.SetGenerateDeclEnabled(true); - } bool afterCheckerPhase = false; while (auto phase = context.phaseManager->NextPhase()) { @@ -198,28 +154,17 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & afterCheckerPhase = true; } - if (CheckIfPhaseToSkip(options, name)) { + if (options.GetSkipPhases().count(name) > 0) { continue; } - if (options.IsGenerateDeclEnableIsolated() && name == "plugins-after-check") { - return false; - } - if (CheckOptionsBeforePhase(options, program, name) || !phase->Apply(&context, &program) || CheckOptionsAfterPhase(options, program, name)) { return false; } - if (!DoIsolatedDeclgenCheck(options, name, isolatedDeclgenChecker, context)) { - return false; - } - - if (!options.IsGenerateDeclEnableIsolated()) { - verifier.IntroduceNewInvariants(phase->Name()); - } - - if (verifierEachPhase || options.HasVerifierPhase(phase->Name())) { + if (verifier.IntroduceNewInvariants(phase->Name()); + verifierEachPhase || options.HasVerifierPhase(phase->Name())) { verifier.Verify(phase->Name()); } @@ -235,7 +180,7 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & } else { path = options.GetGenerateDeclPath(); } - HandleGenerateDecl(program, *context.diagnosticEngine, path, options.IsGenerateDeclEnableIsolated()); + HandleGenerateDecl(program, *context.diagnosticEngine, path); } } diff --git a/ets2panda/compiler/core/compilerImpl.h b/ets2panda/compiler/core/compilerImpl.h index 6c669d5e00..02ac0514b2 100644 --- a/ets2panda/compiler/core/compilerImpl.h +++ b/ets2panda/compiler/core/compilerImpl.h @@ -26,7 +26,7 @@ namespace ark::es2panda::compiler { class CompileQueue; void HandleGenerateDecl(const parser::Program &program, util::DiagnosticEngine &diagnosticEngine, - const std::string &outputPath, bool isIsolatedDeclgen); + const std::string &outputPath); class CompilationUnit { public: diff --git a/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.h b/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.h index 1e8a0440a1..780d43d514 100644 --- a/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.h +++ b/ets2panda/compiler/lowering/ets/insertOptionalParametersAnnotation.h @@ -22,10 +22,9 @@ namespace ark::es2panda::compiler { class InsertOptionalParametersAnnotation : public PhaseForDeclarations { public: - static constexpr std::string_view NAME = "InsertOptionalParametersAnnotation"; std::string_view Name() const override { - return NAME; + return "InsertOptionalParametersAnnotation"; } bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; diff --git a/ets2panda/declgen_ets2ts/BUILD.gn b/ets2panda/declgen_ets2ts/BUILD.gn index 165a35a81f..8de1df605d 100644 --- a/ets2panda/declgen_ets2ts/BUILD.gn +++ b/ets2panda/declgen_ets2ts/BUILD.gn @@ -16,6 +16,7 @@ import("//build/ohos.gni") ohos_executable("declgen_ets2ts") { sources = [ + "isolatedDeclgenChecker.cpp", "declgenEts2Ts.cpp", "main.cpp", ] diff --git a/ets2panda/declgen_ets2ts/CMakeLists.txt b/ets2panda/declgen_ets2ts/CMakeLists.txt index 6d0687fa1d..994c760889 100644 --- a/ets2panda/declgen_ets2ts/CMakeLists.txt +++ b/ets2panda/declgen_ets2ts/CMakeLists.txt @@ -14,6 +14,7 @@ set(DECLGEN_ETS2TS_SRC main.cpp declgenEts2Ts.cpp + isolatedDeclgenChecker.cpp ) set(DECLGEN_ETS2TS_INCLUDE_DIRS diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp index 6dd04a3916..ebdc7c56d6 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp @@ -14,8 +14,8 @@ */ #include "declgenEts2Ts.h" -#include +#include "isolatedDeclgenChecker.h" #include "checker/types/ets/etsTupleType.h" #include "generated/diagnostic.h" #include "ir/base/classProperty.h" @@ -700,8 +700,8 @@ void TSDeclGen::ProcessFunctionReturnType(const checker::Signature *sig) } std::string typeStr = sig->ReturnType()->ToString(); - if (declgenOptions_.isIsolatedDeclgen && typeStr.find(ERROR_TYPE) != std::string::npos) { - typeStr = sig->Function()->GetIsolatedDeclgenReturnType(); + if (declgenOptions_.isolated && typeStr.find(ERROR_TYPE) != std::string::npos) { + typeStr = isolatedDeclgenChecker_->Check(const_cast(sig->Function())); OutDts(typeStr); SplitUnionTypes(typeStr); return; @@ -2062,7 +2062,12 @@ bool WriteToFile(const std::string &path, const std::string &content, checker::E bool GenerateTsDeclarations(checker::ETSChecker *checker, const ark::es2panda::parser::Program *program, const DeclgenOptions &declgenOptions) { - TSDeclGen declBuilder(checker, program); + declgen::IsolatedDeclgenChecker isolatedDeclgenChecker(checker->DiagnosticEngine(), *program); + if (declgenOptions.isolated) { + isolatedDeclgenChecker.Check(); + } + + TSDeclGen declBuilder(checker, &isolatedDeclgenChecker, program); declBuilder.SetDeclgenOptions(declgenOptions); if ((declBuilder.GetDeclgenOptions().outputDeclEts.empty() && !declBuilder.GetDeclgenOptions().outputEts.empty()) || diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.h b/ets2panda/declgen_ets2ts/declgenEts2Ts.h index fda8c826a1..81f29c2a6b 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.h +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.h @@ -22,12 +22,13 @@ #include "libpandabase/utils/arena_containers.h" #include "util/options.h" #include "util/diagnosticEngine.h" +#include "isolatedDeclgenChecker.h" namespace ark::es2panda::declgen_ets2ts { struct DeclgenOptions { bool exportAll = false; - bool isIsolatedDeclgen = false; + bool isolated = false; std::string outputDeclEts; std::string outputEts; }; @@ -38,8 +39,10 @@ bool GenerateTsDeclarations(checker::ETSChecker *checker, const ark::es2panda::p class TSDeclGen { public: - TSDeclGen(checker::ETSChecker *checker, const ark::es2panda::parser::Program *program) + TSDeclGen(checker::ETSChecker *checker, declgen::IsolatedDeclgenChecker *isolatedDeclgenChecker, + const ark::es2panda::parser::Program *program) : checker_(checker), + isolatedDeclgenChecker_(isolatedDeclgenChecker), program_(program), diagnosticEngine_(checker->DiagnosticEngine()), allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true), @@ -95,9 +98,9 @@ private: const checker::Signature *GetFuncSignature(const checker::ETSFunctionType *etsFunctionType, const ir::MethodDefinition *methodDef); - void SplitUnionTypes(std::string &unionTypeString); void GenType(const checker::Type *checkerType); void GenFunctionType(const checker::ETSFunctionType *functionType, const ir::MethodDefinition *methodDef = nullptr); + void SplitUnionTypes(std::string &unionTypeString); void ProcessFunctionReturnType(const checker::Signature *sig); bool ProcessTSQualifiedName(const ir::ETSTypeReference *typeReference); void ProcessETSTypeReferenceType(const ir::ETSTypeReference *typeReference, @@ -289,6 +292,7 @@ private: std::stringstream outputDts_; std::stringstream outputTs_; checker::ETSChecker *checker_ {}; + declgen::IsolatedDeclgenChecker *isolatedDeclgenChecker_ {}; const ark::es2panda::parser::Program *program_ {}; util::DiagnosticEngine &diagnosticEngine_; ArenaAllocator allocator_; diff --git a/ets2panda/checker/IsolatedDeclgenChecker.cpp b/ets2panda/declgen_ets2ts/isolatedDeclgenChecker.cpp similarity index 75% rename from ets2panda/checker/IsolatedDeclgenChecker.cpp rename to ets2panda/declgen_ets2ts/isolatedDeclgenChecker.cpp index ed623f5cb4..052a88c503 100644 --- a/ets2panda/checker/IsolatedDeclgenChecker.cpp +++ b/ets2panda/declgen_ets2ts/isolatedDeclgenChecker.cpp @@ -13,11 +13,13 @@ * limitations under the License. */ -#include "checker/IsolatedDeclgenChecker.h" +#include "isolatedDeclgenChecker.h" + +#include "es2panda.h" #include "clang.h" #include "utils/logger.h" -namespace ark::es2panda::checker { +namespace ark::es2panda::declgen { using AstNodePtr = ir::AstNode *; void IsolatedDeclgenChecker::LogError(const diagnostic::DiagnosticKind &diagnostic, @@ -27,23 +29,28 @@ void IsolatedDeclgenChecker::LogError(const diagnostic::DiagnosticKind &diagnost diagnosticEngine_.LogDiagnostic(diagnostic, diagnosticParams, pos); } +static bool IsUnionTypeWithError(const checker::Type *type) +{ + if (type == nullptr || !type->IsUnionType()) { + return false; + } + + return type->ToString().find(ERROR_TYPE) != std::string::npos; +} + void IsolatedDeclgenChecker::Check(ir::ClassProperty *ast) { if (ast->Parent()->IsAnnotationUsage()) { return; } - if (ast->TypeAnnotation() == nullptr) { - LogError(diagnostic::PROPERTY_MUST_HAVE_EXPLICIT_TYPE_ANNOTATION_WITH_ISOLATED_DECL, {}, ast->Start()); + if (ast->IsPrivate()) { + return; } -} - -void IsolatedDeclgenChecker::Check(ir::ObjectExpression *ast) -{ - for (auto property : ast->Properties()) { - if (property->IsSpreadElement()) { - LogError(diagnostic::OBJECTS_THAT_CONTAIN_SPREAD_ASSIGNMENTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, - property->Start()); - } + if (ast->TypeAnnotation() != nullptr) { + return; + } + if (ast->TsType()->IsTypeError() || IsUnionTypeWithError(ast->TsType())) { + LogError(diagnostic::PROPERTY_MUST_HAVE_EXPLICIT_TYPE_ANNOTATION_WITH_ISOLATED_DECL, {}, ast->Start()); } } @@ -76,9 +83,30 @@ void IsolatedDeclgenChecker::Check(ir::ArrayExpression *ast) } } +static std::string GetETSTypeReferenceName(ir::ETSTypeReference *typeRef) +{ + if (typeRef == nullptr) { + return ""; + } + auto *part = typeRef->Part(); + if (part == nullptr) { + return ""; + } + if (part->Name()->IsIdentifier()) { + return part->Name()->AsIdentifier()->Name().Mutf8(); + } + if (part->Name()->IsTSQualifiedName()) { + return part->Name()->AsTSQualifiedName()->Name().Mutf8(); + } + return ""; +} + void IsolatedDeclgenChecker::Check(ir::ETSParameterExpression *ast) { - if (ast->TypeAnnotation() == nullptr) { + if (ast->TypeAnnotation() != nullptr) { + return; + } + if (ast->TsType()->IsTypeError() || IsUnionTypeWithError(ast->TsType())) { LogError(diagnostic::PARAMETER_MUST_HAVE_EXPLICIT_TYPE_ANNOTATION_WITH_ISOLATED_DECL, {}, ast->Start()); } } @@ -87,57 +115,57 @@ void IsolatedDeclgenChecker::Check(ir::ExportDefaultDeclaration *ast) { auto *decl = ast->Decl(); if (decl == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); return; } if (decl->IsClassDeclaration()) { auto *classDecl = decl->AsClassDeclaration(); if (classDecl == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } return; } if (decl->IsTSInterfaceDeclaration()) { auto *interfaceDecl = decl->AsTSInterfaceDeclaration(); if (interfaceDecl == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } return; } if (decl->IsTSEnumDeclaration()) { auto *enumDecl = decl->AsTSEnumDeclaration(); if (enumDecl == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } return; } if (decl->IsFunctionDeclaration()) { auto *funcDecl = decl->AsFunctionDeclaration(); if (funcDecl == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } return; } if (decl->IsClassProperty()) { auto *classProperty = decl->AsClassProperty(); if (classProperty == nullptr) { - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } return; } - LogError(diagnostic::DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); + LogError(diagnostic::DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL, {}, ast->Start()); } -std::string GetLiteralType(const ir::Literal *literal) +static std::string GetLiteralType(const ir::Literal *literal) { if (literal->IsStringLiteral()) { - return "String"; + return "string"; } if (literal->IsNumberLiteral()) { - return "Number"; + return "number"; } if (literal->IsBooleanLiteral()) { - return "Boolean"; + return "boolean"; } return ""; } @@ -170,15 +198,8 @@ std::string IsolatedDeclgenChecker::ProcessIdentifierArgument(ir::Identifier *id } if (decl->IsLetOrConstDecl()) { - return decl->Node() - ->AsClassProperty() - ->TypeAnnotation() - ->AsETSTypeReference() - ->Part() - ->Name() - ->AsIdentifier() - ->Name() - .Mutf8(); + auto *typeAnnotationRef = decl->Node()->AsClassProperty()->TypeAnnotation()->AsETSTypeReference(); + return GetETSTypeReferenceName(typeAnnotationRef); } LogError(diagnostic::FUNCTION_MUST_HAVE_AN_EXPLICIT_RETURN_TYPE_ANNOTATION_WITH_ISOLATED_DECL, {}, returnStatement->Start()); @@ -206,7 +227,7 @@ std::string IsolatedDeclgenChecker::ProcessNewClassInstanceExpressionArgument( returnStatement->Start()); return ""; } - return classType->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8(); + return GetETSTypeReferenceName(classType->AsETSTypeReference()); } std::string IsolatedDeclgenChecker::InferReturnTypeForArgument(ir::ReturnStatement *returnStatement) @@ -281,9 +302,9 @@ std::string IsolatedDeclgenChecker::Check(ir::ScriptFunction *ast) return returnTypeStr; } -void IsolatedDeclgenChecker::CheckBeforeChecker() +void IsolatedDeclgenChecker::Check() { - program_.Ast()->TransformChildrenRecursively( + const_cast(program_).Ast()->TransformChildrenRecursively( [&](ir::AstNode *ast) -> AstNodePtr { if (ast->IsClassProperty()) { Check(ast->AsClassProperty()); @@ -300,10 +321,6 @@ void IsolatedDeclgenChecker::CheckBeforeChecker() return ast; } - if (ast->IsObjectExpression()) { - Check(ast->AsObjectExpression()); - return ast; - } if (ast->IsExportDefaultDeclaration()) { Check(ast->AsExportDefaultDeclaration()); return ast; @@ -311,31 +328,6 @@ void IsolatedDeclgenChecker::CheckBeforeChecker() return ast; }, - "CheckIsolatedDeclBeforeChecker"); -} - -void IsolatedDeclgenChecker::CheckAfterChecker() -{ - program_.Ast()->TransformChildrenRecursively( - [&](ir::AstNode *ast) -> AstNodePtr { - if (!ast->IsScriptFunction()) { - return ast; - } - - auto *scriptFunction = ast->AsScriptFunction(); - auto *returnType = scriptFunction->Signature()->ReturnType(); - if (returnType == nullptr) { - return ast; - } - std::string returnTypeStr = Check(scriptFunction); - if (returnType->ToString().find(ERROR_TYPE) == std::string::npos) { - scriptFunction->SetIsolatedDeclgenReturnType(returnType->ToString()); - return ast; - } - scriptFunction->SetIsolatedDeclgenReturnType(returnTypeStr); - - return ast; - }, - "CheckIsolatedDeclAfterChecker"); + "CheckIsolatedDecl"); } -} // namespace ark::es2panda::checker \ No newline at end of file +} // namespace ark::es2panda::declgen \ No newline at end of file diff --git a/ets2panda/checker/IsolatedDeclgenChecker.h b/ets2panda/declgen_ets2ts/isolatedDeclgenChecker.h similarity index 90% rename from ets2panda/checker/IsolatedDeclgenChecker.h rename to ets2panda/declgen_ets2ts/isolatedDeclgenChecker.h index eef54b0232..3769b90ea1 100644 --- a/ets2panda/checker/IsolatedDeclgenChecker.h +++ b/ets2panda/declgen_ets2ts/isolatedDeclgenChecker.h @@ -19,10 +19,10 @@ #include "macros.h" #include "checker/checker.h" -namespace ark::es2panda::checker { +namespace ark::es2panda::declgen { class IsolatedDeclgenChecker { public: - explicit IsolatedDeclgenChecker(util::DiagnosticEngine &diagnosticEngine, parser::Program &program) + explicit IsolatedDeclgenChecker(util::DiagnosticEngine &diagnosticEngine, const parser::Program &program) : diagnosticEngine_(diagnosticEngine), program_(program) { } @@ -31,18 +31,16 @@ public: NO_COPY_SEMANTIC(IsolatedDeclgenChecker); NO_MOVE_SEMANTIC(IsolatedDeclgenChecker); - void CheckBeforeChecker(); - void CheckAfterChecker(); + void Check(); + std::string Check(ir::ScriptFunction *ast); + +private: void Check(ir::ClassProperty *ast); - void Check(ir::ObjectExpression *ast); void Check(ir::ArrayExpression *ast); void Check(ir::ETSParameterExpression *ast); void Check(ir::ExportDefaultDeclaration *ast); - std::string Check(ir::ScriptFunction *ast); - -private: std::string InferReturnTypeForArgument(ir::ReturnStatement *returnStatement); std::string ProcessLiteralArgument(ir::Literal *literal, ir::ReturnStatement *returnStatement); @@ -56,8 +54,8 @@ private: private: util::DiagnosticEngine &diagnosticEngine_; - parser::Program &program_; + const parser::Program &program_; }; -} // namespace ark::es2panda::checker +} // namespace ark::es2panda::declgen #endif // ES2PANDA_CHECKER_ISOLATED_DECLGEN_CHECKER_H \ No newline at end of file diff --git a/ets2panda/util/diagnostic/isolated_declgen.yaml b/ets2panda/declgen_ets2ts/isolated_declgen.yaml similarity index 88% rename from ets2panda/util/diagnostic/isolated_declgen.yaml rename to ets2panda/declgen_ets2ts/isolated_declgen.yaml index fb9d9d2c32..bfde0c6897 100644 --- a/ets2panda/util/diagnostic/isolated_declgen.yaml +++ b/ets2panda/declgen_ets2ts/isolated_declgen.yaml @@ -23,26 +23,22 @@ isolated_declgen: id: 3 message: Property must have an explicit type annotation when using isolated declaration. -- name: OBJECTS_THAT_CONTAIN_SPREAD_ASSIGNMENTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL - id: 4 - message: Objects that contain spread assignments cannot be inferred with isolated declaration. - - name: ONLY_CONST_ARRAYS_CAN_BE_INFERRED_WITH_ISOLATED_DECL - id: 5 + id: 4 message: Only const arrays can be inferred with isolated declaration. - name: DECLARATION_EMIT_FOR_THIS_PARAMETER_REQUIRES_IMPLICITLY_ADD_UNDEFINED_TO_ITS_TYPE_NOT_ALLOWED_IN_ISOLATED_DECL - id: 6 + id: 5 message: Declaration emit for this parameter requires implicitly adding undefined to its type, which is not allowed in isolated declaration. -- name: DEFAULT_EXPORTS__CANNOT_BE_INFERRED_WITH_ISOLATED_DECL - id: 7 +- name: DEFAULT_EXPORTS_CANNOT_BE_INFERRED_WITH_ISOLATED_DECL + id: 6 message: Cannot use array creation expression with type parameter. - name: FUNCTION_MUST_HAVE_AN_EXPLICIT_RETURN_TYPE_ANNOTATION_WITH_ISOLATED_DECL - id: 8 + id: 7 message: Function must have an explicit return type annotation when using isolated declaration. - name: METHOD_MUST_HAVE_AN_EXPLICIT_RETURN_TYPE_ANNOTATION_WITH_ISOLATED_DECL - id: 9 + id: 8 message: Method must have an explicit return type annotation when using isolated declaration. \ No newline at end of file diff --git a/ets2panda/declgen_ets2ts/main.cpp b/ets2panda/declgen_ets2ts/main.cpp index 385e9f37c8..a13937b367 100644 --- a/ets2panda/declgen_ets2ts/main.cpp +++ b/ets2panda/declgen_ets2ts/main.cpp @@ -13,10 +13,10 @@ * limitations under the License. */ -#include #include "public/es2panda_lib.h" #include "public/public.h" #include "declgenEts2Ts.h" +#include "isolatedDeclgenChecker.h" namespace ark::es2panda::declgen_ets2ts { @@ -26,7 +26,6 @@ static void PrintUsage() std::cerr << " --export-all Treat all top level statements as exported\n"; std::cerr << " --output-dets=[FILE] Path to output .d.ets file\n"; std::cerr << " --output-ets=[FILE] Path to output .ets file\n"; - std::cerr << " --generate-decl:enable-isolated Generate isolated decl\n"; std::cerr << " --help Print this message and exit. Default: false\n"; std::cerr << "Tail arguments:\n"; std::cerr << "input: input file\n"; @@ -68,21 +67,11 @@ static DeclgenOptions ParseOptions(Span args) std::strchr(args[i], '=') != nullptr) { std::string arg = args[i]; options.outputEts = arg.substr(std::strlen("--output-ets=")); - } else if (std::strcmp(args[i], "--generate-decl:enable-isolated") == 0) { - options.isIsolatedDeclgen = true; } } return options; } -static void DestroyContextAndConfig(const es2panda_Impl *impl, es2panda_Context *ctx, es2panda_Config *cfg, - const char **newArgv) -{ - impl->DestroyContext(ctx); - impl->DestroyConfig(cfg); - delete[] newArgv; -} - static int Run(int argc, const char **argv) { Span args(argv, static_cast(argc)); @@ -107,31 +96,16 @@ static int Run(int argc, const char **argv) auto *ctxImpl = reinterpret_cast(ctx); auto *checker = reinterpret_cast(ctxImpl->GetChecker()); - auto *isolatedDeclgenChecker = reinterpret_cast(ctxImpl->isolatedDeclgenChecker); - impl->ProceedToState(ctx, ES2PANDA_STATE_BOUND); - if (declgenOptions.isIsolatedDeclgen) { - isolatedDeclgenChecker->CheckBeforeChecker(); - if (ctxImpl->diagnosticEngine->IsAnyError()) { - DestroyContextAndConfig(impl, ctx, cfg, newArgv); - return 1; - } - } - impl->ProceedToState(ctx, ES2PANDA_STATE_CHECKED); - if (declgenOptions.isIsolatedDeclgen) { - isolatedDeclgenChecker->CheckAfterChecker(); - if (ctxImpl->diagnosticEngine->IsAnyError()) { - DestroyContextAndConfig(impl, ctx, cfg, newArgv); - return 1; - } - } int res = 0; if (!GenerateTsDeclarations(checker, ctxImpl->parserProgram, declgenOptions)) { res = 1; } - DestroyContextAndConfig(impl, ctx, cfg, newArgv); + impl->DestroyContext(ctx); + impl->DestroyConfig(cfg); + delete[] newArgv; return res; } diff --git a/ets2panda/driver/build_system/src/build/base_mode.ts b/ets2panda/driver/build_system/src/build/base_mode.ts index e1d65f97f6..32c7bbf70a 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -194,6 +194,7 @@ export abstract class BaseMode { arkts.generateTsDeclarationsFromContext( declEtsOutputPath, etsOutputPath, + false, false ); // Generate 1.0 declaration files & 1.0 glue code this.logger.printInfo('declaration files generated'); diff --git a/ets2panda/driver/build_system/src/build/declgen_worker.ts b/ets2panda/driver/build_system/src/build/declgen_worker.ts index 63968d0d15..dbf67a1147 100644 --- a/ets2panda/driver/build_system/src/build/declgen_worker.ts +++ b/ets2panda/driver/build_system/src/build/declgen_worker.ts @@ -94,6 +94,7 @@ process.on('message', (message: { arkts.generateTsDeclarationsFromContext( declEtsOutputPath, etsOutputPath, + false, false ); // Generate 1.0 declaration files & 1.0 glue code logger.printInfo('declaration files generated'); diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 9661f1c36c..6c9b210ee2 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -266,13 +266,6 @@ std::string AstNode::DumpDecl() const return dumper.Str(); } -std::string AstNode::IsolatedDumpDecl() const -{ - ir::SrcDumper dumper {this, true, true}; - dumper.Run(); - return dumper.Str(); -} - void AstNode::SetOriginalNode(AstNode *originalNode) noexcept { if (OriginalNode() != originalNode) { diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 1fd37c07dd..99b589133f 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -555,7 +555,6 @@ public: std::string DumpJSON() const; std::string DumpEtsSrc() const; std::string DumpDecl() const; - std::string IsolatedDumpDecl() const; virtual void Dump(ir::AstDumper *dumper) const = 0; virtual void Dump(ir::SrcDumper *dumper) const = 0; diff --git a/ets2panda/ir/base/classProperty.cpp b/ets2panda/ir/base/classProperty.cpp index 2bacec57d1..9fb04ee715 100644 --- a/ets2panda/ir/base/classProperty.cpp +++ b/ets2panda/ir/base/classProperty.cpp @@ -14,7 +14,6 @@ */ #include "classProperty.h" -#include #include "checker/ETSchecker.h" #include "checker/TSchecker.h" @@ -199,10 +198,6 @@ void ClassProperty::DumpCheckerTypeForDeclGen(ir::SrcDumper *dumper) const } auto typeStr = TsType()->ToString(); - if (TsType()->IsTypeError() && dumper->IsIsolatedDeclgen() && typeAnnotation_ != nullptr) { - typeStr = typeAnnotation_->AsETSTypeReference()->Part()->Name()->AsIdentifier()->Name().Mutf8(); - } - dumper->Add(": "); dumper->Add(typeStr); diff --git a/ets2panda/ir/base/scriptFunction.cpp b/ets2panda/ir/base/scriptFunction.cpp index 73ef90390f..71fe36ba69 100644 --- a/ets2panda/ir/base/scriptFunction.cpp +++ b/ets2panda/ir/base/scriptFunction.cpp @@ -294,8 +294,7 @@ void ScriptFunction::DumpCheckerTypeForDeclGen(ir::SrcDumper *dumper) const return; } - auto typeStr = dumper->IsIsolatedDeclgen() ? GetIsolatedDeclgenReturnType() : Signature()->ReturnType()->ToString(); - + auto typeStr = Signature()->ReturnType()->ToString(); dumper->Add(": "); dumper->Add(typeStr); @@ -409,8 +408,8 @@ void ScriptFunction::CopyTo(AstNode *other) const otherImpl->preferredReturnType_ = preferredReturnType_; otherImpl->lang_ = lang_; otherImpl->returnStatements_ = returnStatements_; - otherImpl->isolatedDeclGenInferType_ = isolatedDeclGenInferType_; JsDocAllowed>::CopyTo(other); } + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index e5a246ebb6..56ba72e368 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -344,16 +344,6 @@ public: checker::Type *Check(checker::TSChecker *checker) override; checker::VerifiedType Check(checker::ETSChecker *checker) override; - void SetIsolatedDeclgenReturnType(std::string type) noexcept - { - isolatedDeclGenInferType_ = std::move(type); - } - - [[nodiscard]] std::string GetIsolatedDeclgenReturnType() const noexcept - { - return isolatedDeclGenInferType_; - } - void Accept(ASTVisitorT *v) override { v->Accept(this); @@ -391,7 +381,6 @@ private: checker::Type *preferredReturnType_ {}; es2panda::Language lang_; ArenaVector returnStatements_; - std::string isolatedDeclGenInferType_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/srcDump.cpp b/ets2panda/ir/srcDump.cpp index da7293ca38..d3b7c1da85 100644 --- a/ets2panda/ir/srcDump.cpp +++ b/ets2panda/ir/srcDump.cpp @@ -31,9 +31,7 @@ SrcDumper::SrcDumper(const ir::AstNode *node) node->Dump(this); } -SrcDumper::SrcDumper(const ir::AstNode *node, bool isDeclgen, bool isIsolatedDeclgen) - : isDeclgen_(isDeclgen), isIsolatedDeclgen_(isIsolatedDeclgen) - +SrcDumper::SrcDumper(const ir::AstNode *node, bool isDeclgen) : isDeclgen_(isDeclgen) { node->Dump(this); } diff --git a/ets2panda/ir/srcDump.h b/ets2panda/ir/srcDump.h index f21bcc31e8..226108b506 100644 --- a/ets2panda/ir/srcDump.h +++ b/ets2panda/ir/srcDump.h @@ -42,7 +42,7 @@ using NodeVariant = class SrcDumper { public: explicit SrcDumper(const ir::AstNode *node); - explicit SrcDumper(const ir::AstNode *node, bool isDeclgen, bool isIsolatedDeclgen = false); + explicit SrcDumper(const ir::AstNode *node, bool isDeclgen); void Add(const std::string &str); void Add(int8_t i); @@ -62,10 +62,6 @@ public: void Endl(size_t num = 1); bool IsDeclgen() const; - bool IsIsolatedDeclgen() const - { - return isIsolatedDeclgen_; - } void DumpVariant(NodeVariant &node); void DumpNode(const std::string &key); @@ -100,7 +96,6 @@ private: std::stringstream ss_; std::string indent_; bool isDeclgen_ = false; - bool isIsolatedDeclgen_ = false; bool isIndirectDepPhase_ = false; std::unordered_map unExportNode_; diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 36001a7946..9321f21511 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -140,11 +140,9 @@ void ETSParser::ParseProgram(ScriptKind kind) if ((GetContext().Status() & ParserStatus::IN_PACKAGE) != 0) { GetContext().Status() &= ~ParserStatus::IN_PACKAGE; } - - if (!GetOptions().IsGenerateDeclEnableIsolated()) { - AddExternalSource(ParseSources(true)); - } - +#ifndef ENABLE_ISOLATED_DECLGEN + AddExternalSource(ParseSources(true)); +#endif GetProgram()->SetAst(script); } diff --git a/ets2panda/public/CMakeLists.txt b/ets2panda/public/CMakeLists.txt index 12227ac6fe..59a10c7855 100644 --- a/ets2panda/public/CMakeLists.txt +++ b/ets2panda/public/CMakeLists.txt @@ -624,6 +624,7 @@ add_custom_target(gen_yamls DEPENDS es2panda_options_gen es2panda_keywords ${ES2 set(ES2PANDA_PUBLIC_SOURCES ${LIB_NAME}.cpp ../declgen_ets2ts/declgenEts2Ts.cpp + ../declgen_ets2ts/isolatedDeclgenChecker.cpp ../util/generateBin.cpp ../util/options.cpp ../util/plugin.cpp diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index 14a173532e..31255c13b7 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -360,7 +360,6 @@ static void InitializeContext(Context *res) res->parser->SetContext(res); res->PushChecker(res->allocator->New(res->allocator, *res->diagnosticEngine, res->allocator)); - res->isolatedDeclgenChecker = new checker::IsolatedDeclgenChecker(*res->diagnosticEngine, *(res->parserProgram)); res->PushAnalyzer(res->allocator->New(res->GetChecker())); res->GetChecker()->SetAnalyzer(res->GetAnalyzer()); @@ -1171,7 +1170,8 @@ extern "C" es2panda_AstNode **AllDeclarationsByNameFromProgram([[maybe_unused]] extern "C" __attribute__((unused)) int GenerateTsDeclarationsFromContext(es2panda_Context *ctx, const char *outputDeclEts, - const char *outputEts, bool exportAll) + const char *outputEts, bool exportAll, + bool isolated) { auto *ctxImpl = reinterpret_cast(ctx); auto *checker = reinterpret_cast(ctxImpl->GetChecker()); @@ -1180,6 +1180,7 @@ extern "C" __attribute__((unused)) int GenerateTsDeclarationsFromContext(es2pand declgenOptions.exportAll = exportAll; declgenOptions.outputDeclEts = outputDeclEts ? outputDeclEts : ""; declgenOptions.outputEts = outputEts ? outputEts : ""; + declgenOptions.isolated = isolated; return ark::es2panda::declgen_ets2ts::GenerateTsDeclarations(checker, ctxImpl->parserProgram, declgenOptions) ? 0 : 1; @@ -1193,7 +1194,7 @@ extern "C" __attribute__((unused)) int GenerateStaticDeclarationsFromContext(es2 if (ctxImpl->state != ES2PANDA_STATE_CHECKED) { return 1; } - compiler::HandleGenerateDecl(*ctxImpl->parserProgram, *ctxImpl->diagnosticEngine, outputPath, false); + compiler::HandleGenerateDecl(*ctxImpl->parserProgram, *ctxImpl->diagnosticEngine, outputPath); return ctxImpl->diagnosticEngine->IsAnyError() ? 1 : 0; } diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index cf927443b4..0ee2e6932d 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -262,7 +262,7 @@ struct CAPI_EXPORT es2panda_Impl { const char *name, size_t *declsLen); int (*GenerateTsDeclarationsFromContext)(es2panda_Context *context, const char *outputDeclEts, - const char *outputEts, bool exportAll); + const char *outputEts, bool exportAll, bool isolated); void (*InsertETSImportDeclarationAndParse)(es2panda_Context *context, es2panda_Program *program, es2panda_AstNode *importDeclaration); int (*GenerateStaticDeclarationsFromContext)(es2panda_Context *context, const char *outputPath); diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index 8ae7475ff7..447555838c 100644 --- a/ets2panda/public/public.h +++ b/ets2panda/public/public.h @@ -25,7 +25,6 @@ #include "compiler/core/compileQueue.h" #include "parser/ETSparser.h" #include "checker/ETSchecker.h" -#include "checker/IsolatedDeclgenChecker.h" #include "compiler/core/emitter.h" namespace ark::es2panda::util { @@ -212,7 +211,6 @@ struct Context { parser::Program *parserProgram = nullptr; parser::ParserImpl *parser = nullptr; - compiler::Emitter *emitter = nullptr; pandasm::Program *program = nullptr; util::DiagnosticEngine *diagnosticEngine = nullptr; @@ -226,7 +224,6 @@ struct Context { TransitionMemory *transitionMemory {nullptr}; bool isExternal = false; bool compiledByCapi = false; - checker::IsolatedDeclgenChecker *isolatedDeclgenChecker {nullptr}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol-expected.txt b/ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol-expected.txt deleted file mode 100644 index 1804ab1e7b..0000000000 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol-expected.txt +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import A from "./infer_function_return_type_with_literal.ets"; - -import B from "./infer_function_return_type_with_literal.ets"; - -import C from "./infer_function_return_type_with_literal.ets"; - -export declare let b: A; - -export default declare let d: int; - -export declare function foo(a: int, c: C): A | Array | Array | Array | B | Number | String; \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_literal-expected.txt b/ets2panda/test/isolated_declgen/infer_function_return_type_with_literal-expected.txt deleted file mode 100644 index 0580538547..0000000000 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_literal-expected.txt +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - export declare function foo(a: int): Int|Boolean|String; \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_variable-expected.txt b/ets2panda/test/isolated_declgen/infer_function_return_type_with_variable-expected.txt deleted file mode 100644 index 6eced86611..0000000000 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_variable-expected.txt +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - export declare function foo(a: int): String|B|Int|A; \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/isolated_interface-expected.txt b/ets2panda/test/isolated_declgen/isolated_interface-expected.txt deleted file mode 100644 index 029658ebdd..0000000000 --- a/ets2panda/test/isolated_declgen/isolated_interface-expected.txt +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export declare interface User { - set id(id: number): void; - - get id(): double; - set name(name: string): void; - - get name(): String; - set age(age: number | undefined): void; - - get age(): Double|undefined; - get apiUrl(): String; - -} - -export declare interface Animal { - set name(name: string): void; - - get name(): String; - makeSound(): void; - -} \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/isolated_namespace-expected.txt b/ets2panda/test/isolated_declgen/isolated_namespace-expected.txt deleted file mode 100644 index c5d5aa7784..0000000000 --- a/ets2panda/test/isolated_declgen/isolated_namespace-expected.txt +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) 2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - export declare namespace MathOperations { - - let PI: double; - - function add(a: number, b: number): double; - - function subtract(a: number, b: number): double; - - -} \ No newline at end of file diff --git a/ets2panda/test/unit/CMakeLists.txt b/ets2panda/test/unit/CMakeLists.txt index 07663a9a29..c84184cf5f 100644 --- a/ets2panda/test/unit/CMakeLists.txt +++ b/ets2panda/test/unit/CMakeLists.txt @@ -16,6 +16,7 @@ if(NOT PANDA_REGRESSION_TESTS) endif() add_subdirectory(cfg) +add_subdirectory(declgen) add_subdirectory(dynamic) add_subdirectory(lowerings) add_subdirectory(public) diff --git a/ets2panda/test/unit/declgen/CMakeLists.txt b/ets2panda/test/unit/declgen/CMakeLists.txt new file mode 100644 index 0000000000..37a9cc4496 --- /dev/null +++ b/ets2panda/test/unit/declgen/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if (PANDA_ENABLE_ADDRESS_SANITIZER OR PANDA_ENABLE_THREAD_SANITIZER) + return() +endif() + +set(COMMON_SOURCE_FILES + "util.cpp" +) + +set(DECLGEN_PLUGIN_TESTS + "test_ets2ts_isolated_declgen cpp" +) + +set(ETS2TS_ISOLATED_TESTS + "./ets2ts_isolated/test_ets2ts_isolated_class.ets" + "./ets2ts_isolated/test_ets2ts_isolated_enum.ets" + "./ets2ts_isolated/test_ets2ts_isolated_module.ets" + "./ets2ts_isolated/test_ets2ts_isolated_namespace.ets" + "./ets2ts_isolated/test_ets2ts_isolated_interface.ets" + "./ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter.ets" + "./ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol.ets" +) + +foreach(TEST_DATA IN ITEMS ${DECLGEN_PLUGIN_TESTS}) + string(REPLACE " " ";" TEST_DATA_ELEM "${TEST_DATA}") + list(GET TEST_DATA_ELEM 0 TEST_NAME) + list(GET TEST_DATA_ELEM 1 EXTENSION) + + panda_add_executable(${TEST_NAME} ${TEST_NAME}.${EXTENSION} ${COMMON_SOURCE_FILES} OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + panda_add_sanitizers(TARGET ${TEST_NAME} SANITIZERS ${PANDA_SANITIZERS_LIST}) + + panda_target_include_directories(${TEST_NAME} + PRIVATE ${ES2PANDA_PATH} + PRIVATE ${PANDA_ROOT}/libpandafile + PRIVATE ${PANDA_ROOT}/assembler + PRIVATE ${OUTPUT_DIR} + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC ${CMAKE_SOURCE_DIR}/libpandabase + PUBLIC ${CMAKE_SOURCE_DIR}/runtime + PUBLIC ${CMAKE_BINARY_DIR}/libpandabase + PUBLIC ${CMAKE_BINARY_DIR}/libpandafile/include + ${CMAKE_BINARY_DIR} + ) + panda_target_link_libraries(${TEST_NAME} es2panda-public arkassembler arkbase arkfile) +endforeach() + +add_custom_target(es2panda-declgen-plugin-test) + +set(ETS2TS "ets2ts_isolated") +foreach(TEST_DATA IN ITEMS ${DECLGEN_PLUGIN_TESTS}) + string(REPLACE " " ";" TEST_DATA_ELEM "${TEST_DATA}") + list(GET TEST_DATA_ELEM 0 TEST_NAME) + list(GET TEST_DATA_ELEM 1 EXTENSION) + foreach(TEST_ETS_FILE IN ITEMS ${ETS2TS_ISOLATED_TESTS}) + cmake_path(SET PATH_ITEM "${TEST_ETS_FILE}") + cmake_path(GET PATH_ITEM STEM FILE_NAME) + add_custom_target(es2panda-declgen-plugin-test-compile-${FILE_NAME} + COMMAND ${CMAKE_COMMAND} -E env + LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${PANDA_RUN_PREFIX} + ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} $ + --extension=ets --ets-unnamed --output="${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.abc" + "${CMAKE_CURRENT_SOURCE_DIR}/${TEST_ETS_FILE}" > "${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.out" 2>&1 + ) + add_dependencies(es2panda-declgen-plugin-test-compile-${FILE_NAME} es2panda ${TEST_NAME} es2panda-lib) + add_dependencies(es2panda-declgen-plugin-test es2panda-declgen-plugin-test-compile-${FILE_NAME}) + + add_custom_target(es2panda-declgen-plugin-test-expected-${FILE_NAME} + COMMAND ${CMAKE_COMMAND} -E compare_files + "${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.d.ets" "${CMAKE_CURRENT_SOURCE_DIR}/${ETS2TS}/${FILE_NAME}-expected.txt" + ) + add_dependencies(es2panda-declgen-plugin-test-expected-${FILE_NAME} es2panda-declgen-plugin-test-compile-${FILE_NAME} es2panda-lib) + add_dependencies(es2panda-declgen-plugin-test es2panda-declgen-plugin-test-expected-${FILE_NAME}) + endforeach() +endforeach() + +add_dependencies(es2panda_tests es2panda-declgen-plugin-test) \ No newline at end of file diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol-expected.txt new file mode 100644 index 0000000000..ca2fd1c2e9 --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol-expected.txt @@ -0,0 +1,7 @@ +import A from "./test_ets2ts_isolated_enum"; +import B from "./test_ets2ts_isolated_enum"; +import C from "./test_ets2ts_isolated_enum"; +export declare let b: A; +declare let d: number; +export default d; +export declare function foo(a: number, c: C): A | Array | Array | Array | B | number | string; diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol.ets similarity index 84% rename from ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol.ets index 6acccddadf..3948758074 100644 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_import_symbol.ets +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_infer_function_return_type_with_import_symbol.ets @@ -13,9 +13,9 @@ * limitations under the License. */ -import A from "./infer_function_return_type_with_literal.ets" -import B from "./infer_function_return_type_with_literal.ets" -import C from "./infer_function_return_type_with_literal.ets" +import A from "./test_ets2ts_isolated_enum.ets" +import B from "./test_ets2ts_isolated_enum.ets" +import C from "./test_ets2ts_isolated_enum.ets" export let b: A = new A @@ -43,8 +43,4 @@ export function foo(a: int, c: C) } return "hello"; -} - - - - +} \ No newline at end of file diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class-expected.txt new file mode 100644 index 0000000000..4ad14cb500 --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class-expected.txt @@ -0,0 +1,18 @@ +export declare interface I0 { + I0Method(a: string): string; +} +export declare interface I1 { + I1Method(a: number): number; +} +export declare class Base { + public get a(): number; + public set a(value: number); + public constructor(a: number); +} +export declare class Derived extends Base implements I0, I1 { + public I0Method(a: string): string; + public I1Method(a: number): number; + public get b(): number; + public set b(value: number); + public constructor(a: number, b: number); +} diff --git a/ets2panda/test/isolated_declgen/isolated_class.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class.ets similarity index 100% rename from ets2panda/test/isolated_declgen/isolated_class.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_class.ets diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum-expected.txt new file mode 100644 index 0000000000..ae0a088911 --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum-expected.txt @@ -0,0 +1,11 @@ +export declare enum Direction { + Up = 0, + Down = 1, + Left = 2, + Right = 3, +} +export declare enum Message { + Success = "SUCCESS", + Failure = "FAILURE", + Pending = "PENDING", +} diff --git a/ets2panda/test/isolated_declgen/isolated_function_with_optional_parameter-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum.ets similarity index 80% rename from ets2panda/test/isolated_declgen/isolated_function_with_optional_parameter-expected.txt rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum.ets index 5276a1c1bd..045fe8db94 100644 --- a/ets2panda/test/isolated_declgen/isolated_function_with_optional_parameter-expected.txt +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_enum.ets @@ -12,7 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export enum Direction { + Up, + Down, + Left, + Right +} -export declare function greet(name: string, age?: number): String; - -export declare function multiply(x: number, gensym%%_1?: number): double; \ No newline at end of file +export enum Message { + Success = "SUCCESS", + Failure = "FAILURE", + Pending = "PENDING" +} \ No newline at end of file diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter-expected.txt new file mode 100644 index 0000000000..602c65d87e --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter-expected.txt @@ -0,0 +1,2 @@ +export declare function greet(name: string, age?: number): string; +export declare function multiply(x: number, y?: number): number; diff --git a/ets2panda/test/isolated_declgen/isolated_function_with_optional_parameter.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter.ets similarity index 100% rename from ets2panda/test/isolated_declgen/isolated_function_with_optional_parameter.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_function_with_optional_parameter.ets diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface-expected.txt new file mode 100644 index 0000000000..40f1e96753 --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface-expected.txt @@ -0,0 +1,14 @@ +export declare interface User { + get id(): number; + set id(value: number); + get name(): string; + set name(value: string); + get age(): number | undefined; + set age(value: number | undefined); + get apiUrl(): string; +} +export declare interface Animal { + get name(): string; + set name(value: string); + makeSound(): void; +} diff --git a/ets2panda/test/isolated_declgen/isolated_interface.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface.ets similarity index 99% rename from ets2panda/test/isolated_declgen/isolated_interface.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface.ets index 828c677385..1b27d21ef4 100644 --- a/ets2panda/test/isolated_declgen/isolated_interface.ets +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_interface.ets @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + export interface User { id: number; name: string; diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module-expected.txt new file mode 100644 index 0000000000..9091aa582e --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module-expected.txt @@ -0,0 +1,6 @@ +import * as np from "./test_ets2ts_isolated_enum"; +import { B, C0 as C } from "./test_ets2ts_isolated_enum"; +export declare let b: np.A; +declare let d: number; +export default d; +export declare function foo(a: number, c: C): Array | Array | Array | B | np.A | number | string; diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_variable.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module.ets similarity index 63% rename from ets2panda/test/isolated_declgen/infer_function_return_type_with_variable.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module.ets index 4a19a2de33..cd3bbc6bfa 100644 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_variable.ets +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_module.ets @@ -13,20 +13,33 @@ * limitations under the License. */ -class A {} -class B {} +import * as np from "./test_ets2ts_isolated_enum.ets" +import {B, C0 as C} from "./test_ets2ts_isolated_enum.ets" -export function foo(a: int) +export let b: np.A = new np.A + +export default let d: int = 1 + +export function foo(a: int, c: C) { if (a < 0) { return 1; } if (a == 0) { - return new A; + return b; } - if (a > 0) { + if (a == 1) { return new B; } + if (a == 2) { + return ["hello", "arkts"]; + } + if (a == 3) { + return [0, 1, 2]; + } + if (a == 4) { + return [true, false, false, true]; + } return "hello"; } \ No newline at end of file diff --git a/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace-expected.txt b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace-expected.txt new file mode 100644 index 0000000000..d0ac8cfd8a --- /dev/null +++ b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace-expected.txt @@ -0,0 +1,5 @@ +export declare namespace MathOperations { + const PI: number; + function add(a: number, b: number): number; + function subtract(a: number, b: number): number; +} diff --git a/ets2panda/test/isolated_declgen/isolated_namespace.ets b/ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace.ets similarity index 100% rename from ets2panda/test/isolated_declgen/isolated_namespace.ets rename to ets2panda/test/unit/declgen/ets2ts_isolated/test_ets2ts_isolated_namespace.ets diff --git a/ets2panda/test/isolated_declgen/infer_function_return_type_with_literal.ets b/ets2panda/test/unit/declgen/test_ets2ts_isolated_declgen.cpp similarity index 34% rename from ets2panda/test/isolated_declgen/infer_function_return_type_with_literal.ets rename to ets2panda/test/unit/declgen/test_ets2ts_isolated_declgen.cpp index 00375f7d6e..8cb169287b 100644 --- a/ets2panda/test/isolated_declgen/infer_function_return_type_with_literal.ets +++ b/ets2panda/test/unit/declgen/test_ets2ts_isolated_declgen.cpp @@ -12,18 +12,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export function foo(a: int) + +#include +#include +#include + +#include "os/library_loader.h" + +#include "public/es2panda_lib.h" +#include "./util.h" + +// NOLINTBEGIN + +static es2panda_Impl *impl = nullptr; + +int main(int argc, char **argv) { - if (a < 0) { - return 1; + if (argc < MIN_ARGC) { + return INVALID_ARGC_ERROR_CODE; } - if (a == 0) { - return "hello"; + + if (GetImpl() == nullptr) { + return NULLPTR_IMPL_ERROR_CODE; } - if (a > 0) { - return true; + impl = GetImpl(); + std::cout << "LOAD SUCCESS" << std::endl; + + const char **args = const_cast(&(argv[1])); + auto config = impl->CreateConfig(argc - 1, args); + auto context = impl->CreateContextFromFile(config, argv[argc - 1]); + if (context == nullptr) { + std::cerr << "FAILED TO CREATE CONTEXT" << std::endl; + return NULLPTR_CONTEXT_ERROR_CODE; } - + + impl->ProceedToState(context, ES2PANDA_STATE_CHECKED); + CheckForErrors("CHECKED", context); + std::string declName = GetDeclPrefix(argv[argc - 1]) + ".d.ets"; + int result = impl->GenerateTsDeclarationsFromContext(context, declName.c_str(), "dump.ets", false, true); + if (result != 0) { + std::cerr << "FAILED TO GENERATE DECLARATIONS" << std::endl; + return result; + } + + impl->DestroyConfig(config); + return 0; -} \ No newline at end of file +} + +// NOLINTEND diff --git a/ets2panda/test/unit/declgen/util.cpp b/ets2panda/test/unit/declgen/util.cpp new file mode 100644 index 0000000000..ed872305b2 --- /dev/null +++ b/ets2panda/test/unit/declgen/util.cpp @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "util.h" +#include +#include +#include +#include +#include +#include +#include "macros.h" + +static es2panda_Impl *g_implPtr = nullptr; + +es2panda_Impl *GetImpl() +{ + if (g_implPtr != nullptr) { + return g_implPtr; + } + + std::string soName = ark::os::library_loader::DYNAMIC_LIBRARY_PREFIX + std::string("es2panda-public") + + ark::os::library_loader::DYNAMIC_LIBRARY_SUFFIX; + auto libraryRes = ark::os::library_loader::Load(soName); + if (!libraryRes.HasValue()) { + std::cout << "Error in load lib" << std::endl; + return nullptr; + } + + auto library = std::move(libraryRes.Value()); + auto getImpl = ark::os::library_loader::ResolveSymbol(library, "es2panda_GetImpl"); + if (!getImpl.HasValue()) { + std::cout << "Error in load func get g_implPtr" << std::endl; + return nullptr; + } + + auto getImplFunc = reinterpret_cast(getImpl.Value()); + if (getImplFunc != nullptr) { + g_implPtr = const_cast(getImplFunc(ES2PANDA_LIB_VERSION)); + return g_implPtr; + } + return nullptr; +} + +void CheckForErrors(const std::string &stateName, es2panda_Context *context) +{ + if (g_implPtr->ContextState(context) == ES2PANDA_STATE_ERROR) { + std::cout << "PROCEED TO " << stateName << " ERROR" << std::endl; + std::cout << g_implPtr->ContextErrorMessage(context) << std::endl; + } else { + std::cout << "PROCEED TO " << stateName << " SUCCESS" << std::endl; + } +} + +std::string GetDeclPrefix(const char *etsSrcName) +{ + if (etsSrcName == nullptr) { + return ""; + } + std::string_view etsSrc(etsSrcName); + auto pos = etsSrc.find_last_of('/'); + if (pos != std::string_view::npos) { + etsSrc = etsSrc.substr(pos + 1); + } + std::cout << "ETS SRC: " << etsSrc << std::endl; + pos = etsSrc.find_last_of('.'); + if (pos != std::string_view::npos) { + etsSrc = etsSrc.substr(0, pos); + } + std::cout << "ETS SRC PREFIX: " << etsSrc << std::endl; + return std::string(etsSrc); +} \ No newline at end of file diff --git a/ets2panda/test/isolated_declgen/isolated_class-expected.txt b/ets2panda/test/unit/declgen/util.h similarity index 43% rename from ets2panda/test/isolated_declgen/isolated_class-expected.txt rename to ets2panda/test/unit/declgen/util.h index 5ee4f26785..d4c678d9ad 100644 --- a/ets2panda/test/isolated_declgen/isolated_class-expected.txt +++ b/ets2panda/test/unit/declgen/util.h @@ -13,30 +13,34 @@ * limitations under the License. */ -export declare interface I0 { - I0Method(a: string): String; +#ifndef ES2PANDA_TEST_UNIT_DECLGEN_PLUGIN_UTIL_H +#define ES2PANDA_TEST_UNIT_DECLGEN_PLUGIN_UTIL_H -} +#include +#include +#include +#include +#include -export declare interface I1 { - I1Method(a: double): double; +#include "os/library_loader.h" -} +#include "public/es2panda_lib.h" -export declare class Base { - public a: double; +constexpr int MIN_ARGC = 3; - public constructor(a: double); +// error code number +constexpr int NULLPTR_IMPL_ERROR_CODE = 2; +constexpr int PROCEED_ERROR_CODE = 3; +constexpr int TEST_ERROR_CODE = 4; +constexpr int INVALID_ARGC_ERROR_CODE = 5; +constexpr int NULLPTR_CONTEXT_ERROR_CODE = 6; -} +es2panda_Impl *GetImpl(); +void CheckForErrors(const std::string &stateName, es2panda_Context *context); -export declare class Derived extends Base implements I0, I1 { - public I0Method(a: string): String; +es2panda_AstNode *GetETSGlobalClass(es2panda_Context *ctx, es2panda_AstNode *rootNode); - public I1Method(a: double): double; +// CC-OFFNXT(G.NAM.01) false positive +std::string GetDeclPrefix(const char *etsSrcName); - public b: double; - - public constructor(a: double, b: double); - -} \ No newline at end of file +#endif \ No newline at end of file diff --git a/ets2panda/test/unit/sizeof_node_test.cpp b/ets2panda/test/unit/sizeof_node_test.cpp index 61589226cd..b5912cb841 100644 --- a/ets2panda/test/unit/sizeof_node_test.cpp +++ b/ets2panda/test/unit/sizeof_node_test.cpp @@ -283,8 +283,7 @@ size_t SizeOfNodeTest::SizeOf() sizeof(node->signature_) + sizeof(node->preferredReturnType_) + Align(sizeof(node->lang_)) + - sizeof(node->returnStatements_) + - sizeof(node->isolatedDeclGenInferType_); + sizeof(node->returnStatements_); // clang-format on } diff --git a/ets2panda/util/diagnostic.cpp b/ets2panda/util/diagnostic.cpp index 40b71f1e63..8104e2ad61 100644 --- a/ets2panda/util/diagnostic.cpp +++ b/ets2panda/util/diagnostic.cpp @@ -166,12 +166,12 @@ const char *DiagnosticTypeToString(DiagnosticType type) return "Declgen ets2ts error"; case DiagnosticType::DECLGEN_ETS2TS_WARNING: return "Declgen ets2ts warning"; + case DiagnosticType::ISOLATED_DECLGEN: + return "Isolated declgen error"; case DiagnosticType::ARKTS_CONFIG_ERROR: return "ArkTS config error"; case DiagnosticType::SUGGESTION: return "SUGGESTION"; - case DiagnosticType::ISOLATED_DECLGEN: - return "Isolated declgen error"; default: ES2PANDA_UNREACHABLE(); } diff --git a/ets2panda/util/diagnostic.h b/ets2panda/util/diagnostic.h index cb4c70a256..40584dac1c 100644 --- a/ets2panda/util/diagnostic.h +++ b/ets2panda/util/diagnostic.h @@ -50,9 +50,9 @@ enum DiagnosticType { PLUGIN_WARNING, DECLGEN_ETS2TS_ERROR, DECLGEN_ETS2TS_WARNING, + ISOLATED_DECLGEN, ARKTS_CONFIG_ERROR, SUGGESTION, - ISOLATED_DECLGEN, COUNT, INVALID = COUNT }; diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 1108b9e7f1..9e294a8cf8 100644 --- a/ets2panda/util/diagnosticEngine.cpp +++ b/ets2panda/util/diagnosticEngine.cpp @@ -114,8 +114,8 @@ bool DiagnosticEngine::IsError(DiagnosticType type) const case DiagnosticType::SEMANTIC: case DiagnosticType::PLUGIN_ERROR: case DiagnosticType::DECLGEN_ETS2TS_ERROR: - case DiagnosticType::ARKTS_CONFIG_ERROR: case DiagnosticType::ISOLATED_DECLGEN: + case DiagnosticType::ARKTS_CONFIG_ERROR: return true; case DiagnosticType::WARNING: case DiagnosticType::DECLGEN_ETS2TS_WARNING: diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index 2a1894aeb7..22bf3b6f48 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -182,10 +182,6 @@ options: type: std::string default: "" description: Output path for generated static declaration files - - name: enable-isolated - type: bool - default: false - description: Whether to enable isolated declaration file generation - name: thread type: int diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index f2983e06ca..aa10db8d69 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -155,10 +155,7 @@ void ETSBinder::LookupTypeReference(ir::Identifier *ident, bool allowDynamicName return; } - if (!GetContext()->config->options->IsGenerateDeclEnableIsolated()) { - ThrowUnresolvableType(ident->Start(), name); - } - + ThrowUnresolvableType(ident->Start(), name); CreateDummyVariable(this, ident); } @@ -1010,10 +1007,8 @@ varbinder::Variable *ETSBinder::FindStaticBinding(Span r if (result != nullptr) { return result; } - if (!GetContext()->config->options->IsGenerateDeclEnableIsolated()) { - ThrowError(importPath->Start(), diagnostic::DEFAULT_IMPORT_NOT_FOUND); - } + ThrowError(importPath->Start(), diagnostic::DEFAULT_IMPORT_NOT_FOUND); return nullptr; } -- Gitee From aeb0aa77ab4d5d411de430eb31bf67dd9de498af Mon Sep 17 00:00:00 2001 From: leo9001 Date: Wed, 11 Jun 2025 15:41:45 +0800 Subject: [PATCH 081/747] support GetClassHierarchyInfo support GetClassHierarchyInfo Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICD5N1 Signed-off-by: leo9001 --- ets2panda/bindings/native/src/lsp.cpp | 39 +++- .../bindings/src/Es2pandaNativeModule.ts | 12 +- ets2panda/bindings/src/lspNode.ts | 45 +++- ets2panda/lsp/include/class_hierarchy_info.h | 139 ++++++------ ets2panda/lsp/include/class_hierarchy_item.h | 135 ++++++++++++ ets2panda/lsp/include/internal_api.h | 2 +- ets2panda/lsp/src/class_hierarchy_info.cpp | 169 +++++++++++---- ets2panda/lsp/src/completions.cpp | 14 +- .../unit/lsp/class_hierarchy_info_test.cpp | 199 ++++++++++++++++-- 9 files changed, 588 insertions(+), 166 deletions(-) create mode 100644 ets2panda/lsp/include/class_hierarchy_item.h diff --git a/ets2panda/bindings/native/src/lsp.cpp b/ets2panda/bindings/native/src/lsp.cpp index 286efef597..d23b1e01cd 100644 --- a/ets2panda/bindings/native/src/lsp.cpp +++ b/ets2panda/bindings/native/src/lsp.cpp @@ -28,7 +28,9 @@ namespace { using ark::es2panda::lsp::ClassHierarchy; using ark::es2panda::lsp::ClassHierarchyInfo; +using ark::es2panda::lsp::ClassHierarchyItem; using ark::es2panda::lsp::ClassMethodItem; +using ark::es2panda::lsp::ClassPropertyItem; } // namespace char *GetStringCopy(KStringPtr &ptr) @@ -722,14 +724,14 @@ KNativePointer impl_getClassNameFromClassHierarchyInfo(KNativePointer info) } TS_INTEROP_1(getClassNameFromClassHierarchyInfo, KNativePointer, KNativePointer) -KNativePointer impl_getMethodListFromClassHierarchyInfo(KNativePointer info) +KNativePointer impl_getMethodItemsFromClassHierarchyInfo(KNativePointer info) { auto *infoPtr = reinterpret_cast(info); if (infoPtr == nullptr) { return nullptr; } std::vector ptrs; - for (const auto &element : infoPtr->GetMethodList()) { + for (const auto &element : infoPtr->GetMethodItemList()) { if (element.second == nullptr) { continue; } @@ -737,17 +739,34 @@ KNativePointer impl_getMethodListFromClassHierarchyInfo(KNativePointer info) } return new std::vector(ptrs); } -TS_INTEROP_1(getMethodListFromClassHierarchyInfo, KNativePointer, KNativePointer) +TS_INTEROP_1(getMethodItemsFromClassHierarchyInfo, KNativePointer, KNativePointer) -KNativePointer impl_getDetailFromClassMethodItem(KNativePointer item) +KNativePointer impl_getPropertyItemsFromClassHierarchyInfo(KNativePointer info) { - auto *itemPtr = reinterpret_cast(item); + auto *infoPtr = reinterpret_cast(info); + if (infoPtr == nullptr) { + return nullptr; + } + std::vector ptrs; + for (const auto &element : infoPtr->GetPropertyItemList()) { + if (element.second == nullptr) { + continue; + } + ptrs.push_back(new ClassPropertyItem(*(element.second))); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(getPropertyItemsFromClassHierarchyInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getDetailFromClassHierarchyItem(KNativePointer item) +{ + auto *itemPtr = reinterpret_cast(item); if (itemPtr == nullptr) { return nullptr; } - return new std::string(itemPtr->GetFunctionDetail()); + return new std::string(itemPtr->GetDetail()); } -TS_INTEROP_1(getDetailFromClassMethodItem, KNativePointer, KNativePointer) +TS_INTEROP_1(getDetailFromClassHierarchyItem, KNativePointer, KNativePointer) KInt impl_getSetterStyleFromClassMethodItem(KNativePointer item) { @@ -759,15 +778,15 @@ KInt impl_getSetterStyleFromClassMethodItem(KNativePointer item) } TS_INTEROP_1(getSetterStyleFromClassMethodItem, KInt, KNativePointer) -KInt impl_getAccessModifierStyleFromClassMethodItem(KNativePointer item) +KInt impl_getAccessModifierStyleFromClassHierarchyItem(KNativePointer item) { - auto *itemPtr = reinterpret_cast(item); + auto *itemPtr = reinterpret_cast(item); if (itemPtr == nullptr) { return 0; } return static_cast(itemPtr->GetAccessModifierStyle()); } -TS_INTEROP_1(getAccessModifierStyleFromClassMethodItem, KInt, KNativePointer) +TS_INTEROP_1(getAccessModifierStyleFromClassHierarchyItem, KInt, KNativePointer) KInt impl_getAliasScriptElementKind(KNativePointer context, KInt position) { diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index 210ad83e1c..c8ac45f8a8 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -205,19 +205,23 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } - _getMethodListFromClassHierarchyInfo(ptr: KNativePointer): KPtr { + _getMethodItemsFromClassHierarchyInfo(ptr: KNativePointer): KPtr { throw new Error('Not implemented'); } - _getDetailFromClassMethodItem(ptr: KNativePointer): KPtr { + _getPropertyItemsFromClassHierarchyInfo(ptr: KNativePointer): KPtr { throw new Error('Not implemented'); } - _getSetterStyleFromClassMethodItem(ptr: KNativePointer): KInt { + _getDetailFromClassHierarchyItem(ptr: KNativePointer): KPtr { throw new Error('Not implemented'); } - _getAccessModifierStyleFromClassMethodItem(ptr: KNativePointer): KInt { + _getAccessModifierStyleFromClassHierarchyItem(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getSetterStyleFromClassMethodItem(ptr: KNativePointer): KInt { throw new Error('Not implemented'); } diff --git a/ets2panda/bindings/src/lspNode.ts b/ets2panda/bindings/src/lspNode.ts index 17f846fce2..ebe31ff07c 100644 --- a/ets2panda/bindings/src/lspNode.ts +++ b/ets2panda/bindings/src/lspNode.ts @@ -23,7 +23,7 @@ import { NativePtrDecoder } from './Platform'; enum HierarchyType { OTHERS, INTERFACE, CLASS }; export enum SetterStyle { - METHOD = 0, + NONE = 0, SETTER, GETTER } @@ -36,6 +36,11 @@ export enum AccessModifierStyle { enum ClassRelationKind { UNKNOWN, INTERFACE, CLASS, FIELD, METHOD, PROPERTY }; +export enum ClassDefinitionStyle { + FIELD = 0, + METHOD +} + export abstract class LspNode { readonly peer: KNativePointer; @@ -228,30 +233,50 @@ export class LspSymbolDisplayPart extends LspNode { readonly kind: String; } -export class LspClassMethodItem extends LspNode { - constructor(peer: KNativePointer) { +export class LspClassHierarchyItem extends LspNode { + constructor(peer: KNativePointer, style: ClassDefinitionStyle) { super(peer); - this.functionDetail = unpackString(global.es2panda._getDetailFromClassMethodItem(this.peer)); + this.style = style; + this.detail = unpackString(global.es2panda._getDetailFromClassHierarchyItem(this.peer)); + this.accessModifier = global.es2panda._getAccessModifierStyleFromClassHierarchyItem(this.peer); + } + readonly detail: string; + readonly accessModifier: AccessModifierStyle; + readonly style: ClassDefinitionStyle; +} + +export class LspClassMethodItem extends LspClassHierarchyItem { + constructor(peer: KNativePointer) { + super(peer, ClassDefinitionStyle.METHOD); this.setter = global.es2panda._getSetterStyleFromClassMethodItem(this.peer); - this.accessModifier = global.es2panda._getAccessModifierStyleFromClassMethodItem(this.peer); } - readonly functionDetail: string; readonly setter: SetterStyle; - readonly accessModifier: AccessModifierStyle; +} + +export class LspClassPropertyItem extends LspClassHierarchyItem { + constructor(peer: KNativePointer) { + super(peer, ClassDefinitionStyle.FIELD); + } } export class LspClassHierarchyInfo extends LspNode { constructor(peer: KNativePointer) { super(peer); this.className = unpackString(global.es2panda._getClassNameFromClassHierarchyInfo(this.peer)); - this.items = new NativePtrDecoder() - .decode(global.es2panda._getMethodListFromClassHierarchyInfo(this.peer)) + this.methodItems = new NativePtrDecoder() + .decode(global.es2panda._getMethodItemsFromClassHierarchyInfo(this.peer)) .map((elPeer: KNativePointer) => { return new LspClassMethodItem(elPeer); }); + this.fieldItems = new NativePtrDecoder() + .decode(global.es2panda._getPropertyItemsFromClassHierarchyInfo(this.peer)) + .map((elPeer: KNativePointer) => { + return new LspClassPropertyItem(elPeer); + }); } readonly className: string; - readonly items: LspClassMethodItem[]; + readonly methodItems: LspClassMethodItem[]; + readonly fieldItems: LspClassPropertyItem[]; } export class LspClassHierarchy extends LspNode { diff --git a/ets2panda/lsp/include/class_hierarchy_info.h b/ets2panda/lsp/include/class_hierarchy_info.h index f7730151ed..8ff110fa20 100644 --- a/ets2panda/lsp/include/class_hierarchy_info.h +++ b/ets2panda/lsp/include/class_hierarchy_info.h @@ -17,9 +17,9 @@ #define ES2PANDA_LSP_CLASS_HIERARCHY_INFO_H #include -#include #include #include +#include "class_hierarchy_item.h" #include "public/es2panda_lib.h" namespace ark::es2panda::lsp { @@ -45,59 +45,6 @@ private: std::string kind_; }; -enum class SetterStyle { METHOD = 0, SETTER, GETTER }; - -enum class AccessModifierStyle { PUBLIC = 0, PROTECTED, PRIVATE }; - -class ClassMethodItem { -public: - ClassMethodItem(std::string detail, SetterStyle setter, AccessModifierStyle access) - : detail_(std::move(detail)), setter_(setter), accessModifier_(access) - { - } - - virtual ~ClassMethodItem() = default; - - ClassMethodItem(const ClassMethodItem &other) = default; - ClassMethodItem(ClassMethodItem &&other) = default; - ClassMethodItem &operator=(const ClassMethodItem &other) = default; - ClassMethodItem &operator=(ClassMethodItem &&other) = default; - - void SetFunctionName(const std::string &functionName) - { - if (functionName.empty()) { - return; - } - funcName_ = functionName; - } - - const std::string &GetFunctionName() const - { - return funcName_; - } - - const std::string &GetFunctionDetail() const - { - return detail_; - } - - SetterStyle GetSetterStyle() const - { - return setter_; - } - - AccessModifierStyle GetAccessModifierStyle() const - { - return accessModifier_; - } - -private: - std::string funcName_; - std::string detail_; - SetterStyle setter_; - AccessModifierStyle accessModifier_; -}; - class ClassHierarchyInfo { public: ClassHierarchyInfo() = default; @@ -122,58 +69,98 @@ public: return className_; } - const std::unordered_map> &GetMethodList() const + const std::unordered_map> &GetMethodItemList() const + { + return methodItems_; + } + + const std::unordered_map> &GetPropertyItemList() const + { + return propertyItems_; + } + + bool AddItemToMethodList(const std::shared_ptr &item) { - return methods_; + if (item == nullptr) { + return false; + } + auto detail = item->GetDetail(); + auto result = methodItems_.try_emplace(detail, item); + return result.second; } - bool AddClassMethodItem(const std::shared_ptr &item) + bool AddItemToPropertyList(const std::shared_ptr &item) { - if (item == nullptr || IsItemExist(item)) { + if (item == nullptr) { return false; } - auto funcDetail = item->GetFunctionDetail(); - methods_[funcDetail] = item; - return true; + auto detail = item->GetDetail(); + auto result = propertyItems_.try_emplace(detail, item); + return result.second; } - void DeleteClassMethodItem(const std::shared_ptr &item) + void DeleteTargetItemInMethodList(const std::shared_ptr &item) { if (item == nullptr) { return; } - auto funcDetail = item->GetFunctionDetail(); - methods_.erase(funcDetail); + auto detail = item->GetDetail(); + methodItems_.erase(detail); } - void DeleteAllClassMethodItem() + void DeleteTargetItemInPropertyList(const std::shared_ptr &item) { - methods_.clear(); + if (item == nullptr) { + return; + } + auto detail = item->GetDetail(); + propertyItems_.erase(detail); } - bool IsItemExist(const std::shared_ptr &item) const + void DeleteAllItemsInMethodList() + { + methodItems_.clear(); + } + + void DeleteAllItemsInPropertyList() + { + propertyItems_.clear(); + } + + bool IsItemExistInMethodList(const std::shared_ptr &item) const { if (item == nullptr) { return false; } - auto func = item->GetFunctionDetail(); - auto iter = methods_.find(func); - return iter != methods_.end(); + auto detail = item->GetDetail(); + auto iter = methodItems_.find(detail); + return iter != methodItems_.end(); + } + + bool IsItemExistInPropertyList(const std::shared_ptr &item) const + { + if (item == nullptr) { + return false; + } + auto detail = item->GetDetail(); + auto iter = propertyItems_.find(detail); + return iter != propertyItems_.end(); } private: std::string className_; - std::unordered_map> methods_; + std::unordered_map> methodItems_; + std::unordered_map> propertyItems_; }; using ClassHierarchy = std::vector; /** - * Retrieve the list of undefined virtual functions in the parent class. + * Retrieve the list of undefined virtual functions and properties in the parent class. * * such as ets: * class Animal { - * private body_: string = ''; + * public body_: string = ''; * * public action(): void { * console.log("need Animal action"); @@ -192,9 +179,9 @@ using ClassHierarchy = std::vector; * console.log("need Bird Drink"); * } * } - * - * when clicking 'Bird'. - * ClassHierarchy is [ { "Animal", { detail: sleep(), SetterStyle: METHOD, AccessModifierStyle: PUBLIC } } ]. + * when clicking 'Bird'. ClassHierarchy is : + * [ { "Animal", { detail: body_: string, ClassDefinitionStyle FIELD, AccessModifierStyle: PUBLIC } }, + * { "Animal", { detail: sleep(): void, ClassDefinitionStyle: METHOD, AccessModifierStyle: PUBLIC } } ]. */ ClassHierarchy GetClassHierarchyInfoImpl(es2panda_Context *context, size_t position); } // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/include/class_hierarchy_item.h b/ets2panda/lsp/include/class_hierarchy_item.h new file mode 100644 index 0000000000..a2d6789aa7 --- /dev/null +++ b/ets2panda/lsp/include/class_hierarchy_item.h @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_LSP_CLASS_HIERARCHY_ITEM_H +#define ES2PANDA_LSP_CLASS_HIERARCHY_ITEM_H + +#include + +namespace ark::es2panda::lsp { +enum class SetterStyle { NONE = 0, SETTER, GETTER }; + +enum class AccessModifierStyle { PUBLIC = 0, PROTECTED, PRIVATE }; + +enum class ClassDefinitionStyle { FIELD = 0, METHOD }; + +class ClassHierarchyItem { +public: + ClassHierarchyItem(AccessModifierStyle access, std::string detail) + : accessModifier_(access), detail_(std::move(detail)) + { + } + + virtual ~ClassHierarchyItem() = default; + + ClassHierarchyItem(const ClassHierarchyItem &other) = default; + ClassHierarchyItem(ClassHierarchyItem &&other) = default; + ClassHierarchyItem &operator=(const ClassHierarchyItem &other) = default; + ClassHierarchyItem &operator=(ClassHierarchyItem &&other) = default; + + virtual ClassDefinitionStyle GetClassDefinitionStyle() const = 0; + + AccessModifierStyle GetAccessModifierStyle() const + { + return accessModifier_; + } + + const std::string &GetDetail() const + { + return detail_; + } + +private: + AccessModifierStyle accessModifier_; + std::string detail_; +}; + +class ClassPropertyItem : public ClassHierarchyItem { +public: + ClassPropertyItem(AccessModifierStyle access, std::string detail) : ClassHierarchyItem(access, std::move(detail)) {} + + ~ClassPropertyItem() override = default; + + ClassPropertyItem(const ClassPropertyItem &other) = default; + ClassPropertyItem(ClassPropertyItem &&other) = default; + ClassPropertyItem &operator=(const ClassPropertyItem &other) = default; + ClassPropertyItem &operator=(ClassPropertyItem &&other) = default; + + ClassDefinitionStyle GetClassDefinitionStyle() const override + { + return ClassDefinitionStyle::FIELD; + } + + void SetVariableName(const std::string &variableName) + { + if (variableName.empty()) { + return; + } + variableName_ = variableName; + } + + const std::string &GetVariableName() const + { + return variableName_; + } + +private: + std::string variableName_; +}; + +class ClassMethodItem : public ClassHierarchyItem { +public: + ClassMethodItem(AccessModifierStyle access, std::string detail, SetterStyle setter) + : ClassHierarchyItem(access, std::move(detail)), setter_(setter) + { + } + + ~ClassMethodItem() override = default; + + ClassMethodItem(const ClassMethodItem &other) = default; + ClassMethodItem(ClassMethodItem &&other) = default; + ClassMethodItem &operator=(const ClassMethodItem &other) = default; + ClassMethodItem &operator=(ClassMethodItem &&other) = default; + + ClassDefinitionStyle GetClassDefinitionStyle() const override + { + return ClassDefinitionStyle::METHOD; + } + + void SetFunctionName(const std::string &functionName) + { + if (functionName.empty()) { + return; + } + funcName_ = functionName; + } + + const std::string &GetFunctionName() const + { + return funcName_; + } + + SetterStyle GetSetterStyle() const + { + return setter_; + } + +private: + std::string funcName_; + SetterStyle setter_; +}; +} // namespace ark::es2panda::lsp + +#endif diff --git a/ets2panda/lsp/include/internal_api.h b/ets2panda/lsp/include/internal_api.h index 9d1f8ff9b6..428dbbf806 100644 --- a/ets2panda/lsp/include/internal_api.h +++ b/ets2panda/lsp/include/internal_api.h @@ -93,7 +93,7 @@ std::vector GetCodeFixesAtPositionImpl(es2panda_Context *cont CodeFixOptions &codeFixOptions); CombinedCodeActionsInfo GetCombinedCodeFixImpl(es2panda_Context *context, const std::string &fixId, CodeFixOptions &codeFixOptions); - +ir::Identifier *GetIdentFromNewClassExprPart(const ir::Expression *value); } // namespace ark::es2panda::lsp #endif \ No newline at end of file diff --git a/ets2panda/lsp/src/class_hierarchy_info.cpp b/ets2panda/lsp/src/class_hierarchy_info.cpp index 6534cd30d9..94aa7c9c7a 100644 --- a/ets2panda/lsp/src/class_hierarchy_info.cpp +++ b/ets2panda/lsp/src/class_hierarchy_info.cpp @@ -17,6 +17,7 @@ #include "internal_api.h" #include "public/public.h" #include "compiler/lowering/util.h" +#include "quick_info.h" namespace ark::es2panda::lsp { std::string GetNameFromIdentifierNode(const ir::AstNode *node) @@ -24,7 +25,7 @@ std::string GetNameFromIdentifierNode(const ir::AstNode *node) if (node == nullptr || !node->IsIdentifier()) { return ""; } - return std::string(node->AsIdentifier()->Name()); + return node->AsIdentifier()->ToString(); } // Currently only considering enum scenarios. @@ -77,9 +78,17 @@ std::string SpliceFunctionDetailStr(const std::string &functionName, const std:: return result; } +std::string SplicePropertyDetailStr(const std::string &name, const std::string &type) +{ + if (name.empty() || type.empty()) { + return ""; + } + return name + ": " + type; +} + std::string GetFunctionNameFromScriptFunction(const ir::ScriptFunction *function) { - if (function == nullptr) { + if (function == nullptr || function->Id() == nullptr) { return ""; } return function->Id()->ToString(); @@ -92,21 +101,23 @@ std::vector GetParamListFromScriptFunction(const ir::ScriptF return params; } auto nodeParams = function->Params(); - for (const auto &nodeParam : nodeParams) { + for (const auto *it : nodeParams) { + if (it == nullptr || !it->IsETSParameterExpression()) { + continue; + } std::string paramName; std::string paramKind; - if (!nodeParam->IsETSParameterExpression()) { + auto nodeParam = it->AsETSParameterExpression(); + if (nodeParam->IsRestParameter()) { + paramName = nodeParam->RestParameter()->ToString(); + } else { + paramName = GetNameFromIdentifierNode(nodeParam->Ident()); + } + if (paramName == INVALID_EXPRESSION || nodeParam->TypeAnnotation() == nullptr) { continue; } - paramName = std::string(nodeParam->AsETSParameterExpression()->Name()); - nodeParam->AsETSParameterExpression()->FindChild([¶mKind](ir::AstNode *childNode) { - if (childNode->IsETSTypeReference()) { - paramKind = childNode->AsETSTypeReference()->Part()->Name()->ToString(); - } - return false; - }); - FunctionParamStyle tmp(paramName, paramKind); - params.emplace_back(std::move(tmp)); + paramKind = GetNameForTypeNode(nodeParam->TypeAnnotation()); + params.emplace_back(FunctionParamStyle(std::move(paramName), std::move(paramKind))); } return params; } @@ -116,20 +127,17 @@ std::string GetReturnTypeFromScriptFunction(const ir::ScriptFunction *function) if (function == nullptr) { return ""; } - auto nodeReturn = function->ReturnTypeAnnotation(); - if (nodeReturn == nullptr || !nodeReturn->IsETSTypeReference()) { + auto returnNode = function->ReturnTypeAnnotation(); + if (returnNode == nullptr) { return ""; } - auto ident = nodeReturn->AsETSTypeReference()->Part()->Name(); - if (ident == nullptr || !ident->IsIdentifier()) { - return ""; - } - return std::string(ident->AsIdentifier()->Name()); + auto returnType = GetNameForTypeNode(returnNode); + return returnType; } SetterStyle CreateSetterStyle(ir::MethodDefinitionKind kind) { - SetterStyle setter = SetterStyle::METHOD; + SetterStyle setter = SetterStyle::NONE; switch (kind) { case ir::MethodDefinitionKind::GET: case ir::MethodDefinitionKind::EXTENSION_GET: @@ -151,17 +159,31 @@ std::shared_ptr CreateClassMethodItem(const ir::MethodDefinitio if (methodDefinition == nullptr || funcName.empty() || detail.empty()) { return nullptr; } - auto setter = CreateSetterStyle(methodDefinition->Kind()); AccessModifierStyle access = AccessModifierStyle::PUBLIC; if (methodDefinition->IsProtected()) { access = AccessModifierStyle::PROTECTED; } - auto item = std::make_shared(std::move(detail), setter, access); + auto item = std::make_shared(access, std::move(detail), setter); item->SetFunctionName(funcName); return item; } +std::shared_ptr CreateClassPropertyItem(const ir::ClassProperty *property, + const std::string &propertyName, std::string detail) +{ + if (property == nullptr || propertyName.empty() || detail.empty()) { + return nullptr; + } + AccessModifierStyle access = AccessModifierStyle::PUBLIC; + if (property->IsProtected()) { + access = AccessModifierStyle::PROTECTED; + } + auto item = std::make_shared(access, std::move(detail)); + item->SetVariableName(propertyName); + return item; +} + std::shared_ptr ParseFunctionStyleWithCreateItem(const ir::MethodDefinition *methodDefinition, bool isCurrentToken) { @@ -184,6 +206,48 @@ std::shared_ptr ParseFunctionStyleWithCreateItem(const ir::Meth return CreateClassMethodItem(methodDefinition, functionName, functionDetail); } +ir::Identifier *GetIdentFromNewClassExprPart(const ir::Expression *value) +{ + if (value == nullptr || !value->IsETSNewClassInstanceExpression()) { + return nullptr; + } + auto typeRef = value->AsETSNewClassInstanceExpression()->GetTypeRef(); + if (typeRef == nullptr || !typeRef->IsETSTypeReference()) { + return nullptr; + } + auto part = typeRef->AsETSTypeReference()->Part(); + if (part == nullptr) { + return nullptr; + } + return part->GetIdent(); +} + +std::shared_ptr ParsePropertyStyleWithCreateItem(const ir::ClassProperty *property, + bool isCurrentToken) +{ + if (property == nullptr) { + return nullptr; + } + if ((isCurrentToken && property->IsStatic()) || + (!isCurrentToken && (property->IsPrivate() || property->IsStatic()))) { + return nullptr; + } + std::string propertyName = GetNameFromIdentifierNode(property->Key()); + std::string type; + if (property->TypeAnnotation() == nullptr) { + auto value = property->Value(); + auto ident = GetIdentFromNewClassExprPart(value); + type = GetNameFromIdentifierNode(ident); + } else { + type = GetNameForTypeNode(property->TypeAnnotation()); + } + if (propertyName == INVALID_EXPRESSION || type == INVALID_EXPRESSION) { + return nullptr; + } + auto detail = SplicePropertyDetailStr(propertyName, type); + return CreateClassPropertyItem(property, propertyName, detail); +} + ClassHierarchyInfo CreateClassHierarchyInfoFromBody(const ir::ClassDefinition *classDefinition, const std::string &className, bool isCurrentToken) { @@ -194,23 +258,28 @@ ClassHierarchyInfo CreateClassHierarchyInfoFromBody(const ir::ClassDefinition *c result.SetClassName(className); auto bodyNodes = classDefinition->Body(); for (const auto &node : bodyNodes) { - if (node == nullptr || !node->IsMethodDefinition()) { - continue; - } - auto methodDefinition = node->AsMethodDefinition(); - if (methodDefinition == nullptr) { + if (node == nullptr) { continue; } - auto item = ParseFunctionStyleWithCreateItem(methodDefinition, isCurrentToken); - if (item != nullptr) { - result.AddClassMethodItem(item); - } - auto overLoads = methodDefinition->Overloads(); - for (const auto *overLoadMethodDefinition : overLoads) { - auto overLoadItem = ParseFunctionStyleWithCreateItem(overLoadMethodDefinition, isCurrentToken); - if (overLoadItem != nullptr) { - result.AddClassMethodItem(overLoadItem); + if (node->IsMethodDefinition()) { + auto methodDefinition = node->AsMethodDefinition(); + if (methodDefinition == nullptr) { + continue; + } + auto item = ParseFunctionStyleWithCreateItem(methodDefinition, isCurrentToken); + result.AddItemToMethodList(item); + auto overLoads = methodDefinition->Overloads(); + for (const auto *overLoadMethodDefinition : overLoads) { + auto overLoadItem = ParseFunctionStyleWithCreateItem(overLoadMethodDefinition, isCurrentToken); + result.AddItemToMethodList(overLoadItem); + } + } else if (node->IsClassProperty()) { + auto property = node->AsClassProperty(); + if (property == nullptr) { + continue; } + auto item = ParsePropertyStyleWithCreateItem(property, isCurrentToken); + result.AddItemToPropertyList(item); } } return result; @@ -230,13 +299,29 @@ ir::AstNode *GetSuperClassNode(const ir::ClassDefinition *classDefinition) void ComputeClassHierarchyInfo(const ClassHierarchyInfo &deriveInfo, ClassHierarchyInfo &superInfo) { - auto deriveMethods = deriveInfo.GetMethodList(); + auto deriveMethods = deriveInfo.GetMethodItemList(); for (const auto &method : deriveMethods) { - superInfo.DeleteClassMethodItem(method.second); + superInfo.DeleteTargetItemInMethodList(method.second); + } + auto deriveProperties = deriveInfo.GetPropertyItemList(); + for (const auto &property : deriveProperties) { + superInfo.DeleteTargetItemInPropertyList(property.second); + } +} + +void FillBaseClassHierarchyInfo(const ClassHierarchyInfo &extraInfo, ClassHierarchyInfo &baseInfo) +{ + auto extraMethods = extraInfo.GetMethodItemList(); + for (const auto &method : extraMethods) { + baseInfo.AddItemToMethodList(method.second); + } + auto extraProperties = extraInfo.GetPropertyItemList(); + for (const auto &property : extraProperties) { + baseInfo.AddItemToPropertyList(property.second); } } -void ProcessClassHierarchy(const ir::AstNode *token, const ClassHierarchyInfo &baseInfo, ClassHierarchy &result) +void ProcessClassHierarchy(const ir::AstNode *token, ClassHierarchyInfo &baseInfo, ClassHierarchy &result) { if (token == nullptr || !token->IsIdentifier()) { return; @@ -250,8 +335,10 @@ void ProcessClassHierarchy(const ir::AstNode *token, const ClassHierarchyInfo &b if (!className.empty()) { // Calculate the difference between the obtained parent class info and the current clicked node class info. ComputeClassHierarchyInfo(baseInfo, info); - if (info.GetClassName() == className && !info.GetMethodList().empty()) { + if (info.GetClassName() == className && + (!info.GetMethodItemList().empty() || !info.GetPropertyItemList().empty())) { result.emplace_back(info); + FillBaseClassHierarchyInfo(info, baseInfo); } } auto superClass = GetSuperClassNode(classDefinition); diff --git a/ets2panda/lsp/src/completions.cpp b/ets2panda/lsp/src/completions.cpp index cc8bda9324..8b1961ff2f 100644 --- a/ets2panda/lsp/src/completions.cpp +++ b/ets2panda/lsp/src/completions.cpp @@ -303,17 +303,9 @@ ir::AstNode *GetClassDefinitionFromClassProperty(ir::AstNode *node) return nullptr; } auto value = node->AsClassProperty()->Value(); - if (value != nullptr && value->IsETSNewClassInstanceExpression() && - value->AsETSNewClassInstanceExpression()->GetTypeRef() != nullptr && - value->AsETSNewClassInstanceExpression()->GetTypeRef()->IsETSTypeReference()) { - auto typeReferencePart = value->AsETSNewClassInstanceExpression()->GetTypeRef()->AsETSTypeReference()->Part(); - if (typeReferencePart == nullptr) { - return nullptr; - } - auto id = typeReferencePart->Name(); - if (id != nullptr && id->IsIdentifier()) { - return compiler::DeclarationFromIdentifier(id->AsIdentifier()); - } + auto ident = GetIdentFromNewClassExprPart(value); + if (ident != nullptr) { + return compiler::DeclarationFromIdentifier(ident); } auto type = node->AsClassProperty()->TypeAnnotation(); if (type != nullptr && type->IsETSTypeReference()) { diff --git a/ets2panda/test/unit/lsp/class_hierarchy_info_test.cpp b/ets2panda/test/unit/lsp/class_hierarchy_info_test.cpp index 6d2466a99b..231e38ae56 100644 --- a/ets2panda/test/unit/lsp/class_hierarchy_info_test.cpp +++ b/ets2panda/test/unit/lsp/class_hierarchy_info_test.cpp @@ -22,9 +22,9 @@ using ark::es2panda::lsp::Initializer; namespace { -class LspScriptElementKindTests : public LSPAPITests {}; +class LspGetClassHierarchyInfoTests : public LSPAPITests {}; -TEST_F(LSPAPITests, GetClassHierarchyInfo_1) +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_1) { LSPAPI const *lspApi = GetImpl(); ASSERT_TRUE(lspApi != nullptr); @@ -56,21 +56,21 @@ private privateMethod(): void { ASSERT_EQ(classHierarchy.size(), 1); ASSERT_EQ(classHierarchy[0].GetClassName(), "Parent"); - auto methods = classHierarchy[0].GetMethodList(); - auto it = methods.find("publicMethod()"); + auto methods = classHierarchy[0].GetMethodItemList(); + auto it = methods.find("publicMethod(): void"); ASSERT_TRUE(it != methods.end()); ASSERT_TRUE(it->second != nullptr); - ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::METHOD); + ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::NONE); ASSERT_EQ(it->second->GetAccessModifierStyle(), ark::es2panda::lsp::AccessModifierStyle::PUBLIC); it = methods.find("action(fileName: string, position: number): number"); ASSERT_TRUE(it != methods.end()); ASSERT_TRUE(it->second != nullptr); - ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::METHOD); + ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::NONE); ASSERT_EQ(it->second->GetAccessModifierStyle(), ark::es2panda::lsp::AccessModifierStyle::PROTECTED); initializer.DestroyContext(context); } -TEST_F(LSPAPITests, GetClassHierarchyInfo_2) +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_2) { LSPAPI const *lspApi = GetImpl(); ASSERT_TRUE(lspApi != nullptr); @@ -110,16 +110,16 @@ class Magpie extends Bird { ASSERT_EQ(classHierarchy.size(), 1); ASSERT_EQ(classHierarchy[0].GetClassName(), "Animal"); - auto methods = classHierarchy[0].GetMethodList(); - auto it = methods.find("sleep()"); + auto methods = classHierarchy[0].GetMethodItemList(); + auto it = methods.find("sleep(): void"); ASSERT_TRUE(it != methods.end()); ASSERT_TRUE(it->second != nullptr); - ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::METHOD); + ASSERT_EQ(it->second->GetSetterStyle(), ark::es2panda::lsp::SetterStyle::NONE); ASSERT_EQ(it->second->GetAccessModifierStyle(), ark::es2panda::lsp::AccessModifierStyle::PROTECTED); initializer.DestroyContext(context); } -TEST_F(LSPAPITests, GetClassHierarchyInfo_3) +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_3) { LSPAPI const *lspApi = GetImpl(); ASSERT_TRUE(lspApi != nullptr); @@ -143,7 +143,7 @@ TEST_F(LSPAPITests, GetClassHierarchyInfo_3) initializer.DestroyContext(context); } -TEST_F(LSPAPITests, GetClassHierarchyInfo_4) +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_4) { LSPAPI const *lspApi = GetImpl(); ASSERT_TRUE(lspApi != nullptr); @@ -177,7 +177,7 @@ TEST_F(LSPAPITests, GetClassHierarchyInfo_4) ASSERT_EQ(classHierarchy.size(), 1); ASSERT_EQ(classHierarchy[0].GetClassName(), "ii"); - auto methods = classHierarchy[0].GetMethodList(); + auto methods = classHierarchy[0].GetMethodItemList(); auto it = methods.find("Body(): string"); ASSERT_TRUE(it != methods.end()); ASSERT_TRUE(it->second != nullptr); @@ -190,4 +190,177 @@ TEST_F(LSPAPITests, GetClassHierarchyInfo_4) ASSERT_EQ(it->second->GetAccessModifierStyle(), ark::es2panda::lsp::AccessModifierStyle::PUBLIC); initializer.DestroyContext(context); } + +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_5) +{ + LSPAPI const *lspApi = GetImpl(); + ASSERT_TRUE(lspApi != nullptr); + const std::string text = R"(class C { + func1(): void {} + func2(): string { + return "1"; + } + func3(): number { + return 1; + } + func4(): boolean { + return false; + } + func5(): Array { + return [1, 2]; + } +} + +class B extends C { + method1(): void {} + method2(parameter1: string, callBack: () => void): void {} +} + +class A extends B {/*1*/};)"; + + auto pos = text.find("/*1*/"); + ASSERT_NE(pos, std::string::npos); + Initializer initializer = Initializer(); + auto context = initializer.CreateContext("class_hierarchy_info_5.ets", ES2PANDA_STATE_CHECKED, text.c_str()); + auto classHierarchy = lspApi->getClassHierarchyInfo(context, pos); + size_t expectInfoListSize = 2; + ASSERT_EQ(classHierarchy.size(), expectInfoListSize); + ASSERT_EQ(classHierarchy[0].GetClassName(), "B"); + ASSERT_EQ(classHierarchy[1].GetClassName(), "C"); + auto classBItems = classHierarchy[0].GetMethodItemList(); + ASSERT_TRUE(classBItems.find("method1(): void") != classBItems.end()); + ASSERT_TRUE(classBItems.find("method2(parameter1: string, callBack: (() => void)): void") != classBItems.end()); + auto classCItems = classHierarchy[1].GetMethodItemList(); + ASSERT_TRUE(classCItems.find("func1(): void") != classCItems.end()); + ASSERT_TRUE(classCItems.find("func2(): string") != classCItems.end()); + ASSERT_TRUE(classCItems.find("func3(): number") != classCItems.end()); + ASSERT_TRUE(classCItems.find("func4(): boolean") != classCItems.end()); + ASSERT_TRUE(classCItems.find("func5(): Array") != classCItems.end()); + initializer.DestroyContext(context); +} + +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_6) +{ + LSPAPI const *lspApi = GetImpl(); + ASSERT_TRUE(lspApi != nullptr); + const std::string text = R"(type parameter = number; + +class B { + public method1(parameter1: number): parameter { + return 1; + } + method2(parameter1: number): number { + return parameter1 as number; + } + async method3(parameter1: string): Promise { + return '1'; + } +} + +class A extends B {/*1*/};)"; + + auto pos = text.find("/*1*/"); + ASSERT_NE(pos, std::string::npos); + Initializer initializer = Initializer(); + auto context = initializer.CreateContext("class_hierarchy_info_6.ets", ES2PANDA_STATE_CHECKED, text.c_str()); + auto classHierarchy = lspApi->getClassHierarchyInfo(context, pos); + ASSERT_FALSE(classHierarchy.empty()); + ASSERT_EQ(classHierarchy[0].GetClassName(), "B"); + auto classBItems = classHierarchy[0].GetMethodItemList(); + ASSERT_TRUE(classBItems.find("method1(parameter1: number): parameter") != classBItems.end()); + ASSERT_TRUE(classBItems.find("method2(parameter1: number): number") != classBItems.end()); + ASSERT_TRUE(classBItems.find("method3(parameter1: string): Promise") != classBItems.end()); + initializer.DestroyContext(context); +} + +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_7) +{ + LSPAPI const *lspApi = GetImpl(); + ASSERT_TRUE(lspApi != nullptr); + const std::string text = R"(class C { + func1(): void {} + + func2(): boolean { + return false; + } + + func3(): Array { + return [1, 2]; + } +}; + +class B extends C { + method1() {} + func2(): boolean { + return false; + } +} + +class A extends B { + method1() {} + func3(): Array { + return [1, 2]; + }/*1*/ +})"; + + auto pos = text.find("/*1*/"); + ASSERT_NE(pos, std::string::npos); + Initializer initializer = Initializer(); + auto context = initializer.CreateContext("class_hierarchy_info_7.ets", ES2PANDA_STATE_CHECKED, text.c_str()); + auto classHierarchy = lspApi->getClassHierarchyInfo(context, pos); + size_t expectInfoListSize = 2; + ASSERT_EQ(classHierarchy.size(), expectInfoListSize); + ASSERT_EQ(classHierarchy[0].GetClassName(), "B"); + ASSERT_EQ(classHierarchy[1].GetClassName(), "C"); + auto classBItems = classHierarchy[0].GetMethodItemList(); + ASSERT_EQ(classBItems.size(), 1); + ASSERT_TRUE(classBItems.find("func2(): boolean") != classBItems.end()); + auto classCItems = classHierarchy[1].GetMethodItemList(); + ASSERT_EQ(classCItems.size(), 1); + ASSERT_TRUE(classCItems.find("func1(): void") != classCItems.end()); + initializer.DestroyContext(context); +} + +TEST_F(LspGetClassHierarchyInfoTests, GetClassHierarchyInfo_8) +{ + LSPAPI const *lspApi = GetImpl(); + ASSERT_TRUE(lspApi != nullptr); + const std::string text = R"(class Parent { + public property1: number = 1; + protected property2: string = '1'; + private property3: boolean = true; + readonly property4: number = 1; + static property5: number = 1; +} + +class Son extends Parent { + property1: number = 2; + ChildExtraProperty1: number = 2; + ChildExtraProperty2: number = 2; +} + +class GrandSon extends Son {/*1*/ + public property2: string = '2'; + ChildExtraProperty1: number = 3; +})"; + + auto pos = text.find("/*1*/"); + ASSERT_NE(pos, std::string::npos); + Initializer initializer = Initializer(); + auto context = initializer.CreateContext("class_hierarchy_info_8.ets", ES2PANDA_STATE_CHECKED, text.c_str()); + auto classHierarchy = lspApi->getClassHierarchyInfo(context, pos); + size_t expectInfoListSize = 2; + ASSERT_EQ(classHierarchy.size(), expectInfoListSize); + ASSERT_EQ(classHierarchy[0].GetClassName(), "Son"); + ASSERT_EQ(classHierarchy[1].GetClassName(), "Parent"); + auto sonItems = classHierarchy[0].GetPropertyItemList(); + size_t expectPropertyListSize = 2; + ASSERT_EQ(sonItems.size(), expectPropertyListSize); + ASSERT_TRUE(sonItems.find("property1: number") != sonItems.end()); + ASSERT_TRUE(sonItems.find("ChildExtraProperty2: number") != sonItems.end()); + auto parentItems = classHierarchy[1].GetPropertyItemList(); + ASSERT_EQ(parentItems.size(), 1); + ASSERT_TRUE(parentItems.find("property4: number") != parentItems.end()); + initializer.DestroyContext(context); +} } // namespace -- Gitee From 2be8ac88545c14ea3f13e5ec2bf290a9ee07d0bd Mon Sep 17 00:00:00 2001 From: xudan16 Date: Wed, 11 Jun 2025 16:19:24 +0800 Subject: [PATCH 082/747] fix bug of custom-builder rule Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICED88 Signed-off-by: xudan16 --- .../src/checker/migration/CustomBuilderCheck.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts index b8dcb06db7..8aa70c4807 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/CustomBuilderCheck.ts @@ -149,15 +149,18 @@ export class CustomBuilderCheck implements BaseChecker { } private isPassToCustomBuilder(stmt: Stmt, locals: Set): Local | undefined { + let res: Local | undefined = undefined; if (stmt instanceof ArkAssignStmt) { - if (!this.isCustomBuilderTy(stmt.getLeftOp().getType())) { - return undefined; - } - const rightOp = stmt.getRightOp(); - if (rightOp instanceof Local && locals.has(rightOp)) { - return rightOp; + if (this.isCustomBuilderTy(stmt.getLeftOp().getType())) { + const rightOp = stmt.getRightOp(); + if (rightOp instanceof Local && locals.has(rightOp)) { + res = rightOp; + } } } + if (res !== undefined) { + return res; + } const invokeExpr = stmt.getInvokeExpr(); if (invokeExpr) { const paramTys = invokeExpr.getMethodSignature().getMethodSubSignature().getParameterTypes(); -- Gitee From 3b2d793f53ff705c13fda8b81c3b1551c7dafaec Mon Sep 17 00:00:00 2001 From: Okolnov Evgeniy Date: Mon, 2 Jun 2025 22:46:08 +0300 Subject: [PATCH 083/747] Fix missing report on invalid properties Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICBZBZ Test scenarios: new tests added to the linter Signed-off-by: Okolnov Evgeniy --- ets2panda/linter/src/lib/LinterRunner.ts | 5 +- ets2panda/linter/src/lib/TypeScriptLinter.ts | 3 - ets2panda/linter/src/lib/utils/TsUtils.ts | 8 +- .../test/main/literals_as_prop_names.ets | 20 +- .../literals_as_prop_names.ets.arkts2.json | 158 ++++++- .../literals_as_prop_names.ets.autofix.json | 248 ++++++++++- .../test/main/literals_as_prop_names.ets.json | 30 ++ .../literals_as_prop_names.ets.migrate.ets | 20 +- .../literals_as_prop_names.ets.migrate.json | 90 ++++ .../test/main/object_literals_properties.ets | 8 +- ...object_literals_properties.ets.arkts2.json | 188 ++++++++- ...bject_literals_properties.ets.autofix.json | 397 +++++++++++++++++- .../main/object_literals_properties.ets.json | 10 - ...object_literals_properties.ets.migrate.ets | 43 +- ...bject_literals_properties.ets.migrate.json | 144 +++---- 15 files changed, 1214 insertions(+), 158 deletions(-) diff --git a/ets2panda/linter/src/lib/LinterRunner.ts b/ets2panda/linter/src/lib/LinterRunner.ts index 83d5c4ba59..9cf5cd2f09 100644 --- a/ets2panda/linter/src/lib/LinterRunner.ts +++ b/ets2panda/linter/src/lib/LinterRunner.ts @@ -43,7 +43,10 @@ import { ProjectStatistics } from './statistics/ProjectStatistics'; import type { BaseTypeScriptLinter } from './BaseTypeScriptLinter'; function prepareInputFilesList(cmdOptions: CommandLineOptions): string[] { - let inputFiles = cmdOptions.inputFiles; + let inputFiles = cmdOptions.inputFiles.map((x) => { + return path.normalize(x); + }); + if (!cmdOptions.parsedConfigFile) { return inputFiles; } diff --git a/ets2panda/linter/src/lib/TypeScriptLinter.ts b/ets2panda/linter/src/lib/TypeScriptLinter.ts index ca016e788d..005e998117 100644 --- a/ets2panda/linter/src/lib/TypeScriptLinter.ts +++ b/ets2panda/linter/src/lib/TypeScriptLinter.ts @@ -617,9 +617,6 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } for (const prop of invalidProps) { - if (ts.isShorthandPropertyAssignment(prop) && !TsUtils.isAnyType(this.tsTypeChecker.getTypeAtLocation(prop))) { - continue; - } const autofix = ts.isShorthandPropertyAssignment(prop) ? this.autofixer?.fixShorthandPropertyAssignment(prop) : objLiteralAutofix; diff --git a/ets2panda/linter/src/lib/utils/TsUtils.ts b/ets2panda/linter/src/lib/utils/TsUtils.ts index 5ed15ab452..3a0f7b32eb 100644 --- a/ets2panda/linter/src/lib/utils/TsUtils.ts +++ b/ets2panda/linter/src/lib/utils/TsUtils.ts @@ -2174,8 +2174,10 @@ export class TsUtils { return true; } } - // We allow computed property names if expression is string literal or string Enum member - return ts.isStringLiteralLike(expr) || this.isEnumStringLiteral(computedProperty.expression); + // In ArkTS 1.0, the computed property names are allowed if expression is string literal or string Enum member. + return ( + !this.options.arkts2 && (ts.isStringLiteralLike(expr) || this.isEnumStringLiteral(computedProperty.expression)) + ); } skipPropertyInferredTypeCheck( @@ -3733,7 +3735,7 @@ export class TsUtils { if (sourceFile.fileName.endsWith(EXTNAME_D_ETS)) { return true; } - return !!this.options.inputFiles?.includes(sourceFile.fileName); + return !!this.options.inputFiles?.includes(path.normalize(sourceFile.fileName)); } static removeOrReplaceQuotes(str: string, isReplace: boolean): string { diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets b/ets2panda/linter/test/main/literals_as_prop_names.ets index c994718102..114339394c 100755 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets @@ -128,11 +128,23 @@ class A{ let a:A = { "age": 30} -class B{ +class B { public 'age': number = 1 // error in arkts2 } let obj11: Record = { -['value']: 1, // 误扫 -'value2': 1 // ok -} \ No newline at end of file + ['value']: 1, // Error in arkts 2.0 + 'value2': 1 // ok +} + +class CompPropClass { + ['CompProp'] = 1; // Error in arkts 2.0 + [2] = 'CompProp2'; // Error in arkts 2.0 + [LiteralAsPropertyNameEnum.One] = 3; // Error in arkts 2.0 +} + +let compPropObj = { + ['CompProp']: 1, // Error in arkts 2.0 + [2]: 'CompProp2', // Error in arkts 2.0 + [LiteralAsPropertyNameEnum.One]: 3 // Error in arkts 2.0 +}; \ No newline at end of file diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json index 79102a9b70..f6df27e1d6 100755 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.arkts2.json @@ -494,11 +494,31 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 135, + "column": 37, + "endLine": 135, + "endColumn": 38, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, { "line": 136, - "column": 12, + "column": 3, "endLine": 136, - "endColumn": 13, + "endColumn": 12, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 136, + "column": 14, + "endLine": 136, + "endColumn": 15, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", @@ -506,9 +526,139 @@ }, { "line": 137, - "column": 11, + "column": 13, "endLine": 137, - "endColumn": 12, + "endColumn": 14, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 141, + "column": 3, + "endLine": 141, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 141, + "column": 18, + "endLine": 141, + "endColumn": 19, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 142, + "column": 3, + "endLine": 142, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 142, + "column": 4, + "endLine": 142, + "endColumn": 5, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 143, + "column": 3, + "endLine": 143, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 143, + "column": 37, + "endLine": 143, + "endColumn": 38, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 146, + "column": 19, + "endLine": 146, + "endColumn": 20, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 147, + "column": 3, + "endLine": 147, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 147, + "column": 17, + "endLine": 147, + "endColumn": 18, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 3, + "endLine": 148, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 4, + "endLine": 148, + "endColumn": 5, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 3, + "endLine": 149, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 36, + "endLine": 149, + "endColumn": 37, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json index 82e0ac288a..d66cfd8c7c 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.autofix.json @@ -1035,8 +1035,8 @@ "autofix": [ { "replacementText": "age", - "start": 2465, - "end": 2470, + "start": 2466, + "end": 2471, "line": 132, "column": 10, "endLine": 132, @@ -1055,8 +1055,8 @@ "problem": "NumericSemantics", "autofix": [ { - "start": 2481, - "end": 2482, + "start": 2482, + "end": 2483, "replacementText": "1.0", "line": 132, "column": 26, @@ -1068,21 +1068,41 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 135, + "column": 37, + "endLine": 135, + "endColumn": 38, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, { "line": 136, - "column": 12, + "column": 3, "endLine": 136, - "endColumn": 13, + "endColumn": 12, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 136, + "column": 14, + "endLine": 136, + "endColumn": 15, "problem": "NumericSemantics", "autofix": [ { - "start": 2554, - "end": 2555, + "start": 2557, + "end": 2558, "replacementText": "1.0", "line": 136, - "column": 12, + "column": 14, "endLine": 136, - "endColumn": 13 + "endColumn": 15 } ], "suggest": "", @@ -1091,19 +1111,215 @@ }, { "line": 137, - "column": 11, + "column": 13, "endLine": 137, - "endColumn": 12, + "endColumn": 14, "problem": "NumericSemantics", "autofix": [ { - "start": 2573, - "end": 2574, + "start": 2594, + "end": 2595, "replacementText": "1.0", "line": 137, - "column": 11, + "column": 13, "endLine": 137, - "endColumn": 12 + "endColumn": 14 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 141, + "column": 3, + "endLine": 141, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 141, + "column": 18, + "endLine": 141, + "endColumn": 19, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2644, + "end": 2645, + "replacementText": "1.0", + "line": 141, + "column": 18, + "endLine": 141, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 142, + "column": 3, + "endLine": 142, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 142, + "column": 4, + "endLine": 142, + "endColumn": 5, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2672, + "end": 2673, + "replacementText": "2.0", + "line": 142, + "column": 4, + "endLine": 142, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 143, + "column": 3, + "endLine": 143, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 143, + "column": 37, + "endLine": 143, + "endColumn": 38, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2748, + "end": 2749, + "replacementText": "3.0", + "line": 143, + "column": 37, + "endLine": 143, + "endColumn": 38 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 146, + "column": 19, + "endLine": 146, + "endColumn": 20, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 147, + "column": 3, + "endLine": 147, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 147, + "column": 17, + "endLine": 147, + "endColumn": 18, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2812, + "end": 2813, + "replacementText": "1.0", + "line": 147, + "column": 17, + "endLine": 147, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 3, + "endLine": 148, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 4, + "endLine": 148, + "endColumn": 5, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2840, + "end": 2841, + "replacementText": "2.0", + "line": 148, + "column": 4, + "endLine": 148, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 3, + "endLine": 149, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 36, + "endLine": 149, + "endColumn": 37, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 2914, + "end": 2915, + "replacementText": "3.0", + "line": 149, + "column": 36, + "endLine": 149, + "endColumn": 37 } ], "suggest": "", diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.json index 7e721f74f1..dfce9f6d57 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.json @@ -144,6 +144,36 @@ "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", "severity": "ERROR" }, + { + "line": 142, + "column": 3, + "endLine": 142, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 146, + "column": 19, + "endLine": 146, + "endColumn": 20, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 3, + "endLine": 148, + "endColumn": 6, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, { "line": 42, "column": 11, diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets index 54ed22aed8..5211df075e 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.ets @@ -134,11 +134,23 @@ class A{ let a:A = { age: 30.0} -class B{ +class B { public age: number = 1.0 // error in arkts2 } let obj11: Record = { -['value']: 1.0, // 误扫 -'value2': 1.0 // ok -} \ No newline at end of file + ['value']: 1.0, // Error in arkts 2.0 + 'value2': 1.0 // ok +} + +class CompPropClass { + ['CompProp'] = 1.0; // Error in arkts 2.0 + [2.0] = 'CompProp2'; // Error in arkts 2.0 + [LiteralAsPropertyNameEnum.One] = 3.0; // Error in arkts 2.0 +} + +let compPropObj = { + ['CompProp']: 1.0, // Error in arkts 2.0 + [2.0]: 'CompProp2', // Error in arkts 2.0 + [LiteralAsPropertyNameEnum.One]: 3.0 // Error in arkts 2.0 +}; \ No newline at end of file diff --git a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json index 97c0791cc5..adafc797dd 100644 --- a/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json +++ b/ets2panda/linter/test/main/literals_as_prop_names.ets.migrate.json @@ -104,6 +104,96 @@ "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", "severity": "ERROR" }, + { + "line": 141, + "column": 37, + "endLine": 141, + "endColumn": 38, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 142, + "column": 3, + "endLine": 142, + "endColumn": 12, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 147, + "column": 3, + "endLine": 147, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 148, + "column": 3, + "endLine": 148, + "endColumn": 8, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 149, + "column": 3, + "endLine": 149, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 152, + "column": 19, + "endLine": 152, + "endColumn": 20, + "problem": "ObjectLiteralNoContextType", + "suggest": "", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "severity": "ERROR" + }, + { + "line": 153, + "column": 3, + "endLine": 153, + "endColumn": 15, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 154, + "column": 3, + "endLine": 154, + "endColumn": 8, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, + { + "line": 155, + "column": 3, + "endLine": 155, + "endColumn": 34, + "problem": "ComputedPropertyName", + "suggest": "", + "rule": "Objects with property names that are not identifiers are not supported (arkts-identifiers-as-prop-names)", + "severity": "ERROR" + }, { "line": 28, "column": 11, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets b/ets2panda/linter/test/main/object_literals_properties.ets index d5265f7493..f603b4bcfe 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets +++ b/ets2panda/linter/test/main/object_literals_properties.ets @@ -244,15 +244,15 @@ let b3: Derived3 = { // Fixable m() { console.log(2); } }; -interface A { +interface I4 { map: Map; } let map:Map = new Map(); -let a:A = {map}; +let i4: I4 = {map}; -class C { +class C6 { map1: Map = new Map(); } let map1:Map = new Map(); -let c:C = {map1}; \ No newline at end of file +let c6: C6 = {map1}; \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json index ac48689e30..ed1d4e6f86 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.arkts2.json @@ -124,6 +124,36 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 34, + "column": 3, + "endLine": 34, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 3, + "endLine": 35, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 3, + "endLine": 36, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 39, "column": 14, @@ -164,6 +194,26 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 47, + "column": 3, + "endLine": 47, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 3, + "endLine": 48, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 50, "column": 3, @@ -334,6 +384,36 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 69, + "column": 3, + "endLine": 69, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 3, + "endLine": 70, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 3, + "endLine": 71, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 72, "column": 3, @@ -554,6 +634,36 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 110, + "column": 3, + "endLine": 110, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 111, + "column": 3, + "endLine": 111, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 112, + "column": 3, + "endLine": 112, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 113, "column": 3, @@ -584,6 +694,36 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 117, + "column": 3, + "endLine": 117, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 118, + "column": 3, + "endLine": 118, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 119, + "column": 3, + "endLine": 119, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 120, "column": 3, @@ -694,6 +834,36 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 134, + "column": 3, + "endLine": 134, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 135, + "column": 3, + "endLine": 135, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 136, + "column": 3, + "endLine": 136, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 137, "column": 3, @@ -1104,14 +1274,24 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 251, + "column": 15, + "endLine": 251, + "endColumn": 18, + "problem": "ObjectLiteralProperty", + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 258, - "column": 11, + "column": 15, "endLine": 258, - "endColumn": 12, - "problem": "ObjectLiteralNoContextType", + "endColumn": 19, + "problem": "ObjectLiteralProperty", "suggest": "", - "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, { diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json index 706c09bb34..43d944717d 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.autofix.json @@ -228,6 +228,69 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 34, + "column": 3, + "endLine": 34, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 922, + "end": 923, + "replacementText": "x: x", + "line": 34, + "column": 3, + "endLine": 34, + "endColumn": 4 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 3, + "endLine": 35, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 945, + "end": 946, + "replacementText": "y: y", + "line": 35, + "column": 3, + "endLine": 35, + "endColumn": 4 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 36, + "column": 3, + "endLine": 36, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 968, + "end": 969, + "replacementText": "z: z", + "line": 36, + "column": 3, + "endLine": 36, + "endColumn": 4 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 39, "column": 14, @@ -288,6 +351,48 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 47, + "column": 3, + "endLine": 47, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1112, + "end": 1113, + "replacementText": "x: x", + "line": 47, + "column": 3, + "endLine": 47, + "endColumn": 4 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 48, + "column": 3, + "endLine": 48, + "endColumn": 4, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1126, + "end": 1127, + "replacementText": "y: y", + "line": 48, + "column": 3, + "endLine": 48, + "endColumn": 4 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 50, "column": 3, @@ -601,6 +706,69 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 69, + "column": 3, + "endLine": 69, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1425, + "end": 1427, + "replacementText": "x2: x2", + "line": 69, + "column": 3, + "endLine": 69, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 70, + "column": 3, + "endLine": 70, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1449, + "end": 1451, + "replacementText": "y2: y2", + "line": 70, + "column": 3, + "endLine": 70, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 3, + "endLine": 71, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1473, + "end": 1475, + "replacementText": "z2: z2", + "line": 71, + "column": 3, + "endLine": 71, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 72, "column": 3, @@ -1013,6 +1181,69 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 110, + "column": 3, + "endLine": 110, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1926, + "end": 1928, + "replacementText": "x2: x2", + "line": 110, + "column": 3, + "endLine": 110, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 111, + "column": 3, + "endLine": 111, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1943, + "end": 1945, + "replacementText": "y2: y2", + "line": 111, + "column": 3, + "endLine": 111, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 112, + "column": 3, + "endLine": 112, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 1960, + "end": 1962, + "replacementText": "z2: z2", + "line": 112, + "column": 3, + "endLine": 112, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 113, "column": 3, @@ -1074,6 +1305,69 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 117, + "column": 3, + "endLine": 117, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2034, + "end": 2036, + "replacementText": "x2: x2", + "line": 117, + "column": 3, + "endLine": 117, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 118, + "column": 3, + "endLine": 118, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2051, + "end": 2053, + "replacementText": "y2: y2", + "line": 118, + "column": 3, + "endLine": 118, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 119, + "column": 3, + "endLine": 119, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2068, + "end": 2070, + "replacementText": "z2: z2", + "line": 119, + "column": 3, + "endLine": 119, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 120, "column": 3, @@ -1261,6 +1555,69 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, + { + "line": 134, + "column": 3, + "endLine": 134, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2289, + "end": 2291, + "replacementText": "x2: x2", + "line": 134, + "column": 3, + "endLine": 134, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 135, + "column": 3, + "endLine": 135, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2306, + "end": 2308, + "replacementText": "y2: y2", + "line": 135, + "column": 3, + "endLine": 135, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, + { + "line": 136, + "column": 3, + "endLine": 136, + "endColumn": 5, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 2323, + "end": 2325, + "replacementText": "z2: z2", + "line": 136, + "column": 3, + "endLine": 136, + "endColumn": 5 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 137, "column": 3, @@ -1909,14 +2266,46 @@ "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, + { + "line": 251, + "column": 15, + "endLine": 251, + "endColumn": 18, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 4619, + "end": 4622, + "replacementText": "map: map", + "line": 251, + "column": 15, + "endLine": 251, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", + "severity": "ERROR" + }, { "line": 258, - "column": 11, + "column": 15, "endLine": 258, - "endColumn": 12, - "problem": "ObjectLiteralNoContextType", + "endColumn": 19, + "problem": "ObjectLiteralProperty", + "autofix": [ + { + "start": 4766, + "end": 4770, + "replacementText": "map1: map1", + "line": 258, + "column": 15, + "endLine": 258, + "endColumn": 19 + } + ], "suggest": "", - "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", + "rule": "Object literal properties can only contain name-value pairs (arkts-obj-literal-props)", "severity": "ERROR" }, { diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.json b/ets2panda/linter/test/main/object_literals_properties.ets.json index 8548318c10..c8d9bf18dc 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.json @@ -294,16 +294,6 @@ "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" }, - { - "line": 258, - "column": 11, - "endLine": 258, - "endColumn": 12, - "problem": "ObjectLiteralNoContextType", - "suggest": "", - "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", - "severity": "ERROR" - }, { "line": 187, "column": 3, diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets index eb3a50b921..a47d79115e 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.ets @@ -36,10 +36,15 @@ let setMethod = new GeneratedObjectLiteralClass_3(); let x: number = 1.0, y = '2', z = true; -let shorthand = { - x, // Error, fixable - y, // Error, fixable - z // Error, fixable +interface GeneratedObjectLiteralInterface_1 { + x: number; + y: string; + z: boolean; +} +let shorthand: GeneratedObjectLiteralInterface_1 = { + x: x, // Error, fixable + y: y, // Error, fixable + z: z // Error, fixable }; let spread = { @@ -92,9 +97,9 @@ let x2: number = 1.0, y2: number = 2.0, z2: number = 3.0; let mixedBad = { // Not fixable a: 1.0, b: 2.0, - x2, // Error, fixable - y2, // Error, fixable - z2, // Error, fixable + x2: x2, // Error, fixable + y2: y2, // Error, fixable + z2: z2, // Error, fixable m() {}, ...shorthand // Error, not fixable } @@ -142,7 +147,7 @@ class GeneratedObjectLiteralClass_8 extends C2 { x2: number; y2: number; z2: number; - constructor(init: GeneratedObjectLiteralInitInterface_8) { + constructor(init: GeneratedObjectLiteralInitInterface_1) { super(); this.x2 = init.x2; this.y2 = init.y2; @@ -151,7 +156,7 @@ class GeneratedObjectLiteralClass_8 extends C2 { m() { console.log(1.0); } // Fixable } -interface GeneratedObjectLiteralInitInterface_8 { +interface GeneratedObjectLiteralInitInterface_1 { x2: number; y2: number; z2: number; @@ -164,9 +169,9 @@ let c2: C2 = new GeneratedObjectLiteralClass_8({ }); let c22: C2 = { - x2, // Fixable - y2, // Fixable - z2, // Fixable + x2: x2, // Fixable + y2: y2, // Fixable + z2: z2, // Fixable m() { console.log(1.0); }, // Not fixable, object has spread property ...shorthand // Not fixable }; @@ -181,9 +186,9 @@ class C3 { constructor(a: number) {} } let c3: C3 = { - x2, // Fixable - y2, // Fixable - z2, // Fixable + x2: x2, // Fixable + y2: y2, // Fixable + z2: z2, // Fixable m() { console.log(1.0); } // Not fixable, class type has constructor with parameters }; @@ -301,15 +306,15 @@ class GeneratedObjectLiteralClass_10 extends Derived3 { let b3: Derived3 = new GeneratedObjectLiteralClass_10(); -interface A { +interface I4 { map: Map; } let map:Map = new Map(); -let a:A = {map}; +let i4: I4 = {map: map}; -class C { +class C6 { map1: Map = new Map(); } let map1:Map = new Map(); -let c:C = {map1}; \ No newline at end of file +let c6: C6 = {map1: map1}; \ No newline at end of file diff --git a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json index 972e1c73e2..f7f4541321 100644 --- a/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json +++ b/ets2panda/linter/test/main/object_literals_properties.ets.migrate.json @@ -15,19 +15,9 @@ ], "result": [ { - "line": 39, - "column": 17, - "endLine": 39, - "endColumn": 18, - "problem": "ObjectLiteralNoContextType", - "suggest": "", - "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", - "severity": "ERROR" - }, - { - "line": 45, + "line": 50, "column": 14, - "endLine": 45, + "endLine": 50, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -35,9 +25,9 @@ "severity": "ERROR" }, { - "line": 46, + "line": 51, "column": 3, - "endLine": 46, + "endLine": 51, "endColumn": 15, "problem": "ObjectLiteralProperty", "suggest": "", @@ -45,9 +35,9 @@ "severity": "ERROR" }, { - "line": 46, + "line": 51, "column": 3, - "endLine": 46, + "endLine": 51, "endColumn": 15, "problem": "SpreadOperator", "suggest": "", @@ -55,9 +45,9 @@ "severity": "ERROR" }, { - "line": 92, + "line": 97, "column": 16, - "endLine": 92, + "endLine": 97, "endColumn": 17, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -65,9 +55,9 @@ "severity": "ERROR" }, { - "line": 98, + "line": 103, "column": 3, - "endLine": 98, + "endLine": 103, "endColumn": 9, "problem": "ObjectLiteralProperty", "suggest": "", @@ -75,9 +65,9 @@ "severity": "ERROR" }, { - "line": 99, + "line": 104, "column": 3, - "endLine": 99, + "endLine": 104, "endColumn": 15, "problem": "ObjectLiteralProperty", "suggest": "", @@ -85,9 +75,9 @@ "severity": "ERROR" }, { - "line": 99, + "line": 104, "column": 3, - "endLine": 99, + "endLine": 104, "endColumn": 15, "problem": "SpreadOperator", "suggest": "", @@ -95,9 +85,9 @@ "severity": "ERROR" }, { - "line": 166, + "line": 171, "column": 15, - "endLine": 166, + "endLine": 171, "endColumn": 16, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -105,9 +95,9 @@ "severity": "ERROR" }, { - "line": 170, + "line": 175, "column": 3, - "endLine": 170, + "endLine": 175, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -115,9 +105,9 @@ "severity": "ERROR" }, { - "line": 171, + "line": 176, "column": 3, - "endLine": 171, + "endLine": 176, "endColumn": 15, "problem": "ObjectLiteralProperty", "suggest": "", @@ -125,9 +115,9 @@ "severity": "ERROR" }, { - "line": 171, + "line": 176, "column": 3, - "endLine": 171, + "endLine": 176, "endColumn": 15, "problem": "SpreadOperator", "suggest": "", @@ -135,9 +125,9 @@ "severity": "ERROR" }, { - "line": 183, + "line": 188, "column": 14, - "endLine": 183, + "endLine": 188, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -145,9 +135,9 @@ "severity": "ERROR" }, { - "line": 187, + "line": 192, "column": 3, - "endLine": 187, + "endLine": 192, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -155,9 +145,9 @@ "severity": "ERROR" }, { - "line": 192, + "line": 197, "column": 25, - "endLine": 192, + "endLine": 197, "endColumn": 26, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -165,9 +155,9 @@ "severity": "ERROR" }, { - "line": 193, + "line": 198, "column": 5, - "endLine": 195, + "endLine": 200, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -175,9 +165,9 @@ "severity": "ERROR" }, { - "line": 198, + "line": 203, "column": 29, - "endLine": 198, + "endLine": 203, "endColumn": 30, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -185,9 +175,9 @@ "severity": "ERROR" }, { - "line": 199, + "line": 204, "column": 5, - "endLine": 201, + "endLine": 206, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -195,9 +185,9 @@ "severity": "ERROR" }, { - "line": 209, + "line": 214, "column": 26, - "endLine": 209, + "endLine": 214, "endColumn": 27, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -205,9 +195,9 @@ "severity": "ERROR" }, { - "line": 210, + "line": 215, "column": 5, - "endLine": 212, + "endLine": 217, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -215,9 +205,9 @@ "severity": "ERROR" }, { - "line": 214, + "line": 219, "column": 27, - "endLine": 214, + "endLine": 219, "endColumn": 28, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -225,9 +215,9 @@ "severity": "ERROR" }, { - "line": 215, + "line": 220, "column": 5, - "endLine": 217, + "endLine": 222, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -235,9 +225,9 @@ "severity": "ERROR" }, { - "line": 221, + "line": 226, "column": 27, - "endLine": 221, + "endLine": 226, "endColumn": 28, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -245,9 +235,9 @@ "severity": "ERROR" }, { - "line": 222, + "line": 227, "column": 5, - "endLine": 224, + "endLine": 229, "endColumn": 6, "problem": "ObjectLiteralProperty", "suggest": "", @@ -255,9 +245,9 @@ "severity": "ERROR" }, { - "line": 233, + "line": 238, "column": 14, - "endLine": 233, + "endLine": 238, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -265,9 +255,9 @@ "severity": "ERROR" }, { - "line": 244, + "line": 249, "column": 3, - "endLine": 244, + "endLine": 249, "endColumn": 9, "problem": "ObjectLiteralProperty", "suggest": "", @@ -275,9 +265,9 @@ "severity": "ERROR" }, { - "line": 251, + "line": 256, "column": 14, - "endLine": 251, + "endLine": 256, "endColumn": 15, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -285,9 +275,9 @@ "severity": "ERROR" }, { - "line": 262, + "line": 267, "column": 3, - "endLine": 262, + "endLine": 267, "endColumn": 9, "problem": "ObjectLiteralProperty", "suggest": "", @@ -295,9 +285,9 @@ "severity": "ERROR" }, { - "line": 281, + "line": 286, "column": 16, - "endLine": 281, + "endLine": 286, "endColumn": 29, "problem": "MissingSuperCall", "suggest": "", @@ -305,9 +295,9 @@ "severity": "ERROR" }, { - "line": 284, + "line": 289, "column": 20, - "endLine": 284, + "endLine": 289, "endColumn": 21, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -315,9 +305,9 @@ "severity": "ERROR" }, { - "line": 285, + "line": 290, "column": 3, - "endLine": 285, + "endLine": 290, "endColumn": 28, "problem": "ObjectLiteralProperty", "suggest": "", @@ -325,19 +315,9 @@ "severity": "ERROR" }, { - "line": 315, - "column": 11, - "endLine": 315, - "endColumn": 12, - "problem": "ObjectLiteralNoContextType", - "suggest": "", - "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", - "severity": "ERROR" - }, - { - "line": 240, + "line": 245, "column": 3, - "endLine": 240, + "endLine": 245, "endColumn": 4, "problem": "StrictDiagnostic", "suggest": "Property 'b' has no initializer and is not definitely assigned in the constructor.", -- Gitee From b99a2fab802a8cba5c3b8db72103299ea2c71355 Mon Sep 17 00:00:00 2001 From: xudan16 Date: Wed, 11 Jun 2025 16:00:53 +0800 Subject: [PATCH 084/747] arkts-no-ts-like-as add class field check Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICE9CY Signed-off-by: xudan16 --- .../src/checker/migration/NoTSLikeAsCheck.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts b/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts index 7375978f11..3e6f594aa1 100644 --- a/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts +++ b/ets2panda/linter/homecheck/src/checker/migration/NoTSLikeAsCheck.ts @@ -42,6 +42,8 @@ import { UnaryOperator, ArkNormalBinopExpr, NormalBinaryOperator, + AbstractFieldRef, + ClassSignature, } from 'arkanalyzer/lib'; import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger'; import { BaseChecker, BaseMetaData } from '../BaseChecker'; @@ -368,6 +370,11 @@ export class NoTSLikeAsCheck implements BaseChecker { if (this.isWithInterfaceAnnotation(currentStmt, scene)) { return currentStmt; } + + const fieldDeclareStmt = this.isCastOpFieldWithInterfaceType(currentStmt, scene); + if (fieldDeclareStmt) { + return fieldDeclareStmt; + } const gv = this.checkIfCastOpIsGlobalVar(currentStmt); if (gv) { const globalDefs = globalVarMap.get(gv.getName()); @@ -418,6 +425,34 @@ export class NoTSLikeAsCheck implements BaseChecker { return null; } + private isCastOpFieldWithInterfaceType(stmt: Stmt, scene: Scene): Stmt | undefined { + const obj = this.getCastOp(stmt); + if (obj === null || !(obj instanceof Local)) { + return undefined; + } + const declaringStmt = obj.getDeclaringStmt(); + if (declaringStmt === null || !(declaringStmt instanceof ArkAssignStmt)) { + return undefined; + } + const rightOp = declaringStmt.getRightOp(); + if (!(rightOp instanceof AbstractFieldRef)) { + return undefined; + } + const fieldDeclaring = rightOp.getFieldSignature().getDeclaringSignature(); + if (fieldDeclaring instanceof ClassSignature) { + const field = scene.getClass(fieldDeclaring)?.getField(rightOp.getFieldSignature()); + if (!field) { + return undefined; + } + const fieldInitializer = field.getInitializer(); + const lastStmt = fieldInitializer[fieldInitializer.length - 1]; + if (this.isWithInterfaceAnnotation(lastStmt, scene)) { + return lastStmt; + } + } + return undefined; + } + private checkIfCastOpIsGlobalVar(stmt: Stmt): Local | undefined { const obj = this.getCastOp(stmt); if (obj instanceof Local && !obj.getDeclaringStmt()) { -- Gitee From fd4ec4369341547ee050e11818a910562ec933b0 Mon Sep 17 00:00:00 2001 From: zengyuan Date: Wed, 11 Jun 2025 17:01:27 +0800 Subject: [PATCH 085/747] Fix the bug that generates redundant comments Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICEE3M Signed-off-by: zengyuan Change-Id: I1b59b310d365afdad0f65502bfd3d7332420a36f --- .../linter/src/lib/autofixes/Autofixer.ts | 4 +- ets2panda/linter/test/main/comment_test.ets | 23 ++++ .../test/main/comment_test.ets.args.json | 21 +++ .../test/main/comment_test.ets.arkts2.json | 68 ++++++++++ .../test/main/comment_test.ets.autofix.json | 123 ++++++++++++++++++ .../linter/test/main/comment_test.ets.json | 17 +++ .../test/main/comment_test.ets.migrate.ets | 23 ++++ .../test/main/comment_test.ets.migrate.json | 17 +++ 8 files changed, 294 insertions(+), 2 deletions(-) create mode 100644 ets2panda/linter/test/main/comment_test.ets create mode 100644 ets2panda/linter/test/main/comment_test.ets.args.json create mode 100644 ets2panda/linter/test/main/comment_test.ets.arkts2.json create mode 100644 ets2panda/linter/test/main/comment_test.ets.autofix.json create mode 100644 ets2panda/linter/test/main/comment_test.ets.json create mode 100644 ets2panda/linter/test/main/comment_test.ets.migrate.ets create mode 100644 ets2panda/linter/test/main/comment_test.ets.migrate.json diff --git a/ets2panda/linter/src/lib/autofixes/Autofixer.ts b/ets2panda/linter/src/lib/autofixes/Autofixer.ts index eb940bc3ab..67ce638be6 100644 --- a/ets2panda/linter/src/lib/autofixes/Autofixer.ts +++ b/ets2panda/linter/src/lib/autofixes/Autofixer.ts @@ -3332,7 +3332,7 @@ export class Autofixer { node.initializer ); - const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, newProperty, node.getSourceFile()); + const replacementText = this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, newProperty, node.getSourceFile()); return [ { @@ -3457,7 +3457,7 @@ export class Autofixer { initializer ); - const text = this.printer.printNode(ts.EmitHint.Unspecified, newPropDecl, node.getSourceFile()); + const text = this.nonCommentPrinter.printNode(ts.EmitHint.Unspecified, newPropDecl, node.getSourceFile()); return [{ start: node.getStart(), end: node.getEnd(), replacementText: text }]; } diff --git a/ets2panda/linter/test/main/comment_test.ets b/ets2panda/linter/test/main/comment_test.ets new file mode 100644 index 0000000000..3731be6780 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class TestClass { + /** + * This is a comment. + */ + property = 123; // This is a comment. + // This is a comment. + arr = [1, 0]; // This is a comment. +} diff --git a/ets2panda/linter/test/main/comment_test.ets.args.json b/ets2panda/linter/test/main/comment_test.ets.args.json new file mode 100644 index 0000000000..ef3938e967 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.args.json @@ -0,0 +1,21 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "mode": { + "arkts2": "", + "autofix": "--arkts-2", + "migrate": "--arkts-2" + } +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/comment_test.ets.arkts2.json b/ets2panda/linter/test/main/comment_test.ets.arkts2.json new file mode 100644 index 0000000000..76f0d20523 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.arkts2.json @@ -0,0 +1,68 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 20, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 16, + "endLine": 20, + "endColumn": 19, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 18, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 12, + "endLine": 22, + "endColumn": 13, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 15, + "endLine": 22, + "endColumn": 16, + "problem": "NumericSemantics", + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + } + ] +} diff --git a/ets2panda/linter/test/main/comment_test.ets.autofix.json b/ets2panda/linter/test/main/comment_test.ets.autofix.json new file mode 100644 index 0000000000..e1951adff8 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.autofix.json @@ -0,0 +1,123 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [ + { + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 20, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 669, + "end": 684, + "replacementText": "property: number = 123;", + "line": 20, + "column": 5, + "endLine": 20, + "endColumn": 20 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 20, + "column": 16, + "endLine": 20, + "endColumn": 19, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 680, + "end": 683, + "replacementText": "123.0", + "line": 20, + "column": 16, + "endLine": 20, + "endColumn": 19 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 18, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 737, + "end": 750, + "replacementText": "arr: number[] = [1, 0];", + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 18 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 12, + "endLine": 22, + "endColumn": 13, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 744, + "end": 745, + "replacementText": "1.0", + "line": 22, + "column": 12, + "endLine": 22, + "endColumn": 13 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 15, + "endLine": 22, + "endColumn": 16, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 747, + "end": 748, + "replacementText": "0.0", + "line": 22, + "column": 15, + "endLine": 22, + "endColumn": 16 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + } + ] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/comment_test.ets.json b/ets2panda/linter/test/main/comment_test.ets.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/comment_test.ets.migrate.ets b/ets2panda/linter/test/main/comment_test.ets.migrate.ets new file mode 100644 index 0000000000..2131000bfa --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.migrate.ets @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class TestClass { + /** + * This is a comment. + */ + property: number = 123.0; // This is a comment. + // This is a comment. + arr: number[] = [1.0, 0.0]; // This is a comment. +} diff --git a/ets2panda/linter/test/main/comment_test.ets.migrate.json b/ets2panda/linter/test/main/comment_test.ets.migrate.json new file mode 100644 index 0000000000..ca88f857e9 --- /dev/null +++ b/ets2panda/linter/test/main/comment_test.ets.migrate.json @@ -0,0 +1,17 @@ +{ + "copyright": [ + "Copyright (c) 2025 Huawei Device Co., Ltd.", + "Licensed under the Apache License, Version 2.0 (the 'License');", + "you may not use this file except in compliance with the License.", + "You may obtain a copy of the License at", + "", + "http://www.apache.org/licenses/LICENSE-2.0", + "", + "Unless required by applicable law or agreed to in writing, software", + "distributed under the License is distributed on an 'AS IS' BASIS,", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", + "See the License for the specific language governing permissions and", + "limitations under the License." + ], + "result": [] +} \ No newline at end of file -- Gitee From b2151fbc896945c068715ba8ccc62db29b640363 Mon Sep 17 00:00:00 2001 From: fcc Date: Tue, 10 Jun 2025 15:43:56 +0800 Subject: [PATCH 086/747] fix unicode whitespace in lexer Fix Unicode whitespace in lexer. Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICE0R4 Signed-off-by: fcc --- ets2panda/lexer/lexer.cpp | 15 ++++++++++-- ets2panda/lexer/token/letters.h | 24 ++++++++++++------- .../test/runtime/ets/unicode_whitespace.ets | 17 +++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 ets2panda/test/runtime/ets/unicode_whitespace.ets diff --git a/ets2panda/lexer/lexer.cpp b/ets2panda/lexer/lexer.cpp index 3868b42336..5cbf89f97c 100644 --- a/ets2panda/lexer/lexer.cpp +++ b/ets2panda/lexer/lexer.cpp @@ -1340,17 +1340,27 @@ bool Lexer::SkipWhiteSpacesHelperDefault(const char32_t &cp) size_t cpSize {}; - switch (Iterator().PeekCp(&cpSize)) { + char32_t ch = Iterator().PeekCp(&cpSize); + switch (ch) { case LEX_CHAR_LS: case LEX_CHAR_PS: pos_.nextTokenLine_++; [[fallthrough]]; case LEX_CHAR_NBSP: case LEX_CHAR_ZWNBSP: + case LEX_CHAR_OGHAM: + case LEX_CHAR_NARROW_NO_BREAK_SP: + case LEX_CHAR_MATHEMATICAL_SP: + case LEX_CHAR_IDEOGRAPHIC_SP: Iterator().Forward(cpSize); return true; default: - return false; + if (ch >= LEX_CHAR_ENQUAD && ch <= LEX_CHAR_ZERO_WIDTH_SP) { + Iterator().Forward(cpSize); + return true; + } else { + return false; + } } } @@ -1376,6 +1386,7 @@ void Lexer::SkipWhiteSpaces() case LEX_CHAR_FF: case LEX_CHAR_SP: case LEX_CHAR_TAB: + case LEX_CHAR_NEXT_LINE: Iterator().Forward(1); continue; case LEX_CHAR_SLASH: diff --git a/ets2panda/lexer/token/letters.h b/ets2panda/lexer/token/letters.h index 222aa6ca68..e33d21b114 100644 --- a/ets2panda/lexer/token/letters.h +++ b/ets2panda/lexer/token/letters.h @@ -82,14 +82,22 @@ inline constexpr char32_t LEX_CHAR_UPPERCASE_X = 0x58; /* X */ inline constexpr char32_t LEX_CHAR_UPPERCASE_Y = 0x59; /* Y */ inline constexpr char32_t LEX_CHAR_UPPERCASE_Z = 0x5A; /* Y */ -inline constexpr char32_t LEX_CHAR_BS = 0x08; /* backspace */ -inline constexpr char32_t LEX_CHAR_TAB = 0x09; /* character tabulation */ -inline constexpr char32_t LEX_CHAR_VT = 0x0B; /* liner tabulation */ -inline constexpr char32_t LEX_CHAR_FF = 0x0C; /* form feed */ -inline constexpr char32_t LEX_CHAR_SP = 0x20; /* space */ -inline constexpr char32_t LEX_CHAR_NBSP = 0xA0; /* no-break space */ -inline constexpr char32_t LEX_CHAR_ZWNBSP = 0xFEFF; /* zero width no-break space */ -inline constexpr char32_t LEX_CHAR_MVS = 0x180e; /* MONGOLIAN VOWEL SEPARATOR (U+180E) */ +inline constexpr char32_t LEX_CHAR_BS = 0x08; /* backspace */ +inline constexpr char32_t LEX_CHAR_TAB = 0x09; /* character tabulation */ +inline constexpr char32_t LEX_CHAR_VT = 0x0B; /* liner tabulation */ +inline constexpr char32_t LEX_CHAR_FF = 0x0C; /* form feed */ +inline constexpr char32_t LEX_CHAR_SP = 0x20; /* space */ +inline constexpr char32_t LEX_CHAR_NBSP = 0xA0; /* no-break space */ +inline constexpr char32_t LEX_CHAR_ZWNBSP = 0xFEFF; /* zero width no-break space */ +inline constexpr char32_t LEX_CHAR_MVS = 0x180e; /* MONGOLIAN VOWEL SEPARATOR (U+180E) */ +inline constexpr char32_t LEX_CHAR_NEXT_LINE = 0x85; /* next line */ +inline constexpr char32_t LEX_CHAR_OGHAM = 0x1680; /* ogham */ +inline constexpr char32_t LEX_CHAR_ENQUAD = 0X2000; +inline constexpr char32_t LEX_CHAR_ZERO_WIDTH_SP = 0x200B; +inline constexpr char32_t LEX_CHAR_NARROW_NO_BREAK_SP = 0x202F; +inline constexpr char32_t LEX_CHAR_MATHEMATICAL_SP = 0x205F; +inline constexpr char32_t LEX_CHAR_IDEOGRAPHIC_SP = 0x3000; + inline constexpr char32_t LEX_CHAR_DOUBLE_QUOTE = 0x22; /* " */ inline constexpr char32_t LEX_CHAR_DOLLAR_SIGN = 0x24; /* $ */ inline constexpr char32_t LEX_CHAR_SINGLE_QUOTE = 0x27; /* ' */ diff --git a/ets2panda/test/runtime/ets/unicode_whitespace.ets b/ets2panda/test/runtime/ets/unicode_whitespace.ets new file mode 100644 index 0000000000..dc0042c7b9 --- /dev/null +++ b/ets2panda/test/runtime/ets/unicode_whitespace.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// this function intentionally contains unicode whitespace +function main() { assertTrue(true) } -- Gitee From 4011b6f280dab4b83ee99d78be7e07a7832e8c61 Mon Sep 17 00:00:00 2001 From: groshevmaksim Date: Mon, 2 Jun 2025 16:31:48 +0300 Subject: [PATCH 087/747] Remove JSValue-based front-end types Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICCBO1 Tests: ninja all tests Signed-off-by: groshevmaksim Change-Id: I14a13f57dbe165fb7fe9354a36e89fef37ef8d28 Change-Id: If52946c70a02d4e1782f7e28d352e0a493eca16f --- ets2panda/BUILD.gn | 7 - ets2panda/CMakeLists.txt | 3 - ets2panda/REVIEWERS | 2 - ets2panda/checker/ETSAnalyzer.cpp | 58 +- ets2panda/checker/ETSAnalyzerHelpers.cpp | 2 +- ets2panda/checker/ETSchecker.cpp | 7 - ets2panda/checker/ETSchecker.h | 14 - ets2panda/checker/ets/arithmetic.cpp | 37 +- ets2panda/checker/ets/dynamic.cpp | 481 ----------------- ets2panda/checker/ets/dynamic/dynamicCall.cpp | 80 --- ets2panda/checker/ets/dynamic/dynamicCall.h | 60 --- ets2panda/checker/ets/function.cpp | 9 +- ets2panda/checker/ets/helpers.cpp | 7 +- ets2panda/checker/ets/object.cpp | 11 - ets2panda/checker/ets/typeCheckingHelpers.cpp | 12 - ets2panda/checker/ets/typeCreation.cpp | 43 -- ets2panda/checker/ets/validateHelpers.cpp | 2 +- .../types/ets/etsDynamicFunctionType.h | 54 -- .../checker/types/ets/etsDynamicType.cpp | 119 ----- ets2panda/checker/types/ets/etsDynamicType.h | 73 --- .../checker/types/ets/etsFunctionType.cpp | 10 - ets2panda/checker/types/ets/etsObjectType.cpp | 34 -- ets2panda/checker/types/ets/types.h | 1 - ets2panda/checker/types/type.h | 36 -- ets2panda/checker/types/typeRelation.cpp | 8 - ets2panda/compiler/base/lreference.cpp | 19 +- ets2panda/compiler/core/ETSCompiler.cpp | 122 +---- ets2panda/compiler/core/ETSCompiler.h | 1 - ets2panda/compiler/core/ETSGen.cpp | 502 ------------------ ets2panda/compiler/core/ETSGen.h | 19 - ets2panda/compiler/core/ETSemitter.cpp | 5 - .../lowering/ets/asyncMethodLowering.cpp | 2 +- .../lowering/ets/dynamicImportLowering.cpp | 28 - .../lowering/ets/dynamicImportLowering.h | 35 -- .../compiler/lowering/ets/lambdaLowering.cpp | 3 - .../lowering/ets/objectIndexAccess.cpp | 9 +- .../lowering/ets/restArgsLowering.cpp | 2 +- .../compiler/lowering/ets/unboxLowering.cpp | 52 +- ets2panda/compiler/lowering/phase.cpp | 3 - ets2panda/ir/expressions/memberExpression.cpp | 7 - ets2panda/public/CMakeLists.txt | 4 - ets2panda/public/README.md | 2 - ets2panda/public/es2panda_lib.rb | 2 - .../compiler/ets/esobject_with_string_key.ets | 18 - .../ets/esobject_with_string_key_1.ets | 19 - .../dynamic_import_interop_neg.ets | 18 - .../ets/test_jsvalue_set_property_1.ets | 23 - .../ets/test_jsvalue_set_property_2.ets | 21 - .../test-lists/parser/parser-js-ignored.txt | 22 +- .../test-lists/recheck/recheck-ignored.txt | 1 - .../test/tsconfig/test-decl/CMakeLists.txt | 6 +- ets2panda/test/unit/dynamic/CMakeLists.txt | 3 +- .../test/unit/dynamic/dynamic_call_test.cpp | 2 - ..._verifier_identifier_has_variable_test.cpp | 3 +- ets2panda/varbinder/ETSBinder.cpp | 121 +---- ets2panda/varbinder/ETSBinder.h | 24 +- 56 files changed, 78 insertions(+), 2190 deletions(-) delete mode 100644 ets2panda/checker/ets/dynamic/dynamicCall.cpp delete mode 100644 ets2panda/checker/ets/dynamic/dynamicCall.h delete mode 100644 ets2panda/checker/types/ets/etsDynamicFunctionType.h delete mode 100644 ets2panda/checker/types/ets/etsDynamicType.cpp delete mode 100644 ets2panda/checker/types/ets/etsDynamicType.h delete mode 100644 ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp delete mode 100644 ets2panda/compiler/lowering/ets/dynamicImportLowering.h delete mode 100644 ets2panda/test/ast/compiler/ets/esobject_with_string_key.ets delete mode 100644 ets2panda/test/ast/compiler/ets/esobject_with_string_key_1.ets delete mode 100644 ets2panda/test/ast/compiler/ets/import_tests/dynamic_import_interop_neg.ets delete mode 100644 ets2panda/test/ast/parser/ets/test_jsvalue_set_property_1.ets delete mode 100644 ets2panda/test/ast/parser/ets/test_jsvalue_set_property_2.ets diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 42c9d7f055..2e31993bf1 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -74,7 +74,6 @@ libes2panda_sources = [ "checker/ets/castingContext.cpp", "checker/ets/conversion.cpp", "checker/ets/dynamic.cpp", - "checker/ets/dynamic/dynamicCall.cpp", "checker/ets/etsWarningAnalyzer.cpp", "checker/ets/function.cpp", "checker/ets/helpers.cpp", @@ -103,7 +102,6 @@ libes2panda_sources = [ "checker/types/ets/etsAsyncFuncReturnType.cpp", "checker/types/ets/etsBigIntType.cpp", "checker/types/ets/etsBooleanType.cpp", - "checker/types/ets/etsDynamicType.cpp", "checker/types/ets/etsEnumType.cpp", "checker/types/ets/etsExtensionFuncHelperType.cpp", "checker/types/ets/etsFunctionType.cpp", @@ -213,7 +211,6 @@ libes2panda_sources = [ "compiler/lowering/ets/declareOverloadLowering.cpp", "compiler/lowering/ets/defaultParametersInConstructorLowering.cpp", "compiler/lowering/ets/defaultParametersLowering.cpp", - "compiler/lowering/ets/dynamicImportLowering.cpp", "compiler/lowering/ets/enumLowering.cpp", "compiler/lowering/ets/enumPostCheckLowering.cpp", "compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp", @@ -542,7 +539,6 @@ HEADERS_TO_BE_PARSED = [ "checker/types/ts/nonPrimitiveType.h", "ir/ts/tsTypeParameterInstantiation.h", "ir/module/importDeclaration.h", - "checker/types/ets/etsDynamicType.h", "ir/statements/doWhileStatement.h", "ir/expressions/literals/bigIntLiteral.h", "ir/expressions/assignmentExpression.h", @@ -630,7 +626,6 @@ HEADERS_TO_BE_PARSED = [ "ir/ts/tsParenthesizedType.h", "ir/ts/tsModuleDeclaration.h", "ir/ets/etsPackageDeclaration.h", - "checker/types/ets/etsDynamicFunctionType.h", "ir/expressions/literals/regExpLiteral.h", "ir/ets/etsNewArrayInstanceExpression.h", "checker/types/ets/etsVoidType.h", @@ -803,7 +798,6 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/ir/expressions/objectExpression.yaml", "$LIBGEN_DIR/gen/headers/ir/module/importSpecifier.yaml", "$LIBGEN_DIR/gen/headers/ir/expressions/conditionalExpression.yaml", - "$LIBGEN_DIR/gen/headers/checker/types/ets/etsDynamicFunctionType.yaml", "$LIBGEN_DIR/gen/headers/ir/expressions/callExpression.yaml", "$LIBGEN_DIR/gen/headers/ir/expressions/literals/bigIntLiteral.yaml", "$LIBGEN_DIR/gen/headers/ir/base/classElement.yaml", @@ -927,7 +921,6 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/ir/expressions/blockExpression.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsTypeLiteral.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsTypeParameter.yaml", - "$LIBGEN_DIR/gen/headers/checker/types/ets/etsDynamicType.yaml", "$LIBGEN_DIR/gen/headers/checker/types/ets/charType.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsBooleanKeyword.yaml", "$LIBGEN_DIR/gen/headers/ir/base/spreadElement.yaml", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index 695f3a76f9..cdc7ad2904 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -285,7 +285,6 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/declareOverloadLowering.cpp compiler/lowering/ets/defaultParametersInConstructorLowering.cpp compiler/lowering/ets/defaultParametersLowering.cpp - compiler/lowering/ets/dynamicImportLowering.cpp compiler/lowering/ets/exportAnonymousConst.cpp compiler/lowering/ets/lateInitialization.cpp compiler/lowering/ets/lambdaLowering.cpp @@ -553,7 +552,6 @@ set(ES2PANDA_LIB_SRC checker/ets/castingContext.cpp checker/ets/conversion.cpp checker/ets/dynamic.cpp - checker/ets/dynamic/dynamicCall.cpp checker/ets/function.cpp checker/ets/validateHelpers.cpp checker/ets/typeCheckingHelpers.cpp @@ -587,7 +585,6 @@ set(ES2PANDA_LIB_SRC checker/types/ets/etsAnyType.cpp checker/types/ets/etsArrayType.cpp checker/types/ets/etsBooleanType.cpp - checker/types/ets/etsDynamicType.cpp checker/types/ets/etsEnumType.cpp checker/types/ets/etsExtensionFuncHelperType.cpp checker/types/ets/etsFunctionType.cpp diff --git a/ets2panda/REVIEWERS b/ets2panda/REVIEWERS index 8d77d32339..6835ef0e17 100644 --- a/ets2panda/REVIEWERS +++ b/ets2panda/REVIEWERS @@ -47,7 +47,6 @@ /ets2panda/util/diagnostic* @chernykhsergey ^igelhaus ^Prof1983 /ets2panda/util/importPathManager* @dreamdoomwalker ^trubachevilya ^igelhaus ^Prof1983 /test/workload/ignored*.txt @shirunova_viktoria @kuchkovairina @gavin1012_hw @zhuheng27 -/ets2panda/checker/ets/dynamic.cpp @akmaevaleksey ^vpukhov ^igelhaus ^Prof1983 /ets2panda/checker/ets/function.cpp ^vpukhov @gogabr ^igelhaus ^Prof1983 /ets2panda/checker/ets/helpers.cpp @zelentsovdmitry ^igelhaus ^Prof1983 /ets2panda/checker/ets/object.cpp @zelentsovdmitry ^vpukhov ^igelhaus ^Prof1983 @@ -61,7 +60,6 @@ /ets2panda/test/test-lists/parser @chernykhsergey ^igelhaus ^Prof1983 /ets2panda/test/unit/lsp ^igelhaus ^Prof1983 @dreamdoomwalker @Ascnbio ^muhammet-fevzi-bayiroglu @utkugursel /ets2panda/checker/types/ets/Nullish.* ^vpukhov @gogabr ^igelhaus ^Prof1983 -/ets2panda/checker/types/ets/etsDynamicType.* ^vpukhov @gogabr ^igelhaus ^Prof1983 /ets2panda/checker/types/ets/etsFunctionType.* ^vpukhov @gogabr ^igelhaus ^Prof1983 /ets2panda/checker/types/ets/etsTypeParameter.* ^vpukhov @gogabr ^igelhaus ^Prof1983 /ets2panda/checker/types/ets/etsUnionType.* @akmaevaleksey ^vpukhov @gogabr ^igelhaus ^Prof1983 diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 43ab9c71bf..3aa4109c2e 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -514,29 +514,17 @@ checker::Type *ETSAnalyzer::Check(ir::ETSNewClassInstanceExpression *expr) const auto *calleeObj = calleeType->AsETSObjectType(); expr->SetTsType(calleeObj); - if (calleeType->IsETSDynamicType() && !calleeType->AsETSDynamicType()->HasDecl()) { - auto lang = calleeType->AsETSDynamicType()->Language(); - expr->SetSignature(checker->ResolveDynamicCallExpression(expr->GetTypeRef(), expr->GetArguments(), lang, true)); - } else { - auto *signature = checker->ResolveConstructExpression(calleeObj, expr->GetArguments(), expr->Start()); + auto *signature = checker->ResolveConstructExpression(calleeObj, expr->GetArguments(), expr->Start()); - if (signature == nullptr) { - return checker->InvalidateType(expr); - } + if (signature == nullptr) { + return checker->InvalidateType(expr); + } - checker->CheckObjectLiteralArguments(signature, expr->GetArguments()); + checker->CheckObjectLiteralArguments(signature, expr->GetArguments()); - checker->ValidateSignatureAccessibility(calleeObj, signature, expr->Start()); + checker->ValidateSignatureAccessibility(calleeObj, signature, expr->Start()); - if (calleeType->IsETSDynamicType()) { - ES2PANDA_ASSERT(signature->Function()->IsDynamic()); - auto lang = calleeType->AsETSDynamicType()->Language(); - expr->SetSignature( - checker->ResolveDynamicCallExpression(expr->GetTypeRef(), signature->Params(), lang, true)); - } else { - expr->SetSignature(signature); - } - } + expr->SetSignature(signature); return expr->TsType(); } @@ -1406,13 +1394,7 @@ Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, Type *calleeType) con checker->ValidateSignatureAccessibility(calleeObj, signature, expr->Start()); } - if (calleeType->IsETSMethodType() && signature->Function()->IsDynamic()) { - ES2PANDA_ASSERT(signature->Function()->IsDynamic()); - auto lang = signature->Function()->Language(); - expr->SetSignature(checker->ResolveDynamicCallExpression(expr->Callee(), signature->Params(), lang, false)); - } else { - expr->SetSignature(signature); - } + expr->SetSignature(signature); // #22951: this type should not be encoded as a signature flag if (signature->HasSignatureFlag(SignatureFlags::THIS_RETURN_TYPE)) { @@ -1469,16 +1451,7 @@ static checker::SavedCheckerContext ReconstructOwnerClassContext(ETSChecker *che checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr, checker::Type *calleeType) const { ETSChecker *checker = GetETSChecker(); - checker::Type *returnType = nullptr; - if (UNLIKELY(calleeType->IsETSDynamicType() && !calleeType->AsETSDynamicType()->HasDecl())) { - // Trailing lambda for js function call is not supported, check the correctness of `foo() {}` - checker->EnsureValidCurlyBrace(expr); - auto lang = calleeType->AsETSDynamicType()->Language(); - expr->SetSignature(checker->ResolveDynamicCallExpression(expr->Callee(), expr->Arguments(), lang, false)); - returnType = expr->Signature()->ReturnType(); - } else { - returnType = GetReturnType(expr, calleeType); - } + checker::Type *returnType = GetReturnType(expr, calleeType); if (returnType->IsTypeError()) { return checker->GlobalTypeError(); @@ -2277,16 +2250,11 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const return expr->TsType(); } - if (!expr->PreferredType()->IsETSUnionType() && !expr->PreferredType()->IsETSDynamicType() && - !ValidatePreferredType(checker, expr)) { + if (!expr->PreferredType()->IsETSUnionType() && !ValidatePreferredType(checker, expr)) { expr->SetTsType(checker->GlobalTypeError()); return expr->TsType(); } - if (expr->PreferredType()->IsETSDynamicType() && !expr->PreferredType()->AsETSDynamicType()->HasDecl()) { - return CheckDynamic(expr); - } - checker::ETSObjectType *objType = ResolveObjectTypeFromPreferredType(checker, expr); if (objType == nullptr) { @@ -3545,12 +3513,6 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const {sourceType, targetType}, checker::CastingContext::ConstructorData {expr->Expr(), sourceType, targetType, expr->Expr()->Start()}); - if (sourceType->IsETSDynamicType() && targetType->IsLambdaObject()) { - // NOTE: itrubachev. change targetType to created lambdaobject type. - // Now targetType is not changed, only construct signature is added to it - checker->BuildLambdaObjectClass(targetType->AsETSObjectType(), - expr->TypeAnnotation()->AsETSFunctionType()->ReturnType()); - } expr->isUncheckedCast_ = ctx.UncheckedCast(); // Make sure the array type symbol gets created for the assembler to be able to emit checkcast. diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index cec0d02e2d..2a5443ae23 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -244,7 +244,7 @@ void ComposeAsyncImplFuncReturnType(ETSChecker *checker, ir::ScriptFunction *scr auto *objectId = checker->ProgramAllocNode(compiler::Signatures::BUILTIN_OBJECT_CLASS, checker->ProgramAllocator()); - checker->VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false); + checker->VarBinder()->AsETSBinder()->LookupTypeReference(objectId); auto *returnType = checker->ProgramAllocNode( checker->ProgramAllocNode(objectId, nullptr, nullptr, checker->ProgramAllocator()), checker->ProgramAllocator()); diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index f345e2e86b..ce5dd58750 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -318,13 +318,6 @@ bool ETSChecker::StartChecker(varbinder::VarBinder *varbinder, const util::Optio auto *etsBinder = varbinder->AsETSBinder(); InitializeBuiltins(etsBinder); - for (auto &entry : etsBinder->DynamicImportVars()) { - auto &data = entry.second; - if (data.import->IsPureDynamic()) { - data.variable->SetTsType(GlobalBuiltinDynamicType(data.import->Language())); - } - } - bool isEvalMode = (debugInfoPlugin_ != nullptr); if (UNLIKELY(isEvalMode)) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 97ae5b8f2b..7de58a472e 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -329,9 +329,6 @@ public: bool isRecursive = false); ETSFunctionType *CreateETSArrowType(Signature *signature); ETSFunctionType *CreateETSMethodType(util::StringView name, ArenaVector &&signatures); - ETSFunctionType *CreateETSDynamicArrowType(Signature *signature, Language lang); - ETSFunctionType *CreateETSDynamicMethodType(util::StringView name, ArenaVector &&signatures, - Language lang); ETSExtensionFuncHelperType *CreateETSExtensionFuncHelperType(ETSFunctionType *classMethodType, ETSFunctionType *extensionFunctionType); void AddThisReturnTypeFlagForInterfaceInvoke(ETSObjectType *interface); @@ -341,7 +338,6 @@ public: std::tuple CreateBuiltinArraySignatureInfo(const ETSArrayType *arrayType, size_t dim); Signature *CreateBuiltinArraySignature(const ETSArrayType *arrayType, size_t dim); - std::tuple CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName); ETSObjectType *CreatePromiseOf(Type *type); Signature *CreateSignature(SignatureInfo *info, Type *returnType, ir::ScriptFunction *func); @@ -783,15 +779,6 @@ public: static Type *TryToInstantiate(Type *type, ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); - // Dynamic interop - template - Signature *ResolveDynamicCallExpression(ir::Expression *callee, const ArenaVector &arguments, Language lang, - bool isConstruct); - ir::ClassProperty *CreateStaticReadonlyField(const char *name); - void BuildClassBodyFromDynamicImports(const ArenaVector &dynamicImports, - ArenaVector *classBody); - void BuildDynamicImportClass(); - void BuildLambdaObjectClass(ETSObjectType *functionalInterface, ir::TypeNode *retTypeAnnotation); // Trailing lambda void EnsureValidCurlyBrace(ir::CallExpression *callExpr); @@ -1007,7 +994,6 @@ private: ir::MethodDefinition *CreateLambdaObjectClassInvokeMethod(Signature *invokeSignature, ir::TypeNode *retTypeAnnotation); - void ClassInitializerFromImport(ir::ETSImportDeclaration *import, ArenaVector *statements); void EmitDynamicModuleClassInitCall(); DynamicCallIntrinsicsMap *DynamicCallIntrinsics(bool isConstruct) { diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index 3f7cdeda3d..8eebfe0d38 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -655,36 +655,10 @@ std::tuple ETSChecker::CheckBinaryOperatorStrictEqual(ir::Expres } tsType = GlobalETSBooleanType(); - if (rightType->IsETSDynamicType() && leftType->IsETSDynamicType()) { - return {tsType, GlobalBuiltinJSValueType()}; - } return {tsType, GlobalETSObjectType()}; } -static Type *CheckOperatorEqualDynamic(ETSChecker *checker, BinaryArithmOperands const &ops) -{ - auto left = ops.expr->Left(); - auto right = ops.expr->Right(); - // canonicalize - auto *const dynExp = left->TsType()->IsETSDynamicType() ? left : right; - auto *const otherExp = dynExp == left ? right : left; - - if (otherExp->TsType()->IsETSDynamicType()) { - return checker->GlobalBuiltinJSValueType(); - } - if (dynExp->TsType()->AsETSDynamicType()->IsConvertible(otherExp->TsType())) { - // NOTE: vpukhov. boxing flags are not set in dynamic values - return otherExp->TsType(); - } - if (otherExp->TsType()->IsETSReferenceType()) { - // have to prevent casting dyn_exp via ApplyCast without nullish flag - return checker->GlobalETSAnyType(); - } - checker->LogError(diagnostic::BINOP_DYN_UNIMPLEMENTED, {}, ops.expr->Start()); - return checker->GlobalETSAnyType(); -} - static Type *HandelReferenceBinaryEquality(ETSChecker *checker, BinaryArithmOperands const &ops) { [[maybe_unused]] auto const [expr, typeL, typeR, reducedL, reducedR] = ops; @@ -722,10 +696,6 @@ static Type *CheckBinaryOperatorEqual(ETSChecker *checker, BinaryArithmOperands return checker->GlobalTypeError(); } - if (typeL->IsETSDynamicType() || typeR->IsETSDynamicType()) { - return CheckOperatorEqualDynamic(checker, ops); - } - if (reducedL->IsETSBooleanType() && reducedR->IsETSBooleanType()) { if (reducedL->IsConstantType() && reducedR->IsConstantType()) { return checker->GetGlobalTypesHolder()->GlobalETSBooleanBuiltinType(); @@ -819,12 +789,7 @@ std::tuple ETSChecker::CheckBinaryOperatorInstanceOf(lexer::Sour return {GlobalETSBooleanBuiltinType(), leftType}; } - if (rightType->IsETSDynamicType() && !rightType->AsETSDynamicType()->HasDecl()) { - LogError(diagnostic::INSTANCEOF_NOT_TYPE, {}, pos); - return {GlobalETSBooleanBuiltinType(), leftType}; - } - - checker::Type *opType = rightType->IsETSDynamicType() ? GlobalBuiltinJSValueType() : GlobalETSObjectType(); + checker::Type *opType = GlobalETSObjectType(); RemoveStatus(checker::CheckerStatus::IN_INSTANCEOF_CONTEXT); return {GlobalETSBooleanBuiltinType(), opType}; diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index f5d2544345..e5530fc812 100644 --- a/ets2panda/checker/ets/dynamic.cpp +++ b/ets2panda/checker/ets/dynamic.cpp @@ -20,8 +20,6 @@ #include "varbinder/declaration.h" #include "varbinder/varbinder.h" #include "varbinder/ETSBinder.h" -#include "checker/types/ets/etsDynamicFunctionType.h" -#include "checker/ets/dynamic/dynamicCall.h" #include "compiler/lowering/scopesInit/scopesInitPhase.h" #include "ir/base/classProperty.h" #include "ir/base/classStaticBlock.h" @@ -94,147 +92,6 @@ ir::ETSParameterExpression *ETSChecker::AddParam(util::StringView name, ir::Type return ProgramAllocNode(paramIdent, false, ProgramAllocator()); } -template -ir::MethodDefinition *ETSChecker::CreateDynamicCallIntrinsic(ir::Expression *callee, const ArenaVector &arguments, - Language lang) -{ - ArenaVector params(ProgramAllocator()->Adapter()); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto dynamicTypeNode = ProgramAllocNode(GlobalBuiltinDynamicType(lang), ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto intTypeNode = ProgramAllocNode(ir::PrimitiveType::INT, ProgramAllocator()); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *objParam = AddParam("obj", dynamicTypeNode); - params.push_back(objParam); - - ir::ETSParameterExpression *param2; - if (!DynamicCall::IsByValue(VarBinder()->AsETSBinder(), callee)) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - param2 = AddParam("qname_start", intTypeNode); - params.push_back(param2); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - param2 = AddParam("qname_len", intTypeNode->Clone(ProgramAllocator(), nullptr)); - } else { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - param2 = AddParam("this", dynamicTypeNode->Clone(ProgramAllocator(), nullptr)); - } - - params.push_back(param2); - - for (size_t i = 0; i < arguments.size(); i++) { - util::UString paramName("p" + std::to_string(i), ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto paramType = arguments[i]->TsType()->IsLambdaObject() - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ? dynamicTypeNode->Clone(ProgramAllocator(), nullptr) - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - : ProgramAllocNode(arguments[i]->TsType(), ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - params.emplace_back(AddParam(paramName.View(), paramType)); - } - - auto funcSignature = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ir::FunctionSignature(nullptr, std::move(params), dynamicTypeNode->Clone(ProgramAllocator(), nullptr)); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *func = ProgramAllocNode( - ProgramAllocator(), - ir::ScriptFunction::ScriptFunctionData {nullptr, std::move(funcSignature), ir::ScriptFunctionFlags::METHOD, - ir::ModifierFlags::NONE}); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *name = ProgramAllocNode(compiler::Signatures::STATIC_INVOKE_METHOD, ProgramAllocator()); - func->SetIdent(name); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *funcExpr = ProgramAllocNode(func); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *method = ProgramAllocNode( - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ir::MethodDefinitionKind::METHOD, func->Id()->Clone(ProgramAllocator(), nullptr), funcExpr, - ir::ModifierFlags::PUBLIC | ir::ModifierFlags::NATIVE | ir::ModifierFlags::STATIC, ProgramAllocator(), false); - return method; -} - -static void ToString(ETSChecker *checker, const ArenaVector &arguments, std::stringstream &ss) -{ - for (auto *arg : arguments) { - auto type = arg->Check(checker); - ss << "-"; - type->ToString(ss); - } -} - -static void ToString([[maybe_unused]] ETSChecker *checker, const ArenaVector &arguments, - std::stringstream &ss) -{ - for (auto *arg : arguments) { - auto *type = arg->TsType(); - ss << "-"; - type->ToString(ss); - } -} - -template -Signature *ETSChecker::ResolveDynamicCallExpression(ir::Expression *callee, const ArenaVector &arguments, - Language lang, bool isConstruct) -{ - auto &dynamicIntrinsics = *DynamicCallIntrinsics(isConstruct); - - auto mapIt = dynamicIntrinsics.find(lang); - if (mapIt == dynamicIntrinsics.cend()) { - std::tie(mapIt, std::ignore) = dynamicIntrinsics.emplace(lang, ProgramAllocator()->Adapter()); - } - - auto &map = mapIt->second; - - std::stringstream ss; - ss << "dyncall"; - if (DynamicCall::IsByValue(VarBinder()->AsETSBinder(), callee)) { - ss << "-byvalue"; - } else { - const auto callNames = DynamicCall::ResolveCall(VarBinder()->AsETSBinder(), callee); - DynamicCallNames(isConstruct)->try_emplace(callNames.name, 0); - } - - ToString(this, arguments, ss); - - auto key = ss.str(); - auto it = map.find(util::StringView(key)); - if (it == map.end()) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto klass = GetDynamicClass(lang, isConstruct); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *method = CreateDynamicCallIntrinsic(callee, arguments, lang); - auto props = ArenaVector(ProgramAllocator()->Adapter()); - props.emplace_back(method); - klass->Definition()->AddProperties(std::move(props)); - - { - auto prevClass = VarBinder()->AsETSBinder()->GetGlobalRecordTable()->ClassDefinition(); - VarBinder()->AsETSBinder()->GetGlobalRecordTable()->SetClassDefinition(klass->Definition()); - ProcessScopesNode(this, method); - ProcessCheckerNode(this, method); - VarBinder()->AsETSBinder()->GetGlobalRecordTable()->SetClassDefinition(prevClass); - } - method->Function()->Signature()->SetReturnType(GlobalBuiltinDynamicType(lang)); - - map.emplace(util::UString(key, ProgramAllocator()).View(), method->Function()); - return method->Function()->Signature(); - } - - return it->second->Signature(); -} - -template Signature *ETSChecker::ResolveDynamicCallExpression( - ir::Expression *callee, const ArenaVector &arguments, Language lang, bool isConstruct); - -template Signature *ETSChecker::ResolveDynamicCallExpression( - ir::Expression *callee, const ArenaVector &arguments, Language lang, bool isConstruct); - std::pair ETSChecker::CreateStaticScriptFunction( ClassInitializerBuilder const &builder) { @@ -325,33 +182,6 @@ ir::MethodDefinition *ETSChecker::CreateClassInstanceInitializer(const ClassInit return ctor; } -ir::ClassStaticBlock *ETSChecker::CreateDynamicCallClassInitializer(Language lang, bool isConstruct) -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateClassStaticInitializer( - [this, lang, isConstruct](ArenaVector *statements, - [[maybe_unused]] ArenaVector *params) { - auto [builtin_class_name, builtin_method_name] = - util::Helpers::SplitSignature(isConstruct ? compiler::Signatures::Dynamic::InitNewClassBuiltin(lang) - : compiler::Signatures::Dynamic::InitCallClassBuiltin(lang)); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *classId = ProgramAllocNode(builtin_class_name, ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *methodId = ProgramAllocNode(builtin_method_name, ProgramAllocator()); - auto *callee = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, - false, false); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *initCall = ProgramAllocNode( - callee, ArenaVector(ProgramAllocator()->Adapter()), nullptr, false); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - statements->push_back(ProgramAllocNode(initCall)); - }); -} - ir::ClassDeclaration *ETSChecker::BuildClass(util::StringView name, const ClassBuilder &builder) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) @@ -385,94 +215,6 @@ ir::ClassDeclaration *ETSChecker::BuildClass(util::StringView name, const ClassB return classDecl; } -ir::ClassProperty *ETSChecker::CreateStaticReadonlyField(const char *name) -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *fieldIdent = ProgramAllocNode(name, ProgramAllocator()); - auto flags = ir::ModifierFlags::STATIC | ir::ModifierFlags::PRIVATE | ir::ModifierFlags::READONLY; - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *field = ProgramAllocNode( - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - fieldIdent, nullptr, ProgramAllocNode(ir::PrimitiveType::INT, ProgramAllocator()), flags, - ProgramAllocator(), false); - return field; -} - -ir::ClassDeclaration *ETSChecker::GetDynamicClass(Language lang, bool isConstruct) -{ - auto &klasses = dynamicClasses_[static_cast(isConstruct)]; - if (klasses.count(lang) != 0U) { - return klasses[lang]; - } - auto className = - isConstruct ? compiler::Signatures::Dynamic::NewClass(lang) : compiler::Signatures::Dynamic::CallClass(lang); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto klass = BuildClass(className, [this, lang, isConstruct](ArenaVector *classBody) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateStaticReadonlyField("qname_start_from")); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateDynamicCallClassInitializer(lang, isConstruct)); - }); - klasses.emplace(lang, klass); - return klass; -} - -void ETSChecker::ClassInitializerFromImport(ir::ETSImportDeclaration *import, ArenaVector *statements) -{ - auto builtin = compiler::Signatures::Dynamic::LoadModuleBuiltin(import->Language()); - auto [builtin_class_name, builtin_method_name] = util::Helpers::SplitSignature(builtin); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *classId = ProgramAllocNode(builtin_class_name, ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *methodId = ProgramAllocNode(builtin_method_name, ProgramAllocator()); - auto *callee = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, - false); - - // NOTE: #23698. Make 'ohmUrl' mandatory in 'dynamicPaths'. - util::StringView ohmUrl = util::UString(import->OhmUrl(), ProgramAllocator()).View(); - if (ohmUrl.Empty()) { - ohmUrl = import->ResolvedSource(); - if (ark::os::file::File::IsRegularFile(ohmUrl.Mutf8())) { - ohmUrl = util::UString(ark::os::RemoveExtension(ohmUrl.Mutf8()), ProgramAllocator()).View(); - } - } - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ArenaVector callParams({ProgramAllocNode(ohmUrl)}, - ProgramAllocator()->Adapter()); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *loadCall = ProgramAllocNode(callee, std::move(callParams), nullptr, false); - auto *moduleClassId = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(compiler::Signatures::DYNAMIC_MODULE_CLASS, ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *fieldId = ProgramAllocNode(import->AssemblerName(), ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *property = ProgramAllocNode(moduleClassId, fieldId, - ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - - auto *initializer = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(property, loadCall, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - statements->push_back(ProgramAllocNode(initializer)); -} - -ir::ClassStaticBlock *ETSChecker::CreateDynamicModuleClassInitializer( - const std::vector &imports) -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateClassStaticInitializer([this, imports](ArenaVector *statements, - [[maybe_unused]] ArenaVector *params) { - for (auto *import : imports) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ClassInitializerFromImport(import, statements); - } - }); -} - ir::MethodDefinition *ETSChecker::CreateClassMethod(const std::string_view name, ir::ScriptFunctionFlags funcFlags, ir::ModifierFlags modifierFlags, const MethodBuilder &builder) { @@ -510,227 +252,4 @@ ir::MethodDefinition *ETSChecker::CreateClassMethod(const std::string_view name, return method; } -ir::MethodDefinition *ETSChecker::CreateDynamicModuleClassInitMethod() -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateClassMethod(compiler::Signatures::DYNAMIC_MODULE_CLASS_INIT, ir::ScriptFunctionFlags::METHOD, - ir::ModifierFlags::PUBLIC | ir::ModifierFlags::STATIC, - [this]([[maybe_unused]] ArenaVector *statements, - [[maybe_unused]] ArenaVector *params, - Type **returnType) { *returnType = GlobalVoidType(); }); -} - -ir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInvokeMethod(Signature *invokeSignature, - ir::TypeNode *retTypeAnnotation) -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateClassMethod( - compiler::Signatures::LAMBDA_OBJECT_INVOKE, ir::ScriptFunctionFlags::METHOD, ir::ModifierFlags::PUBLIC, - [this, invokeSignature, retTypeAnnotation](ArenaVector *statements, - ArenaVector *params, Type **returnType) { - util::UString thisParamName(std::string("this"), ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ir::ETSParameterExpression *thisParam = AddParam(thisParamName.View(), nullptr); - params->push_back(thisParam); - - ArenaVector callParams(ProgramAllocator()->Adapter()); - for (auto *invokeParam : invokeSignature->Params()) { - auto paramName = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - util::UString(std::string("p") + std::to_string(callParams.size()), ProgramAllocator()).View(); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *param = AddParam(paramName, - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(invokeParam->TsType(), ProgramAllocator())); - params->push_back(param); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - callParams.push_back(param->Clone(ProgramAllocator(), nullptr)); - } - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *properyId = ProgramAllocNode("jsvalue_lambda", ProgramAllocator()); - auto *callee = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(thisParam->Clone(ProgramAllocator(), nullptr), properyId, - ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *callLambda = ProgramAllocNode(callee, std::move(callParams), nullptr, false); - - auto *castToRetTypeExpr = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(callLambda, retTypeAnnotation->Clone(ProgramAllocator(), nullptr), - false); - castToRetTypeExpr->SetTsType(invokeSignature->ReturnType()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *retStatement = ProgramAllocNode(castToRetTypeExpr); - statements->push_back(retStatement); - - *returnType = invokeSignature->ReturnType(); - }); -} - -void ETSChecker::EmitDynamicModuleClassInitCall() -{ - auto *globalClass = VarBinder()->Program()->GlobalClass(); - auto &body = globalClass->Body(); - auto it = std::find_if(body.begin(), body.end(), [](ir::AstNode *node) { return node->IsClassStaticBlock(); }); - - ES2PANDA_ASSERT(it != body.end()); - - auto *staticBlock = (*it)->AsClassStaticBlock(); - auto *cctorBody = staticBlock->Function()->Body()->AsBlockStatement(); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *classId = ProgramAllocNode(compiler::Signatures::DYNAMIC_MODULE_CLASS, ProgramAllocator()); - auto *methodId = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(compiler::Signatures::DYNAMIC_MODULE_CLASS_INIT, ProgramAllocator()); - auto *callee = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(classId, methodId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, - false); - - ArenaVector callParams(ProgramAllocator()->Adapter()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *initCall = ProgramAllocNode(callee, std::move(callParams), nullptr, false); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *const node = ProgramAllocNode(initCall); - node->SetParent(cctorBody); - cctorBody->AddStatement(node); - - ProcessScopesNode(this, node); - ProcessCheckerNode(this, node); -} - -void ETSChecker::BuildClassBodyFromDynamicImports(const ArenaVector &dynamicImports, - ArenaVector *classBody) -{ - std::unordered_set fields; - std::vector imports; - - for (auto *import : dynamicImports) { - auto source = import->Source()->Str(); - if (fields.find(source) != fields.cend()) { - continue; - } - - auto assemblyName = std::string(source); - std::replace_if( - assemblyName.begin(), assemblyName.end(), [](char c) { return std::isalnum(c) == 0; }, '_'); - assemblyName.append(std::to_string(fields.size())); - - import->SetAssemblerName(util::UString(assemblyName, ProgramAllocator()).View()); - fields.insert(import->AssemblerName()); - imports.push_back(import); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *fieldIdent = ProgramAllocNode(import->AssemblerName(), ProgramAllocator()); - auto flags = ir::ModifierFlags::STATIC | ir::ModifierFlags::PUBLIC | ir::ModifierFlags::READONLY; - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *field = ProgramAllocNode( - fieldIdent, nullptr, - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(GlobalBuiltinDynamicType(import->Language()), ProgramAllocator()), - flags, ProgramAllocator(), false); - - classBody->push_back(field); - } - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateDynamicModuleClassInitializer(imports)); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateDynamicModuleClassInitMethod()); -} - -void ETSChecker::BuildDynamicImportClass() -{ - const auto &dynamicImports = VarBinder()->AsETSBinder()->DynamicImports(); - if (dynamicImports.empty()) { - return; - } - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - BuildClass(compiler::Signatures::DYNAMIC_MODULE_CLASS, - [this, dynamicImports](ArenaVector *classBody) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - BuildClassBodyFromDynamicImports(dynamicImports, classBody); - }); - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - EmitDynamicModuleClassInitCall(); -} - -ir::MethodDefinition *ETSChecker::CreateLambdaObjectClassInitializer(ETSObjectType *functionalInterface) -{ - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - return CreateClassInstanceInitializer( - [this](ArenaVector *statements, ArenaVector *params) { - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ir::ETSParameterExpression *thisParam = AddParam(varbinder::VarBinder::MANDATORY_PARAM_THIS, nullptr); - params->push_back(thisParam); - - util::UString jsvalueParamName(std::string("jsvalue_param"), ProgramAllocator()); - ir::ETSParameterExpression *jsvalueParam = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - AddParam(jsvalueParamName.View(), - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(GlobalBuiltinJSValueType(), ProgramAllocator())); - params->push_back(jsvalueParam); - auto *moduleClassId = - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - ProgramAllocNode(varbinder::VarBinder::MANDATORY_PARAM_THIS, ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *fieldId = ProgramAllocNode("jsvalue_lambda", ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *property = ProgramAllocNode( - moduleClassId, fieldId, ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *initializer = ProgramAllocNode( - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - property, jsvalueParam->Clone(ProgramAllocator(), nullptr), lexer::TokenType::PUNCTUATOR_SUBSTITUTION); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - statements->push_back(ProgramAllocNode(initializer)); - }, - functionalInterface); -} - -void ETSChecker::BuildLambdaObjectClass(ETSObjectType *functionalInterface, ir::TypeNode *retTypeAnnotation) -{ - auto *invokeMethod = functionalInterface->GetOwnProperty( - compiler::Signatures::STATIC_INVOKE_METHOD); - auto *invokeSignature = invokeMethod->TsType()->AsETSFunctionType()->CallSignatures()[0]; - - std::stringstream ss; - ss << compiler::Signatures::LAMBDA_OBJECT; - ToString(this, invokeSignature->Params(), ss); - auto syntheticLambdaObjName = ss.str(); - if (dynamicLambdaSignatureCache_.count(syntheticLambdaObjName) != 0) { - functionalInterface->AddConstructSignature(dynamicLambdaSignatureCache_[syntheticLambdaObjName]); - return; - } - - auto buildBody = [this, invokeSignature, retTypeAnnotation, - functionalInterface](ArenaVector *classBody) { - auto assemblyName = "jsvalue_lambda"; - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *fieldIdent = ProgramAllocNode(assemblyName, ProgramAllocator()); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - auto *field = ProgramAllocNode( - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - fieldIdent, nullptr, ProgramAllocNode(GlobalBuiltinJSValueType(), ProgramAllocator()), - ir::ModifierFlags::PRIVATE, ProgramAllocator(), false); - classBody->push_back(field); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateLambdaObjectClassInitializer(functionalInterface)); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - classBody->push_back(CreateLambdaObjectClassInvokeMethod(invokeSignature, retTypeAnnotation)); - }; - - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - BuildClass(util::StringView(syntheticLambdaObjName), buildBody); - - dynamicLambdaSignatureCache_[syntheticLambdaObjName] = functionalInterface->ConstructSignatures()[0]; -} - } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/dynamic/dynamicCall.cpp b/ets2panda/checker/ets/dynamic/dynamicCall.cpp deleted file mode 100644 index a80dd1fd2d..0000000000 --- a/ets2panda/checker/ets/dynamic/dynamicCall.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2021-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "checker/ets/dynamic/dynamicCall.h" - -#include "ir/ets/etsImportDeclaration.h" -#include "ir/ets/etsTypeReference.h" -#include "ir/ets/etsTypeReferencePart.h" -#include "ir/module/importSpecifier.h" -#include "ir/ts/tsQualifiedName.h" -#include "ir/expressions/memberExpression.h" - -namespace ark::es2panda::checker { - -DynamicCall::Result DynamicCall::ResolveCall(const varbinder::ETSBinder *varbinder, const ir::Expression *callee) -{ - auto calleeName = NameHolder(varbinder->Allocator()->Adapter()); - - if (callee->IsETSTypeReference()) { - // new A.B.C() => call js.new(A, ".B.C") - callee = callee->AsETSTypeReference()->Part()->Name(); - while (callee->IsTSQualifiedName()) { - auto *qname = callee->AsTSQualifiedName(); - callee = qname->Left(); - calleeName.emplace_back(qname->Right()->AsIdentifier()->Name()); - } - ES2PANDA_ASSERT(callee->IsIdentifier()); - } else if (callee->IsMemberExpression()) { - const auto memberExpr = callee->AsMemberExpression(); - callee = SqueezeExpr(memberExpr, calleeName); - } - if (callee->IsIdentifier()) { - // kinda optimization in case: - // `import X from Y` to use (load Y, call "X"), instead of (load Y, load X, call) - const auto var = callee->AsIdentifier()->Variable(); - const auto *data = varbinder->DynamicImportDataForVar(var); - if (data != nullptr && data->specifier != nullptr && data->specifier->IsImportSpecifier()) { - calleeName.emplace_back(data->specifier->AsImportSpecifier()->Imported()->Name()); - std::reverse(calleeName.begin(), calleeName.end()); - return {data->import, calleeName}; - } - } - std::reverse(calleeName.begin(), calleeName.end()); - return {callee, calleeName}; -} - -DynamicCall::Result DynamicCall::SqueezeExpr(ArenaAllocator *allocator, const ir::MemberExpression *expr) -{ - NameHolder name(allocator->Adapter()); - auto obj = SqueezeExpr(expr, name); - std::reverse(name.begin(), name.end()); - return {obj, name}; -} - -const ir::Expression *DynamicCall::SqueezeExpr(const ir::MemberExpression *memberExpr, NameHolder &name) -{ - if (!memberExpr->Object()->TsType()->IsETSDynamicType() || memberExpr->IsComputed()) { - return memberExpr; - } - ES2PANDA_ASSERT(memberExpr->Property()->IsIdentifier()); - name.emplace_back(memberExpr->Property()->AsIdentifier()->Name()); - if (memberExpr->Object()->IsMemberExpression()) { - return SqueezeExpr(memberExpr->Object()->AsMemberExpression(), name); - } - return memberExpr->Object(); -} - -} // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/dynamic/dynamicCall.h b/ets2panda/checker/ets/dynamic/dynamicCall.h deleted file mode 100644 index b4de6cfd0a..0000000000 --- a/ets2panda/checker/ets/dynamic/dynamicCall.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2021 - 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ARK_DYNAMICCALLINFO_H -#define ARK_DYNAMICCALLINFO_H - -#include - -#include "varbinder/ETSBinder.h" -#include "ir/expression.h" - -namespace ark::es2panda::checker { - -class DynamicCall { - using NameHolder = ArenaVector; - -public: - struct Result { - const ir::AstNode *obj; - const NameHolder name; // NOLINT(readability-identifier-naming) - }; - - /** - * Resolve callee - * @param varbinder - * @param callee expression used to call method - * @return callee and name from which should be used to produce call - */ - static Result ResolveCall(const varbinder::ETSBinder *varbinder, const ir::Expression *callee); - static bool IsByValue(const varbinder::ETSBinder *varbinder, const ir::Expression *callee) - { - return ResolveCall(varbinder, callee).name.empty(); - } - - /** - * Example: A[0].C.D => return: A[0], name: ".C.D" - * @param expr member expression - * @param name to store result - * @return object with remaining member expression - */ - static Result SqueezeExpr(ArenaAllocator *allocator, const ir::MemberExpression *expr); - -private: - static const ir::Expression *SqueezeExpr(const ir::MemberExpression *expr, NameHolder &name); -}; - -} // namespace ark::es2panda::checker -#endif // ARK_DYNAMICCALLINFO_H diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 40338b0c4a..ea80a961c3 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1686,13 +1686,8 @@ checker::ETSFunctionType *ETSChecker::BuildMethodType(ir::ScriptFunction *func) { ES2PANDA_ASSERT(!func->IsArrow()); auto *nameVar = func->Id()->Variable(); - ETSFunctionType *funcType; - if (func->IsDynamic()) { - funcType = CreateETSDynamicMethodType(nameVar->Name(), {{func->Signature()}, ProgramAllocator()->Adapter()}, - func->Language()); - } else { - funcType = CreateETSMethodType(nameVar->Name(), {{func->Signature()}, ProgramAllocator()->Adapter()}); - } + ETSFunctionType *funcType = + CreateETSMethodType(nameVar->Name(), {{func->Signature()}, ProgramAllocator()->Adapter()}); funcType->SetVariable(nameVar); return funcType; } diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 13f3575f66..553abd66e2 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -652,7 +652,7 @@ static bool SetPreferredTypeForExpression(ETSChecker *checker, ir::Identifier *i checker->SetArrayPreferredTypeForNestedMemberExpressions(init->AsMemberExpression(), annotationType); } - if (init->IsArrayExpression() && (annotationType != nullptr) && !annotationType->IsETSDynamicType()) { + if (init->IsArrayExpression() && (annotationType != nullptr)) { if (annotationType->IsETSTupleType() && !checker->IsArrayExprSizeValidForTuple(init->AsArrayExpression(), annotationType->AsETSTupleType())) { return false; @@ -1756,11 +1756,6 @@ Type *ETSChecker::GetReferencedTypeBase(ir::Expression *name) return name->SetTsType(GlobalTypeError()); } - auto *importData = VarBinder()->AsETSBinder()->DynamicImportDataForVar(var); - if (importData != nullptr && importData->import->IsPureDynamic()) { - return name->SetTsType(GlobalBuiltinDynamicType(importData->import->Language())); - } - return name->SetTsType(ResolveReferencedType(var->AsLocalVariable(), name)); } diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 4760ea0ca1..ce34a1924a 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -16,7 +16,6 @@ #include #include "checker/ETSchecker.h" #include "checker/ets/typeRelationContext.h" -#include "checker/types/ets/etsDynamicType.h" #include "checker/types/ets/etsObjectType.h" #include "checker/types/ets/etsTupleType.h" #include "checker/types/ets/etsPartialTypeParameter.h" @@ -2177,13 +2176,6 @@ std::vector ETSChecker::ResolveMemberReference(const ir::Member { std::vector resolveRes {}; - if (target->IsETSDynamicType() && !target->AsETSDynamicType()->HasDecl()) { - auto propName = memberExpr->Property()->AsIdentifier()->Name(); - varbinder::LocalVariable *propVar = target->AsETSDynamicType()->GetPropertyDynamic(propName, this); - resolveRes.emplace_back(ProgramAllocator()->New(propVar, ResolvedKind::PROPERTY)); - return resolveRes; - } - if (target->GetDeclNode() != nullptr && target->GetDeclNode()->IsClassDefinition() && !target->GetDeclNode()->AsClassDefinition()->IsClassDefinitionChecked()) { // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) @@ -2258,9 +2250,6 @@ void ETSChecker::CheckValidInheritance(ETSObjectType *classType, ir::ClassDefini if (classType->SuperType() == nullptr) { return; } - if (classType->SuperType()->IsETSDynamicType()) { - LogError(diagnostic::EXTEND_DYNAMIC, {classDef->Ident()->Name()}, classDef->Start()); - } const auto &allProps = classType->GetAllProperties(); diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 39970f37d6..dbb75b798a 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -563,14 +563,6 @@ Type *ETSChecker::GetTypeOfVariable(varbinder::Variable *const var) return var->TsType(); } - // NOTE: kbaladurin. forbid usage of imported entities as types without declarations - if (VarBinder()->AsETSBinder()->IsDynamicModuleVariable(var)) { - auto *importData = VarBinder()->AsETSBinder()->DynamicImportDataForVar(var); - if (importData->import->IsPureDynamic()) { - return GlobalBuiltinDynamicType(importData->import->Language()); - } - } - checker::SavedCheckerContext savedContext(this, CheckerStatus::NO_OPTS); checker::ScopeContext scopeCtx(this, var->GetScope()); IterateInVariableContext(var); @@ -1308,10 +1300,6 @@ void ETSChecker::CheckBoxedSourceTypeAssignable(TypeRelation *relation, Type *so return; } ES2PANDA_ASSERT(target != nullptr); - // Do not box primitive in case of cast to dynamic types - if (target->IsETSDynamicType()) { - return; - } relation->IsAssignableTo(boxedSourceType, target); if (!relation->IsTrue()) { auto unboxedTargetType = MaybeUnboxInRelation(target); diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index fd835f0b7a..1c8c6c9a98 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -17,7 +17,6 @@ #include "checker/types/ets/etsAsyncFuncReturnType.h" #include "checker/types/ets/etsEnumType.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "checker/types/ets/etsResizableArrayType.h" #include "checker/types/globalTypesHolder.h" #include "checker/types/type.h" @@ -158,17 +157,6 @@ ETSFunctionType *ETSChecker::CreateETSMethodType(util::StringView name, ArenaVec return ProgramAllocator()->New(this, name, std::move(signatures)); } -ETSFunctionType *ETSChecker::CreateETSDynamicArrowType(Signature *signature, Language lang) -{ - return ProgramAllocator()->New(this, signature, lang); -} - -ETSFunctionType *ETSChecker::CreateETSDynamicMethodType(util::StringView name, ArenaVector &&signatures, - Language lang) -{ - return ProgramAllocator()->New(this, name, std::move(signatures), lang); -} - static SignatureFlags ConvertToSignatureFlags(ir::ModifierFlags inModifiers, ir::ScriptFunctionFlags inFunctionFlags) { SignatureFlags outFlags = SignatureFlags::NO_OPTS; @@ -341,31 +329,6 @@ ETSObjectType *ETSChecker::CreateETSObjectTypeOrBuiltin(ir::AstNode *declNode, E return InitializeGlobalBuiltinObjectType(this, globalId.value(), declNode, flags); } -std::tuple ETSChecker::CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName) -{ - Language lang(Language::Id::ETS); - bool hasDecl = false; - - if (declNode->IsClassDefinition()) { - auto *clsDef = declNode->AsClassDefinition(); - lang = clsDef->Language(); - hasDecl = clsDef->IsDeclare(); - } - - if (declNode->IsTSInterfaceDeclaration()) { - auto *ifaceDecl = declNode->AsTSInterfaceDeclaration(); - lang = ifaceDecl->Language(); - hasDecl = ifaceDecl->IsDeclare(); - } - - auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8()); - if (res) { - lang = *res; - } - - return std::make_tuple(lang, hasDecl); -} - ETSObjectType *ETSChecker::CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags) { auto const [name, internalName] = GetObjectTypeDeclNames(declNode); @@ -383,12 +346,6 @@ ETSObjectType *ETSChecker::CreateETSObjectType(ir::AstNode *declNode, ETSObjectF return ProgramAllocator()->New(ProgramAllocator(), name, std::make_tuple(declNode, flags, Relation())); } - - if (auto [lang, hasDecl] = CheckForDynamicLang(declNode, internalName); lang.IsDynamic()) { - return ProgramAllocator()->New(ProgramAllocator(), std::make_tuple(name, internalName, lang), - std::make_tuple(declNode, flags, Relation()), hasDecl); - } - return ProgramAllocator()->New(ProgramAllocator(), name, internalName, std::make_tuple(declNode, flags, Relation())); } diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index 8d28ba8fd7..96d8ceedff 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -68,7 +68,7 @@ void ETSChecker::ValidateCallExpressionIdentifier(ir::Identifier *const ident, T ident->Variable()->Declaration()->Node()->IsImportNamespaceSpecifier()) { std::ignore = TypeError(ident->Variable(), diagnostic::NAMESPACE_CALL, {ident->ToString()}, ident->Start()); } - if (type->IsETSFunctionType() || type->IsETSDynamicType()) { + if (type->IsETSFunctionType()) { return; } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) diff --git a/ets2panda/checker/types/ets/etsDynamicFunctionType.h b/ets2panda/checker/types/ets/etsDynamicFunctionType.h deleted file mode 100644 index 77a3c5731b..0000000000 --- a/ets2panda/checker/types/ets/etsDynamicFunctionType.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2024-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_FUNCTION_TYPE_H -#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_FUNCTION_TYPE_H - -#include "checker/types/ets/etsFunctionType.h" -#include "checker/ETSchecker.h" - -namespace ark::es2panda::checker { - -class ETSDynamicFunctionType : public ETSFunctionType { -public: - explicit ETSDynamicFunctionType(ETSChecker *checker, util::StringView name, ArenaVector &&signatures, - Language lang) - : ETSFunctionType(checker, name, std::move(signatures)), lang_(lang) - { - AddTypeFlag(TypeFlag::ETS_DYNAMIC_FUNCTION_TYPE); - } - - explicit ETSDynamicFunctionType(ETSChecker *checker, Signature *signature, Language lang) - : ETSFunctionType(checker, signature), lang_(lang) - { - AddTypeFlag(TypeFlag::ETS_DYNAMIC_FUNCTION_TYPE); - } - - ETSDynamicFunctionType() = delete; - ~ETSDynamicFunctionType() override = default; - NO_COPY_SEMANTIC(ETSDynamicFunctionType); - NO_MOVE_SEMANTIC(ETSDynamicFunctionType); - - es2panda::Language Language() const - { - return lang_; - } - -private: - es2panda::Language lang_; -}; -} // namespace ark::es2panda::checker - -#endif /* ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_FUNCTION_TYPE_H */ diff --git a/ets2panda/checker/types/ets/etsDynamicType.cpp b/ets2panda/checker/types/ets/etsDynamicType.cpp deleted file mode 100644 index cd6be095d6..0000000000 --- a/ets2panda/checker/types/ets/etsDynamicType.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2021-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "etsDynamicType.h" -#include "checker/ETSchecker.h" -#include "checker/ets/conversion.h" -#include "checker/types/ets/etsDynamicFunctionType.h" - -namespace ark::es2panda::checker { - -varbinder::LocalVariable *ETSDynamicType::GetPropertyDynamic(const util::StringView &name, - const ETSChecker *checker) const -{ - auto it = propertiesCache_.find(name); - if (it != propertiesCache_.end()) { - return it->second; - } - - varbinder::LocalVariable *var = varbinder::Scope::CreateVar( - Allocator(), name, varbinder::VariableFlags::BUILTIN_TYPE, nullptr); - var->SetTsType(checker->GlobalBuiltinDynamicType(lang_)); - propertiesCache_.emplace(name, var); - - return var; -} - -void ETSDynamicType::AssignmentTarget(TypeRelation *relation, Type *source) -{ - if (hasDecl_) { - return ETSObjectType::AssignmentTarget(relation, source); - } - - if (relation->ApplyBoxing() && !relation->IsTrue() && IsConvertible(source)) { - relation->Result(true); - return; - } - - if (source->IsETSDynamicType()) { - relation->Result(true); - } -} - -bool ETSDynamicType::AssignmentSource(TypeRelation *relation, Type *target) -{ - if (hasDecl_) { - return ETSObjectType::AssignmentSource(relation, target); - } - - if (relation->ApplyUnboxing() && IsConvertible(target)) { - relation->Result(true); - return true; - } - - if (target->IsETSDynamicType()) { - relation->Result(true); - } - return relation->IsTrue(); -} - -void ETSDynamicType::Cast(TypeRelation *relation, Type *target) -{ - if (hasDecl_) { - return ETSObjectType::Cast(relation, target); - } - - if (relation->InCastingContext() || IsConvertible(target)) { - relation->Result(true); - return; - } - - conversion::Forbidden(relation); -} - -void ETSDynamicType::CastTarget(TypeRelation *relation, Type *source) -{ - if (hasDecl_) { - ETSObjectType::CastTarget(relation, source); - return; - } - - if (relation->InCastingContext() || IsConvertible(source)) { - relation->Result(true); - return; - } - - conversion::Forbidden(relation); -} - -bool ETSDynamicType::IsConvertible(Type const *target) -{ - return target->IsETSDynamicType() || target->IsETSObjectType() || target->IsETSArrayType() || - target->IsETSTupleType() || target->IsETSFunctionType() || - target->HasTypeFlag(checker::TypeFlag::ETS_CONVERTIBLE_TO_NUMERIC | checker::TypeFlag::ETS_BOOLEAN); -} - -ETSFunctionType *ETSDynamicType::CreateMethodTypeForProp(util::StringView name) const -{ - auto checker = GetRelation()->GetChecker()->AsETSChecker(); - return checker->CreateETSDynamicMethodType(name, {{}, Allocator()->Adapter()}, lang_); -} - -void ETSDynamicType::ToAssemblerType(std::stringstream &ss) const -{ - ss << compiler::Signatures::Dynamic::Type(lang_); -} - -} // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsDynamicType.h b/ets2panda/checker/types/ets/etsDynamicType.h deleted file mode 100644 index 47b99e3102..0000000000 --- a/ets2panda/checker/types/ets/etsDynamicType.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2021-2025 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_TYPE_H -#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_TYPE_H - -#include "checker/types/ets/etsObjectType.h" - -namespace ark::es2panda::checker { -class ETSDynamicType : public ETSObjectType { - static constexpr auto NAME = 0; - static constexpr auto ASSEMBLER_NAME = 1; - static constexpr auto LANGUAGE = 2; - static constexpr auto DECL_NODE = 0; - static constexpr auto FLAGS = 1; - static constexpr auto RELATION = 2; - -public: - explicit ETSDynamicType(ThreadSafeArenaAllocator *allocator, - std::tuple label, - std::tuple info, bool hasDecl) - : ETSObjectType(allocator, std::get(label), std::get(label), - std::make_tuple(std::get(info), std::get(info) | ETSObjectFlags::DYNAMIC, - std::get(info))), - propertiesCache_ {allocator->Adapter()}, - lang_(std::get(label)), - hasDecl_(hasDecl) - { - AddTypeFlag(TypeFlag::ETS_DYNAMIC_TYPE); - } - - varbinder::LocalVariable *GetPropertyDynamic(const util::StringView &name, const ETSChecker *checker) const; - void AssignmentTarget(TypeRelation *relation, Type *source) override; - bool AssignmentSource(TypeRelation *relation, Type *target) override; - void Cast(TypeRelation *relation, Type *target) override; - void CastTarget(TypeRelation *relation, Type *source) override; - - es2panda::Language Language() const - { - return lang_; - } - - bool HasDecl() const - { - return hasDecl_; - } - - ETSFunctionType *CreateMethodTypeForProp(util::StringView name) const override; - - void ToAssemblerType(std::stringstream &ss) const override; - - static bool IsConvertible(Type const *target); - -private: - mutable PropertyMap propertiesCache_; - es2panda::Language lang_; - bool hasDecl_; -}; -} // namespace ark::es2panda::checker - -#endif diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index 5a9a176d9c..d6b776d64c 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -263,16 +263,6 @@ bool ETSFunctionType::AssignmentSource(TypeRelation *relation, Type *target) { AssertNoMethodsInFunctionRelation(this, target); - // this should be defined by the dynamic type itself - if (target->IsETSDynamicType()) { - ES2PANDA_ASSERT(relation->GetNode() != nullptr); - if (relation->GetNode()->IsArrowFunctionExpression()) { - ES2PANDA_ASSERT(callSignatures_.size() == 1 && ArrowSignature()->HasSignatureFlag(SignatureFlags::CALL)); - return relation->Result(true); - } - return relation->Result(false); - } - return relation->IsSupertypeOf(target, this); } diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index c86dbcd510..f4626cb22a 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -553,9 +553,6 @@ bool ETSObjectType::AssignmentSource(TypeRelation *const relation, [[maybe_unuse bool ETSObjectType::IsBoxedPrimitive() const { - if (this->IsETSDynamicType()) { - return false; - } if (this->IsETSEnumType()) { return false; } @@ -1137,31 +1134,6 @@ static std::pair GetObjectTypeDeclNames(ir:: return {node->AsAnnotationDeclaration()->GetBaseName()->Name(), node->AsAnnotationDeclaration()->InternalName()}; } -static std::tuple CheckForDynamicLang(ir::AstNode *declNode, util::StringView assemblerName) -{ - Language lang(Language::Id::ETS); - bool hasDecl = false; - - if (declNode->IsClassDefinition()) { - auto *clsDef = declNode->AsClassDefinition(); - lang = clsDef->Language(); - hasDecl = clsDef->IsDeclare(); - } - - if (declNode->IsTSInterfaceDeclaration()) { - auto *ifaceDecl = declNode->AsTSInterfaceDeclaration(); - lang = ifaceDecl->Language(); - hasDecl = ifaceDecl->IsDeclare(); - } - - auto res = compiler::Signatures::Dynamic::LanguageFromType(assemblerName.Utf8()); - if (res) { - lang = *res; - } - - return std::make_tuple(lang, hasDecl); -} - ETSObjectType *ETSObjectType::CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags) { auto const [name, internalName] = GetObjectTypeDeclNames(declNode); @@ -1173,12 +1145,6 @@ ETSObjectType *ETSObjectType::CreateETSObjectType(ir::AstNode *declNode, ETSObje ES2PANDA_ASSERT(declNode->AsClassDefinition()->IsStringEnumTransformed()); return Allocator()->New(Allocator(), name, internalName, declNode, GetRelation()); } - - if (auto [lang, hasDecl] = CheckForDynamicLang(declNode, internalName); lang.IsDynamic()) { - return Allocator()->New(Allocator(), std::make_tuple(name, internalName, lang), - std::make_tuple(declNode, flags, GetRelation()), hasDecl); - } - if (internalName == compiler::Signatures::BUILTIN_ARRAY) { return Allocator()->New(Allocator(), name, std::make_tuple(declNode, flags, GetRelation())); diff --git a/ets2panda/checker/types/ets/types.h b/ets2panda/checker/types/ets/types.h index ce05b8b154..e82a8fa0a5 100644 --- a/ets2panda/checker/types/ets/types.h +++ b/ets2panda/checker/types/ets/types.h @@ -32,7 +32,6 @@ #include "etsBigIntType.h" #include "etsObjectType.h" #include "etsTypeAliasType.h" -#include "etsDynamicType.h" #include "etsArrayType.h" #include "wildcardType.h" #include "etsTypeParameter.h" diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index c3d06181de..d3f83e9d37 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -29,10 +29,8 @@ class Variable; namespace ark::es2panda::checker { class ObjectDescriptor; class GlobalTypesHolder; -class ETSDynamicType; class ETSAsyncFuncReturnType; class ETSChecker; -class ETSDynamicFunctionType; class ETSTypeParameter; class ETSEnumType; @@ -143,25 +141,8 @@ public: return reinterpret_cast(this); } - [[nodiscard]] bool IsETSDynamicType() const noexcept - { - return IsETSObjectType() && HasTypeFlag(TypeFlag::ETS_DYNAMIC_FLAG); - } - [[nodiscard]] bool IsBuiltinNumeric() const noexcept; - ETSDynamicType *AsETSDynamicType() - { - ES2PANDA_ASSERT(IsETSDynamicType()); - return reinterpret_cast(this); - } - - const ETSDynamicType *AsETSDynamicType() const - { - ES2PANDA_ASSERT(IsETSDynamicType()); - return reinterpret_cast(this); - } - ETSAsyncFuncReturnType *AsETSAsyncFuncReturnType() { ES2PANDA_ASSERT(IsETSAsyncFuncReturnType()); @@ -174,23 +155,6 @@ public: return reinterpret_cast(this); } - bool IsETSDynamicFunctionType() const - { - return TypeFlags() == TypeFlag::ETS_DYNAMIC_FUNCTION_TYPE; - } - - ETSDynamicFunctionType *AsETSDynamicFunctionType() - { - ES2PANDA_ASSERT(IsETSDynamicFunctionType()); - return reinterpret_cast(this); - } - - const ETSDynamicFunctionType *AsETSDynamicFunctionType() const - { - ES2PANDA_ASSERT(IsETSDynamicFunctionType()); - return reinterpret_cast(this); - } - bool IsConstantType() const { return HasTypeFlag(checker::TypeFlag::CONSTANT); diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index 80a8ad001a..5ebe65a859 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -154,14 +154,6 @@ bool TypeRelation::IsAssignableTo(Type *source, Type *target) bool TypeRelation::IsComparableTo(Type *source, Type *target) { result_ = CacheLookup(source, target, checker_->ComparableResults(), RelationType::COMPARABLE); - - // NOTE: vpukhov. reimplement dynamic comparison and remove this check - if (source->IsETSDynamicType() || target->IsETSDynamicType()) { - if (!(source->IsETSDynamicType() && target->IsETSDynamicType())) { - return false; - } - } - if (result_ == RelationResult::CACHE_MISS) { if (IsAssignableTo(source, target)) { return true; diff --git a/ets2panda/compiler/base/lreference.cpp b/ets2panda/compiler/base/lreference.cpp index 9f9a3c45c0..96572db071 100644 --- a/ets2panda/compiler/base/lreference.cpp +++ b/ets2panda/compiler/base/lreference.cpp @@ -183,8 +183,7 @@ ETSLReference::ETSLReference(CodeGen *cg, const ir::AstNode *node, ReferenceKind const auto *memberExpr = Node()->AsMemberExpression(); staticObjRef_ = memberExpr->Object()->TsType(); - if (!memberExpr->IsComputed() && etsg_->Checker()->IsVariableStatic(memberExpr->PropVar()) && - !staticObjRef_->IsETSDynamicType()) { + if (!memberExpr->IsComputed() && etsg_->Checker()->IsVariableStatic(memberExpr->PropVar())) { return; } @@ -281,11 +280,6 @@ void ETSLReference::SetValueComputed(const ir::MemberExpression *memberExpr) con { const auto *const objectType = memberExpr->Object()->TsType(); - if (objectType->IsETSDynamicType()) { - etsg_->StoreElementDynamic(Node(), baseReg_, propReg_); - return; - } - if (objectType->IsETSTupleType()) { ES2PANDA_ASSERT(memberExpr->GetTupleIndexValue().has_value()); @@ -350,22 +344,13 @@ void ETSLReference::SetValue() const if (memberExpr->PropVar()->HasFlag(varbinder::VariableFlags::STATIC)) { const util::StringView fullName = etsg_->FormClassPropReference(staticObjRef_->AsETSObjectType(), propName); - if (staticObjRef_->IsETSDynamicType()) { - etsg_->StorePropertyDynamic(Node(), memberExprTsType, baseReg_, propName); - } else { - etsg_->StoreStaticProperty(Node(), memberExprTsType, fullName); - } + etsg_->StoreStaticProperty(Node(), memberExprTsType, fullName); return; } auto const *objectType = memberExpr->Object()->TsType(); - if (objectType->IsETSDynamicType()) { - etsg_->StorePropertyDynamic(Node(), memberExprTsType, baseReg_, propName); - return; - } - if (objectType->IsETSUnionType()) { etsg_->StorePropertyByName(Node(), baseReg_, checker::ETSChecker::FormNamedAccessMetadata(memberExpr->PropVar())); diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index bae951abe4..09d7df240a 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -16,12 +16,10 @@ #include "ETSCompiler.h" #include "compiler/base/catchTable.h" -#include "checker/ets/dynamic/dynamicCall.h" #include "compiler/base/condition.h" #include "compiler/base/lreference.h" #include "compiler/core/switchBuilder.h" #include "checker/ETSchecker.h" -#include "checker/types/ets/etsDynamicFunctionType.h" #include "checker/types/ets/etsTupleType.h" #include "ETSGen-inl.h" @@ -151,41 +149,6 @@ void ETSCompiler::Compile(const ir::ETSNewArrayInstanceExpression *expr) const ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); } -static std::pair LoadDynamicName(compiler::ETSGen *etsg, const ir::AstNode *node, - const ArenaVector &dynName, bool isConstructor) -{ - auto *checker = const_cast(etsg->Checker()->AsETSChecker()); - auto *callNames = checker->DynamicCallNames(isConstructor); - - auto qnameStart = etsg->AllocReg(); - auto qnameLen = etsg->AllocReg(); - - TargetTypeContext ttctx(etsg, nullptr); // without this ints will be cast to JSValue - etsg->LoadAccumulatorInt(node, callNames->at(dynName)); - etsg->StoreAccumulator(node, qnameStart); - etsg->LoadAccumulatorInt(node, dynName.size()); - etsg->StoreAccumulator(node, qnameLen); - return {qnameStart, qnameLen}; -} - -static void CreateDynamicObject(const ir::AstNode *node, compiler::ETSGen *etsg, const ir::Expression *typeRef, - checker::Signature *signature, const ArenaVector &arguments) -{ - auto objReg = etsg->AllocReg(); - - auto callInfo = checker::DynamicCall::ResolveCall(etsg->VarBinder(), typeRef); - if (callInfo.obj->IsETSImportDeclaration()) { - etsg->LoadAccumulatorDynamicModule(node, callInfo.obj->AsETSImportDeclaration()); - } else { - callInfo.obj->Compile(etsg); - } - - etsg->StoreAccumulator(node, objReg); - - auto [qnameStart, qnameLen] = LoadDynamicName(etsg, node, callInfo.name, true); - etsg->CallDynamic(ETSGen::CallDynamicData {node, objReg, qnameStart}, qnameLen, signature, arguments); -} - static void ConvertRestArguments(checker::ETSChecker *const checker, const ir::ETSNewClassInstanceExpression *expr) { if (expr->GetSignature()->RestVar() != nullptr && (expr->GetSignature()->RestVar()->TsType()->IsETSArrayType() || @@ -279,14 +242,8 @@ static void GetSizeInForOf(compiler::ETSGen *etsg, checker::Type const *const ex void ETSCompiler::Compile(const ir::ETSNewClassInstanceExpression *expr) const { ETSGen *etsg = GetETSGen(); - if (expr->TsType()->IsETSDynamicType()) { - compiler::RegScope rs(etsg); - auto *name = expr->GetTypeRef(); - CreateDynamicObject(expr, etsg, name, expr->signature_, expr->GetArguments()); - } else { - ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr); - etsg->InitObject(expr, expr->signature_, expr->GetArguments()); - } + ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr); + etsg->InitObject(expr, expr->signature_, expr->GetArguments()); etsg->SetAccumulatorType(expr->TsType()); } @@ -529,15 +486,8 @@ static void CompileInstanceof(compiler::ETSGen *etsg, const ir::BinaryExpression expr->Left()->Compile(etsg); etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); - if (expr->Left()->TsType()->IsETSDynamicType() || expr->Right()->TsType()->IsETSDynamicType()) { - auto rhs = etsg->AllocReg(); - expr->Right()->Compile(etsg); - etsg->StoreAccumulator(expr, rhs); - etsg->IsInstanceDynamic(expr, lhs, rhs); - } else { - auto target = expr->Right()->TsType(); - etsg->IsInstance(expr, lhs, target); - } + auto target = expr->Right()->TsType(); + etsg->IsInstance(expr, lhs, target); ES2PANDA_ASSERT(etsg->Checker()->Relation()->IsIdenticalTo(etsg->GetAccumulatorType(), expr->TsType())); } @@ -696,38 +646,6 @@ void ETSCompiler::Compile(const ir::BlockExpression *expr) const expr->Scope()->SetParent(oldParent); } -void ETSCompiler::CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const -{ - ETSGen *etsg = GetETSGen(); - auto callInfo = checker::DynamicCall::ResolveCall(etsg->VarBinder(), expr->Callee()); - if (callInfo.obj->IsETSImportDeclaration()) { - etsg->LoadAccumulatorDynamicModule(expr, callInfo.obj->AsETSImportDeclaration()); - } else { - callInfo.obj->Compile(etsg); - } - etsg->StoreAccumulator(expr, calleeReg); - - if (!callInfo.name.empty()) { - auto [qnameStart, qnameLen] = LoadDynamicName(etsg, expr, callInfo.name, false); - etsg->CallDynamic(ETSGen::CallDynamicData {expr, calleeReg, qnameStart}, qnameLen, expr->Signature(), - expr->Arguments()); - } else { - compiler::VReg dynParam2 = etsg->AllocReg(); - - auto lang = expr->Callee()->TsType()->IsETSDynamicFunctionType() - ? expr->Callee()->TsType()->AsETSDynamicFunctionType()->Language() - : expr->Callee()->TsType()->AsETSDynamicType()->Language(); - etsg->LoadUndefinedDynamic(expr, lang); - etsg->StoreAccumulator(expr, dynParam2); - etsg->CallDynamic(ETSGen::CallDynamicData {expr, calleeReg, dynParam2}, expr->Signature(), expr->Arguments()); - } - etsg->SetAccumulatorType(expr->Signature()->ReturnType()); - - if (etsg->GetAccumulatorType() != expr->TsType()) { - etsg->ApplyConversion(expr, expr->TsType()); - } -} - bool IsCastCallName(util::StringView name) { return name == Signatures::BYTE_CAST || name == Signatures::SHORT_CAST || name == Signatures::INT_CAST || @@ -795,9 +713,7 @@ void ETSCompiler::Compile(const ir::CallExpression *expr) const ConvertRestArguments(const_cast(etsg->Checker()->AsETSChecker()), expr, signature); - if (callee->TsType()->HasTypeFlag(checker::TypeFlag::ETS_DYNAMIC_FLAG)) { - CompileDynamic(expr, calleeReg); - } else if (callee->IsIdentifier()) { + if (callee->IsIdentifier()) { if (!isStatic) { etsg->LoadThis(expr); etsg->StoreAccumulator(expr, calleeReg); @@ -869,17 +785,6 @@ void ETSCompiler::Compile(const ir::Identifier *expr) const etsg->SetAccumulatorType(smartType); } -static void LoadETSDynamicTypeFromMemberExpr(compiler::ETSGen *etsg, const ir::MemberExpression *expr, - compiler::VReg objReg) -{ - if (etsg->Checker()->AsETSChecker()->Relation()->IsSupertypeOf(etsg->Checker()->GlobalBuiltinETSStringType(), - expr->Property()->TsType())) { - etsg->LoadPropertyDynamic(expr, expr->TsType(), objReg, expr->Property()); - } else { - etsg->LoadElementDynamic(expr, objReg); - } -} - bool ETSCompiler::CompileComputed(compiler::ETSGen *etsg, const ir::MemberExpression *expr) { if (!expr->IsComputed()) { @@ -905,8 +810,6 @@ bool ETSCompiler::CompileComputed(compiler::ETSGen *etsg, const ir::MemberExpres auto indexValue = *expr->GetTupleIndexValue(); auto *tupleElementType = objectType->AsETSTupleType()->GetTypeAtIndex(indexValue); etsg->LoadTupleElement(expr, objReg, tupleElementType, indexValue); - } else if (objectType->IsETSDynamicType()) { - LoadETSDynamicTypeFromMemberExpr(etsg, expr, objReg); } else { ES2PANDA_ASSERT(objectType->IsETSArrayType()); etsg->LoadArrayElement(expr, objReg); @@ -956,8 +859,6 @@ void ETSCompiler::Compile(const ir::MemberExpression *expr) const } else { etsg->CallVirtual(expr, variableType->AsETSFunctionType()->FindGetter(), objReg); } - } else if (objectType->IsETSDynamicType()) { - etsg->LoadPropertyDynamic(expr, expr->TsType(), objReg, propName); } else if (objectType->IsETSUnionType()) { etsg->LoadPropertyByName(expr, objReg, checker::ETSChecker::FormNamedAccessMetadata(expr->PropVar())); } else { @@ -1018,9 +919,6 @@ void ETSCompiler::Compile(const ir::ObjectExpression *expr) const compiler::RegScope rs {etsg}; compiler::VReg objReg = etsg->AllocReg(); - // NOTE: object expressions of dynamic type are not handled in objectLiteralLowering phase - ES2PANDA_ASSERT(expr->TsType()->IsETSDynamicType()); - auto *signatureInfo = etsg->Allocator()->New(etsg->Allocator()); auto *createObjSig = etsg->Allocator()->New(signatureInfo, nullptr, nullptr); createObjSig->SetInternalName(compiler::Signatures::BUILTIN_JSRUNTIME_CREATE_OBJECT); @@ -1048,11 +946,7 @@ void ETSCompiler::Compile(const ir::ObjectExpression *expr) const value->Compile(etsg); etsg->ApplyConversion(value, key->TsType()); - if (expr->TsType()->IsETSDynamicType()) { - etsg->StorePropertyDynamic(expr, value->TsType(), objReg, pname); - } else { - etsg->StoreProperty(expr, key->TsType(), objReg, pname); - } + etsg->StoreProperty(expr, key->TsType(), objReg, pname); } etsg->LoadAccumulator(expr, objReg); @@ -1662,10 +1556,6 @@ void ETSCompiler::CompileCast(const ir::TSAsExpression *expr, checker::Type cons etsg->CastToReftype(expr, targetType, expr->isUncheckedCast_); break; } - case checker::TypeFlag::ETS_DYNAMIC_TYPE: { - etsg->CastToDynamic(expr, targetType->AsETSDynamicType()); - break; - } // NOTE(gogabr): will be needed once we forbid as conversion /* // CC-OFFNXT(redundant_code[C++]) tmp code diff --git a/ets2panda/compiler/core/ETSCompiler.h b/ets2panda/compiler/core/ETSCompiler.h index 42f81ca50a..d09df63fd6 100644 --- a/ets2panda/compiler/core/ETSCompiler.h +++ b/ets2panda/compiler/core/ETSCompiler.h @@ -35,7 +35,6 @@ public: private: void GetDynamicNameParts(const ir::CallExpression *expr, ArenaVector &parts) const; - void CompileDynamic(const ir::CallExpression *expr, compiler::VReg &calleeReg) const; void CompileCastPrimitives(const ir::Expression *expr, checker::Type const *targetType) const; void CompileCast(const ir::TSAsExpression *expr, checker::Type const *targetType) const; void EmitCall(const ir::CallExpression *expr, compiler::VReg &calleeReg, checker::Signature *signature) const; diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index fde13df423..149c12d4d5 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -234,71 +234,8 @@ void ETSGen::LoadAccumulatorPoison(const ir::AstNode *node, const checker::Type SetAccumulatorType(type); } -util::StringView ETSGen::FormDynamicModulePropReference(const varbinder::Variable *var) -{ - ES2PANDA_ASSERT(VarBinder()->IsDynamicModuleVariable(var) || VarBinder()->IsDynamicNamespaceVariable(var)); - - auto *data = VarBinder()->DynamicImportDataForVar(var); - ES2PANDA_ASSERT(data != nullptr); - - auto *import = data->import; - - return FormDynamicModulePropReference(import); -} - -void ETSGen::LoadAccumulatorDynamicModule(const ir::AstNode *node, const ir::ETSImportDeclaration *import) -{ - ES2PANDA_ASSERT(import->Language().IsDynamic()); - LoadStaticProperty(node, Checker()->GlobalBuiltinDynamicType(import->Language()), - FormDynamicModulePropReference(import)); -} - -util::StringView ETSGen::FormDynamicModulePropReference(const ir::ETSImportDeclaration *import) -{ - std::stringstream ss; - ss << VarBinder()->Program()->ModulePrefix(); - ss << compiler::Signatures::DYNAMIC_MODULE_CLASS; - ss << '.'; - ss << import->AssemblerName(); - return util::UString(ss.str(), Allocator()).View(); -} - -void ETSGen::LoadDynamicModuleVariable(const ir::AstNode *node, varbinder::Variable const *const var) -{ - RegScope rs(this); - - auto *data = VarBinder()->DynamicImportDataForVar(var); - auto *import = data->import; - - LoadStaticProperty(node, var->TsType(), FormDynamicModulePropReference(var)); - - auto objReg = AllocReg(); - StoreAccumulator(node, objReg); - - auto *id = data->specifier->AsImportSpecifier()->Imported(); - auto lang = import->Language(); - LoadPropertyDynamic(node, Checker()->GlobalBuiltinDynamicType(lang), objReg, id->Name()); - - ApplyConversion(node); -} - -void ETSGen::LoadDynamicNamespaceVariable(const ir::AstNode *node, varbinder::Variable const *const var) -{ - LoadStaticProperty(node, var->TsType(), FormDynamicModulePropReference(var)); -} - void ETSGen::LoadVar(const ir::Identifier *node, varbinder::Variable const *const var) { - if (VarBinder()->IsDynamicModuleVariable(var)) { - LoadDynamicModuleVariable(node, var); - return; - } - - if (VarBinder()->IsDynamicNamespaceVariable(var)) { - LoadDynamicNamespaceVariable(node, var); - return; - } - auto *local = var->AsLocalVariable(); switch (ETSLReference::ResolveReferenceKind(var)) { @@ -488,139 +425,6 @@ void ETSGen::LoadPropertyByName([[maybe_unused]] const ir::AstNode *const node, #endif // PANDA_WITH_ETS } -void ETSGen::StorePropertyDynamic(const ir::AstNode *node, const checker::Type *propType, VReg objReg, - const util::StringView &propName) -{ - auto const lang = GetVRegType(objReg)->AsETSDynamicType()->Language(); - std::string_view methodName {}; - if (propType->IsETSBooleanType()) { - methodName = Signatures::Dynamic::SetPropertyBooleanBuiltin(lang); - } else if (propType->IsByteType()) { - methodName = Signatures::Dynamic::SetPropertyByteBuiltin(lang); - } else if (propType->IsCharType()) { - methodName = Signatures::Dynamic::SetPropertyCharBuiltin(lang); - } else if (propType->IsShortType()) { - methodName = Signatures::Dynamic::SetPropertyShortBuiltin(lang); - } else if (propType->IsIntType()) { - methodName = Signatures::Dynamic::SetPropertyIntBuiltin(lang); - } else if (propType->IsLongType()) { - methodName = Signatures::Dynamic::SetPropertyLongBuiltin(lang); - } else if (propType->IsFloatType()) { - methodName = Signatures::Dynamic::SetPropertyFloatBuiltin(lang); - } else if (propType->IsDoubleType()) { - methodName = Signatures::Dynamic::SetPropertyDoubleBuiltin(lang); - } else if (propType->IsETSStringType()) { - methodName = Signatures::Dynamic::SetPropertyStringBuiltin(lang); - } else if (propType->IsETSObjectType() || propType->IsETSTypeParameter()) { - methodName = Signatures::Dynamic::SetPropertyDynamicBuiltin(lang); - // NOTE: vpukhov. add non-dynamic builtin - if (!propType->IsETSDynamicType()) { - CastToDynamic(node, Checker()->GlobalBuiltinDynamicType(lang)->AsETSDynamicType()); - } - } else { - ASSERT_PRINT(false, "Unsupported property type"); - } - - RegScope rs(this); - VReg propValueReg = AllocReg(); - VReg propNameReg = AllocReg(); - - StoreAccumulator(node, propValueReg); - - // Load property name - LoadAccumulatorString(node, propName); - StoreAccumulator(node, propNameReg); - - // Set property by name - Ra().Emit(node, methodName, objReg, propNameReg, propValueReg, dummyReg_); - SetAccumulatorType(Checker()->GlobalBuiltinJSValueType()); -} - -void ETSGen::LoadPropertyDynamic(const ir::AstNode *node, const checker::Type *propType, VReg objReg, - std::variant property) -{ - auto const lang = GetVRegType(objReg)->AsETSDynamicType()->Language(); - auto *type = propType; - std::string_view methodName {}; - if (propType->IsETSBooleanType()) { - methodName = Signatures::Dynamic::GetPropertyBooleanBuiltin(lang); - } else if (propType->IsByteType()) { - methodName = Signatures::Dynamic::GetPropertyByteBuiltin(lang); - } else if (propType->IsCharType()) { - methodName = Signatures::Dynamic::GetPropertyCharBuiltin(lang); - } else if (propType->IsShortType()) { - methodName = Signatures::Dynamic::GetPropertyShortBuiltin(lang); - } else if (propType->IsIntType()) { - methodName = Signatures::Dynamic::GetPropertyIntBuiltin(lang); - } else if (propType->IsLongType()) { - methodName = Signatures::Dynamic::GetPropertyLongBuiltin(lang); - } else if (propType->IsFloatType()) { - methodName = Signatures::Dynamic::GetPropertyFloatBuiltin(lang); - } else if (propType->IsDoubleType()) { - methodName = Signatures::Dynamic::GetPropertyDoubleBuiltin(lang); - } else if (propType->IsETSStringType()) { - methodName = Signatures::Dynamic::GetPropertyStringBuiltin(lang); - } else if (propType->IsETSObjectType() || propType->IsETSTypeParameter()) { - methodName = Signatures::Dynamic::GetPropertyDynamicBuiltin(lang); - type = Checker()->GlobalBuiltinDynamicType(lang); - } else { - ASSERT_PRINT(false, "Unsupported property type"); - } - - RegScope rs(this); - - VReg propNameObject; - - if (node->IsMemberExpression() && node->AsMemberExpression()->IsComputed()) { - (std::get(property))->Compile(this); - } else { - // Load property name - LoadAccumulatorString(node, std::get(property)); - } - - propNameObject = AllocReg(); - StoreAccumulator(node, propNameObject); - - // Get property - Ra().Emit(node, methodName, objReg, propNameObject); - - SetAccumulatorType(type); - - if (propType != type && !propType->IsETSDynamicType()) { - CastDynamicToObject(node, propType); - } -} - -void ETSGen::StoreElementDynamic(const ir::AstNode *node, VReg objectReg, VReg index) -{ - auto const lang = GetVRegType(objectReg)->AsETSDynamicType()->Language(); - std::string_view methodName = Signatures::Dynamic::SetElementDynamicBuiltin(lang); - - RegScope rs(this); - - VReg valueReg = AllocReg(); - StoreAccumulator(node, valueReg); - - // Set property by index - Ra().Emit(node, methodName, objectReg, index, valueReg, dummyReg_); - SetAccumulatorType(Checker()->GlobalVoidType()); -} - -void ETSGen::LoadElementDynamic(const ir::AstNode *node, VReg objectReg) -{ - auto const lang = GetVRegType(objectReg)->AsETSDynamicType()->Language(); - std::string_view methodName = Signatures::Dynamic::GetElementDynamicBuiltin(lang); - - RegScope rs(this); - - VReg indexReg = AllocReg(); - StoreAccumulator(node, indexReg); - - // Get property by index - Ra().Emit(node, methodName, objectReg, indexReg); - SetAccumulatorType(Checker()->GlobalBuiltinDynamicType(lang)); -} - void ETSGen::CallRangeFillUndefined(const ir::AstNode *const node, checker::Signature *const signature, const VReg thisReg) { @@ -725,83 +529,10 @@ static bool IsNullUnsafeObjectType(checker::Type const *type) return type->IsETSObjectType() && type->AsETSObjectType()->IsGlobalETSObjectType(); } -void ETSGen::IsInstanceDynamic(const ir::BinaryExpression *const node, const VReg srcReg, - [[maybe_unused]] const VReg tgtReg) -{ - ES2PANDA_ASSERT(node->OperatorType() == lexer::TokenType::KEYW_INSTANCEOF); - const checker::Type *lhsType = node->Left()->TsType(); - const checker::Type *rhsType = node->Right()->TsType(); - ES2PANDA_ASSERT(rhsType->IsETSDynamicType() || lhsType->IsETSDynamicType()); - - const RegScope rs(this); - if (rhsType->IsETSDynamicType()) { - ES2PANDA_ASSERT(node->Right()->TsType()->AsETSDynamicType()->HasDecl()); - if (lhsType->IsETSDynamicType()) { - VReg dynTypeReg = MoveAccToReg(node); - // Semantics: - // let dyn_val: JSValue = ... - // dyn_value instanceof DynamicDecl - // Bytecode: - // call runtime intrinsic_dynamic - CallExact(node, Signatures::BUILTIN_JSRUNTIME_INSTANCE_OF_DYNAMIC, srcReg, dynTypeReg); - } else if (lhsType == Checker()->GlobalETSObjectType()) { - // Semantics: - // let obj: Object = ... - // obj instanceof DynamicDecl - // Bytecode: - // if isinstance : - // checkcast - // return call runtime intrinsic_dynamic - // return false - Label *ifFalse = AllocLabel(); - Language lang = rhsType->AsETSDynamicType()->Language(); - VReg dynTypeReg = MoveAccToReg(node); - LoadAccumulator(node, srcReg); - EmitIsInstance(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); - BranchIfFalse(node, ifFalse); - LoadAccumulator(node, srcReg); - EmitCheckCast(node, Checker()->GlobalBuiltinDynamicType(lang)->AssemblerName()); - CallExact(node, Signatures::BUILTIN_JSRUNTIME_INSTANCE_OF_DYNAMIC, srcReg, dynTypeReg); - SetLabel(node, ifFalse); - } else { - // Semantics: - // let obj: EtsType = ... - // obj instanceof DynamicDecl - // Bytecode: - // False - Sa().Emit(node, 0); - } - } else { - if (lhsType->IsETSDynamicType()) { - if (rhsType == Checker()->GlobalETSObjectType()) { - // Semantics: - // let dyn_val: JSValue = ... - // dyn_val instanceof Object - // Bytecode: - // True - Sa().Emit(node, 1); - } else { - // Semantics: - // let dyn_val: JSValue = ... - // dyn_val instanceof EtsType - // Bytecode: - // lda.type + call runtime instrinsic_static - Sa().Emit(node, rhsType->AsETSObjectType()->AssemblerName()); - VReg typeReg = MoveAccToReg(node); - CallExact(node, Signatures::BUILTIN_JSRUNTIME_INSTANCE_OF_STATIC, srcReg, typeReg); - } - } else { - ES2PANDA_UNREACHABLE(); - } - } - SetAccumulatorType(Checker()->GlobalETSBooleanType()); -} - // Implemented on top of the runtime type system, do not relax checks, do not introduce new types void ETSGen::TestIsInstanceConstituent(const ir::AstNode *const node, std::tuple