diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 0a01661fb61174a8a749066a33e9f9f07399edc5..2ef3ae274a71ebe4ad29af07f83652d856c8d81e 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -210,7 +210,6 @@ libes2panda_sources = [ "compiler/lowering/ets/boxingForLocals.cpp", "compiler/lowering/ets/capturedVariables.cpp", "compiler/lowering/ets/cfgBuilderPhase.cpp", - "compiler/lowering/ets/constStringToCharLowering.cpp", "compiler/lowering/ets/constantExpressionLowering.cpp", "compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp", "compiler/lowering/ets/declareOverloadLowering.cpp", @@ -479,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 3bec339eb42eb49f0cd076c10d8623e2d3a74772..0857184f54be9013c34c14c7e67067b4d2f9163b 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -301,7 +301,6 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/ambientLowering.cpp compiler/lowering/ets/asyncMethodLowering.cpp compiler/lowering/ets/bigintLowering.cpp - compiler/lowering/ets/constStringToCharLowering.cpp compiler/lowering/ets/recordLowering.cpp compiler/lowering/ets/resizableArrayLowering.cpp compiler/lowering/ets/restArgsLowering.cpp @@ -527,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/bindings/native/src/lsp.cpp b/ets2panda/bindings/native/src/lsp.cpp index 56e959a8e4421156abc3b81d96b913f68acfc371..286efef5979db72e531f34aaf04047fea3954b6e 100644 --- a/ets2panda/bindings/native/src/lsp.cpp +++ b/ets2panda/bindings/native/src/lsp.cpp @@ -19,12 +19,18 @@ #include "common.h" #include "panda_types.h" #include "public/es2panda_lib.h" - +#include "lsp/include/refactors/refactor_types.h" #include #include #include #include +namespace { +using ark::es2panda::lsp::ClassHierarchy; +using ark::es2panda::lsp::ClassHierarchyInfo; +using ark::es2panda::lsp::ClassMethodItem; +} // namespace + char *GetStringCopy(KStringPtr &ptr) { return strdup(ptr.c_str()); @@ -57,6 +63,17 @@ KNativePointer impl_getClassPropertyInfo(KNativePointer context, KInt position, } TS_INTEROP_3(getClassPropertyInfo, KNativePointer, KNativePointer, KInt, KBoolean) +KNativePointer impl_getFieldsInfoFromPropertyInfo(KNativePointer infoPtr) +{ + auto info = reinterpret_cast *>(infoPtr); + std::vector ptrs; + for (auto &el : *info) { + ptrs.push_back(new FieldsInfo(el)); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(getFieldsInfoFromPropertyInfo, KNativePointer, KNativePointer) + KNativePointer impl_getNameFromPropertyInfo(KNativePointer infoPtr) { auto info = reinterpret_cast(infoPtr); @@ -301,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)); @@ -350,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); @@ -720,6 +686,228 @@ KNativePointer impl_getQuickInfoFileName(KNativePointer ref) } TS_INTEROP_1(getQuickInfoFileName, KNativePointer, KNativePointer) +KNativePointer impl_getClassHierarchyInfo(KNativePointer context, KInt position) +{ + LSPAPI const *ctx = GetImpl(); + if (ctx == nullptr) { + return nullptr; + } + auto *classHierarchyPtr = + new ClassHierarchy(ctx->getClassHierarchyInfo(reinterpret_cast(context), position)); + return classHierarchyPtr; +} +TS_INTEROP_2(getClassHierarchyInfo, KNativePointer, KNativePointer, KInt) + +KNativePointer impl_castToClassHierarchyInfos(KNativePointer infos) +{ + auto *infosPtr = reinterpret_cast(infos); + if (infosPtr == nullptr) { + return nullptr; + } + std::vector ptrs; + for (const auto &element : *infosPtr) { + ptrs.push_back(new ClassHierarchyInfo(element)); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(castToClassHierarchyInfos, KNativePointer, KNativePointer) + +KNativePointer impl_getClassNameFromClassHierarchyInfo(KNativePointer info) +{ + auto *infoPtr = reinterpret_cast(info); + if (infoPtr == nullptr) { + return nullptr; + } + return new std::string(infoPtr->GetClassName()); +} +TS_INTEROP_1(getClassNameFromClassHierarchyInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getMethodListFromClassHierarchyInfo(KNativePointer info) +{ + auto *infoPtr = reinterpret_cast(info); + if (infoPtr == nullptr) { + return nullptr; + } + std::vector ptrs; + for (const auto &element : infoPtr->GetMethodList()) { + if (element.second == nullptr) { + continue; + } + ptrs.push_back(new ClassMethodItem(*(element.second))); + } + return new std::vector(ptrs); +} +TS_INTEROP_1(getMethodListFromClassHierarchyInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getDetailFromClassMethodItem(KNativePointer item) +{ + auto *itemPtr = reinterpret_cast(item); + if (itemPtr == nullptr) { + return nullptr; + } + return new std::string(itemPtr->GetFunctionDetail()); +} +TS_INTEROP_1(getDetailFromClassMethodItem, KNativePointer, KNativePointer) + +KInt impl_getSetterStyleFromClassMethodItem(KNativePointer item) +{ + auto *itemPtr = reinterpret_cast(item); + if (itemPtr == nullptr) { + return 0; + } + return static_cast(itemPtr->GetSetterStyle()); +} +TS_INTEROP_1(getSetterStyleFromClassMethodItem, KInt, KNativePointer) + +KInt impl_getAccessModifierStyleFromClassMethodItem(KNativePointer item) +{ + auto *itemPtr = reinterpret_cast(item); + if (itemPtr == nullptr) { + return 0; + } + return static_cast(itemPtr->GetAccessModifierStyle()); +} +TS_INTEROP_1(getAccessModifierStyleFromClassMethodItem, KInt, KNativePointer) + +KInt impl_getAliasScriptElementKind(KNativePointer context, KInt position) +{ + LSPAPI const *ctx = GetImpl(); + if (ctx == nullptr) { + return 1; + } + auto kind = + static_cast(ctx->getAliasScriptElementKind(reinterpret_cast(context), position)); + return kind; +} +TS_INTEROP_2(getAliasScriptElementKind, KInt, KNativePointer, KInt) + +KNativePointer impl_getClassHierarchies(KNativePointer context, KStringPtr &fileNamePtr, KInt pos) +{ + LSPAPI const *ctx = GetImpl(); + if (ctx == nullptr) { + return nullptr; + } + auto infos = + ctx->getClassHierarchiesImpl(reinterpret_cast(context), GetStringCopy(fileNamePtr), pos); + std::vector ptrs; + ptrs.reserve(infos.size()); + for (auto &info : infos) { + ptrs.push_back(new ark::es2panda::lsp::ClassHierarchyItemInfo(info)); + } + return new std::vector(std::move(ptrs)); +} +TS_INTEROP_3(getClassHierarchies, KNativePointer, KNativePointer, KStringPtr, KInt) + +KNativePointer impl_getClassHierarchyList(KNativePointer infosPtr) +{ + auto *infos = reinterpret_cast *>(infosPtr); + std::vector infoPtrList; + for (auto &info : *infos) { + infoPtrList.push_back(new ark::es2panda::lsp::ClassHierarchyItemInfo(info)); + } + return new std::vector(infoPtrList); +} +TS_INTEROP_1(getClassHierarchyList, KNativePointer, KNativePointer) + +KInt impl_getPosFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return static_cast(info->pos); +} +TS_INTEROP_1(getPosFromClassHierarchyItemInfo, KInt, KNativePointer) + +KInt impl_getKindFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + return static_cast(info->kind); +} +TS_INTEROP_1(getKindFromClassHierarchyItemInfo, KInt, KNativePointer) + +KNativePointer impl_getDescriptionFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + auto description = info->description; + return new std::string(description); +} +TS_INTEROP_1(getDescriptionFromClassHierarchyItemInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getOverriddenFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + auto &overridden = info->overridden; + std::vector overriddenPtrList; + overriddenPtrList.reserve(overridden.size()); + size_t idx = 0; + for (auto &details : overridden) { + overriddenPtrList[idx++] = new ark::es2panda::lsp::ClassRelationDetails(details); + } + return new std::vector(std::move(overriddenPtrList)); +} +TS_INTEROP_1(getOverriddenFromClassHierarchyItemInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getOverridingFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + auto &overriding = info->overriding; + std::vector overridingPtrList; + overridingPtrList.reserve(overriding.size()); + size_t idx = 0; + for (auto &details : overriding) { + overridingPtrList[idx++] = new ark::es2panda::lsp::ClassRelationDetails(details); + } + return new std::vector(std::move(overridingPtrList)); +} +TS_INTEROP_1(getOverridingFromClassHierarchyItemInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getImplementedFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + auto implemented = info->implemented; + std::vector implementedPtrList; + implementedPtrList.reserve(implemented.size()); + size_t idx = 0; + for (auto &details : implemented) { + implementedPtrList[idx++] = new ark::es2panda::lsp::ClassRelationDetails(details); + } + return new std::vector(std::move(implementedPtrList)); +} +TS_INTEROP_1(getImplementedFromClassHierarchyItemInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getImplementingFromClassHierarchyItemInfo(KNativePointer infoPtr) +{ + auto *info = reinterpret_cast(infoPtr); + auto implementing = info->implementing; + std::vector implementingPtrList; + implementingPtrList.reserve(implementing.size()); + size_t idx = 0; + for (auto &details : implementing) { + implementingPtrList[idx++] = new ark::es2panda::lsp::ClassRelationDetails(details); + } + return new std::vector(std::move(implementingPtrList)); +} +TS_INTEROP_1(getImplementingFromClassHierarchyItemInfo, KNativePointer, KNativePointer) + +KNativePointer impl_getFileNameFromClassRelationDetails(KNativePointer detailsPtr) +{ + auto *details = reinterpret_cast(detailsPtr); + return new std::string(details->fileName); +} +TS_INTEROP_1(getFileNameFromClassRelationDetails, KNativePointer, KNativePointer) + +KInt impl_getPosFromClassRelationDetails(KNativePointer detailsPtr) +{ + auto *details = reinterpret_cast(detailsPtr); + return static_cast(details->pos); +} +TS_INTEROP_1(getPosFromClassRelationDetails, KInt, KNativePointer) + +KInt impl_getKindFromClassRelationDetails(KNativePointer detailsPtr) +{ + auto *details = reinterpret_cast(detailsPtr); + return static_cast(details->kind); +} +TS_INTEROP_1(getKindFromClassRelationDetails, KInt, KNativePointer) + KNativePointer impl_getSymbolDisplayPart(KNativePointer quickInfoPtr) { auto *quickInfo = reinterpret_cast(quickInfoPtr); diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index 0c2bf515c28e7778bfadcbd9cb09ed5e3ae3d276..210ad83e1cdbc4ee92919e027e49b61c61c67017 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -193,6 +193,74 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } + _getClassHierarchyInfo(context: KNativePointer, position: KInt): KPtr { + throw new Error('Not implemented'); + } + + _castToClassHierarchyInfos(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getClassNameFromClassHierarchyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getMethodListFromClassHierarchyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getDetailFromClassMethodItem(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getSetterStyleFromClassMethodItem(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getAccessModifierStyleFromClassMethodItem(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getAliasScriptElementKind(ptr: KNativePointer, position: KInt): KInt { + throw new Error('Not implemented'); + } + + _getClassPropertyInfo(context: KNativePointer, position: KInt, shouldCollectInherited: boolean): KPtr { + throw new Error('Not implemented'); + } + + _getFieldsInfoFromPropertyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getNameFromPropertyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFieldListPropertyFromPropertyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getModifierKindsFromPropertyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getDisplayNameFromPropertyInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getStartFromPropertyInfo(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getEndFromPropertyInfo(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getKindFromPropertyInfo(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + _organizeImports(context: KNativePointer, filename: String): KPtr { throw new Error('Not implemented'); } @@ -313,6 +381,54 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } + _getClassHierarchies(context: KNativePointer, fileName: String, position: number): KPtr { + throw new Error('Not implemented'); + } + + _getClassHierarchyList(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getPosFromClassHierarchyItemInfo(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getKindFromClassHierarchyItemInfo(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getDescriptionFromClassHierarchyItemInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getOverriddenFromClassHierarchyItemInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getOverridingFromClassHierarchyItemInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getImplementedFromClassHierarchyItemInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getImplementingFromClassHierarchyItemInfo(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getFileNameFromClassRelationDetails(ptr: KNativePointer): KPtr { + throw new Error('Not implemented'); + } + + _getPosFromClassRelationDetails(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + + _getKindFromClassRelationDetails(ptr: KNativePointer): KInt { + throw new Error('Not implemented'); + } + _getFileNameFromDef(ptr: KNativePointer): KPtr { throw new Error('Not implemented'); } diff --git a/ets2panda/bindings/src/lspNode.ts b/ets2panda/bindings/src/lspNode.ts index 11e70a39fab3c26a6fd4cae69777fd9fadbbf6de..17f846fce21df036fb1b966dca1ac0218aeff665 100644 --- a/ets2panda/bindings/src/lspNode.ts +++ b/ets2panda/bindings/src/lspNode.ts @@ -22,6 +22,20 @@ import { NativePtrDecoder } from './Platform'; enum HierarchyType { OTHERS, INTERFACE, CLASS }; +export enum SetterStyle { + METHOD = 0, + SETTER, + GETTER +} + +export enum AccessModifierStyle { + PUBLIC = 0, + PROTECTED, + PRIVATE +} + +enum ClassRelationKind { UNKNOWN, INTERFACE, CLASS, FIELD, METHOD, PROPERTY }; + export abstract class LspNode { readonly peer: KNativePointer; @@ -214,6 +228,150 @@ export class LspSymbolDisplayPart extends LspNode { readonly kind: String; } +export class LspClassMethodItem extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.functionDetail = unpackString(global.es2panda._getDetailFromClassMethodItem(this.peer)); + 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 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)) + .map((elPeer: KNativePointer) => { + return new LspClassMethodItem(elPeer); + }); + } + readonly className: string; + readonly items: LspClassMethodItem[]; +} + +export class LspClassHierarchy extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.infos = new NativePtrDecoder() + .decode(global.es2panda._castToClassHierarchyInfos(this.peer)) + .map((elPeer: KNativePointer) => { + return new LspClassHierarchyInfo(elPeer); + }); + } + readonly infos: LspClassHierarchyInfo[]; +} + +export class LspClassPropertyInfo extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.fieldsInfo = new NativePtrDecoder() + .decode(global.es2panda._getFieldsInfoFromPropertyInfo(peer)) + .map((elPeer: KNativePointer) => { + return new FieldsInfo(elPeer); + }); + } + readonly fieldsInfo: FieldsInfo[]; +} + +export class FieldsInfo extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.name = unpackString(global.es2panda._getNameFromPropertyInfo(peer)); + this.properties = new NativePtrDecoder() + .decode(global.es2panda._getFieldListPropertyFromPropertyInfo(peer)) + .map((elPeer: KNativePointer) => { + return new FieldListProperty(elPeer); + }); + } + readonly name: String; + readonly properties: FieldListProperty[]; +} + +export class FieldListProperty extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.kind = unpackString(global.es2panda._getKindFromPropertyInfo(peer)); + this.modifierKinds = new NativePtrDecoder() + .decode(global.es2panda._getModifierKindsFromPropertyInfo(peer)) + .map((elPeer: KNativePointer) => { + return new String(elPeer); + }); + this.displayName = unpackString(global.es2panda._getDisplayNameFromPropertyInfo(peer)); + this.start = global.es2panda._getStartFromPropertyInfo(peer); + this.end = global.es2panda._getEndFromPropertyInfo(peer); + } + readonly kind: String; + readonly modifierKinds: String[]; + readonly displayName: String; + readonly start: number; + readonly end: number; +} + +export class LspClassHierarchies extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.classHierarchies = new NativePtrDecoder() + .decode(global.es2panda._getClassHierarchyList(peer)) + .map((elPeer: KNativePointer) => { + return new ClassHierarchyItemInfo(elPeer); + }); + } + readonly classHierarchies: ClassHierarchyItemInfo[]; +} + +export class ClassHierarchyItemInfo extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.pos = global.es2panda._getPosFromClassHierarchyItemInfo(peer); + this.kind = global.es2panda._getKindFromClassHierarchyItemInfo(peer); + this.description = unpackString(global.es2panda._getDescriptionFromClassHierarchyItemInfo(peer)); + this.overridden = new NativePtrDecoder() + .decode(global.es2panda._getOverriddenFromClassHierarchyItemInfo(peer)) + .map((elPeer: KNativePointer) => { + return new ClassRelationDetails(elPeer); + }); + this.overriding = new NativePtrDecoder() + .decode(global.es2panda._getOverridingFromClassHierarchyItemInfo(peer)) + .map((elPeer: KNativePointer) => { + return new ClassRelationDetails(elPeer); + }); + this.implemented = new NativePtrDecoder() + .decode(global.es2panda._getImplementedFromClassHierarchyItemInfo(peer)) + .map((elPeer: KNativePointer) => { + return new ClassRelationDetails(elPeer); + }); + this.implementing = new NativePtrDecoder() + .decode(global.es2panda._getImplementingFromClassHierarchyItemInfo(peer)) + .map((elPeer: KNativePointer) => { + return new ClassRelationDetails(elPeer); + }); + } + readonly pos: number; + readonly kind: ClassRelationKind; + readonly description: String; + readonly overridden: ClassRelationDetails[]; + readonly overriding: ClassRelationDetails[]; + readonly implemented: ClassRelationDetails[]; + readonly implementing: ClassRelationDetails[]; +} + +export class ClassRelationDetails extends LspNode { + constructor(peer: KNativePointer) { + super(peer); + this.fileName = unpackString(global.es2panda._getFileNameFromClassRelationDetails(peer)); + this.pos = global.es2panda._getPosFromClassRelationDetails(peer); + this.kind = global.es2panda._getKindFromClassRelationDetails(peer); + } + readonly fileName: String; + readonly pos: number; + readonly kind: ClassRelationKind; +} + export class LspQuickInfo extends LspNode { constructor(peer: KNativePointer) { super(peer); diff --git a/ets2panda/bindings/src/lsp_helper.ts b/ets2panda/bindings/src/lsp_helper.ts index ba5b82dc9fb5a6fcaab8e930848f3f98632d3fa5..b543a2b07ea6fb3041a82eb9e609208085c3fd45 100644 --- a/ets2panda/bindings/src/lsp_helper.ts +++ b/ets2panda/bindings/src/lsp_helper.ts @@ -20,6 +20,10 @@ import { LspDiagsNode, LspReferences, LspQuickInfo, + LspClassHierarchy, + LspCompletionEntryKind, + LspClassPropertyInfo, + LspClassHierarchies, LspDocumentHighlightsReferences, LspCompletionInfo, LspReferenceLocationList, @@ -325,6 +329,82 @@ export class Lsp { return result[0]; } + getClassHierarchyInfo(filename: String, offset: number): LspClassHierarchy { + 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.getFileContent(filePath).replace(/\r\n/g, '\n'); + 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._getClassHierarchyInfo(localCtx, offset); + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + lspDriverHelper.destroyContext(localCtx); + lspDriverHelper.destroyConfig(localCfg); + return new LspClassHierarchy(ptr); + } + + getAliasScriptElementKind(filename: String, offset: number): LspCompletionEntryKind { + 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.getFileContent(filePath).replace(/\r\n/g, '\n'); + 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 kind = global.es2panda._getAliasScriptElementKind(localCtx, offset); + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + lspDriverHelper.destroyContext(localCtx); + lspDriverHelper.destroyConfig(localCfg); + return kind; + } + + getClassHierarchies(filename: String, offset: number): LspClassHierarchies { + 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.getFileContent(filePath).replace(/\r\n/g, '\n'); + 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._getClassHierarchies(localCtx, filename, offset); + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + lspDriverHelper.destroyContext(localCtx); + lspDriverHelper.destroyConfig(localCfg); + return new LspClassHierarchies(ptr); + } + + getClassPropertyInfo(filename: String, offset: number, shouldCollectInherited: boolean = false): LspClassPropertyInfo { + 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.getFileContent(filePath).replace(/\r\n/g, '\n'); + 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._getClassPropertyInfo(localCtx, offset, shouldCollectInherited); + PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); + lspDriverHelper.destroyContext(localCtx); + lspDriverHelper.destroyConfig(localCfg); + return new LspClassPropertyInfo(ptr); + } + getOrganizeImports(filename: String): LspFileTextChanges { let lspDriverHelper = new LspDriverHelper(); let filePath = path.resolve(filename.valueOf()); diff --git a/ets2panda/checker/ASchecker.cpp b/ets2panda/checker/ASchecker.cpp index 3a3cb8e6919aafd41329ac9b4fa2d6880ee55fff..ee3cd234f8fcdb5e5d20957c1ff19f7d17086b66 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 69a80488abb56b310d61bc7464e0480245f93cb7..84ba809e5b0d673bdfc99f006a9ea7a649a2b281 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 e889e393d757b7c78bc43da78c0bbf9ff6d13fad..cc87b76f3415a275a203b6ca591e1364e7951a92 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -25,6 +25,8 @@ #include "checker/types/ets/etsAsyncFuncReturnType.h" #include "util/es2pandaMacros.h" +#include + namespace ark::es2panda::checker { ETSChecker *ETSAnalyzer::GetETSChecker() const @@ -1323,6 +1325,15 @@ checker::Type *ETSAnalyzer::Check(ir::BlockExpression *st) const return st->TsType(); } +static bool LambdaIsField(ir::CallExpression *expr) +{ + if (!expr->Callee()->IsMemberExpression()) { + return false; + } + auto *me = expr->Callee()->AsMemberExpression(); + return me->PropVar() != nullptr; +} + checker::Signature *ETSAnalyzer::ResolveSignature(ETSChecker *checker, ir::CallExpression *expr, checker::Type *calleeType) const { @@ -1343,7 +1354,9 @@ checker::Signature *ETSAnalyzer::ResolveSignature(ETSChecker *checker, ir::CallE return signature; } - if (checker->IsExtensionETSFunctionType(calleeType)) { + // when a lambda with receiver is a class field or interface property, + // then it can only be called like a lambda without receiver. + if (checker->IsExtensionETSFunctionType(calleeType) && !LambdaIsField(expr)) { auto *signature = ResolveCallExtensionFunction(calleeType, checker, expr); if (signature != nullptr && signature->IsExtensionAccessor() && !checker->HasStatus(CheckerStatus::IN_EXTENSION_ACCESSOR_CHECK)) { @@ -1679,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 {}; @@ -1846,7 +1859,7 @@ static bool ValidatePreferredType(ETSChecker *checker, ir::ObjectExpression *exp } if (!preferredType->IsETSObjectType()) { - checker->LogError(diagnostic::CKASS_COMPOSITE_INVALID_TARGET, {preferredType}, expr->Start()); + checker->LogError(diagnostic::CLASS_COMPOSITE_INVALID_TARGET, {preferredType}, expr->Start()); return false; } @@ -1867,6 +1880,359 @@ static void SetTypeforRecordProperties(const ir::ObjectExpression *expr, checker } } +// Helper to check for parameterless constructor +static bool HasParameterlessConstructor(checker::ETSObjectType *objType, ETSChecker *checker, + const lexer::SourcePosition &pos) +{ + for (checker::Signature *sig : objType->ConstructSignatures()) { + if (sig->Params().empty()) { + checker->ValidateSignatureAccessibility(objType, sig, pos); + return true; + } + } + return false; +} + +// Helper to resolve property name from key expression +static std::optional GetPropertyNameFromKey(ir::Expression *key) +{ + if (key->IsStringLiteral()) { + return key->AsStringLiteral()->Str(); + } + if (key->IsIdentifier()) { + return key->AsIdentifier()->Name(); + } + return std::nullopt; // Indicates invalid key type +} + +// Helper to determine property search flags based on object type +static checker::PropertySearchFlags DetermineSearchFlagsForLiteral(checker::ETSObjectType *potentialObjType) +{ + if (potentialObjType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) { + return checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | + checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | + checker::PropertySearchFlags::SEARCH_INSTANCE_DECL | checker::PropertySearchFlags::SEARCH_IN_INTERFACES; + } + return checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | checker::PropertySearchFlags::SEARCH_IN_BASE | + checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD; +} + +static bool CheckSinglePropertyCompatibility(ir::Expression *propExpr, checker::ETSObjectType *potentialObjType) +{ + if (!propExpr->IsProperty()) { + return false; // Not a key-value property + } + ir::Expression *key = propExpr->AsProperty()->Key(); + + std::optional optPname = GetPropertyNameFromKey(key); + if (!optPname.has_value()) { + return false; // Invalid key type in literal + } + util::StringView pname = optPname.value(); + + checker::PropertySearchFlags searchFlags = DetermineSearchFlagsForLiteral(potentialObjType); + + return potentialObjType->GetProperty(pname, searchFlags) != nullptr; +} + +static bool CheckObjectLiteralCompatibility(ir::ObjectExpression *expr, checker::ETSObjectType *potentialObjType) +{ + for (ir::Expression *propExpr : expr->Properties()) { + if (!CheckSinglePropertyCompatibility(propExpr, potentialObjType)) { + return false; + } + } + return true; // All properties found +} + +// Helper to check if a property type indicates optionality (union with undefined) +static bool IsPropertyTypeOptional(checker::Type *propertyType) +{ + if (!propertyType->IsETSUnionType()) { + return false; + } + + auto *unionType = propertyType->AsETSUnionType(); + for (auto *constituentType : unionType->ConstituentTypes()) { + if (constituentType->IsETSUndefinedType()) { + return true; + } + } + return false; +} + +// Helper to check if a property has a default value in its declaration +static bool HasPropertyDefaultValue(varbinder::LocalVariable *property) +{ + auto *decl = property->Declaration(); + if (decl == nullptr || decl->Node() == nullptr || !decl->Node()->IsClassProperty()) { + return false; + } + + auto *classProp = decl->Node()->AsClassProperty(); + return classProp->Value() != nullptr; +} + +// Helper to check if a property is optional (flag or declaration) +static bool IsPropertyOptional(varbinder::LocalVariable *property, checker::Type *propertyType) +{ + // Check if property is marked as optional + if (property->HasFlag(varbinder::VariableFlags::OPTIONAL)) { + return true; + } + + // Check if property type includes undefined (indicating optional) + if (IsPropertyTypeOptional(propertyType)) { + return true; + } + + // Check if declaration has optional modifier + auto *decl = property->Declaration(); + if (decl != nullptr && decl->Node() != nullptr && decl->Node()->IsClassProperty()) { + auto *classProp = decl->Node()->AsClassProperty(); + if (classProp->IsOptionalDeclaration()) { + return true; + } + } + + return false; +} + +// Helper to check if a method property is only getters/setters +static bool IsMethodOnlyAccessors(checker::Type *propertyType) +{ + if (!propertyType->IsETSMethodType()) { + return false; + } + + auto methodType = propertyType->AsETSFunctionType(); + for (auto *sig : methodType->CallSignatures()) { + if (!sig->HasSignatureFlag(checker::SignatureFlags::GETTER) && + !sig->HasSignatureFlag(checker::SignatureFlags::SETTER)) { + // Regular method found + return false; + } + } + return true; +} + +// Helper to check if an interface property is compatible with object literal property +static bool IsInterfacePropertyCompatible(ir::Expression *propExpr, checker::ETSObjectType *interfaceType, + ETSChecker *checker) +{ + if (!propExpr->IsProperty()) { + return false; + } + + ir::Expression *key = propExpr->AsProperty()->Key(); + std::optional optPname = GetPropertyNameFromKey(key); + if (!optPname.has_value()) { + return false; + } + util::StringView pname = optPname.value(); + + // Check if property exists in interface + varbinder::LocalVariable *property = + interfaceType->GetProperty(pname, checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | + checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | + checker::PropertySearchFlags::SEARCH_INSTANCE_DECL | + checker::PropertySearchFlags::SEARCH_IN_INTERFACES); + + if (property == nullptr) { + return false; + } + + auto *propertyType = checker->GetTypeOfVariable(property); + + // If it's a method type, it should only be getter/setter, not regular methods + if (propertyType->IsETSMethodType()) { + return IsMethodOnlyAccessors(propertyType); + } + + return true; +} + +// Helper to check if all required interface properties are satisfied +static bool AreAllRequiredInterfacePropertiesSatisfied(ir::ObjectExpression *expr, + checker::ETSObjectType *interfaceType, ETSChecker *checker) +{ + // Get all properties of the interface using GetAllProperties + auto allProperties = interfaceType->GetAllProperties(); + + // Create a set of property names provided in the object literal + std::unordered_set literalProperties; + for (ir::Expression *propExpr : expr->Properties()) { + if (propExpr->IsProperty()) { + ir::Expression *key = propExpr->AsProperty()->Key(); + if (auto optPname = GetPropertyNameFromKey(key); optPname.has_value()) { + literalProperties.insert(std::string(optPname.value().Utf8())); + } + } + } + + // Check if all literal properties exist in this interface + for (const auto &litPropName : literalProperties) { + bool found = false; + for (auto *property : allProperties) { + if (property->Name().Utf8() == litPropName) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + + // Check that all required interface properties are satisfied + for (auto *property : allProperties) { + std::string propName(property->Name().Utf8()); + auto *propertyType = checker->GetTypeOfVariable(property); + + // Skip method types that aren't getters/setters (they make interface incompatible anyway) + if (propertyType->IsETSMethodType()) { + if (!IsMethodOnlyAccessors(propertyType)) { + // Regular methods not allowed + return false; + } + } + // Check if this property is provided in the literal + bool isInLiteral = literalProperties.find(propName) != literalProperties.end(); + if (!isInLiteral) { + // Property not in literal - check if it's optional or has default value + bool isOptional = IsPropertyOptional(property, propertyType); + bool hasDefaultValue = HasPropertyDefaultValue(property); + if (!isOptional && !hasDefaultValue) { + return false; + } + } + } + + return true; // All required properties are satisfied +} + +static bool IsObjectTypeCompatibleWithLiteral(ETSChecker *checker, ir::ObjectExpression *expr, + checker::ETSObjectType *potentialObjType) +{ + // Split record/map types, class types and interfaces as requested by reviewer + + checker::ETSObjectType *originalBaseType = potentialObjType->GetOriginalBaseType(); + checker::GlobalTypesHolder *globalTypes = checker->GetGlobalTypesHolder(); + + // Handle Record/Map types + if (checker->IsTypeIdenticalTo(originalBaseType, globalTypes->GlobalMapBuiltinType()) || + checker->IsTypeIdenticalTo(originalBaseType, globalTypes->GlobalRecordBuiltinType())) { + // Maps and Records are always compatible with object literals + return true; + } + + // Handle interface types + if (potentialObjType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) { + // For interface types, check that all literal properties exist in the interface + // and that interface has no regular methods (only getters/setters allowed) + + // For non-empty literals, check that all literal properties exist in interface + // and all required interface properties are satisfied + for (ir::Expression *propExpr : expr->Properties()) { + if (!IsInterfacePropertyCompatible(propExpr, potentialObjType, checker)) { + return false; + } + } + + // Check all required interface properties are satisfied + return AreAllRequiredInterfacePropertiesSatisfied(expr, potentialObjType, checker); + } + + // Handle class types + // For class types, you need to check: + // - that there is a parameterless constructor, and + // - that all fields/properties set in the object literal are present in the class + + if (!HasParameterlessConstructor(potentialObjType, checker, expr->Start())) { + return false; + } + + // Check that all properties in literal exist in class + return CheckObjectLiteralCompatibility(expr, potentialObjType); +} + +checker::ETSObjectType *ResolveUnionObjectTypeForObjectLiteral(ETSChecker *checker, ir::ObjectExpression *expr, + checker::ETSUnionType *unionType) +{ + std::vector candidateObjectTypes; + // Phase 1: Gather all ETSObjectTypes from the union + for (auto *constituentType : unionType->ConstituentTypes()) { + if (constituentType->IsETSObjectType()) { + candidateObjectTypes.push_back(constituentType->AsETSObjectType()); + } + } + + if (candidateObjectTypes.empty()) { + // No ETSObjectTypes in the union at all + checker->LogError(diagnostic::CLASS_COMPOSITE_INVALID_TARGET, {expr->PreferredType()}, expr->Start()); + return nullptr; + } + + std::vector matchingObjectTypes; + // Phase 2: Filter candidates using the helper function + for (auto *potentialObjType : candidateObjectTypes) { + if (IsObjectTypeCompatibleWithLiteral(checker, expr, potentialObjType)) { + matchingObjectTypes.push_back(potentialObjType); + } + } + + // Phase 3: Decide based on number of matches + if (matchingObjectTypes.size() == 1) { + return matchingObjectTypes.front(); + } + if (matchingObjectTypes.empty()) { + // No candidate ETSObjectType from the union matched all properties + checker->LogError(diagnostic::CLASS_COMPOSITE_INVALID_TARGET, {expr->PreferredType()}, expr->Start()); + return nullptr; + } + // Ambiguous + checker->LogError(diagnostic::AMBIGUOUS_REFERENCE, {expr->PreferredType()->ToString()}, expr->Start()); + return nullptr; +} + +static checker::ETSObjectType *ResolveObjectTypeFromPreferredType(ETSChecker *checker, ir::ObjectExpression *expr) +{ + // Assume not null, checked by caller in Check() + checker::Type *preferredType = expr->PreferredType(); + + if (preferredType->IsETSUnionType()) { + return ResolveUnionObjectTypeForObjectLiteral(checker, expr, preferredType->AsETSUnionType()); + } + + if (preferredType->IsETSObjectType()) { + return preferredType->AsETSObjectType(); + } + + return nullptr; +} + +// Helper to handle interface type objects +static checker::Type *HandleInterfaceType(ETSChecker *checker, ir::ObjectExpression *expr, + checker::ETSObjectType *objType) +{ + auto *analyzer = static_cast(checker->GetAnalyzer()); + analyzer->CheckObjectExprProps( + expr, objType, + checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | + checker::PropertySearchFlags::SEARCH_INSTANCE_DECL | checker::PropertySearchFlags::SEARCH_IN_INTERFACES); + expr->SetTsType(objType); + return objType; +} + +// Helper to handle Record/Map types +static checker::Type *HandleRecordOrMapType(ETSChecker *checker, ir::ObjectExpression *expr, + checker::ETSObjectType *objType) +{ + expr->SetTsType(objType); + SetTypeforRecordProperties(expr, objType, checker); + return objType; +} + checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const { ETSChecker *checker = GetETSChecker(); @@ -1874,7 +2240,14 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const return expr->TsType(); } - if (!ValidatePreferredType(checker, expr)) { + if (expr->PreferredType() == nullptr) { + checker->LogError(diagnostic::CLASS_COMPOSITE_UNKNOWN_TYPE, {}, expr->Start()); + expr->SetTsType(checker->GlobalTypeError()); + return expr->TsType(); + } + + if (!expr->PreferredType()->IsETSUnionType() && !expr->PreferredType()->IsETSDynamicType() && + !ValidatePreferredType(checker, expr)) { expr->SetTsType(checker->GlobalTypeError()); return expr->TsType(); } @@ -1883,53 +2256,48 @@ checker::Type *ETSAnalyzer::Check(ir::ObjectExpression *expr) const return CheckDynamic(expr); } - checker::ETSObjectType *objType = expr->PreferredType()->AsETSObjectType(); - if (objType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) { - // Object literal of interface tpye - // Further interfaceObjectLiteralLowering phase will resolve interface type - // and create corresponding anonymous class and class type - // Here we just set the type to pass the checker - CheckObjectExprProps(expr, checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | - checker::PropertySearchFlags::SEARCH_IN_INTERFACES); - expr->SetTsType(objType); - return objType; - } - - if (expr->PreferredType()->ToAssemblerName().str() == compiler::Signatures::BUILTIN_RECORD || - expr->PreferredType()->ToAssemblerName().str() == compiler::Signatures::BUILTIN_MAP) { - // 7.6.3 Object Literal of Record Type - // Record is an alias to Map - // Here we just set the type to pass the checker - // See Record Lowering for details - expr->SetTsType(objType); - SetTypeforRecordProperties(expr, objType, checker); - return objType; - } - - bool haveEmptyConstructor = false; - for (checker::Signature *sig : objType->ConstructSignatures()) { - if (sig->Params().empty()) { - haveEmptyConstructor = true; - checker->ValidateSignatureAccessibility(objType, sig, expr->Start()); - break; + checker::ETSObjectType *objType = ResolveObjectTypeFromPreferredType(checker, expr); + + if (objType == nullptr) { + if (!expr->PreferredType()->IsETSUnionType()) { + checker->LogError(diagnostic::CLASS_COMPOSITE_INVALID_TARGET, {expr->PreferredType()}, expr->Start()); } + expr->SetTsType(checker->GlobalTypeError()); + return expr->TsType(); + } + + if (objType->HasObjectFlag(checker::ETSObjectFlags::INTERFACE)) { + return HandleInterfaceType(checker, expr, objType); + } + + checker::ETSObjectType *originalBaseObjType = objType->GetOriginalBaseType(); + checker::GlobalTypesHolder *globalTypes = checker->GetGlobalTypesHolder(); + if (checker->IsTypeIdenticalTo(originalBaseObjType, globalTypes->GlobalMapBuiltinType()) || + checker->IsTypeIdenticalTo(originalBaseObjType, globalTypes->GlobalRecordBuiltinType())) { + return HandleRecordOrMapType(checker, expr, objType); } - if (!haveEmptyConstructor) { - return checker->TypeError(expr, diagnostic::NO_PARAMLESS_CTOR, {objType->Name()}, expr->Start()); + + // If we reach here, objType is a class. It must have a parameterless constructor + if (!HasParameterlessConstructor(objType, checker, expr->Start())) { + expr->SetTsType(checker->TypeError(expr, diagnostic::NO_PARAMLESS_CTOR, {objType->Name()}, expr->Start())); + return expr->TsType(); } - CheckObjectExprProps(expr, checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | - checker::PropertySearchFlags::SEARCH_IN_BASE | - checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD); + CheckObjectExprProps(expr, objType, + checker::PropertySearchFlags::SEARCH_INSTANCE_FIELD | + checker::PropertySearchFlags::SEARCH_IN_BASE | + checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD); expr->SetTsType(objType); return objType; } -void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, checker::PropertySearchFlags searchFlags) const +void ETSAnalyzer::CheckObjectExprProps(const ir::ObjectExpression *expr, + checker::ETSObjectType *objectTypeForProperties, + checker::PropertySearchFlags searchFlags) const { ETSChecker *checker = GetETSChecker(); - checker::ETSObjectType *objType = expr->PreferredType()->AsETSObjectType(); + checker::ETSObjectType *objType = objectTypeForProperties; for (ir::Expression *propExpr : expr->Properties()) { if (!propExpr->IsProperty()) { @@ -2385,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; } } @@ -2724,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/ETSAnalyzer.h b/ets2panda/checker/ETSAnalyzer.h index 91c846e4255aefd2566f2db4aa19baf9abe7da2f..c9a398b319b807b28c697498308e787f9103af69 100644 --- a/ets2panda/checker/ETSAnalyzer.h +++ b/ets2panda/checker/ETSAnalyzer.h @@ -40,7 +40,8 @@ public: checker::Type *CheckDynamic(ir::ObjectExpression *expr) const; checker::Type *GetPreferredType(ir::ArrayExpression *expr) const; void GetUnionPreferredType(ir::Expression *expr, Type *originalType) const; - void CheckObjectExprProps(const ir::ObjectExpression *expr, checker::PropertySearchFlags searchFlags) const; + void CheckObjectExprProps(const ir::ObjectExpression *expr, checker::ETSObjectType *objectTypeForProperties, + checker::PropertySearchFlags searchFlags) const; std::tuple CheckAssignmentExprOperatorType(ir::AssignmentExpression *expr, Type *leftType) const; [[nodiscard]] checker::Type *ReturnTypeForStatement([[maybe_unused]] const ir::Statement *const st) const; diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index f652f68e788bf04c99f3cf5025e85efc5da534f2..ff4be3487e2d1f5ac6cd8e4aa1a8b2ba08f0120c 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 452cf67b950b0b7caf454c600c134c4b527a0d8e..01e68b8bac1558bd1cc48be51c9d1a66d9b08084 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 06de9f47df7fc3cd76ba9417daf3c146cc31b52d..bf9cd81c5f6056e58738977b9eb36ddbcbaf4e7c 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 { @@ -455,6 +479,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, @@ -884,6 +909,21 @@ public: return overloadSigContainer_; } + ObjectInstantiationMap &GetObjectInstantiationMap() + { + return objectInstantiationMap_; + } + + FunctionSignatureMap &GetInvokeToArrowSignatures() + { + return invokeToArrowSignatures_; + } + + FunctionInterfaceMap &GetArrowToFuncInterfaces() + { + return arrowToFuncInterfaces_; + } + void CleanUp() override { Checker::CleanUp(); @@ -1028,6 +1068,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 +1094,9 @@ private: ArrayMap arrayTypes_; ArenaVector pendingConstraintCheckRecords_; + ObjectInstantiationMap objectInstantiationMap_; + FunctionSignatureMap invokeToArrowSignatures_; + FunctionInterfaceMap arrowToFuncInterfaces_; size_t constraintCheckScopesCount_ {0}; GlobalArraySignatureMap globalArraySignatures_; ComputedAbstracts *cachedComputedAbstracts_ {nullptr}; @@ -1067,6 +1111,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 3efe6f5b8d7bbc0d6d74297acdd42fcab796c441..62c02cc2064b2540fbdcc5551816e2681d53fa0f 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 0d0a6052089ea1bd959d2a88ca3b4774b31a2d69..3e261069aa8196ca0803ad84e0d67a53e8d9112d 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 9e820dfc4d067f98c1dfe1c36f675edcd0e9ed44..4fe4acde5426a0b21f5bd43b23d7fb79f17e0d44 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 83ecaa50ca0e3d5ecf6df95e1d76e898c693a1cb..4d360a1f4fa9a948ca4eace745779c1adb8b7aaf 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 d4adeb07cc20d29c1f6cd650981628aeb2c0df7f..39c4be1b5982acc392442724bc58a9d76b98126a 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 8c0e0dc583d66fc04ca0e3b7c8175699eead9846..c41af2dbd818e3aa0df7266e0b115847fb411979 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/conversion.cpp b/ets2panda/checker/ets/conversion.cpp index e165cb0e9a3491fecc9d078e62921ba3bce4567f..345a1a4f672ee164be2b91985212a77493fc625f 100644 --- a/ets2panda/checker/ets/conversion.cpp +++ b/ets2panda/checker/ets/conversion.cpp @@ -346,14 +346,12 @@ void String(TypeRelation *const relation, Type *const source) auto *const tempInt = relation->GetChecker()->AsETSChecker()->GetGlobalTypesHolder()->GlobalIntType(); WideningPrimitive(relation, source, tempInt); Boxing(relation, tempInt); - relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::CONVERT_TO_STRING); return; } if (source->HasTypeFlag(TypeFlag::ETS_BOOLEAN | TypeFlag::CHAR | TypeFlag::INT | TypeFlag::LONG | TypeFlag::FLOAT | TypeFlag::DOUBLE)) { Boxing(relation, source); - relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::CONVERT_TO_STRING); return; } diff --git a/ets2panda/checker/ets/dynamic.cpp b/ets2panda/checker/ets/dynamic.cpp index 90abef0f88868f0bf982a1ca26ec3b8788c9f65e..f5d2544345b31dd7d9677a2248c32ca4b9186ba8 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 de2fe9821ae6c0eb600c6f2e24164c12677f04ff..2e33f3143634b478e9dbb21f3113d78fa216bfd7 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); }; @@ -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, @@ -575,9 +611,7 @@ 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 = - ((flags & TypeRelationFlag::ONLY_CHECK_BOXING_UNBOXING) == 0 && !unique) - ? baseSignature - : MaybeSubstituteTypeParameters(this, baseSignature, typeArguments, arguments, pos, flags); + MaybeSubstituteTypeParameters(this, baseSignature, typeArguments, arguments, pos, flags); if (signature == nullptr) { return nullptr; } @@ -671,7 +705,6 @@ std::array GetFlagVariants() TypeRelationFlag::NO_BOXING, TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::IGNORE_REST_PARAM, TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING, - TypeRelationFlag::NO_THROW | TypeRelationFlag::STRING_TO_CHAR, }; } @@ -708,25 +741,15 @@ ArenaVector ETSChecker::CollectSignatures(ArenaVector // If there's only one signature, we don't need special checks for boxing/unboxing/widening. // We are also able to provide more specific error messages. if (signatures.size() == 1) { - TypeRelationFlag flags = TypeRelationFlag::WIDENING | TypeRelationFlag::STRING_TO_CHAR | resolveFlags; + TypeRelationFlag flags = TypeRelationFlag::WIDENING | resolveFlags; collectSignatures(flags); } else { for (auto flags : GetFlagVariants()) { - // CollectSignatures gathers the possible signatures, but in doing so, it also sets the boxing/unboxing - // flags where necessary. Since these might not be the actually used functions in every cases, - // this setting needs to be delayed for compatibleSignatures. In case of only one signature, - // it is not required, only when the signatures.size() > 1 - flags = flags | resolveFlags | TypeRelationFlag::ONLY_CHECK_BOXING_UNBOXING; + flags = flags | resolveFlags; collectSignatures(flags); - if (compatibleSignatures.empty()) { - continue; - } - for (auto signature : compatibleSignatures) { - flags &= ~TypeRelationFlag::ONLY_CHECK_BOXING_UNBOXING; - ValidateSignature(std::make_tuple(signature, typeArguments, flags), arguments, pos, - argTypeInferenceRequired, signatures.size() == 1); + if (!compatibleSignatures.empty()) { + break; } - break; } } @@ -737,7 +760,22 @@ ArenaVector ETSChecker::CollectSignatures(ArenaVector return compatibleSignatures; } -static void UpdateArrayArgs(ETSChecker *checker, Signature *sig, const ArenaVector &arguments) +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) { auto const commonArity = std::min(arguments.size(), sig->ArgCount()); for (size_t index = 0; index < commonArity; ++index) { @@ -746,6 +784,7 @@ static void UpdateArrayArgs(ETSChecker *checker, Signature *sig, const ArenaVect auto flags = TypeRelationFlag::NO_THROW | TypeRelationFlag::BOXING | TypeRelationFlag::UNBOXING | TypeRelationFlag::WIDENING; ClearPreferredTypeForArray(checker, argument, paramType, flags, true); + ClearUnboxingFlags(checker->Relation(), sig, argument, index); } } @@ -768,7 +807,7 @@ Signature *ETSChecker::GetMostSpecificSignature(ArenaVector &compat } // revalidate signature for arrays - UpdateArrayArgs(this, mostSpecificSignature, arguments); + UpdateArrayArgsAndUnboxingFlags(this, mostSpecificSignature, arguments); return mostSpecificSignature; } @@ -1095,7 +1134,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, @@ -1105,7 +1144,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", @@ -1221,7 +1260,7 @@ void ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVectorGetOverloadInfo(); + ir::OverloadInfo &ldInfo = method->GetOverloadInfoForUpdate(); ArenaVector overloads(checker->ProgramAllocator()->Adapter()); for (ir::MethodDefinition *const currentFunc : method->Overloads()) { @@ -1233,11 +1272,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()) { @@ -1281,7 +1325,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) { @@ -1471,6 +1515,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(); @@ -2124,11 +2172,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); @@ -2175,7 +2220,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 95f7eed99f9324b54b17ebdae2d5707d3b2740d2..82a6fdb2c2b478b9eaf620d12aa8df2c5dc60cd6 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -614,16 +614,29 @@ checker::Type *PreferredObjectTypeFromAnnotation(checker::Type *annotationType) } checker::Type *resolvedType = nullptr; + int objectTypeCount = 0; for (auto constituentType : annotationType->AsETSUnionType()->ConstituentTypes()) { if (constituentType->IsETSObjectType()) { - if (resolvedType != nullptr) { - return nullptr; + objectTypeCount++; + if (resolvedType == nullptr) { + resolvedType = constituentType; } - resolvedType = constituentType; } } - return resolvedType; + // If there's exactly one object type, return it + if (objectTypeCount == 1) { + return resolvedType; + } + + // If there are multiple object types, return the union type itself + // so that our union resolution logic can handle it + if (objectTypeCount > 1) { + return annotationType; + } + + // If there are no object types, return nullptr + return nullptr; } bool SetPreferredTypeForExpression(ETSChecker *checker, ir::Identifier *ident, ir::TypeNode *typeAnnotation, @@ -1656,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); @@ -2805,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); @@ -2823,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; } @@ -2890,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 c5724a9d7e175efa7d20ad4fda5cfce5b6e2c599..cbf729d09f454287d1086ccf8e384f6ecc21ea42 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/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 7905ad0b00b6053a72ea0986d8d4d2dfb313a148..1fa0493279befe6b6429cb10983fd5d8b5782f9d 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -293,22 +293,23 @@ bool Type::PossiblyETSString() const static bool IsValueTypedObjectType(ETSObjectType const *t) { - return t->IsGlobalETSObjectType() || t->HasObjectFlag(ETSObjectFlags::VALUE_TYPED) || - t->HasObjectFlag(ETSObjectFlags::ENUM_OBJECT); + ETSObjectFlags flags = ETSObjectFlags::FUNCTIONAL_REFERENCE | ETSObjectFlags::VALUE_TYPED | + ETSObjectFlags::ENUM_OBJECT | ETSObjectFlags::FUNCTIONAL; + return t->IsGlobalETSObjectType() || t->HasObjectFlag(flags); } bool Type::PossiblyETSValueTyped() const { - return MatchConstituentOrConstraint(this, [](const Type *t) { - return t->IsETSNullType() || t->IsETSUndefinedType() || - (t->IsETSObjectType() && IsValueTypedObjectType(t->AsETSObjectType())); - }); + return MatchConstituentOrConstraint(this, + [](const Type *t) { return t->IsETSNullType() || t->IsETSUndefinedType(); }) || + PossiblyETSValueTypedExceptNullish(); } bool Type::PossiblyETSValueTypedExceptNullish() const { - return MatchConstituentOrConstraint( - this, [](const Type *t) { return t->IsETSObjectType() && IsValueTypedObjectType(t->AsETSObjectType()); }); + return MatchConstituentOrConstraint(this, [](const Type *t) { + return t->IsETSFunctionType() || (t->IsETSObjectType() && IsValueTypedObjectType(t->AsETSObjectType())); + }); } bool Type::IsETSArrowType() const diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 4c35d829af3a26b73da9834501dd945f6dccaad4..53b6838523debd2753639fa0ebed2702c14a6745 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 00dcde0ae4f6226f2eee1d2649cfaf76282d2fd1..f8a63c3124d2491566597e6e17444b8c26872b8a 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 b2d95bd91d730743bac2ae4a6aa46895dfa27d90..c77f536455038d1fbfc515fa394857d494d936f1 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/charType.cpp b/ets2panda/checker/types/ets/charType.cpp index 044657176938dfc8ba8914c7faeea14277b7dc57..62fad52d6eb2f8e635e2943810a817976103d996 100644 --- a/ets2panda/checker/types/ets/charType.cpp +++ b/ets2panda/checker/types/ets/charType.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 @@ -37,11 +37,6 @@ void CharType::AssignmentTarget(TypeRelation *relation, [[maybe_unused]] Type *s bool CharType::AssignmentSource([[maybe_unused]] TypeRelation *relation, [[maybe_unused]] Type *target) { if (relation->InAssignmentContext()) { - if (target->IsETSStringType()) { - conversion::Boxing(relation, this); - relation->GetNode()->AddAstNodeFlags(ir::AstNodeFlags::CONVERT_TO_STRING); - return relation->Result(true); - } relation->GetChecker()->AsETSChecker()->CheckUnboxedTypeWidenable(relation, target, this); if (!relation->IsTrue()) { return false; @@ -72,11 +67,6 @@ void CharType::Cast(TypeRelation *const relation, Type *const target) return; } - if (target->IsETSStringType()) { - conversion::String(relation, this); - return; - } - if (target->HasTypeFlag(TypeFlag::ETS_OBJECT)) { if (target->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)) { conversion::Boxing(relation, this); diff --git a/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h b/ets2panda/checker/types/ets/etsAsyncFuncReturnType.h index e1ede4842b6fe35b3dc6ac4d712bf8e26ed064f2..e079ff71a6802e5d9e84768e4484c6288bc40fce 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 279c5d08170a65b67037458472b7d959bcc61005..8ed5f40ccb1f3ecdda34f88f5fdc60eee0483297 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 eea79b4fb92a6ea1b1275bdfc17aa8c1a845ad9c..9506417407b68e4c8be22b2d007eb016fcb407bc 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 a5c6bdf33d7a3e767413365b6105f75f9114285b..99e5b34528f8275ab16deaa3690158817ea64ae0 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 1df9fd28eac9bc6271cff13c4bf63277ce2ae0d8..dbb55f46bc6cafa6588d56cc553fd58c2454f407 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 { @@ -73,7 +74,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); } @@ -104,11 +107,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 +129,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 f59b65c709b186655a85fb231952f2884b628baa..14eea128aac6824708397918277d2d9520ad4547 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 733f658a5321354fffcb92de928c42ad72af4540..61a6db0141bf8e1c7eeb777481cebbc09b8bac23 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 9a174689dd7925c03ca8557b5caf2c2a044d2338..20e5811f3d0d524919f40930e1c89e2a437532b2 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/etsObjectTypeConstants.h b/ets2panda/checker/types/ets/etsObjectTypeConstants.h index 22df5674e188a7ae6efe504b2fe7c6884b2abcd0..0a51f2f1d6a1393d49d722194d834fdc8992eb7e 100644 --- a/ets2panda/checker/types/ets/etsObjectTypeConstants.h +++ b/ets2panda/checker/types/ets/etsObjectTypeConstants.h @@ -59,6 +59,8 @@ enum class ETSObjectFlags : std::uint64_t { ENUM_OBJECT = 1ULL << 33U, EXTENSION_FUNCTION = 1ULL << 34U, + FUNCTIONAL_REFERENCE = 1ULL << 35U, + BUILTIN_NUMERIC = BUILTIN_BYTE | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | BUILTIN_FLOAT | BUILTIN_DOUBLE, // Complete set includes null|undefined|Object VALUE_TYPED = BUILTIN_BOOLEAN | BUILTIN_CHAR | BUILTIN_NUMERIC | BUILTIN_BIGINT | STRING, diff --git a/ets2panda/checker/types/ets/etsResizableArrayType.h b/ets2panda/checker/types/ets/etsResizableArrayType.h index 43babf404a36dcfdbce983333683b9a94a0666bd..1301e726931f457b658e626b915696d2f01a50d1 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.cpp b/ets2panda/checker/types/ets/etsStringType.cpp index 648af3cc0137a144315bc3974bc6f456b31ed8b4..1a3c8ba2cc94ec1fc7ea2c58a07b1c419137e8dc 100644 --- a/ets2panda/checker/types/ets/etsStringType.cpp +++ b/ets2panda/checker/types/ets/etsStringType.cpp @@ -40,17 +40,7 @@ void ETSStringType::Identical(TypeRelation *relation, Type *other) bool ETSStringType::AssignmentSource(TypeRelation *relation, Type *target) { - auto node = relation->GetNode(); - if ((relation->InAssignmentContext() || relation->ApplyStringToChar()) && IsConvertibleTo(target)) { - node->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOX_TO_CHAR); - if (target->IsETSObjectType()) { - node->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_CHAR); - } - relation->Result(true); - } else { - relation->Result(target->IsETSStringType() && AreStringTypesAssignable(this, target)); - } - + relation->Result(target->IsETSStringType() && AreStringTypesAssignable(this, target)); return relation->IsTrue(); } @@ -85,14 +75,4 @@ void ETSStringType::IsSubtypeOf(TypeRelation *relation, Type *source) relation->IsSupertypeOf(source, checker->GlobalBuiltinETSStringType()); } -bool ETSStringType::IsConvertibleTo(Type const *to) const -{ - const bool targetIsChar = - to->IsCharType() || - // ETSObjectType is used in arrow function expression call. - (to->IsETSObjectType() && to->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::BUILTIN_CHAR)); - - return targetIsChar && IsConstantType() && value_.IsConvertibleToChar(); -} - } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/ets/etsStringType.h b/ets2panda/checker/types/ets/etsStringType.h index 2e47f48eea53295796b17ada5234f95891e6c5ae..513f4deb5271c35793f4e8f6c8abe1f26795142d 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, @@ -81,8 +81,6 @@ public: return {IsConstantType(), IsConstantType() ? (GetValue().Length() != 0) : false}; } - bool IsConvertibleTo(Type const *to) const; - private: util::StringView value_ {}; }; diff --git a/ets2panda/checker/types/globalTypesHolder.cpp b/ets2panda/checker/types/globalTypesHolder.cpp index 2644c1b7192f9c83e57987746f75fd2c0dc1e8f6..784aa977a409c2561d3418a1ec74d7eb7821fb44 100644 --- a/ets2panda/checker/types/globalTypesHolder.cpp +++ b/ets2panda/checker/types/globalTypesHolder.cpp @@ -63,6 +63,7 @@ void GlobalTypesHolder::AddETSEscompatLayer() builtinNameMappings_.emplace("NullPointerError", GlobalTypeId::ETS_NULL_POINTER_ERROR_BUILTIN); builtinNameMappings_.emplace("UncaughtExceptionError", GlobalTypeId::ETS_UNCAUGHT_EXCEPTION_ERROR_BUILTIN); builtinNameMappings_.emplace("Map", GlobalTypeId::ETS_MAP_BUILTIN); + builtinNameMappings_.emplace("Record", GlobalTypeId::ETS_RECORD_BUILTIN); builtinNameMappings_.emplace("RegExp", GlobalTypeId::ETS_REGEXP_BUILTIN); builtinNameMappings_.emplace("Set", GlobalTypeId::ETS_SET_BUILTIN); } @@ -487,6 +488,11 @@ Type *GlobalTypesHolder::GlobalMapBuiltinType() return globalTypes_.at(static_cast(GlobalTypeId::ETS_MAP_BUILTIN)); } +Type *GlobalTypesHolder::GlobalRecordBuiltinType() +{ + return globalTypes_.at(static_cast(GlobalTypeId::ETS_RECORD_BUILTIN)); +} + Type *GlobalTypesHolder::GlobalErrorBuiltinType() { return globalTypes_.at(static_cast(GlobalTypeId::ETS_ERROR_BUILTIN)); diff --git a/ets2panda/checker/types/globalTypesHolder.h b/ets2panda/checker/types/globalTypesHolder.h index cd5e0235394f9215516b7f0f327eb9c819490e90..2242097f8d854483c454b3d2ab6f24672ae1840c 100644 --- a/ets2panda/checker/types/globalTypesHolder.h +++ b/ets2panda/checker/types/globalTypesHolder.h @@ -75,6 +75,7 @@ enum class GlobalTypeId : std::size_t { ETS_INTEGRAL_BUILTIN, ETS_LONG_BUILTIN, ETS_MAP_BUILTIN, + ETS_RECORD_BUILTIN, ETS_ERROR_BUILTIN, ETS_RUNTIME_BUILTIN, ETS_RUNTIME_LINKER_BUILTIN, @@ -324,6 +325,7 @@ public: Type *GlobalNullPointerErrorBuiltinType(); Type *GlobalUncaughtExceptionErrorBuiltinType(); Type *GlobalMapBuiltinType(); + Type *GlobalRecordBuiltinType(); Type *GlobalRegExpBuiltinType(); Type *GlobalSetBuiltinType(); diff --git a/ets2panda/checker/types/type.cpp b/ets2panda/checker/types/type.cpp index 92368135f34ab098c1a16ecead974eb3b4a03e5c..e03343c7f1ef1a1375d60dc812c4a3a7297b51ab 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 1a0895b37a62d2824bab0b9fbf52314c9f7a80e5..1104cada5f540782858ce5ef1b0b7de8f17639d6 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 ae65dc122971ca47b99299b25a816e826a106eca..6e1ad8cb6d6263e8ac6152029fc6261e7b0cb80b 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" @@ -62,7 +63,6 @@ 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, ASSIGNMENT_CONTEXT = WIDENING | BOXING | UNBOXING, BRIDGE_CHECK = OVERRIDING_CONTEXT | IGNORE_TYPE_PARAMETERS | NO_RETURN_TYPE_CHECK, @@ -111,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 {}; }; @@ -156,11 +163,6 @@ public: return (flags_ & TypeRelationFlag::UNBOXING) != 0; } - bool ApplyStringToChar() const - { - return (flags_ & TypeRelationFlag::STRING_TO_CHAR) != 0; - } - bool NoReturnTypeCheck() const { return (flags_ & TypeRelationFlag::NO_RETURN_TYPE_CHECK) != 0; @@ -251,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; @@ -267,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; @@ -348,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 62c616a88eed4575cbc17915e41b2698e1bd8b6c..004427936cbf08ea19c6b7e32214e490ddf3bf18 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 @@ -1117,12 +1117,6 @@ void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targe const bool hasUnboxingflags = (node->GetBoxingUnboxingFlags() & ir::BoxingUnboxingFlags::UNBOXING_FLAG) != 0U; if (hasBoxingflags && !hasUnboxingflags) { ApplyBoxingConversion(node); - - if (node->HasAstNodeFlags(ir::AstNodeFlags::CONVERT_TO_STRING)) { - CastToString(node); - node->RemoveAstNodeFlags(ir::AstNodeFlags::CONVERT_TO_STRING); - } - return; } @@ -1769,15 +1763,9 @@ void ETSGen::CastToString(const ir::AstNode *const node) if (sourceType->IsETSStringType()) { return; } - if (sourceType->IsETSCharType()) { - Ra().Emit(node, Signatures::BUILTIN_OBJECT_TO_STRING, dummyReg_, 0); - return; - } - if (sourceType->IsETSPrimitiveType()) { - EmitBoxingConversion(node); - } else { - ES2PANDA_ASSERT(sourceType->IsETSReferenceType()); - } + + 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()); diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index a64eee6047b1170fa227d70a00739a43723ebdbc..8f0b822ef9a54cc8c5890d195f500e6a04a388b0 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -127,7 +127,7 @@ static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, if (var->Declaration()->Node() == nullptr || !var->Declaration()->Node()->IsETSParameterExpression()) { continue; } - func.params.back().metadata->SetAnnotations(emitter->GenCustomAnnotations( + func.params.back().GetOrCreateMetadata().SetAnnotations(emitter->GenCustomAnnotations( var->Declaration()->Node()->AsETSParameterExpression()->Annotations(), var->Name().Mutf8())); } @@ -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()) { @@ -436,12 +436,12 @@ void ETSEmitter::GenClassField(const ir::ClassProperty *prop, pandasm::Record &c field.name = prop->Id()->Name().Mutf8(); field.type = PandasmTypeWithRank(prop->TsType()); field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers())); - 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)); @@ -526,6 +526,10 @@ std::vector ETSEmitter::GenAnnotations(const ir::ClassD std::vector annotations; const ir::AstNode *parent = classDef->Parent(); while (parent != nullptr) { + if ((classDef->Modifiers() & ir::ClassDefinitionModifiers::FUNCTIONAL_REFERENCE) != 0U) { + annotations.emplace_back(GenAnnotationFunctionalReference(classDef)); + break; + } if (parent->IsMethodDefinition()) { annotations.emplace_back(GenAnnotationEnclosingMethod(parent->AsMethodDefinition())); annotations.emplace_back(GenAnnotationInnerClass(classDef, parent)); @@ -543,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)); } @@ -752,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()) { @@ -870,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: @@ -993,6 +997,18 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingMethod(const ir::Metho return enclosingMethod; } +pandasm::AnnotationData ETSEmitter::GenAnnotationFunctionalReference(const ir::ClassDefinition *classDef) +{ + GenAnnotationRecord(Signatures::ETS_ANNOTATION_FUNCTIONAL_REFERENCE); + 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()))); + functionalReference.AddElement(std::move(value)); + return functionalReference; +} + pandasm::AnnotationData ETSEmitter::GenAnnotationEnclosingClass(std::string_view className) { GenAnnotationRecord(Signatures::ETS_ANNOTATION_ENCLOSING_CLASS); @@ -1050,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/ETSemitter.h b/ets2panda/compiler/core/ETSemitter.h index f47d2af046eb08142095666debc0994362e22894..b3a894202656a52fe68c177875fe54936c3132fb 100644 --- a/ets2panda/compiler/core/ETSemitter.h +++ b/ets2panda/compiler/core/ETSemitter.h @@ -115,6 +115,7 @@ private: pandasm::AnnotationData GenAnnotationModule(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationEnclosingClass(std::string_view className); pandasm::AnnotationData GenAnnotationEnclosingMethod(const ir::MethodDefinition *methodDef); + pandasm::AnnotationData GenAnnotationFunctionalReference(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationInnerClass(const ir::ClassDefinition *classDef, const ir::AstNode *parent); pandasm::AnnotationData GenAnnotationAsync(ir::ScriptFunction *scriptFunc); pandasm::AnnotationData GenAnnotationDynamicCall(DynamicCallNamesMap &callNames); diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index af038f7485b05af97319c3323ed07111828ae1f2..1e5e752ae776abd6934cf31d8e127a3f69eb6587 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 85ab16b5455323a15f78a485dab62313595ce5a3..3438850966073a81539b9ef3fa910ff7b9dd2a7e 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 019a5ce570f922d4e512c432f22a286d11c05848..7f820e81684e5f102610413e9dcaf64b829adc93 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 03b9e6979b12a3d326a1b34b60f90a870b110652..f9a915da105f23f1e8384d76847d7320add3e2dc 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 b07f25dc9b61789cfc2270a87c542b27046e0e4e..3a52acabc81797b36cf1f21395c64b0b0767cf0a 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 a9aa187de82ac2c266206b969e1b8ef6a7812535..bf9fea2cc5a6552378dff92248dfff73ac4d9e89 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 d801b5526c23dc6f88d31f35fcc4c16c3a85e444..9645a5ff5d01a69b5bbcd5f41b2b18182ced5891 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 132656ee5c82e10a0ed64a7d79d6f5eb698410cd..6d40b4592f21bc21b49271cf9292b964c77cb3a8 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 4c51f695dd50e01be7b072cfa97b1479e6600815..5ad356570b65bfbf06d5a7b9a84a519472b656de 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 cf124f55bb29375e856e38d1df440d4265a45aef..c7d21d52b04b8fcfbc824e2de1ddaf4e730bbf47 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 2f63e74222530e2f0edf6d3029c46af1fd5eb825..a0a8c9534c007d08835434316f03a50a6308b8b0 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 823859d6819d8f9843887e6b86b0bb5b0b0087a3..0a3374acc29ed51294a32aa3902c52e7c829727d 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/constStringToCharLowering.cpp b/ets2panda/compiler/lowering/ets/constStringToCharLowering.cpp deleted file mode 100644 index 563d13096b787362e1003b8f2e5c035192ea7d63..0000000000000000000000000000000000000000 --- a/ets2panda/compiler/lowering/ets/constStringToCharLowering.cpp +++ /dev/null @@ -1,75 +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 "constStringToCharLowering.h" - -#include "checker/ETSchecker.h" - -namespace ark::es2panda::compiler { - -std::string_view ConstStringToCharLowering::Name() const -{ - return "ConstStringToCharLowering"; -} - -ir::AstNode *TryConvertToCharLiteral(public_lib::Context *const ctx, ir::AstNode *ast) -{ - if (!ast->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::UNBOX_TO_CHAR) || !ast->IsExpression() || - ast->AsExpression()->TsType() == nullptr || !ast->AsExpression()->TsType()->IsETSStringType()) { - return nullptr; - } - - auto type = ast->AsExpression()->TsType()->AsETSStringType(); - if (!type->IsConstantType() || !type->GetValue().IsConvertibleToChar()) { - return nullptr; - } - - auto parent = ast->Parent(); - util::StringView::Iterator it(type->GetValue()); - auto value = static_cast(it.PeekCp()); - - auto newValue = ctx->Allocator()->New(value); - newValue->SetParent(parent); - newValue->SetRange(ast->Range()); - if (ast->HasBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_CHAR)) { - newValue->AddBoxingUnboxingFlags(ir::BoxingUnboxingFlags::BOX_TO_CHAR); - } - - newValue->Check(ctx->checker->AsETSChecker()); - return newValue; -} - -bool ConstStringToCharLowering::PerformForModule(public_lib::Context *const ctx, parser::Program *const program) -{ - if (program->GetFlag(parser::ProgramFlags::AST_CONST_STRING_TO_CHAR_LOWERED)) { - return true; - } - - (void)ctx; - program->Ast()->TransformChildrenRecursively( - [ctx](checker::AstNodePtr ast) -> checker::AstNodePtr { - if (auto newValue = TryConvertToCharLiteral(ctx, ast); newValue != nullptr) { - return newValue; - } - - return ast; - }, - Name()); - - program->SetFlag(parser::ProgramFlags::AST_CONST_STRING_TO_CHAR_LOWERED); - return true; -} - -} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp b/ets2panda/compiler/lowering/ets/convertPrimitiveCastMethodCall.cpp index 9d232d1db08070f3e2c72e39da7f6ff0e831ae75..3f5c3219af8d21f83f99b79e8bcbf7cf14f6140f 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 613fcf10d239657b8c98836c6c3e3fda9bf9e6a2..c1e53dd59ba2aab22e37dca6f3ef6f470a149af0 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 d9ede70dc70e83d757ebbd3be280e8859230dada..bf69507850268b5d9664ef982d173045d175b6e1 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 d87fc777fd5283328aa9c22b3f21b944ac3cc7c2..e6bffbeee360a7424ff93c0a5bad1660de6ddeed 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersLowering.cpp @@ -38,6 +38,37 @@ 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(); + auto &bodyStmt = body->StatementsForUpdates(); + + 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); + bodyStmt[dfltIdx] = stmt; + stmt->SetParent(body); + } +} + static void TransformFunction(public_lib::Context *ctx, ir::ScriptFunction *function) { auto const ¶ms = function->Params(); @@ -61,22 +92,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/compiler/lowering/ets/dynamicImportLowering.cpp b/ets2panda/compiler/lowering/ets/dynamicImportLowering.cpp index 8cf9e00c33ef2a8b5a14e7a5285320e4d272e7ae..b4d6f19d1bedad6287b17d2dc3b2a8a4c185ddb7 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 f16b4cd60195d41f32de85fd7a018756672e84c3..8a503952b4dba9be99779f6f54e6f3517d11be02 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; @@ -548,9 +548,12 @@ bool EnumLoweringPhase::PerformForModule(public_lib::Context *ctx, parser::Progr if (ast->IsTSEnumDeclaration()) { auto *enumDecl = ast->AsTSEnumDeclaration(); auto const flags = GetDeclFlags(enumDecl); - if (!flags.IsValid() || enumDecl->Members().empty()) { + if (!flags.IsValid()) { return ast; } + if (enumDecl->Members().empty()) { + return CreateEnumIntClassFromEnumDeclaration(enumDecl, flags); + } bool hasLoggedError = false; bool hasLongLiteral = false; diff --git a/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp b/ets2panda/compiler/lowering/ets/enumPostCheckLowering.cpp index 6e555c258c7b6d94031b4f892ce8b29bf21334c3..a46a63ea5e6e0036ee0a6a7b29b8da687be252f0 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 dbe2fd35b102ed10cdbe94929fce06bb6bdf05f4..1dccd5d05d81e981e9b71f1df760f163893734eb 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 3cb3fd1c2420f8c3a13d1f197cdf293462aadae3..d67d756deceebd7f5d7d3e67d53a450935e89c2a 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 ba1b37d491c9ec136cf800656e71a085c35e776e..13c3e56bc265e69b5616b579ba745563603fe011 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 ab70ff58803f5eb4a24e3a93be40dc453f37adf0..bb3fcbff99a866a86e1c3a58b51fcea1900c09a2 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 51540c092081596f3c6c206486ffe7ec26c958b4..1aa0c072ea59241d4c8282e28f9abc226d28f72d 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, @@ -164,14 +164,19 @@ void GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const return; } + if (overrides(signature, baseSignature1) && overrides(baseSignature1, baseSignature2)) { + // This derived overload already handles the base union signature. + return; + } + if (derivedFunction == nullptr && overrides(signature, baseSignature2)) { - // NOTE: we don't care the possible case of mapping several derived function to the same bridge signature. - // Probably sometimes we will process it correctly or issue warning notification here... + // NOTE: we don't care the possible case of mapping several derived function to the same bridge + // signature. Probably sometimes we will process it correctly or issue warning notification here... derivedFunction = signature->Function(); } } - if (derivedFunction != nullptr) { + if (derivedFunction != nullptr && derivedFunction != baseFunction) { AddGenericBridge(classDefinition, derivedMethod, baseSignature1, derivedFunction); } } @@ -194,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(); @@ -234,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 d8bd398120e66a91a32333679f07bd2d573e6a4a..44d8ae95b58bd29592efd3b26f3324cb7d6890cf 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 7b00e071ae2c56fa630d4cef0600dfb96bc87f85..c88ab3572b51a831e15f60d1bffe3e22bae19a02 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 656abd766b47b1a013b6102b9f69b924914632af..e43a0437b3f408feea03975afb81545670d17a1e 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -30,6 +30,7 @@ struct LambdaInfo { util::StringView originalFuncName = ""; ArenaSet *capturedVars = nullptr; ir::Expression *callReceiver = nullptr; + bool isFunctionReference = false; }; struct CalleeMethodInfo { @@ -74,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(); } @@ -97,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()); @@ -159,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()); @@ -260,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(); @@ -277,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 = @@ -299,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; } @@ -311,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(); @@ -380,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() @@ -419,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) { @@ -444,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) { @@ -490,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); } @@ -499,23 +503,23 @@ 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()); } 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); - 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 +543,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;" @@ -559,21 +564,22 @@ 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); 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); @@ -594,7 +600,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) { @@ -615,16 +621,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; } @@ -669,7 +679,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); @@ -697,7 +707,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()); @@ -712,6 +722,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( @@ -737,7 +748,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); } @@ -799,8 +810,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); @@ -821,7 +832,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); @@ -829,7 +840,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; @@ -838,8 +849,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] = @@ -854,6 +865,11 @@ static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker auto classDeclaration = CreateEmptyLambdaClassDeclaration(ctx, info, newTypeParams, fnInterface, lambdaProviderClass); auto classDefinition = classDeclaration->Definition(); + if (info->isFunctionReference) { + classDefinition->SetFunctionalReferenceReferencedMethod(callee->Function()->Scope()->InternalName()); + classDefinition->SetModifiers(classDefinition->Modifiers() | + ir::ClassDefinitionModifiers::FUNCTIONAL_REFERENCE); + } CreateLambdaClassFields(ctx, classDefinition, info, substitution); CreateLambdaClassConstructor(ctx, classDefinition, info, substitution); @@ -874,6 +890,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); @@ -889,8 +912,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) { @@ -917,9 +940,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; @@ -928,7 +951,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()); @@ -946,6 +969,7 @@ static ir::AstNode *ConvertLambda(public_lib::Context *ctx, ir::ArrowFunctionExp auto capturedVars = FindCaptured(allocator, lambda); info.capturedVars = &capturedVars; info.callReceiver = CheckIfNeedThis(lambda, checker) ? allocator->New() : nullptr; + info.isFunctionReference = false; auto *callee = CreateCallee(ctx, lambda, &info); auto *lambdaType = lambda->TsType()->AsETSFunctionType(); @@ -987,7 +1011,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); @@ -1001,7 +1025,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(); @@ -1018,10 +1042,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; } @@ -1067,6 +1091,7 @@ static ir::AstNode *ConvertFunctionReference(public_lib::Context *ctx, ir::Expre info.originalFuncName = method->Id()->Name(); auto emptySet = ArenaSet(allocator->Adapter()); info.capturedVars = &emptySet; + info.isFunctionReference = true; if (method->IsStatic()) { info.callReceiver = nullptr; } else { @@ -1077,6 +1102,8 @@ static ir::AstNode *ConvertFunctionReference(public_lib::Context *ctx, ir::Expre ES2PANDA_ASSERT(funcRef->TsType()->IsETSArrowType()); auto *lambdaClass = CreateLambdaClass(ctx, funcRef->TsType()->AsETSFunctionType(), method, &info); auto *constructorCall = CreateConstructorCall(ctx, funcRef, lambdaClass, &info); + constructorCall->TsType()->AsETSObjectType()->AddObjectFlag(checker::ETSObjectFlags::FUNCTIONAL_REFERENCE); + return constructorCall; } @@ -1116,7 +1143,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(); @@ -1125,13 +1152,15 @@ 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 | checker::PropertySearchFlags::SEARCH_IN_INTERFACES); ES2PANDA_ASSERT(prop != nullptr); @@ -1152,6 +1181,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); @@ -1235,7 +1267,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); @@ -1245,7 +1277,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"); @@ -1263,7 +1295,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 a6e6b950983766166f77e7e65d014c0ce1fcfa61..108d21c318c16c6908f6519ab4a51e9b3ab5c9e5 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 a9b4095219f019a40e3e881109fe5746210375d1..febb95ab47b37460f58f61183d64b182f764a3a8 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 deefde6145b899278ad075e57cc06081c2aff4da..1f35c823d69cc6f96d0858d423cd5f91a0bb53ef 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 cf43ac31d1e336ef4535651a524e674094e13657..c3136f256e52160a0174d63b0f35d44e74cd005e 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 e24fe2ea47447cb4b85a8a6b508f29360ce798ce..d0f415917df8b09997b5b5bff31639751f60d695 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 62e38b69c3584f143f715898bf6fb91ba450a01b..2f6c22e715defd7f0f1f35a6975cb114cefa6fd5 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 701623fc5240c7e27b072978287c06d0c7907a47..94ce1794274081033d3b74167141e6e6fd066f7f 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 fae3b44254e113007ca72550f1b32837c6af0535..550acfe70304ee28c99440ee24a8549287983357 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 19f0157be76a2d10b33ba40927fd2fd7952aadff..a0814250f82eb35d9a3a59af109e855a23479e51 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 dbe558e0e6512d4c9daf48012d787151c45a4213..1c8114a44885b6dca753a0582a358373cef53bd8 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 8897cd7ddb4e521edb24814712738a325dfb6951..870a9c2aed319fe18f1ec54a6d7fddf6457b369f 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 12d58293e39aac300a120e5a9be316f38bb8746c..804519f9116bbd8fc2bd9aa7da4212b2c78a4330 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 224e98033560d2240fcfd1498fc54056b0af6138..a34c623cf942f386e043190b9427c89d74060cce 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 7e9724a1bf1c84794fbcda4e4404e30226645fa3..36554fe955212ce3e679794bc205195106f145e5 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 95b29ec11e1053bd79416072d903908722f47265..46b9c961e7287c21d2bc6ece17607110318e202d 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 79eb75efe431b4f827f6cc041e07fcd0956f7c76..ddef1ff51b4b92080a07176cb8c057324126907d 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 1c2f4241cfe1d3dc64d53e299a1d4cf8b96c6e17..8c0c488a32a4042e3a14323aa545094cdd1c71ab 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 e7f0cb4f16fe5e16ef9f78fa01daad65ff108d95..d10fdb7b50a0e303bcae0730038064fa1497833a 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 e2bae0b0e62d24f600bdbb885562b031ecb3f7f0..8f255cb45715e17a0db9c14bbbf919e719abb85d 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 d69fcb533944685b1ceed95600bd591e2964b724..4b0ce4e6ea95a145b32e27021b0fd2d3452aa38d 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 1e4060b5ea1894cc86d32652231b13108af88bfd..e3c4f2e73f5c6354ac46f625454573c3a7841cb1 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 a914f8ad66a9f5933b7aa81757a056ca933f5573..c30b85b05f929c09158a15aff144226fc7ebad43 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 ae589327d1f9cafc16e003de9f9d4a35a80ae261..18d7fbbbc49fcd33eff7e4420dbd6b357badf017 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 8e3afe694c15eb116ba7c15555f1fa064a140c5c..dc8869fffa872ddab6fbd2b0acda0100c0a107b5 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 aa76dbdc4501ac5ca7613deefe713b487ccb93d5..fd25d833a5663af3292bf7752b304ae7531253a6 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 28c205ee509256dbc3b010038bd740d490f63768..3db02c721890af92dc6d2e6db41205f3d28c0dc1 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 2ee7cc83d808ec0e86c4e6474c486d8a59ab8380..31f98cba357c1ae0c9bba133238f47b42d9818f9 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 2df65448a029407d1a46f92db37df06b62ab9823..ecbedb0619bc957337ddc2ba387c27652a6d1911 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 41cf70c6afef0e773f71f5766209fca11872fd54..a871d1f962bab02d92219218356f59d30f350f82 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -23,7 +23,6 @@ #include "compiler/lowering/ets/boxedTypeLowering.h" #include "compiler/lowering/ets/boxingForLocals.h" #include "compiler/lowering/ets/capturedVariables.h" -#include "compiler/lowering/ets/constStringToCharLowering.h" #include "compiler/lowering/ets/constantExpressionLowering.h" #include "compiler/lowering/ets/convertPrimitiveCastMethodCall.h" #include "compiler/lowering/ets/declareOverloadLowering.h" @@ -75,68 +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 ConstStringToCharLowering g_constStringToCharLowering; -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() @@ -144,67 +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_constStringToCharLowering, - &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 { @@ -242,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); @@ -249,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 @@ -260,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 @@ -273,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; } @@ -284,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); + } } } @@ -301,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; } @@ -333,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; @@ -372,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_) { @@ -393,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++; } } @@ -406,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 e1ff9c3885ed7db22ca7262b95cfa0c1f55f2ac2..63c3e493f413c60c1113510a05d91575cc0c8feb 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 0000000000000000000000000000000000000000..a3ba46c8f54a6df64e012af88a4801d8ce980a1a --- /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 14f72aa7f02c87f3130dabdcc180b4d5e946d523..f4dcbebf93a94529540a6141deb7c52d8ad6d8e6 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 cc13b62ce39ef58262e6e87fd129f0f71870af43..541af34dee0a131f484d6806cbd4eaf7e953ef4b 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 186363fbb0abe9113e21027fccee5dca44310441..1b7f962edba2f4aeaa7d5da2cb288f20e4e89826 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 56aa8c831837de719f0573f586776fb400e6129a..8d4ee9e016b7997ab9d78709d9ac59ea180a78ca 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 49bec80f6e38a0c9e12e80624376907d72e2e027..b0c239c3819bc522fa4f8e4baa61f553cc977afe 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 09fe048e25753659dcfa420616aba94052201b83..a80338b1f7fa95ce71c241dea26f49d3913b6e95 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; } @@ -262,6 +293,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/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 51135c383c480ac427a0cd16e2667dba3d68a8cd..496aa8e961e6aee144f65ee1a300f5aac0366e8d 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -104,6 +104,9 @@ defines: - name: ets/annotation/Module ref: ETS_ANNOTATION_MODULE comment: Ets record + - name: ets/annotation/FunctionalReference + ref: ETS_ANNOTATION_FUNCTIONAL_REFERENCE + comment: Ets record - name: ets/coroutine/Async ref: ETS_COROUTINE_ASYNC - name: ets/annotation/DynamicCall diff --git a/ets2panda/declgen_ets2ts/main.cpp b/ets2panda/declgen_ets2ts/main.cpp index d55467fc90f819e774fc9bfab3801c1e1059ee2a..385e9f37c8d4ff9dc87a97495ca2986f25d0e736 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 99fad43361e17410ff39ad8d33eea57178f1010c..d74d252dc912c30c6687c619b19e499b335456b2 100644 --- a/ets2panda/driver/build_system/src/build/base_mode.ts +++ b/ets2panda/driver/build_system/src/build/base_mode.ts @@ -17,14 +17,20 @@ 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, - BUILD_MODE, DEFAULT_WOKER_NUMS, DECL_ETS_SUFFIX, DEPENDENCY_JSON_FILE, @@ -56,16 +62,23 @@ import { ArkTS, ArkTSGlobal, BuildConfig, + BUILD_MODE, + OHOS_MODULE_TYPE, 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; @@ -85,6 +98,7 @@ export abstract class BaseMode { isDebug: boolean; enableDeclgenEts2Ts: boolean; declgenV1OutPath: string | undefined; + declgenV2OutPath: string | undefined; declgenBridgeCodePath: string | undefined; hasMainModule: boolean; abcFiles: Set; @@ -93,6 +107,8 @@ export abstract class BaseMode { isCacheFileExists: boolean; dependencyFileMap: DependencyFileConfig | null; isBuildConfigModified: boolean | undefined; + hasCleanWorker: boolean; + byteCodeHar: boolean; constructor(buildConfig: BuildConfig) { this.buildConfig = buildConfig; @@ -105,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; @@ -117,16 +134,19 @@ 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(); 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 { @@ -159,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); @@ -225,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; @@ -373,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); }); @@ -396,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 }; } @@ -465,8 +503,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,32 +588,36 @@ export abstract class BaseMode { } protected collectCompileFiles(): void { - if (!this.isBuildConfigModified && this.isCacheFileExists && !this.enableDeclgenEts2Ts) { + if (!this.enableDeclgenEts2Ts) { this.collectDependentCompileFiles(); 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)); 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( @@ -577,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 { @@ -615,6 +690,7 @@ export abstract class BaseMode { this.mergeAbcFiles(); } + // -- runParallell code begins -- private terminateAllWorkers(): void { Object.values(cluster.workers || {}).forEach(worker => { worker?.kill(); @@ -622,7 +698,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 +884,6 @@ export abstract class BaseMode { }); return JSON.parse(jsonStr); } - setupCluster(cluster: Cluster, options: SetupClusterOptions): void { const { clearExitListeners, @@ -825,4 +900,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 59bdb759ab010c12b508de796c7b775b504e83d1..accdafbccaec2d83f2a93bf2d7d06ab9178cc3fd 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 0000000000000000000000000000000000000000..eef6db8d34a8b822f64c832bce713c005d754712 --- /dev/null +++ b/ets2panda/driver/build_system/src/build/compile_thread_worker.ts @@ -0,0 +1,187 @@ +/* + * 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 { + 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 { + 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); + + 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); + } 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/build/compile_worker.ts b/ets2panda/driver/build_system/src/build/compile_worker.ts index 38a1fcdb596325139a0fe145d26194643394950b..fdf1c651a57360f5d8a0069bbb0f3e140ac3e2ea 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 c0a0542d9d4a9e1531c0c30ca01b87e60e4bc7dd..c20fe57e7a73f0d3a35845687dc5e79a1e245e75 100644 --- a/ets2panda/driver/build_system/src/entry.ts +++ b/ets2panda/driver/build_system/src/entry.ts @@ -18,17 +18,17 @@ 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 { 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(); @@ -39,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(); } @@ -54,8 +54,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/error_code.ts b/ets2panda/driver/build_system/src/error_code.ts index 5a0dc72b4cc0be8f2fb4c2cf1e613bb91a1bd788..ed2562f43af53a41f528df4275d5c3dafc296cfb 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 596b32486dfd8b5493feb9a1767fb373868b3723..2f77380538a7e35a708d4cdfb394ddc001f4097d 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/plugins/FileManager.ts b/ets2panda/driver/build_system/src/plugins/FileManager.ts index 8548c8d092b4dd4d211c83455005208bc0510206..9a2c8b4e189e8081bc08acd878395c80bd4916a8 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 eb556eb023ae5bd29141986b1df3d66c1e5a4f06..67203f601dcc973398d5469c3ae58a5e26159fc7 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/pre_define.ts b/ets2panda/driver/build_system/src/pre_define.ts index a51032f4a7557e87baaaf6e97a0e8b94a9acd488..0b42278bebc8a67326b381d9b4d7f303f241ec6c 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 0d0d0d38ac13cc5f06542d4a6b13be320a1f2f62..0afb84da0714b559931641d5547c43b6dd7c234e 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; @@ -37,6 +54,10 @@ export interface ArkTSGlobal { }; es2panda: { _DestroyContext: Function; + _MemInitialize: Function; + _MemFinalize: Function; + _CreateGlobalContext: Function; + _DestroyGlobalContext: Function; } } @@ -52,8 +73,11 @@ export interface ArkTS { }; proceedToState: Function; generateTsDeclarationsFromContext: Function; + generateStaticDeclarationsFromContext: Function; destroyConfig: Function; Es2pandaContextState: typeof Es2pandaContextState; + MemInitialize: Function; + CreateGlobalContext: Function; } export enum Es2pandaContextState { @@ -69,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 { @@ -109,6 +134,7 @@ export interface FrameworkConfig { export interface DeclgenConfig { enableDeclgenEts2Ts: boolean; declgenV1OutPath?: string; + declgenV2OutPath?: string; declgenBridgeCodePath?: string; } @@ -126,43 +152,50 @@ 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 { plugins: PluginsConfig; compileFiles: string[]; + entryFiles?: string[]; dependentModuleList: DependentModuleConfig[]; } // 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 = { @@ -178,4 +211,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 76a66d7bbfd24d99a07b0ee71e0e6225ec62d355..03e10fb47a6de6ecbe014b8d1d67cb7008d8f24a 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 bfbc0dd50e88078824c60ed21c1c68e9b22a98cc..1fd443aa1fdb951bdf3c705862fc6c663fceeac7 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 0cd8a4308447c0ddce876a8f243663267d63afcc..a880df3c2adb64491a1c5891f5494217bd4dbbe2 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 1ddb8ad777487dbc1484dd01ed0392aec492bc7f..1ea40a4e2bfd1d9a9c0b72adb16ec9fbed9e2544 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 aadd815b18e4239bda794de4a8aac0f20a6d84cd..b2b63e0635fceb402425dc6bd9e747c1ccb65e5b 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 21c202e4058aff8955edadf33b6cc4035c02a897..39cdbf9e1b203bdfae6550abb2d6e2f814194403 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 e78fd348d346ec89dd67765cb6de41ce4c2a8cba..e1101e2b0037ff38a6ab9cb79ec45a030dfd40cd 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 fc8666dc9ebbb6231b6b31fa2bf9673f0ddfe407..16b6396f9f7e2318fa7da5a9a2d6423080cd9c6c 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 0053c073dc9ce0a2cc91e6e6b80bbe7304135ad2..90eea9d9542ac2c5668e163977c4f9fc06fe5b3d 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 7bf5f66ecbc38e3e9c0da0d9778078a0bad6ac03..48880e158992324656f677fc6c14b7cf8f6a4a10 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 9d920eeac2eff215edc709c65a0cf0002332fb55..3b8a45b1bc71070ef18c30b44b0baf98c49b4385 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 c8f07a0c751f162e969992f6f46e04afb5047ea1..5489ceb5f6b6c1cf272bfecbf6c7fe4f8113cbab 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 d471894a2acf3d57a97766c03423830264fc349e..617e3e42f82e3df96f1409c529c08d9d70154605 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -27,7 +27,6 @@ using ENUMBITOPS_OPERATORS; enum class AstNodeFlags { NO_OPTS = 0, CHECKCAST = 1U << 0U, - CONVERT_TO_STRING = 1U << 1U, ALLOW_REQUIRED_INSTANTIATION = 1U << 2U, HAS_EXPORT_ALIAS = 1U << 3U, GENERATE_VALUE_OF = 1U << 4U, @@ -106,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 c27d68e8d203ad21cf24960d112e264f3eddd580..5d46aea8b2177508375a9104dc69e46c7fbce405 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 8aebde4a7a90a7dfc83bce7065edb2d3394256dd..e424046403117b23da2fc4d6aa85259482ce646d 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 3bf590dd44ee17129ac765356b7d6939d21193e6..5fe57979b3febc8c29b9a88686744169729a3a5f 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 @@ -361,11 +495,12 @@ void ClassDefinition::CopyTo(AstNode *other) const otherImpl->anonClass_ = anonClass_; otherImpl->localIndex_ = localIndex_; otherImpl->localPrefix_ = localPrefix_; + otherImpl->functionalReferenceReferencedMethod_ = functionalReferenceReferencedMethod_; otherImpl->exportedClasses_ = exportedClasses_; 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 1539b6c3467015bd658922334902053eeb5a02c6..7a8c0ed2ef238c968318e9c9e0bb345364770746 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" @@ -57,6 +58,7 @@ enum class ClassDefinitionModifiers : uint32_t { STRING_ENUM_TRANSFORMED = 1U << 14U, INT_ENUM_TRANSFORMED = 1U << 15U, FROM_STRUCT = 1U << 16U, + FUNCTIONAL_REFERENCE = 1U << 17U, DECLARATION_ID_REQUIRED = DECLARATION | ID_REQUIRED, ETS_MODULE = NAMESPACE_TRANSFORMED | GLOBAL }; @@ -100,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, @@ -116,6 +119,7 @@ public: localPrefix_("$" + std::to_string(localIndex_)), exportedClasses_(body_.get_allocator()) { + InitHistory(); } explicit ClassDefinition(ArenaAllocator *allocator, Identifier *ident, ClassDefinitionModifiers modifiers, @@ -132,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 @@ -251,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 @@ -266,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) @@ -315,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_; @@ -380,57 +375,61 @@ public: [[nodiscard]] int LocalIndex() const noexcept { - return localIndex_; + return GetHistoryNodeAs()->localIndex_; + } + + [[nodiscard]] util::StringView FunctionalReferenceReferencedMethod() const noexcept + { + return functionalReferenceReferencedMethod_; + } + + void SetFunctionalReferenceReferencedMethod(util::StringView functionalReferenceReferencedMethod) + { + functionalReferenceReferencedMethod_ = functionalReferenceReferencedMethod; } [[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; @@ -439,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; @@ -472,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; @@ -517,9 +565,10 @@ private: ArenaSet localVariableIsNeeded_; TSEnumDeclaration *origEnumDecl_ {}; ClassDeclaration *anonClass_ {nullptr}; - static int classCounter_; + static std::atomic classCounter_; int localIndex_ {}; std::string localPrefix_ {}; + util::StringView functionalReferenceReferencedMethod_ {}; ArenaVector exportedClasses_; }; } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/base/classElement.cpp b/ets2panda/ir/base/classElement.cpp index 9c54368dd8bc51eb3e3c3ddb35b153d5f850374b..24c42eeb71e3e6c5ec239cbf148dc7b242d12b50 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 fc372f8dc270498320a63006e8660b9f01f9872e..45101a888b954d2572312277fcc91a058e44d166 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 0ec31492bcfe5eb10f847bee9fa1170af1e89dcf..2bacec57d1c0375a4dd0d1a93d3bb87634224ae3 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 9725118c5768c391a30a843346f9b0d86d1423ba..ebdd968dc436bf1af9e9014d3820e7987e8b2575 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 d58703d0b7caba8e2d83492a1ac157024241f261..f8b01d54a74793c7fd1baeb48743ea551c13a731 100644 --- a/ets2panda/ir/base/classStaticBlock.cpp +++ b/ets2panda/ir/base/classStaticBlock.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 @@ -30,25 +30,38 @@ 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 { - // NOTE(nsizov): we don't want to show this node + ES2PANDA_ASSERT(value_); + ES2PANDA_ASSERT(value_->IsFunctionExpression()); + ES2PANDA_ASSERT(value_->AsFunctionExpression()->Function()->IsScriptFunction()); + dumper->Add("static {"); + dumper->IncrIndent(); + dumper->Endl(); + const auto *scriptFunc = value_->AsFunctionExpression()->Function()->AsScriptFunction(); + ES2PANDA_ASSERT(scriptFunc->HasBody()); + scriptFunc->Body()->Dump(dumper); + dumper->DecrIndent(); + dumper->Endl(); + dumper->Add("}"); } void ClassStaticBlock::Compile(compiler::PandaGen *pg) const @@ -73,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 a1a1030b757e57649e0ecddff8eae8fcb4eae2ae..63ffc33f16fcea10152958679bcf6b25a4c7ec75 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 c4a19ecc866d17cbed75c77a5ea85872e3433db3..6f705a2f977eca5675b1fc2d24eecce979da647c 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 @@ -236,6 +261,9 @@ void MethodDefinition::DumpPrefix(ir::SrcDumper *dumper) const } if (compiler::HasGlobalClassParent(this) && !dumper->IsDeclgen()) { + if (IsExported()) { + dumper->Add("export "); + } dumper->Add("function "); return; } @@ -303,22 +331,27 @@ 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()) { - anno->Dump(dumper); + 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); + } } 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); } } @@ -344,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); @@ -355,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)); } @@ -372,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(); @@ -413,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() @@ -442,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 22b53211293c7bbc0986e00ee7a719a93c133621..af54efb58022800c1306774fb87f4d9ec2426714 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 0eb77cd6c8aa3286268294bb1268c2cb4fe7b350..73ef90390f75de42a084ec47c8bf9bbb6816845e 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 56516356429db9f0e736a95a1decdb7867468d9c..e5a246ebb6e1531891af3b6a77ba986459eb834e 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 b3918b5fbe98df543f1ce5e32d5d06294e1b0412..65b977c9626793bee03de09c139b9fd7371c3525 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 1f69ae5286064ab92351f29537edad94f3e8af5c..a8417930319850984ece9b9b5ab10864e48fab4d 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 803e8e32a4de5404e5b17e7ea0c14ed28c4abcb6..f9eefb502c5e3b282ce2c8bfe3d530fc0d64354e 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 da4e93b20cfb8845d2cff05be1bf53c282ece6d1..f2d459dce3ba0ffd35ece5cd05b9e95da24467e8 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 b6ae35203b3b50e8bf6c3ce3b9b5eb1a0b3080ff..142e16671c030f44110dc26e1fdf04be458432fb 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 4abdaff764848f0e02e20160318a4f8edc3fefea..7f7e56683b221a2bc6ac9471678f65c41a3fe307 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 3fea029e815d4d9281ec27a992d00be6be3fdede..4891a53166698946c5d4127c5b5516ef41841d92 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 0c967d8d245aad5bd2186f5f7de6f507ec0be7b8..8f2bb0ecd83ef700ef8d553809331e461decad78 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 79284dd1f72e3bf37538f07f13547c9a08a41bbd..3f40e3475075ab2a1bc7613410322b7179f01387 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 e3e9e7983678fd1e341b4ef1e288950800243472..0957d162a44a9493faa2b1eeae1410807b7609ee 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 382a8a6f11307c438870e9c002f40da30a43ce66..672d060e2a08ec2ab822eb7c746b074166dabb50 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 a38f760c793ff653d24e7e5edfa41a74573c16ca..976e54149f99a83fb6ea6b93684b221ab2cba7d5 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 c18f74350262d4994bce708bdd606cfcf57c1501..c4d18a628dcad9bbcf8a83c5d1d9c95b07fdd8fb 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 49e9d73cc3565bfb1380a86656e276145b3125bb..e26ae82974b0d964dccf4b8f9fd30ae9e4f50c38 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 c5df1d644b18f37e84ca394510cba76380762455..4475c8b08ca38e60ee149065501f58154901a988 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 48d7e6545959250a4ec9fb81a77c536c29ae3c6c..cb43dc8708e8a8c70363a276e3fe9eca00727778 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 d6227f2673e079f710a6e1bb7661a3a91c444be0..178160de40224715787949b5f9dbb6308edd51ea 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 538797da5ddeeb66feb5b729162190497580754d..1ee72040a3a7e34c29eff1cb38679020a8ecdefe 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 b79654c62e2da4901d7417d113a0791d3bb46375..79b9e906fb64642760774848a729be625233ebe1 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 21db7e18148714de68f28570854a57ebbaef4fcc..7986198c729d4d33902ce54239119b9df91e4c72 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 f100af2e5655ac1d19bdb20d12b82830aec8f5c1..a69e3679fe4f8969e809befd9706345f0e86bd23 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 e0686ef0761195da0a48797619b9dd6ca3cdca43..befb99668289ac1918700cba32b279fd6426654f 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 4b1e6aba373dae5440ecf75c7f3606d47b884a2e..54a2156b997be8542d539df7cefeb31dbcc9ceed 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 39860832e491e56ec059c3e1f62a180d340bbe25..de035bcd614e25de7767a2deb57d10ecdda0008f 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 4bc14986b384363d221ee989ac44f3136b475093..21a06d8ef19059da34d02921994798ebd554808e 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 24000a8aa5cfe80c17b98e6c9ec38241fea006d1..ab5ffc9e50fbb072feb58b2639252def5c8c2610 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 52b74a8329b414f344db2dc132fd21f69b1eca28..00c10eaec81bcce401519dc9cef807033c92f126 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 2cc1924a89d1f3e1f2942f7d56d4aaf973c3a724..2af3767f2b671de1b0f2120afad0a66256e950b0 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 c4941954ec3ff972584c78b318450cca6746c6d6..772cf69fc00187f97ae507b676a4bf3f41238c4e 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 3d7f231a15f363bbdc2c3f1091beae5e4cbd7c47..1dc57dca97b45e1b324e62b97ec9c816223d7600 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 ad06be7bfb38e1600628ee3e6cffdc69142811fb..b5c0e1b6ed17a18578f1bdcb11b00868a436f40b 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 da71df56cc59688f33d64751c131a4c1bbbc72f2..6f8814018bebeb38c880903f844442d571181f34 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 7f7e05007f1ef58cdd781ba656d23cdf10619137..45e893cb515170ad7befecf6ad37816a4b32c72f 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 d48246d887744c5e2ce67873d1355c6fe2751dfa..161970f5f50147e5d86bb4768247e8a9f2df32ff 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 c3f28438e23e5974a13d25d6c32d456e7071926c..2da6374989c9541c10731ccc600647b9fbf5dcf1 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 b76b69d868e74c6418b81d26a740307372a81de5..4a74b389756ec682bc543df34f615d8380870601 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 aab66f2db2756339dd3b5047e4d98a6ed5c8ce1c..f353444a467119200613d572cbd67fbcba968163 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 f55f5914444081776373deae34dc9c13edd37b7c..c3d3b8f2f280616e9dad928cbe0556078a30b3fa 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 63cc1287f0571f3ae1827238d251afd1214c8936..abbe7d12b09e925f5b0f41b78027bab834556bc6 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 81745d7f37bb22b6840257ad042f9524b6eb6b1b..e47670c06112b0b5b3f3b784ce961bebdcb6d0ca 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 d459bc5e20c5bdcb57fb1b78d4a94c5f7f1d7a37..398e74f231c4a3fad40511c8d6f3c13d1b066703 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 72a5afe51f3c87fd15474be29ba37ffaa7e29358..5ea6d0e8d01f3ca3d9c240541138d807d62e1308 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 21fb0d5f85eea44a9eec9cc135d0589c74b4b153..be0f1341c4236c1f037cb58711cdfb5950c63bcd 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 55a3443f02a6ce3fe368bab929b555660767d4b3..25a69766e6442b306627baa746d5c9000a74a99d 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 56934876cfc09ba4846b2df06ab28c70542f155b..adbe853c541c2bd7ec89bbdbb15de828f6b06f90 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 7b3f8a58040eb42504a3b93498c06e18c63fbeae..cb3703b27dfa0ba9f5f2b21f31870225c77e6ee4 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 99f5e085a28376e4526ed45b7f19aa3310a3ea5e..f8cde5748f2ff69663acb4834df7daa048b98993 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 8a1e1abd2c4686b611869ca614b316e76b91a2bd..8ab2361fb9039274516edac8ef14f3d914e4b5f2 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 7b42542a7d28362c1530c0b2cacba43e622808d9..0e6a288d941bca5c137af32f77163e961a49ac31 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 4d5b6f018a6dbd9e2b123638e92b7025beba62a5..bae3ac4ae1e718ae4b90c99062bb9beb761f0568 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 6a70708b5c7e42df54454fdf5222eb42dedf9561..6a166ea3f06d02257c0994ce89bcfb8fba60fed6 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 681161a310c8b4e1cb0938d6a0632ee5f96ca22f..327034616d33391c9db631e2518339ae51360301 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 42603eda1e26e930bce2ce4b083fc0a19d4f947a..c3d9c28f0209d0d046394dcbf88c44e6614bb9fb 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 ffb58b61536cfdfc6e0843bf0c50a0fba1ec0765..87bb7c13fd632094d09a98eb9d4f1f3a6b2fc229 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 ed1698e0a2edce79a3efc37ae83f12304caac43d..89e4751aeb965dd49d3133f81e7346ea7512f16d 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 7854c7d3c87ae58d18c666de85a182d52ce5baef..a0f981b892b10daf920ba9c037d28d4acb2c6f8e 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 f2d897be6e70072fe062d1be3229ffc7fee10d3c..e1e110231a601b905106b838db5c8fa0c83df80d 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 5db886b2e48b4338edb27310374479ccf047ddcb..dd9d1746dcbcf30eef9bd39581a407ecd6e3bd70 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 bea508e3884f802432be8774911b354036a61efb..4455a8b7764190e5cef66af761cd7fd5d742f193 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 fb338b4c963b1f945b2cea71299ec20ff1f5b32a..64e6a30e70d85b726d640aee252c352144b97b3b 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 75cf7834dcade735a58447e785512888d409d26b..6dc630a18a4c57e98d0250cdf88bddca4abed7b9 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 25a998cc1791d908f7facc7d9f5d9c691f4a4c7f..a679912bf4dbec77ce97320c56050f0a5e95b96b 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 fef66f0e8c85bc1aea31752ed6cef2f431f55cf3..61da853b75b4d81a1f1d2f1f6cb77ddda83e1e78 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 d07fb3d98260186bfe3a8ed000a077d91a6fdd43..742f9e6cd4f251a3a5beac4026f986dc92e86cdf 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 9b1386dcad545c5d250185cda639b165eb18cecc..a48751933c6adcd2d9da89f246aed6d0f6a185a3 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 d7050a9ff3ce77c11cc906d752ddd93d90526fd7..6e089e142a4f464c021c8b07603eadc74e7d2cc9 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 9c9125def9d5a883b776b0828c39aa386634b019..afcee6e7b57be49fbceed2b822755658ede6cfb5 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 fd807caf030fdb3257289bca399cff81bfcf81fe..3b4ea39d6e3ac55b1ae44e821b1418c6ce9794b1 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 4ee640455b23b6b0bb5f5f9bc0b2e6d7de5bb346..4608efb394706a13363c6b93748cf1b8f4073207 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 825b446bc4b07710cf009bc4f9f2064c28fb0720..be62a340044c1d0222feeb0fb32d75ad919a71d6 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 da5e36ad8ce7686708745112bd1cfb2cdf70101f..9af97be93c8b9f01a491a356b0e06e153cc7b6ec 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 cb69e8542ca30463bedbd2d1b2c1f4dab66f8bd2..d98cbd162299827eb3f569f9e88ad891da90f6aa 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 26bcca0adb196d82c02f067e8d3a4258911e8bfd..75532d60154cff4050fefed4cab1dfcbdf7e5054 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 4d44e9002136b9ce83f5bfd5dd2a9a3140b80aee..fb9b8c160da4f0438b402e9aa95afef5c3a9e4b8 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 418d5aa34da584c298c5e23a46dd7466dff7af61..d13f7662cdbe610180fa9735b0f2f7fc4b03e09e 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 7e66c028434fe001fbb0cafa93a7ca9d59bc2b0e..2fa2ad26adb615ba84351e83fc4004db8bf77aed 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 88d4b0885510fce70ecd42d08eabccb1cf55d1bd..e4a489d11107e54655479c93ad70d0e5ca2c385a 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 fff183fc3c427f2e172728b8c058dd01cd71036e..97c92bf6da7595460cd48fe7f023b1141e0447c5 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 a236ed060c7ce2f83bb27d40e2bea133e6df6d18..1ae682e17f96f248d6503893e11c1186593749c5 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 9fef5c44ff68afe9316bdd7b1242cdb37350463d..a72497e5ce8c5b8e86bc0a3b585a6f2d6d62c397 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 a1b253d850f2e1d375e3d5f7e0cd3b6c4d08d4b0..0ab2158429af2721d494a5d637138a376c662d11 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 70fe7b63fc1e824121bc6d291b74e10ea3954e9f..5fa24495e892a371b09abc180c525b490e16b252 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 459789b7185b1300ff68c8d9c3d2fa6feab061a8..57b8f7d2ae2cd662db0504c73723e943cb43585f 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 4070aaf0b20e9b8a6141702387b01c7c84fe3579..5053cebca07ecfc83a830d9cda91a4cb815e34ad 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 a25ccceccb5ce236864d0f7d524778426a254f31..aca8a8aa8995d717e562b865296923db544b551e 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 f1daafebdc22bbb772af9ba4168b78c37c2886d9..dd0bc5e848c6dff5ce17822b2eddad1c5d6ee49c 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 d5a4341f2c29273020f642963379208472917898..ff09cc56d86b65be9f42072b644186486fbf5a7c 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 0c3f32f3ee4f6799cf522b40cb4248b905a1960f..cec0ce52c33c9240a01591c988efba1244377f63 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 a150a8cfb08cebc09bff2457f506559a42776780..b6557e4d6320509ddfce93860c717d38ec5a289e 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/linter/package.json b/ets2panda/linter/package.json index 73dd2a41801b56968d0cb0ccc2a58ec9b46110bb..9c02abca4546da39b55045be4245ee1f063e3d13 100644 --- a/ets2panda/linter/package.json +++ b/ets2panda/linter/package.json @@ -24,6 +24,7 @@ "test_main": "npm run testrunner -- -d test/main", "test_ohmurl": "npm run testrunner -- -d test/ohmurl", "test_interop": "npm run testrunner -- -d test/interop", + "test_sdk": "npm run testrunner -- -d test/sdkwhite", "test_concurrent": "npm run testrunner -- -d test/concurrent", "test_rules": "npm run testrunner -- -d test/rules", "test_regression": "npm run testrunner -- -d test/regression", diff --git a/ets2panda/linter/src/cli/LinterCLI.ts b/ets2panda/linter/src/cli/LinterCLI.ts index a05def96551ad4a5ce6974b00746c288e75f1de5..45bd9fddcd788362a353d59c33e646bac8156c4e 100644 --- a/ets2panda/linter/src/cli/LinterCLI.ts +++ b/ets2panda/linter/src/cli/LinterCLI.ts @@ -89,7 +89,12 @@ async function runIdeInteractiveMode(cmdOptions: CommandLineOptions): Promise, cmdOptions: CommandLineOptions): void { +function mergeLintProblems( + filePath: string, + problems: ProblemInfo[], + mergedProblems: Map, + cmdOptions: CommandLineOptions +): void { if (!mergedProblems.has(filePath)) { mergedProblems.set(filePath, []); } diff --git a/ets2panda/linter/src/lib/CookBookMsg.ts b/ets2panda/linter/src/lib/CookBookMsg.ts index d44eca5932988372de383b4894e4d5bf00129bc7..dc43661a29ee7556455d05e8cc3a6f7787cacd27 100644 --- a/ets2panda/linter/src/lib/CookBookMsg.ts +++ b/ets2panda/linter/src/lib/CookBookMsg.ts @@ -270,17 +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[271] = 'No support for static dynamic import (arkts-interop-d2s-dynamic-import)'; -cookBookTag[272] = 'No support for static dynamic import (arkts-interop-ts2s-dynamic-import-ts)'; -cookBookTag[273] = 'No support for static dynamic import (arkts-interop-js2s-dynamic-import-js)'; +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] = @@ -290,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] = @@ -360,11 +358,11 @@ cookBookTag[357] = 'Worker are not supported(arkts-no-need-stdlib-worker)'; cookBookTag[358] = 'Using "Object.getOwnPropertyNames" is not allowed in this API (arkts-builtin-object-getOwnPropertyNames))'; cookBookTag[359] = '"@LocalBuilder" Decorator is not supported (arkui-no-localbuilder-decorator)'; -cookBookTag[370] = 'Sparse array are not supported (arkts-no-sparse-array)'; -cookBookTag[371] = 'Enum prop as type are not supported (arkts-no-enum-prop-as-type)'; +cookBookTag[370] = 'Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)'; +cookBookTag[371] = 'Enum elements cannot be types in ArkTS1.2 (arkts-no-enum-prop-as-type)'; cookBookTag[372] = 'Smart type differences (arkts-no-ts-like-smart-type)'; -cookBookTag[373] = 'Array types follow the principle of invariance (arkts-array-type-immutable)'; -cookBookTag[374] = 'ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)'; +cookBookTag[373] = 'Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)'; +cookBookTag[374] = 'Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)'; cookBookTag[375] = 'TS catch type are not supported (arkts-no-ts-like-catch-type)'; cookBookTag[376] = 'Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)'; cookBookTag[377] = diff --git a/ets2panda/linter/src/lib/FaultAttrs.ts b/ets2panda/linter/src/lib/FaultAttrs.ts index e1c16b5497cf95df5416ae07fdb665dd3e27c58d..07f558781204611ba359931c5a7eed7698a7e24f 100644 --- a/ets2panda/linter/src/lib/FaultAttrs.ts +++ b/ets2panda/linter/src/lib/FaultAttrs.ts @@ -186,16 +186,12 @@ 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); +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); -faultsAttrs[FaultID.InteropDynamicImport] = new FaultAttributes(271); -faultsAttrs[FaultID.InteropDynamicImportTs] = new FaultAttributes(272); -faultsAttrs[FaultID.InteropDynamicImportJs] = new FaultAttributes(273); faultsAttrs[FaultID.MissingSuperCall] = new FaultAttributes(274); faultsAttrs[FaultID.CustomLayoutNeedAddDecorator] = new FaultAttributes(275); faultsAttrs[FaultID.PropDecoratorNotSupported] = new FaultAttributes(281); @@ -203,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 f3a311e5f35226e6723a019576a15561736aa8a2..49646a196571a5d6652e4004e62f4ed2c9ae207e 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'; @@ -205,9 +204,6 @@ faultDesc[FaultID.SdkTypeQuery] = 'No typeof as a type in API'; faultDesc[FaultID.IsConcurrentDeprecated] = 'isConcurrent is not supported'; faultDesc[FaultID.InteropStaticObjectLiterals] = 'Interop call object literals'; faultDesc[FaultID.LimitedStdLibNoImportConcurrency] = 'Import Concurrency Deprecated'; -faultDesc[FaultID.InteropDynamicImport] = 'Interop import await is not allowed'; -faultDesc[FaultID.InteropDynamicImportTs] = 'Interop import await is not allowed'; -faultDesc[FaultID.InteropDynamicImportJs] = 'Interop import await is not allowed'; faultDesc[FaultID.MissingSuperCall] = 'Missing super call with args'; faultDesc[FaultID.InterOpImportJs] = 'No JS import'; faultDesc[FaultID.InteropObjectLiteralAmbiguity] = 'Interop Object Literal ambiguity'; @@ -255,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/HomeCheck.ts b/ets2panda/linter/src/lib/HomeCheck.ts index e7bbae43eb15d0fd6ce719c25af20431c534c771..a8845c1999770493fbff6ce4c6e9d8a7147b7a39 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,9 +61,9 @@ 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', + arkAnalyzerLogLevel: cmdOptions.verbose ? 'DEBUG' : 'ERROR' }; return { ruleConfigInfo, projectConfigInfo }; } diff --git a/ets2panda/linter/src/lib/LinterOptions.ts b/ets2panda/linter/src/lib/LinterOptions.ts index f6124ac4ab079343ddac9223baed63f1b58d53ca..72613a4cd1648f8febcc6e49c1263e7d21883b29 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 457dd86a6c63794f02cd1b59a68bf69c7b9d46c3..83d5c4ba59705ca813d48ff2fd8c02e51e60e87d 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,20 +218,30 @@ 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, linterConfig.cmdOptions.linterOptions, undefined, linterConfig.cmdOptions.outputFilePath); - updatedSourceTexts.set(fileName, qe.fix(problemInfos)); + fileName, + srcFile.text, + linterConfig.cmdOptions.linterOptions, + undefined, + linterConfig.cmdOptions.outputFilePath + ); + updatedSourceTexts.set(fileName, qe.fix(problemInfos, needToAddUseStatic)); appliedFix = true; }); @@ -237,7 +261,7 @@ function getMigrationCreateProgramCallback(updatedSourceTexts: Map { this.checkInteropForPropertyAccess(propertyAccessNode); }); - this.propertyAccessExpressionForInterop(exprSym, propertyAccessNode); + this.propertyAccessExpressionForInterop(propertyAccessNode); if (this.isPrototypePropertyAccess(propertyAccessNode, exprSym, baseExprSym, baseExprType)) { this.incrementCounters(propertyAccessNode.name, FaultID.Prototype); } @@ -1413,24 +1412,40 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } - propertyAccessExpressionForInterop( - exprSym: ts.Symbol | undefined, - propertyAccessNode: ts.PropertyAccessExpression - ): void { - if (this.useStatic && this.options.arkts2) { - const declaration = exprSym?.declarations?.[0]; - if (declaration?.getSourceFile().fileName.endsWith(EXTNAME_JS)) { - if ( - ts.isBinaryExpression(propertyAccessNode.parent) && - propertyAccessNode.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken - ) { - const autofix = this.autofixer?.fixInteropBinaryExpression(propertyAccessNode.parent); - this.incrementCounters(propertyAccessNode.parent, FaultID.InteropObjectProperty, autofix); - } else { - const autofix = this.autofixer?.fixInteropPropertyAccessExpression(propertyAccessNode); - this.incrementCounters(propertyAccessNode, FaultID.InteropObjectProperty, autofix); - } + propertyAccessExpressionForInterop(propertyAccessNode: ts.PropertyAccessExpression): void { + if (!this.useStatic || !this.options.arkts2) { + return; + } + + const getFirstObjectNode = (propertyAccessNode: ts.PropertyAccessExpression): ts.Expression => { + let current: ts.Expression = propertyAccessNode.expression; + while (ts.isPropertyAccessExpression(current)) { + current = current.expression; + } + + return current; + }; + + const firstObjNode = getFirstObjectNode(propertyAccessNode); + if (!this.tsUtils.isJsImport(firstObjNode)) { + return; + } + + if ( + ts.isBinaryExpression(propertyAccessNode.parent) && + propertyAccessNode.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken + ) { + if (!ts.isExpressionStatement(propertyAccessNode.parent.parent)) { + return; } + const autofix = this.autofixer?.fixInteropBinaryExpression(propertyAccessNode.parent); + this.incrementCounters(propertyAccessNode.parent, FaultID.InteropObjectProperty, autofix); + } else if ( + ts.isExpressionStatement(propertyAccessNode.parent) || + ts.isVariableDeclaration(propertyAccessNode.parent) + ) { + const autofix = this.autofixer?.fixInteropPropertyAccessExpression(propertyAccessNode); + this.incrementCounters(propertyAccessNode, FaultID.InteropObjectProperty, autofix); } } @@ -1536,7 +1551,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } const baseExprType = this.tsTypeChecker.getTypeAtLocation(propertyAccessNode.expression); - if (!baseExprType.isUnion()) { + if (!baseExprType.isUnion() || this.tsTypeChecker.typeToString(baseExprType) === 'ArrayBufferLike') { return; } const allType = baseExprType.types; @@ -1627,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; @@ -2030,7 +2046,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const propertyAccess = ts.isParenthesizedExpression(expr) ? expr.expression : expr; if (ts.isPropertyAccessExpression(propertyAccess)) { - const exprSym = this.tsUtils.trueSymbolAtLocation(propertyAccess); + const exprSym = this.tsUtils.trueSymbolAtLocation(propertyAccess.expression); const declaration = exprSym?.declarations?.[0]; this.checkAndProcessDeclaration(declaration, tsUnaryArithm); } @@ -2151,7 +2167,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); } }; @@ -3723,6 +3740,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } this.handleInterfaceImport(node); + this.checkAsonSymbol(node); const tsIdentifier = node; this.handleTsInterop(tsIdentifier, () => { const parent = tsIdentifier.parent; @@ -3762,7 +3780,6 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (isArkTs2) { this.checkWorkerSymbol(tsIdentSym, node); this.checkCollectionsSymbol(tsIdentSym, node); - this.checkAsonSymbol(tsIdentSym, node); } } @@ -4431,7 +4448,6 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const tsCallExpr = node as ts.CallExpression; this.handleStateStyles(tsCallExpr); this.handleBuiltinCtorCallSignature(tsCallExpr); - this.handleInteropAwaitImport(tsCallExpr); if (this.options.arkts2 && tsCallExpr.typeArguments !== undefined) { this.handleSdkPropertyAccessByIndex(tsCallExpr); @@ -4547,19 +4563,28 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { sym: ts.Symbol | undefined, callSignature: ts.Signature | undefined ): void { - if (!callSignature) { + if (!this.options.arkts2 || !this.useStatic) { return; } - if (!TypeScriptLinter.isDeclaredInArkTs2(callSignature) && this.options.arkts2) { - if (sym?.declarations?.[0]?.getSourceFile().fileName.endsWith(EXTNAME_JS)) { - this.incrementCounters( - tsCallExpr, - ts.isPropertyAccessExpression(tsCallExpr.expression) ? - FaultID.InteropCallObjectMethods : - FaultID.CallJSFunction - ); - } + if (ts.isAwaitExpression(tsCallExpr.parent) || ts.isTypeOfExpression(tsCallExpr.parent)) { + return; + } + + if (!callSignature || this.isDeclaredInArkTs2(callSignature)) { + return; + } + + if (!sym?.declarations?.[0]?.getSourceFile().fileName.endsWith(EXTNAME_JS)) { + return; } + + const autofix = this.autofixer?.fixInteropInvokeExpression(tsCallExpr); + + this.incrementCounters( + tsCallExpr, + ts.isPropertyAccessExpression(tsCallExpr.expression) ? FaultID.InteropCallObjectMethods : FaultID.CallJSFunction, + autofix + ); } private handleInteropForCallExpression(tsCallExpr: ts.CallExpression): void { @@ -4572,7 +4597,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - if (!TypeScriptLinter.isDeclaredInArkTs2(callSignature)) { + if (!this.isDeclaredInArkTs2(callSignature)) { return; } @@ -4631,7 +4656,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } - private static isDeclaredInArkTs2(callSignature: ts.Signature): boolean | undefined { + private isDeclaredInArkTs2(callSignature: ts.Signature): boolean | undefined { const declarationSourceFile = callSignature?.declaration?.getSourceFile(); if (!declarationSourceFile) { return undefined; @@ -4639,8 +4664,8 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!declarationSourceFile.statements) { return undefined; } - // check for 'use static' at the start of the file this function declared at - if (declarationSourceFile.statements[0].getText() === USE_STATIC) { + + if (this.tsUtils.isArkts12File(declarationSourceFile)) { return true; } return false; @@ -5019,9 +5044,19 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const type = this.tsTypeChecker.getTypeAtLocation(calleeExpr); - if (type.isClassOrInterface()) { - this.incrementCounters(calleeExpr, FaultID.ConstructorIface); + 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 { @@ -5129,6 +5164,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); } @@ -5137,30 +5175,94 @@ 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) { + return; + } + const type = tsAsExpr.type; - const restrictedTypes = [ + const expression = tsAsExpr.expression; + const restrictedPrimitiveTypes = [ ts.SyntaxKind.NumberKeyword, ts.SyntaxKind.BooleanKeyword, ts.SyntaxKind.StringKeyword, - ts.SyntaxKind.BigIntKeyword + ts.SyntaxKind.BigIntKeyword, + ts.SyntaxKind.UndefinedKeyword ]; - if (this.useStatic && this.options.arkts2 && restrictedTypes.includes(type.kind)) { - const expr = ts.isPropertyAccessExpression(tsAsExpr.expression) ? - tsAsExpr.expression.expression : - tsAsExpr.expression; - - if (ts.isIdentifier(expr)) { - const sym = this.tsUtils.trueSymbolAtLocation(expr); - const decl = TsUtils.getDeclaration(sym); - if (decl?.getSourceFile().fileName.endsWith(EXTNAME_JS)) { - this.incrementCounters(tsAsExpr, FaultID.InterOpConvertImport); - } + this.handleAsExpressionImportNull(tsAsExpr); + const isRestrictedPrimitive = restrictedPrimitiveTypes.includes(type.kind); + const isRestrictedArrayType = + type.kind === ts.SyntaxKind.ArrayType || + ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName) && type.typeName.text === 'Array'; + + if (!isRestrictedPrimitive && !isRestrictedArrayType) { + return; + } + + let identifier: ts.Identifier | undefined; + if (ts.isIdentifier(expression)) { + identifier = expression; + } else if (ts.isPropertyAccessExpression(expression)) { + identifier = ts.isIdentifier(expression.expression) ? expression.expression : undefined; + } + + if (identifier) { + const sym = this.tsUtils.trueSymbolAtLocation(identifier); + const decl = TsUtils.getDeclaration(sym); + if (decl?.getSourceFile().fileName.endsWith(EXTNAME_JS)) { + const autofix = this.autofixer?.fixInteropAsExpression(tsAsExpr); + this.incrementCounters(tsAsExpr, FaultID.InterOpConvertImport, autofix); } } } + private handleAsExpressionImportNull(tsAsExpr: ts.AsExpression): void { + const type = tsAsExpr.type; + const isNullAssertion = + type.kind === ts.SyntaxKind.NullKeyword || + ts.isLiteralTypeNode(type) && type.literal.kind === ts.SyntaxKind.NullKeyword || + type.getText() === 'null'; + if (isNullAssertion) { + this.incrementCounters(tsAsExpr, FaultID.InterOpConvertImport); + } + } + private handleSdkConstructorIface(typeRef: ts.TypeReferenceNode): void { if (!this.options.arkts2 && typeRef?.typeName === undefined && !ts.isQualifiedName(typeRef.typeName)) { return; @@ -5184,7 +5286,9 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } - private handleSharedArrayBuffer(node: ts.TypeReferenceNode | ts.NewExpression): void { + private handleSharedArrayBuffer( + node: ts.TypeReferenceNode | ts.NewExpression | ts.ExpressionWithTypeArguments + ): void { if (!this.options.arkts2) { return; } @@ -5199,16 +5303,13 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { const srcFileName = decl.getSourceFile().fileName; return srcFileName.endsWith(ESLIB_SHAREDMEMORY_FILENAME); }); + if (!isSharedMemoryEsLib || this.hasLocalSharedArrayBufferClass()) { return; } - if (ts.isNewExpression(node)) { - const autofix = this.autofixer?.fixSharedArrayBufferConstructor(node); - this.incrementCounters(node.expression, FaultID.SharedArrayBufferDeprecated, autofix); - } else { - const autofix = this.autofixer?.fixSharedArrayBufferTypeReference(node); - this.incrementCounters(node, FaultID.SharedArrayBufferDeprecated, autofix); - } + + const autofix = this.autofixer?.replaceNode(typeNameIdentifier, 'ArrayBuffer'); + this.incrementCounters(typeNameIdentifier, FaultID.SharedArrayBufferDeprecated, autofix); } private hasLocalSharedArrayBufferClass(): boolean { @@ -5895,6 +5996,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); } } @@ -6080,12 +6189,17 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (isInternalFunction && filterDecl.length > 2 || !isInternalFunction && filterDecl.length > 1) { this.incrementCounters(decl, FaultID.TsOverload); } - } else if (ts.isConstructorDeclaration(decl)) { - const parent = decl.parent; - const constructors = parent.members.filter(ts.isConstructorDeclaration); - if (constructors.length > 1) { - this.incrementCounters(decl, FaultID.TsOverload); - } + } else if (ts.isConstructorDeclaration(decl) && decl.getText()) { + this.handleTSOverloadUnderConstructorDeclaration(decl); + } + } + + private handleTSOverloadUnderConstructorDeclaration(decl: ts.ConstructorDeclaration): void { + const parent = decl.parent; + const constructors = parent.members.filter(ts.isConstructorDeclaration); + const isStruct = decl.getText() && ts.isStructDeclaration(parent); + if ((isStruct ? --constructors.length : constructors.length) > 1) { + this.incrementCounters(decl, FaultID.TsOverload); } } @@ -6695,19 +6809,65 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } } - private checkAsonSymbol(symbol: ts.Symbol, node: ts.Node): void { - const cb = (): void => { - let autofix: Autofix[] | undefined; - const parent = node.parent; - autofix = this.autofixer?.replaceNode(parent ? parent : node, JSON_TEXT); + private checkAsonSymbol(node: ts.Identifier): void { + if (!this.options.arkts2) { + return; + } - if (ts.isImportSpecifier(parent) && ts.isIdentifier(node)) { - autofix = this.autofixer?.removeImport(node, parent); - } + if (node.text !== ASON_TEXT) { + return; + } - this.incrementCounters(node, FaultID.LimitedStdLibNoASON, autofix); - }; - this.checkSymbolAndExecute(symbol, ASON_TEXT, ASON_MODULES, cb); + const parent = node.parent; + switch (parent.kind) { + case ts.SyntaxKind.QualifiedName: + if (!ts.isQualifiedName(parent)) { + return; + } + if (parent.right.text !== node.text) { + return; + } + this.checkAsonUsage(parent.left); + + break; + case ts.SyntaxKind.PropertyAccessExpression: + if (!ts.isPropertyAccessExpression(parent)) { + return; + } + if (parent.name.text !== node.text) { + return; + } + this.checkAsonUsage(parent.expression); + + break; + default: + } + } + + private checkAsonUsage(nodeToCheck: ts.Node): void { + if (!ts.isIdentifier(nodeToCheck)) { + return; + } + const declaration = this.tsUtils.getDeclarationNode(nodeToCheck); + if (!declaration && nodeToCheck.text === ARKTS_UTILS_TEXT) { + this.incrementCounters(nodeToCheck, FaultID.LimitedStdLibNoASON); + return; + } + + if (!declaration) { + return; + } + + const sourceFile = declaration.getSourceFile(); + const fileName = path.basename(sourceFile.fileName); + + if ( + ASON_MODULES.some((moduleName) => { + return fileName.startsWith(moduleName); + }) + ) { + this.incrementCounters(nodeToCheck, FaultID.LimitedStdLibNoASON); + } } private checkCollectionsSymbol(symbol: ts.Symbol, node: ts.Node): void { @@ -6833,10 +6993,10 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { private isDeclarationInSameFile(node: ts.Node): boolean { const symbol = this.tsTypeChecker.getSymbolAtLocation(node); - const decl = TsUtils.getDeclaration(symbol); - if (decl?.getSourceFile() === node.getSourceFile()) { - return true; - } + const decl = TsUtils.getDeclaration(symbol); + if (decl?.getSourceFile() === node.getSourceFile()) { + return true; + } return false; } @@ -7189,7 +7349,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - if (!TypeScriptLinter.isDeclaredInArkTs2(callSignature)) { + if (!this.isDeclaredInArkTs2(callSignature)) { return; } @@ -7624,6 +7784,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } if (node.token === ts.SyntaxKind.ExtendsKeyword || node.token === ts.SyntaxKind.ImplementsKeyword) { node.types.forEach((type) => { + this.handleSharedArrayBuffer(type); const expr = type.expression; if (ts.isIdentifier(expr)) { this.processApiNodeSdkDuplicateDeclName(expr.text, expr); @@ -7793,7 +7954,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; } @@ -7806,16 +7972,27 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - // check if any argument is a `new` expression - const hasNewExpressionArg = callExpr.arguments.some((arg) => { - return ts.isNewExpression(arg); + callExpr.arguments.forEach((arg) => { + const type = this.tsTypeChecker.getTypeAtLocation(arg); + if (ts.isArrowFunction(arg)) { + this.incrementCounters(arg, FaultID.InteropJsObjectCallStaticFunc); + } else if (ts.isIdentifier(arg)) { + const sym = this.tsTypeChecker.getSymbolAtLocation(arg); + const decl = sym?.declarations?.[0]; + if ( + decl && + (ts.isFunctionDeclaration(decl) || + ts.isVariableDeclaration(decl) && decl.initializer && ts.isArrowFunction(decl.initializer)) + ) { + this.incrementCounters(arg, FaultID.InteropJsObjectCallStaticFunc); + } + if (type?.isClassOrInterface()) { + this.incrementCounters(arg, FaultID.InteropJsObjectExpandStaticInstance); + } + } else if (ts.isObjectLiteralExpression(arg) || type?.isClassOrInterface()) { + this.incrementCounters(arg, FaultID.InteropJsObjectExpandStaticInstance); + } }); - - const faultId = hasNewExpressionArg ? - FaultID.InteropJsObjectExpandStaticInstance : - FaultID.InteropJsObjectCallStaticFunc; - - this.incrementCounters(callExpr, faultId); } private fixJsImportExtendsClass( @@ -7848,27 +8025,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 { @@ -7894,10 +8060,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); } @@ -7962,6 +8125,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; @@ -8134,7 +8316,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); @@ -8189,70 +8371,45 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return false; } - private handleInteropAwaitImport(callExpr: ts.CallExpression): void { + handleInstanceOfExpression(node: ts.BinaryExpression): void { if (!this.options.arkts2 || !this.useStatic) { return; } - if (callExpr.expression.kind !== ts.SyntaxKind.ImportKeyword) { + 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)) { return; } - if (ts.isAwaitExpression(callExpr.parent) || ts.isPropertyAccessExpression(callExpr.parent)) { - this.checkInteropForDynamicImport(callExpr); - } + const autofix = this.autofixer?.fixInteropJsInstanceOfExpression(node); + this.incrementCounters(node, FaultID.InteropJsInstanceof, autofix); } - private checkInteropForDynamicImport(callExpr: ts.CallExpression): void { - const interopType = TsUtils.resolveModuleAndCheckInterop( - this.options.wholeProjectPath ?? path.resolve(TsUtils.getCurrentModule(callExpr.getSourceFile().fileName)), - callExpr - ); - - if (!interopType) { + private checkAutoIncrementDecrement(unaryExpr: ts.PostfixUnaryExpression | ts.PrefixUnaryExpression): void { + if (!this.useStatic || !this.options.arkts2) { return; } - switch (interopType) { - case InteropType.JS: - this.incrementCounters(callExpr.parent, FaultID.InteropDynamicImportJs); - break; - case InteropType.TS: - this.incrementCounters(callExpr.parent, FaultID.InteropDynamicImportTs); - break; - case InteropType.LEGACY: - this.incrementCounters(callExpr.parent, FaultID.InteropDynamicImport); - break; - default: - break; + if (!ts.isPropertyAccessExpression(unaryExpr.operand)) { + return; } - } - handleInstanceOfExpression(node: ts.BinaryExpression): void { - if (!this.options.arkts2 || !this.useStatic) { + const propertyAccess = unaryExpr.operand; + if (!this.tsUtils.isJsImport(propertyAccess.expression)) { 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); - } - } - 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); - } - } - } + const autofix = this.autofixer?.fixUnaryIncrDecr(unaryExpr, propertyAccess); + + this.incrementCounters(unaryExpr, FaultID.InteropIncrementDecrement, autofix); } private handleObjectLiteralforUnionTypeInterop(node: ts.VariableDeclaration): void { @@ -8280,7 +8437,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; } } @@ -8345,7 +8502,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } const isFromArkTs2 = declarations.some((decl) => { - return TsUtils.isArkts12File(decl.getSourceFile()); + return this.tsUtils.isArkts12File(decl.getSourceFile()); }); if (isFromArkTs2) { @@ -8482,17 +8639,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) { @@ -8538,13 +8695,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; } @@ -8568,7 +8725,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); @@ -8591,7 +8748,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)) { @@ -8601,7 +8758,7 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { } private handleObjectLiteralInReturn(node: ts.ReturnStatement): void { - if (TsUtils.isArkts12File(node.getSourceFile())) { + if (this.tsUtils.isArkts12File(node.getSourceFile())) { return; } @@ -8627,7 +8784,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)) { @@ -8654,10 +8811,6 @@ 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; @@ -8803,23 +8956,149 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return targetTypes.includes(storageType.getText()); } - private handleAwaitExpression(node: ts.Node): void { - if (!this.options.arkts2 || !this.useStatic) { + private handlePropertyAssignmentForProp(node: ts.PropertyAssignment): void { + if (!this.options.arkts2) { 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; + + 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; } - return false; - }; + + 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; + + let ident: undefined | ts.Identifier; + let args: ts.NodeArray | undefined; + const expr = awaitExpr.expression; - checkAndReportJsImportAwait(expr); if (ts.isCallExpression(expr)) { - checkAndReportJsImportAwait(expr.expression); + 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 { 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 { @@ -8827,14 +9106,24 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } const className = classDecl.name?.getText(); + const initializedProperties = new Set(); + classDecl.members.forEach((member) => { + if (ts.isPropertyDeclaration(member) && member.initializer) { + initializedProperties.add(member.name.getText()); + } + }); classDecl.members.forEach((member) => { if (ts.isMethodDeclaration(member)) { - this.checkMethod(member, className); + this.checkMethod(member, className, initializedProperties); } }); } - private checkMethod(methodNode: ts.MethodDeclaration, className: string | undefined): void { + private checkMethod( + methodNode: ts.MethodDeclaration, + className: string | undefined, + initializedProperties: Set + ): void { const variableDeclarations = new Map(); const returnStatements: ts.ReturnStatement[] = []; if (methodNode.body) { @@ -8842,17 +9131,24 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { this.visitMethodBody(node, variableDeclarations, returnStatements); }); } - - const isStaticPropertyAccess = (node: ts.Expression, className: string): boolean => { - return ( - ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === className - ); + const isStaticPropertyAccess = (node: ts.Expression): boolean => { + if ( + ts.isPropertyAccessExpression(node) && + ts.isIdentifier(node.expression) && + node.expression.text === className + ) { + const nextNode = node.name; + return ts.isIdentifier(nextNode) && !initializedProperties.has(nextNode.text); + } + return false; }; - const isInstancePropertyAccess = (node: ts.Expression): boolean => { - return ts.isPropertyAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword; + if (ts.isPropertyAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword) { + const nextNode = node.name; + return ts.isIdentifier(nextNode) && !initializedProperties.has(nextNode.text); + } + return false; }; - this.checkReturnStatements(returnStatements, className, isStaticPropertyAccess, isInstancePropertyAccess); } @@ -8889,11 +9185,12 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { return; } - if (className && isStaticPropertyAccess(returnStmt.expression, className)) { + const returnType = this.tsTypeChecker.getTypeAtLocation(returnStmt.expression); + if (className && isStaticPropertyAccess(returnStmt.expression, className) && returnType.isUnion()) { this.incrementCounters(returnStmt, FaultID.NoTsLikeSmartType); } - if (isInstancePropertyAccess(returnStmt.expression)) { + if (isInstancePropertyAccess(returnStmt.expression) && returnType.isUnion()) { this.incrementCounters(returnStmt, FaultID.NoTsLikeSmartType); } }); @@ -8903,33 +9200,19 @@ export class TypeScriptLinter extends BaseTypeScriptLinter { if (!this.options.arkts2) { return; } - switch (node.operatorToken.kind) { - case ts.SyntaxKind.LessThanEqualsToken: - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.GreaterThanEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.GreaterThanToken: - case ts.SyntaxKind.LessThanToken: - this.reportNumericBigintCompare(node); - break; - default: - } - } - - private reportNumericBigintCompare(node: ts.BinaryExpression): void { const leftType = this.tsTypeChecker.getTypeAtLocation(node.left); const rightType = this.tsTypeChecker.getTypeAtLocation(node.right); - const isLeftNumber = (leftType.flags & ts.TypeFlags.Number) !== 0; - const isLeftBigInt = (leftType.flags & ts.TypeFlags.BigInt) !== 0; - - const isRightNumber = (rightType.flags & ts.TypeFlags.Number) !== 0; - const isRightBigInt = (rightType.flags & ts.TypeFlags.BigInt) !== 0; + const isBigInt = (type: ts.Type): boolean => { + return (type.flags & ts.TypeFlags.BigInt) !== 0 || (type.flags & ts.TypeFlags.BigIntLiteral) !== 0; + }; + const isNumber = (type: ts.Type): boolean => { + return (type.flags & ts.TypeFlags.Number) !== 0 || (type.flags & ts.TypeFlags.NumberLiteral) !== 0; + }; - const valid = isLeftNumber && isRightBigInt || isLeftBigInt && isRightNumber; - if (valid) { + const isBigIntAndNumberOperand = + isNumber(leftType) && isBigInt(rightType) || isBigInt(leftType) && isNumber(rightType); + if (isBigIntAndNumberOperand) { this.incrementCounters(node, FaultID.NumericBigintCompare); } } @@ -8993,8 +9276,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 5b702540223fd80043660cf4d0092bb4949dd18c..b0e3f2289ea6ff5699fb6204c00152a089092b49 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, @@ -52,7 +53,12 @@ import { ARE_STRICTLY_EQUAL, WRAP, INSTANTIATE, - TO_NUMBER + TO_NUMBER, + TO_PROMISE, + INVOKE, + INVOKE_METHOD, + LENGTH, + IS_INSTANCE_OF } from '../utils/consts/InteropAPI'; import { ESLIB_SHAREDARRAYBUFFER } from '../utils/consts/ConcurrentAPI'; @@ -84,6 +90,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'; @@ -148,6 +157,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(); @@ -789,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 += @@ -1030,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 }]; } @@ -1044,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 }]; } @@ -1343,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 { @@ -1466,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--) { @@ -1499,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)) ); } @@ -1836,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. @@ -1968,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. @@ -2223,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; } @@ -3061,6 +3072,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; @@ -3115,6 +3349,41 @@ export class Autofixer { ]; } + /** + * Transforms a call expression invoking an imported function or method into its interop equivalent. + * - For direct calls like foo() or bar(123), transforms to foo.invoke() or bar.invoke(ESValue.wrap(123)) + * - For property access calls like foo.bar(123), transforms to foo.invokeMethod('bar', ESValue.wrap(123)) + * @param expression The call expression node to transform. + * @returns Autofix array or undefined. + */ + fixInteropInvokeExpression(expression: ts.CallExpression): Autofix[] | undefined { + const callee = expression.expression; + const args = this.createArgs(expression.arguments); + + let replacement: ts.CallExpression; + + if (ts.isPropertyAccessExpression(callee)) { + // For expressions like foo.bar(123) => foo.invokeMethod('bar', ...) + replacement = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(callee.expression, ts.factory.createIdentifier(INVOKE_METHOD)), + undefined, + [ts.factory.createStringLiteral(callee.name.getText()), ...(args || [])] + ); + } else if (ts.isIdentifier(callee)) { + // For expressions like foo() or bar(123) => foo.invoke(...) or bar.invoke(...) + replacement = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(callee, ts.factory.createIdentifier(INVOKE)), + undefined, + args + ); + } else { + return undefined; + } + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, replacement, expression.getSourceFile()); + return [{ start: expression.getStart(), end: expression.getEnd(), replacementText }]; + } + fixInteropInstantiateExpression( express: ts.NewExpression, args: ts.NodeArray | undefined @@ -3243,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); @@ -3557,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; @@ -3566,7 +3859,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) { @@ -3585,29 +3878,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; @@ -3634,6 +3991,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) { @@ -3720,30 +4134,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( @@ -3801,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], @@ -3869,6 +4305,105 @@ export class Autofixer { return [{ start: express.getStart(), end: express.getEnd(), replacementText: replacementText }]; } + fixInteropAsExpression(expression: ts.AsExpression): Autofix[] | undefined { + const castMap: Partial> = { + [ts.SyntaxKind.StringKeyword]: 'toString', + [ts.SyntaxKind.NumberKeyword]: 'toNumber', + [ts.SyntaxKind.BooleanKeyword]: 'toBoolean', + [ts.SyntaxKind.BigIntKeyword]: 'toBigInt' + }; + + const castMethod = castMap[expression.type.kind]; + if (!castMethod) { + return undefined; + } + const express = expression.expression; + if (!ts.isPropertyAccessExpression(express)) { + return undefined; + } + + const propertyAccess = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(express.expression, ts.factory.createIdentifier(GET_PROPERTY_BY_NAME)), + undefined, + [ts.factory.createStringLiteral(express.name.getText())] + ); + + const finalCall = ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression(propertyAccess, ts.factory.createIdentifier(castMethod)), + undefined, + [] + ); + + const replacementText = this.printer.printNode(ts.EmitHint.Unspecified, finalCall, expression.getSourceFile()); + + return [ + { + start: expression.getStart(), + end: expression.getEnd(), + replacementText + } + ]; + } + + 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)), @@ -3909,8 +4444,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 { @@ -4086,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; }); @@ -4173,6 +4711,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 462d6d8b133f691bbc7767e37e33d303726b79ca..7d8aad85134f7babf281474ea14ecd7f28229f2c 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 d7e87a00e2e5faaf92f6b40296c4d804d341e735..5ed15ab452126c13aaa528ce98b2a769bb096b61 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 { InteropType, USE_STATIC } from './consts/InteropAPI'; import { ETS_MODULE, PATH_SEPARATOR, VALID_OHM_COMPONENTS_MODULE_PATH } from './consts/OhmUrl'; -import { EXTNAME_D_TS, EXTNAME_ETS, EXTNAME_JS, EXTNAME_TS } 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'; @@ -248,7 +247,11 @@ export class TsUtils { } const declaration = this.getDeclarationNode(ident); - if (!declaration) { + if (!declaration || ident.text.includes(STRING_ERROR_LITERAL)) { + return false; + } + + if (!declaration || !ident.text.includes(STRING_ERROR_LITERAL)) { return true; } @@ -3644,6 +3647,13 @@ export class TsUtils { let current: ts.Node | undefined = node; while (current) { if (ts.isIfStatement(current)) { + if ( + ts.isBinaryExpression(node.parent) && + node.parent.operatorToken.kind === ts.SyntaxKind.EqualsEqualsEqualsToken + ) { + return false; + } + return true; } current = current.parent; @@ -3711,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 { @@ -3742,62 +3750,6 @@ export class TsUtils { return str; } - static getCurrentModule(currentFileName: string): string { - const parts = currentFileName.split(PATH_SEPARATOR); - parts.pop(); - const currentModule = parts.join(PATH_SEPARATOR); - return currentModule; - } - - static resolveModuleAndCheckInterop(wholeProjectPath: string, callExpr: ts.CallExpression): InteropType | undefined { - const moduleName = callExpr.arguments[0]; - if (!ts.isStringLiteral(moduleName)) { - return undefined; - } - - const importedModule = path.resolve(wholeProjectPath, moduleName.text); - - const importedFile = TsUtils.resolveImportModule(importedModule); - if (!importedFile) { - return undefined; - } - - const importSource = ts.sys.readFile(importedFile); - if (!importSource) { - return undefined; - } - - return TsUtils.checkFileForInterop(importedFile, importSource); - } - - static resolveImportModule(importedModule: string): string | undefined { - const extensions = ['.ts', '.js', '.ets']; - for (const ext of extensions) { - const tryPath = path.resolve(importedModule + ext); - if (fs.existsSync(tryPath)) { - return tryPath; - } - } - - return undefined; - } - - static checkFileForInterop(fileName: string, importSource: string): InteropType { - if (fileName.endsWith(EXTNAME_JS)) { - return InteropType.JS; - } - - if (fileName.endsWith(EXTNAME_TS) && !fileName.endsWith(EXTNAME_D_TS)) { - return InteropType.TS; - } - - if (fileName.endsWith(EXTNAME_ETS) && !importSource.includes('\'use static\'')) { - return InteropType.LEGACY; - } - - return InteropType.NONE; - } - isJsImport(node: ts.Node): boolean { const symbol = this.trueSymbolAtLocation(node); if (symbol) { diff --git a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts index 3bf672666f69e6194b9f095372f1e707db3d859b..2eaef243aa86d7ebaefd91e471e66efde1909242 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkTS2Rules.ts @@ -14,12 +14,141 @@ */ export const arkts2Rules: number[] = [ - 1, 25, 30, 34, 37, 29, 111, 137, 139, 140, 144, 149, 183, 184, 189, 190, 191, 192, 193, 198, 199, 202, 203, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 222, 232, 233, 234, 235, 236, 237, 238, 239, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 281, 282, 283, 284, 285, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, 349, 350, 351, 355, 356, 357, 358, 359, 370, 371, 372, 373, 374, 375, 376, 377, 378 + 1, + 25, + 30, + 34, + 37, + 29, + 111, + 137, + 139, + 140, + 144, + 149, + 183, + 184, + 189, + 190, + 191, + 192, + 193, + 198, + 199, + 202, + 203, + 206, + 207, + 208, + 209, + 210, + 211, + 212, + 213, + 214, + 215, + 222, + 232, + 233, + 234, + 235, + 236, + 237, + 238, + 239, + 251, + 252, + 253, + 254, + 255, + 256, + 257, + 258, + 259, + 260, + 261, + 262, + 263, + 265, + 266, + 267, + 268, + 269, + 270, + 274, + 275, + 281, + 282, + 283, + 284, + 285, + 286, + 300, + 301, + 302, + 303, + 304, + 305, + 306, + 307, + 308, + 309, + 310, + 311, + 312, + 313, + 314, + 315, + 316, + 317, + 318, + 319, + 320, + 321, + 322, + 323, + 324, + 325, + 326, + 327, + 328, + 329, + 330, + 331, + 332, + 333, + 334, + 335, + 336, + 337, + 338, + 339, + 340, + 341, + 342, + 343, + 344, + 345, + 346, + 347, + 348, + 349, + 350, + 351, + 355, + 356, + 357, + 358, + 359, + 370, + 371, + 372, + 373, + 374, + 375, + 376, + 377, + 378 ]; export const onlyArkts2SyntaxRules: Map = new Map([ diff --git a/ets2panda/linter/src/lib/utils/consts/ArkTSUtilsAPI.ts b/ets2panda/linter/src/lib/utils/consts/ArkTSUtilsAPI.ts index dcddab08b580a515ee4cbb998d5b2bff7a1025a9..8218ffc5113110bf9692d2a2f8ec847471e0dc93 100644 --- a/ets2panda/linter/src/lib/utils/consts/ArkTSUtilsAPI.ts +++ b/ets2panda/linter/src/lib/utils/consts/ArkTSUtilsAPI.ts @@ -16,3 +16,4 @@ export const ASON_TEXT = 'ASON'; export const ASON_MODULES = ['@arkts.utils', '@kit.ArkTS']; export const JSON_TEXT = 'JSON'; +export const ARKTS_UTILS_TEXT = 'ArkTSUtils'; diff --git a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts index 334f54afad425119f29ae9bc59be243a968390b2..cb8d0468d50b1b0ca34809e628b6b9276c7d4128 100644 --- a/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts +++ b/ets2panda/linter/src/lib/utils/consts/InteropAPI.ts @@ -12,12 +12,17 @@ * 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 IS_INSTANCE_OF = 'isInstanceOf'; export const REFLECT_PROPERTIES = [ 'get', @@ -54,6 +59,8 @@ 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'; @@ -71,3 +78,13 @@ export enum InteropType { LEGACY = '1.0', NONE = 'none' } + +export type IdentifierAndArguments = { + ident: undefined | ts.Identifier; + args: ts.NodeArray | undefined; +}; + +export type IncrementDecrementNodeInfo = { + varAssignText: string; + addOrDecrOperation: ts.BinaryExpression; +}; diff --git a/ets2panda/linter/src/lib/utils/consts/Literals.ts b/ets2panda/linter/src/lib/utils/consts/Literals.ts index 3ca262e108fa4358f39d2498be4cc3a9e1d0d6a7..4b543492615e2d214376244cdfcf0408aad1243b 100644 --- a/ets2panda/linter/src/lib/utils/consts/Literals.ts +++ b/ets2panda/linter/src/lib/utils/consts/Literals.ts @@ -13,4 +13,4 @@ * limitations under the License. */ -export const STRING_ERROR_LITERAL = 'ERROR'; +export const STRING_ERROR_LITERAL = 'Error'; diff --git a/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets b/ets2panda/linter/test/concurrent/concurrent_sharedarraybuffer_arkts2.ets index d3e0b2ca58ad6fde6ac4d5ba2e1d5e38bafd84a0..b6c511a7ad6194f0e29ea43ba3fa1b6843bcd5ca 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 fa8024c8d379432c1df90cff56452f46adf572b1..c390c26562aab76528f553635f51e1d1fd6a142f 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 01e6621c9d4fa857cd90d0c8cf61deab97cebef2..4eea7766a3ba34154a8dff0dd467b21b54e53e37 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 7a393ab10fe816bdd7c0aac6177253fc60e97e4a..b7e398fb0a3d46ac7404e6732e59adc890b68ad0 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 ca28292f8e4d54b3a473114b5d2238f3fa55c03f..9b627b9d723d7f5d127d0724c1c125b3dfa719d3 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 29bfa417e57a9375c0c37fa471bf0fa9b52f0080..472ad5669d75bba44ac209e2e148c3b4570a1a0e --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets @@ -12,8 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' -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 @@ -21,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.args.json b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.args.json index 3318ebbbcfd0ce90dc5f69df69452a3201e4204d..b13bb90d5b5f6d3dc5f0d054663eeba637fcc7dd 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 f069ac9eeb23b6d2519c4392de77121237d91a2f..88784c2392e997667f1905cc123a601a9c260d2f --- 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,29 +15,19 @@ ], "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, - "endColumn": 49, + "endLine": 15, + "endColumn": 53, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", "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,8 +156,38 @@ }, { "line": 23, - "column": 5, + "column": 6, + "endLine": 23, + "endColumn": 7, + "problem": "BinaryOperations", + "suggest": "", + "rule": "Binary operations on js objects (arkts-interop-js2s-binary-op)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 3, "endLine": 23, + "endColumn": 5, + "problem": "ExponentOp", + "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": "", @@ -175,9 +195,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 26, "column": 1, - "endLine": 24, + "endLine": 26, "endColumn": 2, "problem": "BinaryOperations", "suggest": "", @@ -185,9 +205,29 @@ "severity": "ERROR" }, { - "line": 24, + "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": 24, + "endLine": 27, "endColumn": 7, "problem": "BinaryOperations", "suggest": "", @@ -195,14 +235,144 @@ "severity": "ERROR" }, { - "line": 24, + "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": 24, + "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 old mode 100755 new mode 100644 index 18043cd8a08542f8160a583dfa44dbd06ee190d6..02657b315262d64811922b09efbc6f62fb2f933a --- 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,41 +13,31 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [ +"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, - "endColumn": 49, + "endLine": 15, + "endColumn": 53, "problem": "InterOpImportJs", "autofix": [ { - "start": 617, - "end": 665, + "start": 604, + "end": 656, "replacementText": "", - "line": 16, + "line": 15, "column": 1, - "endLine": 16, - "endColumn": 49 + "endLine": 15, + "endColumn": 53 }, { - "start": 665, - "end": 665, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./binary_operation_js_obj_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\n", - "line": 16, + "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": 16, - "endColumn": 49 + "endLine": 15, + "endColumn": 53 } ], "suggest": "", @@ -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": 665, + "end": 670, "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": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\")", "line": 17, "column": 9, "endLine": 17, @@ -93,49 +83,49 @@ } ], "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", "autofix": [ { - "start": 688, - "end": 693, - "replacementText": "foo.getPropertyByName(\"b\")", + "start": 665, + "end": 670, + "replacementText": "foo.getPropertyByName(\"a\").toNumber()", "line": 18, - "column": 9, + "column": 1, "endLine": 18, - "endColumn": 14 + "endColumn": 2 } ], "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", "autofix": [ { - "replacementText": "foo.getPropertyByName('b').toNumber()", - "start": 688, - "end": 693, + "start": 679, + "end": 684, + "replacementText": "foo.getPropertyByName(\"b\").toNumber()", "line": 18, - "column": 9, + "column": 5, "endLine": 18, - "endColumn": 14 + "endColumn": 6 } ], "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" }, { @@ -144,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" @@ -154,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" @@ -164,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" @@ -174,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" @@ -184,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" @@ -194,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" @@ -204,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" @@ -214,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" @@ -224,60 +302,491 @@ "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" }, { "line": 23, - "column": 5, + "column": 6, "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" + }, + { + "line": 23, + "column": 3, + "endLine": 23, + "endColumn": 5, + "problem": "ExponentOp", + "autofix": [ + { + "replacementText": "Math.pow(a, b)", + "start": 715, + "end": 721, + "line": 23, + "column": 3, + "endLine": 23, + "endColumn": 5 + } + ], + "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": 24, + "line": 27, "column": 1, - "endLine": 24, + "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": 24, + "line": 27, "column": 6, - "endLine": 24, + "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": 24, + "line": 27, "column": 3, - "endLine": 24, + "endLine": 27, "endColumn": 5, "problem": "ExponentOp", "autofix": [ { - "replacementText": "Math.pow(a, b)", - "start": 724, - "end": 730, - "line": 24, + "replacementText": "Math.pow(m, n)", + "start": 735, + "end": 741, + "line": 27, "column": 3, - "endLine": 24, + "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 24e48e6dcb622409f469756ff0b09fbb2879d9cc..e28baca176a2b17f328386775efec64717650b4b 100755 --- a/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json +++ b/ets2panda/linter/test/interop/binary_operation_js_obj.ets.json @@ -15,13 +15,13 @@ ], "result": [ { - "line": 16, - "column": 1, - "endLine": 16, - "endColumn": 49, - "problem": "ImportAfterStatement", + "line": 35, + "column": 11, + "endLine": 35, + "endColumn": 12, + "problem": "ObjectLiteralNoContextType", "suggest": "", - "rule": "\"import\" statements after other statements are not allowed (arkts-no-misplaced-imports)", + "rule": "Object literal must correspond to some explicitly declared class or interface (arkts-no-untyped-obj-literals)", "severity": "ERROR" } ] 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 72c3c6c688c6661b162927589e92e506e543da91..f29b91c27508799b1f7054d1ab2b622b82fe51cd 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,9 +12,10 @@ * 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'); +let m = GeneratedImportVar_1.getPropertyByName('m'); +let n = GeneratedImportVar_1.getPropertyByName('n'); let a = foo.getPropertyByName("a") let b = foo.getPropertyByName("b") @@ -23,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 2caa23e507419af4d11c9232fc89618c12ad92f1..817c2a94501ff9e7c7d318f8d8bacf6f388092a8 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 @@ -14,11 +14,21 @@ "limitations under the License." ], "result": [ + { + "line": 15, + "column": 5, + "endLine": 15, + "endColumn": 72, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, { "line": 16, "column": 5, "endLine": 16, - "endColumn": 72, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -28,17 +38,17 @@ "line": 17, "column": 5, "endLine": 17, - "endColumn": 56, + "endColumn": 52, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 5, - "endLine": 19, - "endColumn": 35, + "endLine": 18, + "endColumn": 52, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -55,14 +65,54 @@ "severity": "ERROR" }, { - "line": 26, + "line": 21, + "column": 5, + "endLine": 21, + "endColumn": 35, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "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": 26, + "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": 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 aaf9c1dd4e9e4e7e46d0cf3efb92bb573817fde8..c8f9951bdacb9a6fd47ef3704d312293cb78ffd4 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/call_function.ets b/ets2panda/linter/test/interop/call_function.ets index b76d862f4a67e010fbb3cd04176ba255c400dab8..74665b905caef883c904b8ee1d13c01b7efc4e0a 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 75b5fe5523b8596a04cdb184e1b73bcb3fb72679..66335fa504eb461da8ade9c2cc71a8119f4e11f0 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,19 +25,9 @@ "severity": "ERROR" }, { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 6, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 6, "problem": "CallJSFunction", "suggest": "", @@ -55,19 +35,9 @@ "severity": "ERROR" }, { - "line": 19, - "column": 1, - "endLine": 19, - "endColumn": 9, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 9, "problem": "CallJSFunction", "suggest": "", @@ -75,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 08b4bd7b56c82c9eeb61e1bd092388f21bb9f59a..ca88f857e960b437dcf767c0ac40be998c8f1236 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 ee45f2bcf310af18a40e73daac122f063494253f..891ae57a57c60ed2252efb4a8f74c928702b2589 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 08caa2a29e9cd2a4c445e1140152e08aeed29fc5..92c91ccd5b6de9e797492192e27346ff5d953ddb 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,19 +25,9 @@ "severity": "ERROR" }, { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 13, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 13, "problem": "InteropCallObjectMethods", "suggest": "", @@ -55,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 e60f942acb66489f947a4a4becf3473b46d876a4..5776d747e91eb48f6601bcff75f5fe371e5f1e75 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,39 +45,40 @@ "severity": "ERROR" }, { - "line": 18, - "column": 1, - "endLine": 18, - "endColumn": 13, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 13, "problem": "InteropCallObjectMethods", + "autofix": [ + { + "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 } ], diff --git a/ets2panda/linter/test/interop/call_object_methods.ets.json b/ets2panda/linter/test/interop/call_object_methods.ets.json index 8866623ce527a677439958b81b87b48a69851ee5..ca88f857e960b437dcf767c0ac40be998c8f1236 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 b10b238d4d341e7442b102378af527c9b088c0cf..2d455bda8efef122fba489a3d60a57d3f71c6379 100644 --- a/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets +++ b/ets2panda/linter/test/interop/call_object_methods.ets.migrate.ets @@ -12,10 +12,9 @@ * 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'); -foo.bar(123.0) +foo.invokeMethod("bar", ESValue.wrap(123.0)) 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 5399cc769ed6721762185bea9cbc142c2fc048fb..4f96146af19c8bb188c5157221d11ba6cf249284 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 e1d4d726e42ed9cf3f7fa79d50e53f253d739e58..9d1ec94c5645af3a80526bed72513c2abe775a6b --- a/ets2panda/linter/test/interop/increases_decreases_js_obj.ets +++ b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets @@ -12,10 +12,14 @@ * 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++ 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 3318ebbbcfd0ce90dc5f69df69452a3201e4204d..571ee6bb76b0cad72a9443db47c2f9d7db474bd0 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 old mode 100755 new mode 100644 index 5e29c71a76559ae730740cb0b5a9e50a74732c6a..5733e4a0f97db5f9cd00d71fb1957baef5ac7e53 --- 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, + "line": 15, "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, - "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,22 +56,12 @@ }, { "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, + "column": 5, "endLine": 19, "endColumn": 14, - "problem": "InteropJsObjectUsage", + "problem": "InteropIncrementDecrement", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { @@ -115,54 +75,44 @@ "severity": "ERROR" }, { - "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", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { - "line": 21, - "column": 5, - "endLine": 21, - "endColumn": 14, + "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": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropObjectProperty", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "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": "InteropJsObjectUsage", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "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 old mode 100755 new mode 100644 index 06540703433696ac72e8700e6d11d7e7924f05b5..74a00a0cf400aac6057b177eb9ef4f11c895846d --- 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,55 +66,45 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 5, - "endLine": 18, + "endLine": 17, "endColumn": 14, "problem": "InteropIncrementDecrement", - "suggest": "", - "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", - "severity": "ERROR" - }, - { - "line": 18, - "column": 5, - "endLine": 18, - "endColumn": 12, - "problem": "InteropObjectProperty", "autofix": [ { - "start": 690, - "end": 697, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 18, + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, a + 1)\na = a + 1\n", + "start": 673, + "end": 686, + "line": 17, "column": 5, - "endLine": 18, - "endColumn": 12 + "endLine": 17, + "endColumn": 14 } ], "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { "line": 18, "column": 5, "endLine": 18, - "endColumn": 12, - "problem": "InteropJsObjectUsage", + "endColumn": 14, + "problem": "InteropIncrementDecrement", "autofix": [ { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 690, - "end": 697, + "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": 12 + "endColumn": 14 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { @@ -133,50 +113,19 @@ "endLine": 19, "endColumn": 14, "problem": "InteropIncrementDecrement", - "suggest": "", - "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", - "severity": "ERROR" - }, - { - "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, + "replacementText": "a = foo.getPropertyByName(\"num\").toNumber()\nfoo.setPropertyByName(num, a - 1)\na = a - 1\n", + "start": 701, + "end": 714, "line": 19, - "column": 7, + "column": 5, "endLine": 19, "endColumn": 14 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { @@ -185,103 +134,104 @@ "endLine": 20, "endColumn": 14, "problem": "InteropIncrementDecrement", - "suggest": "", - "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12, - "problem": "InteropObjectProperty", "autofix": [ { - "start": 718, - "end": 725, - "replacementText": "foo.getPropertyByName(\"num\")", + "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": 12 + "endColumn": 14 } ], "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12, - "problem": "InteropJsObjectUsage", + "line": 22, + "column": 1, + "endLine": 22, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "autofix": [ { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 718, - "end": 725, - "line": 20, - "column": 5, - "endLine": 20, - "endColumn": 12 + "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": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Interop objects can't be incremented or decremented (arkts-interop-js2s-self-addtion-reduction)", "severity": "ERROR" }, { - "line": 21, - "column": 5, - "endLine": 21, - "endColumn": 14, + "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": 21, - "column": 7, - "endLine": 21, - "endColumn": 14, - "problem": "InteropObjectProperty", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "autofix": [ { - "start": 734, - "end": 741, - "replacementText": "foo.getPropertyByName(\"num\")", - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14 + "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": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "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": "InteropJsObjectUsage", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 10, + "problem": "InteropIncrementDecrement", "autofix": [ { - "replacementText": "foo.getPropertyByName('num').toNumber()", - "start": 734, - "end": 741, - "line": 21, - "column": 7, - "endLine": 21, - "endColumn": 14 + "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": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "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.json b/ets2panda/linter/test/interop/increases_decreases_js_obj.ets.json index cf493da1d6fe4df6133341a3e3a1db1489feb321..ca88f857e960b437dcf767c0ac40be998c8f1236 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 3be959d07a495d4fd85795cabcff73c1ea30ae9f..f022ce0834ee6528d5c77bf5bd845590530ea4b7 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,40 @@ * 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.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 f6439adcf2637a788231915451071c18bc2f4736..0a10b6a69edbbda115aff18cc7d947ae932ec423 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,14 +25,54 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 5, - "endLine": 17, + "endLine": 16, "endColumn": 56, "problem": "AnyType", "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" } ] } diff --git a/ets2panda/linter/test/interop/instantiated_js_obj.ets b/ets2panda/linter/test/interop/instantiated_js_obj.ets index f24de83f1ac2aea42269962eaa365a8f430dd622..e4208df9fe3ba98ef73b31b1fe28bb5b78d21053 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 d5efb9f32d78bbd43cb4eddaf8e40a4781344054..f116dfb988a075a4decea2af9fadc3167ceb15ba 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 7a22b7b9aa6a59570819d9daf7c69979b32837e8..f9ae170771c98c555d228cd0ac3d36b36294688e 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 ad8f5eb1ae4e1f2ec507367301510cbc9e65607a..ca88f857e960b437dcf767c0ac40be998c8f1236 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 06c8b9ee788e412fb2c6fb8714383fc97dd0c4c7..b033816ddb15de3ae08e462513ec1258f69269e8 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 915dad64c5a1d8dc688978d40079ee4b0251ddbb..2084de8763deeb4f9899489c2da2f6cf454ad82d 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 296d7bb3ed6204c3e6836a9274e9afd1ad8dffe1..02426a43180b9f34518bb0f1601ca6425a1084b6 --- 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"); @@ -14,9 +15,51 @@ */ 'use static' - import {foo, foo2, foo3, foo4} from "./interop_convert_import_js.js" + import {foo, foo2, foo3, foo4, array_val, null_val, undefined_val} 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" \ No newline at end of file + let a1: boolean = foo2.bool as boolean + let a2: string = foo3.str as string + let a3: bigint = foo4.big as bigint + +test_helper.test(() => { +return (array_val as Array).toString() === new Array(1, 2, 3).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,2,3].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"); + * 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.args.json b/ets2panda/linter/test/interop/interop_convert_import.ets.args.json index 88d4f72683443a60125bfe1c47f15ca10daecbfc..b023016d6bc3b2713d4e02b6f765940828db476b 100755 --- a/ets2panda/linter/test/interop/interop_convert_import.ets.args.json +++ b/ets2panda/linter/test/interop/interop_convert_import.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 + } \ No newline at end of file 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 8b318f2ad32df1717c0fc31f8b15ce7f2d8c1eb0..f4460de05a9e7dc5972246339c58ae190b3e0d0c --- a/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.arkts2.json @@ -1,148 +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": 70, - "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": 70, - "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": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 19, - "endLine": 20, - "endColumn": 40, - "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": 19, - "endLine": 20, - "endColumn": 28, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 20, - "column": 19, - "endLine": 20, - "endColumn": 28, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 18, - "endLine": 21, - "endColumn": 37, - "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": 18, - "endLine": 21, - "endColumn": 26, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 18, - "endLine": 21, - "endColumn": 26, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 18, - "endLine": 22, - "endColumn": 37, - "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": 18, - "endLine": 22, - "endColumn": 26, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 18, - "endLine": 22, - "endColumn": 26, - "problem": "InteropJsObjectUsage", - "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", - "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 new file mode 100644 index 0000000000000000000000000000000000000000..cfa646085ae972fb91eb01d4262ff3e50896825c --- /dev/null +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.autofix.json @@ -0,0 +1,318 @@ +{ + "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", + "autofix": [ + { + "start": 649, + "end": 753, + "replacementText": "", + "line": 18, + "column": 2, + "endLine": 18, + "endColumn": 106 + }, + { + "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": 18, + "endColumn": 106 + } + ], + "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", + "autofix": [ + { + "start": 774, + "end": 791, + "replacementText": "foo.getPropertyByName(\"num\").toNumber()", + "line": 20, + "column": 18, + "endLine": 20, + "endColumn": 35 + } + ], + "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", + "autofix": [ + { + "start": 812, + "end": 833, + "replacementText": "foo2.getPropertyByName(\"bool\").toBoolean()", + "line": 21, + "column": 20, + "endLine": 21, + "endColumn": 41 + } + ], + "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", + "autofix": [ + { + "start": 853, + "end": 872, + "replacementText": "foo3.getPropertyByName(\"str\").toString()", + "line": 22, + "column": 19, + "endLine": 22, + "endColumn": 38 + } + ], + "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", + "autofix": [ + { + "start": 892, + "end": 911, + "replacementText": "foo4.getPropertyByName(\"big\").toBigInt()", + "line": 23, + "column": 19, + "endLine": 23, + "endColumn": 38 + } + ], + "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", + "autofix": [ + { + "start": 994, + "end": 995, + "replacementText": "1.0", + "line": 26, + "column": 54, + "endLine": 26, + "endColumn": 55 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 57, + "endLine": 26, + "endColumn": 58, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 997, + "end": 998, + "replacementText": "2.0", + "line": 26, + "column": 57, + "endLine": 26, + "endColumn": 58 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 26, + "column": 60, + "endLine": 26, + "endColumn": 61, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1000, + "end": 1001, + "replacementText": "3.0", + "line": 26, + "column": 60, + "endLine": 26, + "endColumn": 61 + } + ], + "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", + "autofix": [ + { + "start": 1208, + "end": 1209, + "replacementText": "1.0", + "line": 31, + "column": 48, + "endLine": 31, + "endColumn": 49 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 50, + "endLine": 31, + "endColumn": 51, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1210, + "end": 1211, + "replacementText": "2.0", + "line": 31, + "column": 50, + "endLine": 31, + "endColumn": 51 + } + ], + "suggest": "", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 52, + "endLine": 31, + "endColumn": 53, + "problem": "NumericSemantics", + "autofix": [ + { + "start": 1212, + "end": 1213, + "replacementText": "3.0", + "line": 31, + "column": 52, + "endLine": 31, + "endColumn": 53 + } + ], + "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.json b/ets2panda/linter/test/interop/interop_convert_import.ets.json index 1d059f0d382adbf11dac846f30473a60ba3985a2..5a3f5938e4936b27eb26b147f0b5c49254d3902a 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": 70, - "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 new file mode 100644 index 0000000000000000000000000000000000000000..1e107cf338e0678a330243f31895744ea396b428 --- /dev/null +++ b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.ets @@ -0,0 +1,73 @@ +<<<<<<< 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"); + * 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.migrate.json b/ets2panda/linter/test/interop/interop_convert_import.ets.migrate.json new file mode 100644 index 0000000000000000000000000000000000000000..a49b70a95279536d6b68fb9d7385dd46c5986998 --- /dev/null +++ b/ets2panda/linter/test/interop/interop_convert_import.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": 18, + "column": 6, + "endLine": 18, + "endColumn": 75, + "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": 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": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 22, + "column": 5, + "endLine": 22, + "endColumn": 58, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 23, + "column": 5, + "endLine": 23, + "endColumn": 68, + "problem": "AnyType", + "suggest": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "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": "", + "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 44, + "endLine": 34, + "endColumn": 68, + "problem": "GenericCallNoTypeArgs", + "suggest": "", + "rule": "Type inference in case of generic function calls is limited (arkts-no-inferred-generic-params)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 8, + "endLine": 44, + "endColumn": 24, + "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_js.js b/ets2panda/linter/test/interop/interop_convert_import_js.js index f3895baaa7f2e4cf2d75b9c4ecfc5a1c50879481..cce72a8fb7f192f91addc00968c283556c0d205f 100755 --- a/ets2panda/linter/test/interop/interop_convert_import_js.js +++ b/ets2panda/linter/test/interop/interop_convert_import_js.js @@ -16,4 +16,7 @@ export let foo = {name: 123} export let foo2 = {bool: true} export let foo3 = {str: '123'} -export let foo4 = {big: 123n} \ No newline at end of file +export let foo4 = {big: 123n} +export let array_val = [1, 2, 3]; +export let null_val = null; +export let undefined_val = undefined; \ No newline at end of file diff --git a/ets2panda/linter/test/interop/interop_equality_judgment.ets b/ets2panda/linter/test/interop/interop_equality_judgment.ets index 7fe09978d32180c20921249f108ba7cdcd3eea11..65ce20fddcdcb02a9f4cfa54fc92aafdea6934c7 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 916e1b51ca421151b76bc22d2ee1aa9b32f60213..920de865a7bf8abad43c5dda169887cb74d79938 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 c198972221d4d346f4dde0fe036a3063555b2754..7145a50507beed4836a0eebfd568eacf2a450d36 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 e48cf9a99b2e3b05e8a7816bda0738a37d257d25..ca88f857e960b437dcf767c0ac40be998c8f1236 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 8bbbd750c94aad92eee85fa254a6b36667be9a91..796cf7f898e1eab3f91e4b33bfa2bc582fe3a560 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 a3c218b7b22380ea1dc4fdd6c6b1353462bb2ec7..c3d33e531ccd89abf012408dcd79eff047a1c31a 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 4e6b76262c18f4311735b63c041db527415e7491..e729a7c2c33e0c93df578af5602395f62ff99b07 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 4fc44d8a3c257a8f336c85a17edce0306d0745b6..1f92c538cd5688b2fadd03034e6f073f0b789851 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 91f5b61ed193b5db1f2d82123a53ba9fe017a31c..ca88f857e960b437dcf767c0ac40be998c8f1236 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 3325f1bdd99c47feb42c89a27bb2d2255338121a..337d1600c68dd251a1f27b9d96ffb214dcfdf69f --- 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 17f26fd8dcbe4b296c8ad46a6dbf16de2323964d..7d56ee5afdf8f7d33dc5624dcf3c823daece3e83 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 295af0943a99c5d99568ab2f2bae99ac55c17fa7..bda0908dba95e9ecf61d0584931495ee7fa10762 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 c75509e775c31d463f6997a7c8d8ac7ee81ec2bd..ca88f857e960b437dcf767c0ac40be998c8f1236 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 4aa7a4bbf12a582e7ae13712ed83c712f8d96b2d..80f88726e3970aa7134f5f3cd8df012624cb6668 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 625afb93e1e3f253b76950465544c88637ab6973..c422eb1668d691782bb71b25d6c92490f9d6ce38 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 496fe91c554cc5de1e7fafcb58c00041a11234a9..bc8146310144db009331d834e1601f295b703c2b 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.args.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.args.json index e2b903f0aa82e6ca4108ff67d5272bf49d6c2a5b..571ee6bb76b0cad72a9443db47c2f9d7db474bd0 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.arkts2.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.arkts2.json index 4ce217d61eb50c1edbeaeda10aea16054d519d78..0d056023ed8e8713385e538bf7503c5f56f868ac 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.autofix.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.autofix.json new file mode 100644 index 0000000000000000000000000000000000000000..8b8b4fe079c2d73f6205158b607ca2de110deb0d --- /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.json b/ets2panda/linter/test/interop/interop_import_js_compare.ets.json index 25d2c46ecd313256af4ef2245da60133617674c2..e28baca176a2b17f328386775efec64717650b4b 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_compare.ets.migrate.ets b/ets2panda/linter/test/interop/interop_import_js_compare.ets.migrate.ets new file mode 100644 index 0000000000000000000000000000000000000000..76633c942c13423af8c35e3e8fc2b0ff3cf00257 --- /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 0000000000000000000000000000000000000000..0ccdec1005fc3e20d0bdcd40db886bc6f12e3e3a --- /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_index.ets b/ets2panda/linter/test/interop/interop_import_js_index.ets index daf1403ab2b8397e96835718602982113a32a281..ba165c68fd4258b7e047a289c58eed272e3bfd20 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 01e50a4c695af769ff96c170ff87134ac1086f5e..2e7b935be026ffdf75ab6895f00830039391514d 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": "", @@ -111,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 f5e605ca862cb81d76bd021611bd3a80d07b6efc..392ce7c30ef07b6845b963a0ef07362e72b598b8 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 } ], 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 5619e69d7898491f1269e2a8a45cc426ed25574a..ca88f857e960b437dcf767c0ac40be998c8f1236 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 65d9325e8baee8c6496caf7282ec5ef05eaaf771..d521cdc8aa40506062036b0e1fc80ee42359fd93 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 957ef0239d9624c92e24c298a3c7b6e3b2d549ac..d12c3ee91bfba4abfa2d6e26e7d64639010efeba 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 3b88109fc29630d3e6a092967366596f836c6936..d4c110abcf06cbcf3e2626c2640c866038692d3e 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets @@ -27,6 +27,7 @@ import { ff4 } from "./interop_import_js_rules_js" 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) {} @@ -65,3 +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 eb568c3a7ca351a70a508b37ab0cbed3ce539b5c..2fdc4e604ec7c6f910fa33f4722bf2ac4ae60ca8 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 @@ -175,19 +175,29 @@ "severity": "ERROR" }, { - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15, - "problem": "InteropObjectProperty", + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 54, + "problem": "ImportAfterStatement", "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "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", + "suggest": "", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", "severity": "ERROR" }, { - "line": 31, + "line": 32, "column": 5, - "endLine": 31, + "endLine": 32, "endColumn": 15, "problem": "InteropJsObjectConditionJudgment", "suggest": "", @@ -195,9 +205,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11, "problem": "InterOpImportJsDataCompare", "suggest": "", @@ -205,19 +215,9 @@ "severity": "ERROR" }, { - "line": 33, - "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, + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11, "problem": "InteropJsObjectConditionJudgment", "suggest": "", @@ -225,9 +225,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 14, - "endLine": 33, + "endLine": 34, "endColumn": 16, "problem": "NumericSemantics", "suggest": "", @@ -235,9 +235,9 @@ "severity": "ERROR" }, { - "line": 37, + "line": 38, "column": 1, - "endLine": 37, + "endLine": 38, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -245,9 +245,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 42, "column": 1, - "endLine": 41, + "endLine": 42, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -255,29 +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)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 3, - "endLine": 44, - "endColumn": 8, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", + "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": "", @@ -285,9 +275,9 @@ "severity": "ERROR" }, { - "line": 45, + "line": 46, "column": 3, - "endLine": 47, + "endLine": 48, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -295,9 +285,9 @@ "severity": "ERROR" }, { - "line": 49, + "line": 50, "column": 11, - "endLine": 49, + "endLine": 50, "endColumn": 18, "problem": "InteropObjectProperty", "suggest": "", @@ -305,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": "", @@ -335,9 +305,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 10, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -345,9 +315,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 14, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -355,9 +325,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "RuntimeArrayCheck", "suggest": "", @@ -365,9 +335,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -375,9 +345,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InterOpImportJsIndex", "suggest": "", @@ -385,9 +355,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9, "problem": "InteropJsObjectTraverseJsInstance", "suggest": "", @@ -395,9 +365,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "InterOpImportJsIndex", "suggest": "", @@ -405,9 +375,9 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 12, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "NumericSemantics", "suggest": "", @@ -415,19 +385,19 @@ "severity": "ERROR" }, { - "line": 63, - "column": 1, - "endLine": 63, - "endColumn": 13, + "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" + "severity": "WARNING" }, { - "line": 63, + "line": 64, "column": 1, - "endLine": 63, + "endLine": 64, "endColumn": 13, "problem": "CallJSFunction", "suggest": "", @@ -435,19 +405,19 @@ "severity": "ERROR" }, { - "line": 64, - "column": 1, - "endLine": 64, - "endColumn": 15, + "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" + "severity": "WARNING" }, { - "line": 64, + "line": 65, "column": 1, - "endLine": 64, + "endLine": 65, "endColumn": 15, "problem": "CallJSFunction", "suggest": "", @@ -455,9 +425,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 9, - "endLine": 66, + "endLine": 67, "endColumn": 15, "problem": "NumericSemantics", "suggest": "", @@ -465,9 +435,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 13, - "endLine": 66, + "endLine": 67, "endColumn": 14, "problem": "NumericSemantics", "suggest": "", @@ -475,9 +445,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 16, - "endLine": 66, + "endLine": 67, "endColumn": 21, "problem": "NumericSemantics", "suggest": "", @@ -485,9 +455,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 19, - "endLine": 66, + "endLine": 67, "endColumn": 20, "problem": "NumericSemantics", "suggest": "", @@ -495,9 +465,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 22, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "suggest": "", @@ -505,9 +475,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 25, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "suggest": "", @@ -515,24 +485,104 @@ "severity": "ERROR" }, { - "line": 67, + "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": 67, + "endLine": 68, "endColumn": 16, + "problem": "CallJSFunction", + "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": 67, + "line": 80, "column": 1, - "endLine": 67, - "endColumn": 16, + "endLine": 80, + "endColumn": 14, + "problem": "CallJSFunction", + "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", "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", + "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", + "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" + }, + { + "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 5c76ef828f057981a9d0bdf727f05cbf2899e23a..415bd82dc4208d62065c844da75ccded6a6495fd 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,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, @@ -41,8 +41,8 @@ "endColumn": 51 }, { - "start": 1038, - "end": 1038, + "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, @@ -81,8 +81,8 @@ "endColumn": 56 }, { - "start": 1038, - "end": 1038, + "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, @@ -121,8 +121,8 @@ "endColumn": 49 }, { - "start": 1038, - "end": 1038, + "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, @@ -161,8 +161,8 @@ "endColumn": 49 }, { - "start": 1038, - "end": 1038, + "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, @@ -201,8 +201,8 @@ "endColumn": 51 }, { - "start": 1038, - "end": 1038, + "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, @@ -241,8 +241,8 @@ "endColumn": 51 }, { - "start": 1038, - "end": 1038, + "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, @@ -281,8 +281,8 @@ "endColumn": 54 }, { - "start": 1038, - "end": 1038, + "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, @@ -321,8 +321,8 @@ "endColumn": 54 }, { - "start": 1038, - "end": 1038, + "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, @@ -335,40 +335,59 @@ "severity": "ERROR" }, { - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15, - "problem": "InteropObjectProperty", + "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": [ { - "start": 1044, - "end": 1054, - "replacementText": "foo.getPropertyByName(\"isGood\")", - "line": 31, - "column": 5, - "endLine": 31, - "endColumn": 15 + "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": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", "severity": "ERROR" }, { - "line": 31, + "line": 32, "column": 5, - "endLine": 31, + "endLine": 32, "endColumn": 15, "problem": "InteropJsObjectConditionJudgment", "autofix": [ { "replacementText": "foo.getPropertyByName('isGood').toBoolean()", - "start": 1044, - "end": 1054, - "line": 31, + "start": 1098, + "end": 1108, + "line": 32, "column": 5, - "endLine": 31, + "endLine": 32, "endColumn": 15 } ], @@ -377,50 +396,40 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 5, - "endLine": 33, + "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" - }, - { - "line": 33, - "column": 5, - "endLine": 33, - "endColumn": 11, - "problem": "InteropObjectProperty", "autofix": [ { - "start": 1064, - "end": 1070, - "replacementText": "ff1.getPropertyByName(\"f1\")", - "line": 33, + "start": 1118, + "end": 1124, + "replacementText": "ff1.getPropertyByName(\"f1\").toNumber()", + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11 } ], "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": 33, + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11, "problem": "InteropJsObjectConditionJudgment", "autofix": [ { "replacementText": "ff1.getPropertyByName('f1').toNumber()", - "start": 1064, - "end": 1070, - "line": 33, + "start": 1118, + "end": 1124, + "line": 34, "column": 5, - "endLine": 33, + "endLine": 34, "endColumn": 11 } ], @@ -429,19 +438,19 @@ "severity": "ERROR" }, { - "line": 33, + "line": 34, "column": 14, - "endLine": 33, + "endLine": 34, "endColumn": 16, "problem": "NumericSemantics", "autofix": [ { - "start": 1073, - "end": 1075, + "start": 1127, + "end": 1129, "replacementText": "18.0", - "line": 33, + "line": 34, "column": 14, - "endLine": 33, + "endLine": 34, "endColumn": 16 } ], @@ -450,9 +459,9 @@ "severity": "ERROR" }, { - "line": 37, + "line": 38, "column": 1, - "endLine": 37, + "endLine": 38, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -460,9 +469,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 42, "column": 1, - "endLine": 41, + "endLine": 42, "endColumn": 21, "problem": "InteropJsObjectInheritance", "suggest": "", @@ -470,39 +479,40 @@ "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)", - "severity": "ERROR" - }, - { - "line": 44, - "column": 3, - "endLine": 44, - "endColumn": 8, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", + "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", + "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" }, { - "line": 45, + "line": 46, "column": 3, - "endLine": 47, + "endLine": 48, "endColumn": 2, "problem": "TsLikeCatchType", "suggest": "", @@ -510,72 +520,30 @@ "severity": "ERROR" }, { - "line": 49, + "line": 50, "column": 11, - "endLine": 49, + "endLine": 50, "endColumn": 18, "problem": "InteropObjectProperty", "autofix": [ { - "start": 1290, - "end": 1297, + "start": 1344, + "end": 1351, "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": [ - { - "replacementText": "ff3.getPropertyByName('arr')", - "start": 1290, - "end": 1297, - "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": [ - { - "replacementText": "arr.getPropertyByName('length').toNumber()", - "start": 1308, - "end": 1328, "line": 50, "column": 11, "endLine": 50, - "endColumn": 21 + "endColumn": 18 } ], "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": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9, "problem": "RuntimeArrayCheck", "suggest": "", @@ -583,19 +551,19 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 10, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "autofix": [ { - "start": 1338, - "end": 1343, + "start": 1392, + "end": 1397, "replacementText": "i: number = 0", - "line": 51, + "line": 52, "column": 10, - "endLine": 51, + "endLine": 52, "endColumn": 15 } ], @@ -604,19 +572,19 @@ "severity": "ERROR" }, { - "line": 51, + "line": 52, "column": 14, - "endLine": 51, + "endLine": 52, "endColumn": 15, "problem": "NumericSemantics", "autofix": [ { - "start": 1342, - "end": 1343, + "start": 1396, + "end": 1397, "replacementText": "0.0", - "line": 51, + "line": 52, "column": 14, - "endLine": 51, + "endLine": 52, "endColumn": 15 } ], @@ -625,9 +593,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "RuntimeArrayCheck", "suggest": "", @@ -635,19 +603,19 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InteropJsObjectTraverseJsInstance", "autofix": [ { "replacementText": "arr.getPropertyByIndex(i).toNumber()", - "start": 1371, - "end": 1377, - "line": 52, + "start": 1425, + "end": 1431, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17 } ], @@ -656,19 +624,19 @@ "severity": "ERROR" }, { - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17, "problem": "InterOpImportJsIndex", "autofix": [ { - "start": 1371, - "end": 1377, + "start": 1425, + "end": 1431, "replacementText": "arr.getPropertyByIndex(i)", - "line": 52, + "line": 53, "column": 11, - "endLine": 52, + "endLine": 53, "endColumn": 17 } ], @@ -677,19 +645,19 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9, "problem": "InteropJsObjectTraverseJsInstance", "autofix": [ { "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", - "start": 1380, - "end": 1390, - "line": 53, + "start": 1434, + "end": 1444, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 9 } ], @@ -698,19 +666,19 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "InterOpImportJsIndex", "autofix": [ { - "start": 1380, - "end": 1390, + "start": 1434, + "end": 1444, "replacementText": "arr.setPropertyByIndex(i, ESValue.wrap(0))", - "line": 53, + "line": 54, "column": 3, - "endLine": 53, + "endLine": 54, "endColumn": 13 } ], @@ -719,19 +687,19 @@ "severity": "ERROR" }, { - "line": 53, + "line": 54, "column": 12, - "endLine": 53, + "endLine": 54, "endColumn": 13, "problem": "NumericSemantics", "autofix": [ { - "start": 1389, - "end": 1390, + "start": 1443, + "end": 1444, "replacementText": "0.0", - "line": 53, + "line": 54, "column": 12, - "endLine": 53, + "endLine": 54, "endColumn": 13 } ], @@ -740,59 +708,81 @@ "severity": "ERROR" }, { - "line": 63, - "column": 1, - "endLine": 63, - "endColumn": 13, + "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" + "severity": "WARNING" }, { - "line": 63, + "line": 64, "column": 1, - "endLine": 63, + "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" }, { - "line": 64, - "column": 1, - "endLine": 64, - "endColumn": 15, + "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" + "severity": "WARNING" }, { - "line": 64, + "line": 65, "column": 1, - "endLine": 64, + "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" }, { - "line": 66, + "line": 67, "column": 9, - "endLine": 66, + "endLine": 67, "endColumn": 15, "problem": "NumericSemantics", "autofix": [ { - "start": 1528, - "end": 1534, + "start": 1582, + "end": 1588, "replacementText": "a: number = 1;", - "line": 66, + "line": 67, "column": 9, - "endLine": 66, + "endLine": 67, "endColumn": 15 } ], @@ -801,19 +791,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 13, - "endLine": 66, + "endLine": 67, "endColumn": 14, "problem": "NumericSemantics", "autofix": [ { - "start": 1532, - "end": 1533, + "start": 1586, + "end": 1587, "replacementText": "1.0", - "line": 66, + "line": 67, "column": 13, - "endLine": 66, + "endLine": 67, "endColumn": 14 } ], @@ -822,19 +812,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 16, - "endLine": 66, + "endLine": 67, "endColumn": 21, "problem": "NumericSemantics", "autofix": [ { - "start": 1535, - "end": 1540, + "start": 1589, + "end": 1594, "replacementText": "b: number = 2;", - "line": 66, + "line": 67, "column": 16, - "endLine": 66, + "endLine": 67, "endColumn": 21 } ], @@ -843,19 +833,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 19, - "endLine": 66, + "endLine": 67, "endColumn": 20, "problem": "NumericSemantics", "autofix": [ { - "start": 1538, - "end": 1539, + "start": 1592, + "end": 1593, "replacementText": "2.0", - "line": 66, + "line": 67, "column": 19, - "endLine": 66, + "endLine": 67, "endColumn": 20 } ], @@ -864,19 +854,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 22, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "autofix": [ { - "start": 1541, - "end": 1545, + "start": 1595, + "end": 1599, "replacementText": "c: number = 3;", - "line": 66, + "line": 67, "column": 22, - "endLine": 66, + "endLine": 67, "endColumn": 26 } ], @@ -885,19 +875,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 67, "column": 25, - "endLine": 66, + "endLine": 67, "endColumn": 26, "problem": "NumericSemantics", "autofix": [ { - "start": 1544, - "end": 1545, + "start": 1598, + "end": 1599, "replacementText": "3.0", - "line": 66, + "line": 67, "column": 25, - "endLine": 66, + "endLine": 67, "endColumn": 26 } ], @@ -906,24 +896,170 @@ "severity": "ERROR" }, { - "line": 67, + "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": 67, + "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": 67, + "line": 80, "column": 1, - "endLine": 67, - "endColumn": 16, + "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" + }, + { + "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" } ] -} +} \ 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 a3db4edec87910df49c7a5933852334694aba188..ab212bc3f3999cd0aab878e852fd6fdaad9d1c5f 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules.ets.json +++ b/ets2panda/linter/test/interop/interop_import_js_rules.ets.json @@ -1,98 +1,108 @@ { - "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": 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": 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": 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": 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": 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": 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": 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" - } - ] + "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": 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": 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": 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": 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": 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": 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": 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": 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" + } + ] } diff --git a/ets2panda/linter/test/interop/interop_import_js_rules_js.js b/ets2panda/linter/test/interop/interop_import_js_rules_js.js index b22008ced0af8c81e43f4a6b8a358eb8db68046b..cef219665e794ef06e76275a89ed5e52a93e67b3 100644 --- a/ets2panda/linter/test/interop/interop_import_js_rules_js.js +++ b/ets2panda/linter/test/interop/interop_import_js_rules_js.js @@ -35,3 +35,9 @@ export function expand(obj) { let x = obj; let {a, b, c} = obj; } + +export let orange = { + isFruit: true, + isVegetable: false, + isVegetable1: 123 +} 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 eeb6eba253a044d2b496febe2251a3a8f4a1e59d..b8941c7ac57d8a483e829d2f30ae7460555a8495 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets @@ -13,7 +13,6 @@ * 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'; @@ -36,16 +35,16 @@ let person:Person = new Person(); let name =person.name let name2 =person.getName() function getPersonInfo(){ - typeof person; - typeof person.getName(); - typeof name2; - typeof name; - typeof person.setAge(111); - typeof person; - typeof new Person(); //error + typeof person; + typeof person.getName(); + typeof name2; + typeof name; + typeof person.setAge(111); + typeof person; + typeof new Person(); //error } -const age = typeof person.setAge(111); +const age = typeof person.setAge(111); let person2 = typeof person class Object { code: string = "www" 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 0689065be94d05900a62fa395381b6fc841334e0..0d41c5dd8444c533a3ec0c42448f24130efccc3f --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.arkts2.json @@ -15,20 +15,20 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 69, - "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": 69, + "endColumn": 54, "problem": "InterOpImportJs", "suggest": "", "rule": "Importing directly from \"JS\" module is not supported (arkts-interop-js2s-import-js)", @@ -38,36 +38,6 @@ "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": "", @@ -75,9 +45,9 @@ "severity": "ERROR" }, { - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 15, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -86,38 +56,8 @@ }, { "line": 21, - "column": 8, - "endLine": 21, - "endColumn": 15, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 8, - "endLine": 21, - "endColumn": 15, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 11, - "endLine": 22, - "endColumn": 18, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 22, "column": 11, - "endLine": 22, + "endLine": 21, "endColumn": 18, "problem": "CallJSFunction", "suggest": "", @@ -125,9 +65,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 11, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -135,9 +75,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 19, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -145,9 +85,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 8, - "endLine": 25, + "endLine": 24, "endColumn": 19, "problem": "LimitedVoidType", "suggest": "", @@ -156,28 +96,8 @@ }, { "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 26, "column": 1, - "endLine": 26, + "endLine": 25, "endColumn": 20, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -185,9 +105,9 @@ "severity": "ERROR" }, { - "line": 26, + "line": 25, "column": 8, - "endLine": 26, + "endLine": 25, "endColumn": 20, "problem": "LimitedVoidType", "suggest": "", @@ -196,28 +116,8 @@ }, { "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 27, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 12, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -225,9 +125,9 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 17, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -236,28 +136,8 @@ }, { "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, + "endLine": 28, "endColumn": 12, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -265,9 +145,9 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 11, - "endLine": 30, + "endLine": 29, "endColumn": 20, "problem": "InteropObjectProperty", "suggest": "", @@ -275,19 +155,9 @@ "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, + "line": 31, "column": 23, - "endLine": 32, + "endLine": 31, "endColumn": 35, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -295,9 +165,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 1, - "endLine": 33, + "endLine": 32, "endColumn": 20, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -305,9 +175,9 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 8, - "endLine": 33, + "endLine": 32, "endColumn": 20, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -315,9 +185,9 @@ "severity": "ERROR" }, { - "line": 35, + "line": 34, "column": 21, - "endLine": 35, + "endLine": 34, "endColumn": 33, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -326,18 +196,8 @@ }, { "line": 36, - "column": 11, - "endLine": 36, - "endColumn": 22, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 37, "column": 12, - "endLine": 37, + "endLine": 36, "endColumn": 28, "problem": "InteropCallObjectMethods", "suggest": "", @@ -345,69 +205,49 @@ "severity": "ERROR" }, { - "line": 40, - "column": 12, - "endLine": 40, + "line": 42, + "column": 10, + "endLine": 42, "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": 12, - "endLine": 43, - "endColumn": 30, "problem": "LimitedVoidType", "suggest": "", "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, { - "line": 43, - "column": 12, - "endLine": 43, - "endColumn": 30, - "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": 26, - "endLine": 43, - "endColumn": 29, + "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": 45, - "column": 5, - "endLine": 45, - "endColumn": 24, + "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": 45, - "column": 12, - "endLine": 45, - "endColumn": 24, + "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": 48, + "line": 47, "column": 21, - "endLine": 48, + "endLine": 47, "endColumn": 39, "problem": "LimitedVoidType", "suggest": "", @@ -415,19 +255,9 @@ "severity": "ERROR" }, { - "line": 48, - "column": 21, - "endLine": 48, - "endColumn": 39, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 48, + "line": 47, "column": 35, - "endLine": 48, + "endLine": 47, "endColumn": 38, "problem": "NumericSemantics", "suggest": "", @@ -435,9 +265,9 @@ "severity": "ERROR" }, { - "line": 50, + "line": 49, "column": 7, - "endLine": 50, + "endLine": 49, "endColumn": 13, "problem": "InvalidIdentifier", "suggest": "", @@ -445,9 +275,9 @@ "severity": "ERROR" }, { - "line": 62, + "line": 61, "column": 5, - "endLine": 62, + "endLine": 61, "endColumn": 21, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -455,29 +285,9 @@ "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, + "line": 65, "column": 28, - "endLine": 66, + "endLine": 65, "endColumn": 47, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -485,9 +295,9 @@ "severity": "ERROR" }, { - "line": 66, + "line": 65, "column": 35, - "endLine": 66, + "endLine": 65, "endColumn": 47, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -495,9 +305,9 @@ "severity": "ERROR" }, { - "line": 70, + "line": 69, "column": 1, - "endLine": 70, + "endLine": 69, "endColumn": 13, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -505,9 +315,9 @@ "severity": "ERROR" }, { - "line": 71, + "line": 70, "column": 1, - "endLine": 71, + "endLine": 70, "endColumn": 25, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -515,29 +325,9 @@ "severity": "ERROR" }, { - "line": 71, - "column": 8, - "endLine": 71, - "endColumn": 25, - "problem": "InteropObjectProperty", - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "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, + "line": 70, "column": 8, - "endLine": 71, + "endLine": 70, "endColumn": 20, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -545,9 +335,9 @@ "severity": "ERROR" }, { - "line": 72, + "line": 71, "column": 1, - "endLine": 72, + "endLine": 71, "endColumn": 30, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -555,29 +345,9 @@ "severity": "ERROR" }, { - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 30, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 30, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 72, + "line": 71, "column": 8, - "endLine": 72, + "endLine": 71, "endColumn": 20, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -585,9 +355,9 @@ "severity": "ERROR" }, { - "line": 73, + "line": 72, "column": 1, - "endLine": 73, + "endLine": 72, "endColumn": 31, "problem": "InterOpImportJsForTypeOf", "suggest": "", @@ -595,9 +365,9 @@ "severity": "ERROR" }, { - "line": 73, + "line": 72, "column": 8, - "endLine": 73, + "endLine": 72, "endColumn": 31, "problem": "LimitedVoidType", "suggest": "", @@ -605,29 +375,9 @@ "severity": "ERROR" }, { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 31, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 31, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 73, + "line": 72, "column": 8, - "endLine": 73, + "endLine": 72, "endColumn": 20, "problem": "InstantiatedJsOjbect", "suggest": "", @@ -635,9 +385,9 @@ "severity": "ERROR" }, { - "line": 73, + "line": 72, "column": 28, - "endLine": 73, + "endLine": 72, "endColumn": 30, "problem": "NumericSemantics", "suggest": "", 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 360a6a5794cb2df663a9fccac83544b74916889b..f9f9b5c81454c42c3c524171aa8aa7a2597004e6 --- a/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json +++ b/ets2panda/linter/test/interop/interop_import_typeof_js.ets.autofix.json @@ -15,35 +15,29 @@ ], "result": [ { - "line": 17, + "line": 16, "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, + "endLine": 16, "endColumn": 69, "problem": "InterOpImportJs", "autofix": [ { - "start": 619, - "end": 687, + "start": 606, + "end": 674, "replacementText": "", - "line": 17, + "line": 16, "column": 1, - "endLine": 17, + "endLine": 16, "endColumn": 69 }, { - "start": 796, - "end": 796, - "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" + "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": "", @@ -51,35 +45,29 @@ "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, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 54, "problem": "InterOpImportJs", "autofix": [ { - "start": 688, - "end": 741, + "start": 675, + "end": 728, "replacementText": "", - "line": 18, + "line": 17, "column": 1, - "endLine": 18, + "endLine": 17, "endColumn": 54 }, { - "start": 796, - "end": 796, - "replacementText": "let GeneratedImportVar_2 = ESValue.load('./interop_import_js_js');\nlet Doge = GeneratedImportVar_2.getPropertyByName('Dog');\n" + "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": "", @@ -87,35 +75,29 @@ "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, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 55, "problem": "InterOpImportJs", "autofix": [ { - "start": 742, - "end": 796, + "start": 729, + "end": 783, "replacementText": "", - "line": 19, + "line": 18, "column": 1, - "endLine": 19, + "endLine": 18, "endColumn": 55 }, { - "start": 796, - "end": 796, - "replacementText": "let GeneratedImportVar_3 = ESValue.load('./interop_import_js_js');\nlet wiki = GeneratedImportVar_3.getPropertyByName('Wiki');\n" + "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": "", @@ -123,19 +105,19 @@ "severity": "ERROR" }, { - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 15, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 798, - "end": 812, + "start": 785, + "end": 799, "replacementText": "myAaa.invoke().typeOf()", - "line": 21, + "line": 20, "column": 1, - "endLine": 21, + "endLine": 20, "endColumn": 15 } ], @@ -145,58 +127,39 @@ }, { "line": 21, - "column": 8, - "endLine": 21, - "endColumn": 15, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 21, - "column": 8, - "endLine": 21, - "endColumn": 15, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 22, "column": 11, - "endLine": 22, - "endColumn": 18, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 11, - "endLine": 22, + "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": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 11, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 853, - "end": 863, + "start": 840, + "end": 850, "replacementText": "Dog.typeOf()", - "line": 24, + "line": 23, "column": 1, - "endLine": 24, + "endLine": 23, "endColumn": 11 } ], @@ -205,16 +168,20 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 1, - "endLine": 25, + "endLine": 24, "endColumn": 19, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 873, - "end": 891, - "replacementText": "Dog.invoke(ESValue.wrap('doge')).typeOf()" + "start": 860, + "end": 878, + "replacementText": "Dog.invoke(ESValue.wrap('doge')).typeOf()", + "line": 24, + "column": 1, + "endLine": 24, + "endColumn": 19 } ], "suggest": "", @@ -222,9 +189,9 @@ "severity": "ERROR" }, { - "line": 25, + "line": 24, "column": 8, - "endLine": 25, + "endLine": 24, "endColumn": 19, "problem": "LimitedVoidType", "suggest": "", @@ -233,35 +200,19 @@ }, { "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 25, - "column": 8, - "endLine": 25, - "endColumn": 19, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 26, "column": 1, - "endLine": 26, + "endLine": 25, "endColumn": 20, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 901, - "end": 920, - "replacementText": "Doge.invoke(ESValue.wrap('doge')).typeOf()" + "start": 888, + "end": 907, + "replacementText": "Doge.invoke(ESValue.wrap('doge')).typeOf()", + "line": 25, + "column": 1, + "endLine": 25, + "endColumn": 20 } ], "suggest": "", @@ -269,9 +220,9 @@ "severity": "ERROR" }, { - "line": 26, + "line": 25, "column": 8, - "endLine": 26, + "endLine": 25, "endColumn": 20, "problem": "LimitedVoidType", "suggest": "", @@ -280,38 +231,18 @@ }, { "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 26, - "column": 8, - "endLine": 26, - "endColumn": 20, - "problem": "CallJSFunction", - "suggest": "", - "rule": "ArkTS directly call JS functions or parameters is not supported (arkts-interop-js2s-call-js-func)", - "severity": "ERROR" - }, - { - "line": 27, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 12, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 930, - "end": 941, + "start": 917, + "end": 928, "replacementText": "Wiki.typeOf()", - "line": 27, + "line": 26, "column": 1, - "endLine": 27, + "endLine": 26, "endColumn": 12 } ], @@ -320,19 +251,19 @@ "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 17, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 950, - "end": 966, + "start": 937, + "end": 953, "replacementText": "Wiki.getPropertyByName('name').typeOf()", - "line": 28, + "line": 27, "column": 1, - "endLine": 28, + "endLine": 27, "endColumn": 17 } ], @@ -342,60 +273,18 @@ }, { "line": 28, - "column": 8, - "endLine": 28, - "endColumn": 17, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 957, - "end": 966, - "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": 957, - "end": 966, - "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, + "endLine": 28, "endColumn": 12, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 975, - "end": 986, + "start": 962, + "end": 973, "replacementText": "wiki.typeOf()", - "line": 29, + "line": 28, "column": 1, - "endLine": 29, + "endLine": 28, "endColumn": 12 } ], @@ -404,19 +293,19 @@ "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 11, - "endLine": 30, + "endLine": 29, "endColumn": 20, "problem": "InteropObjectProperty", "autofix": [ { - "start": 1005, - "end": 1014, + "start": 992, + "end": 1001, "replacementText": "wiki.getPropertyByName(\"name\")", - "line": 30, + "line": 29, "column": 11, - "endLine": 30, + "endLine": 29, "endColumn": 20 } ], @@ -425,40 +314,19 @@ "severity": "ERROR" }, { - "line": 30, - "column": 11, - "endLine": 30, - "endColumn": 20, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "wiki.getPropertyByName('name').toString()", - "start": 1005, - "end": 1014, - "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, + "line": 31, "column": 23, - "endLine": 32, + "endLine": 31, "endColumn": 35, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1049, - "end": 1061, + "start": 1036, + "end": 1048, "replacementText": "ClassA.instantiate()", - "line": 32, + "line": 31, "column": 23, - "endLine": 32, + "endLine": 31, "endColumn": 35 } ], @@ -467,19 +335,19 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 1, - "endLine": 33, + "endLine": 32, "endColumn": 20, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1062, - "end": 1081, + "start": 1049, + "end": 1068, "replacementText": "ClassA.instantiate().typeOf()", - "line": 33, + "line": 32, "column": 1, - "endLine": 33, + "endLine": 32, "endColumn": 20 } ], @@ -488,19 +356,19 @@ "severity": "ERROR" }, { - "line": 33, + "line": 32, "column": 8, - "endLine": 33, + "endLine": 32, "endColumn": 20, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1069, - "end": 1081, + "start": 1056, + "end": 1068, "replacementText": "ClassA.instantiate()", - "line": 33, + "line": 32, "column": 8, - "endLine": 33, + "endLine": 32, "endColumn": 20 } ], @@ -509,19 +377,19 @@ "severity": "ERROR" }, { - "line": 35, + "line": 34, "column": 21, - "endLine": 35, + "endLine": 34, "endColumn": 33, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1125, - "end": 1137, + "start": 1112, + "end": 1124, "replacementText": "Person.instantiate()", - "line": 35, + "line": 34, "column": 21, - "endLine": 35, + "endLine": 34, "endColumn": 33 } ], @@ -531,80 +399,50 @@ }, { "line": 36, - "column": 11, + "column": 12, "endLine": 36, - "endColumn": 22, - "problem": "InteropObjectProperty", + "endColumn": 28, + "problem": "InteropCallObjectMethods", "autofix": [ { - "start": 1149, - "end": 1160, - "replacementText": "person.getPropertyByName(\"name\")", + "start": 1159, + "end": 1175, + "replacementText": "person.invokeMethod(\"getName\")", "line": 36, - "column": 11, + "column": 12, "endLine": 36, - "endColumn": 22 + "endColumn": 28 } ], "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "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": 40, - "column": 12, - "endLine": 40, + "line": 42, + "column": 10, + "endLine": 42, "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": 12, - "endLine": 43, - "endColumn": 30, "problem": "LimitedVoidType", "suggest": "", "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, { - "line": 43, - "column": 12, - "endLine": 43, - "endColumn": 30, - "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": 26, - "endLine": 43, - "endColumn": 29, + "line": 42, + "column": 24, + "endLine": 42, + "endColumn": 27, "problem": "NumericSemantics", "autofix": [ { - "start": 1323, - "end": 1326, + "start": 1300, + "end": 1303, "replacementText": "111.0", - "line": 43, - "column": 26, - "endLine": 43, - "endColumn": 29 + "line": 42, + "column": 24, + "endLine": 42, + "endColumn": 27 } ], "suggest": "", @@ -612,20 +450,20 @@ "severity": "ERROR" }, { - "line": 45, - "column": 5, - "endLine": 45, - "endColumn": 24, + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 22, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1352, - "end": 1371, + "start": 1325, + "end": 1344, "replacementText": "Person.instantiate().typeOf()", - "line": 45, - "column": 5, - "endLine": 45, - "endColumn": 24 + "line": 44, + "column": 3, + "endLine": 44, + "endColumn": 22 } ], "suggest": "", @@ -633,20 +471,20 @@ "severity": "ERROR" }, { - "line": 45, - "column": 12, - "endLine": 45, - "endColumn": 24, + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 22, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1359, - "end": 1371, + "start": 1332, + "end": 1344, "replacementText": "Person.instantiate()", - "line": 45, - "column": 12, - "endLine": 45, - "endColumn": 24 + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 22 } ], "suggest": "", @@ -654,9 +492,9 @@ "severity": "ERROR" }, { - "line": 48, + "line": 47, "column": 21, - "endLine": 48, + "endLine": 47, "endColumn": 39, "problem": "LimitedVoidType", "suggest": "", @@ -664,29 +502,19 @@ "severity": "ERROR" }, { - "line": 48, - "column": 21, - "endLine": 48, - "endColumn": 39, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 48, + "line": 47, "column": 35, - "endLine": 48, + "endLine": 47, "endColumn": 38, "problem": "NumericSemantics", "autofix": [ { - "start": 1418, - "end": 1421, + "start": 1391, + "end": 1394, "replacementText": "111.0", - "line": 48, + "line": 47, "column": 35, - "endLine": 48, + "endLine": 47, "endColumn": 38 } ], @@ -695,9 +523,9 @@ "severity": "ERROR" }, { - "line": 50, + "line": 49, "column": 7, - "endLine": 50, + "endLine": 49, "endColumn": 13, "problem": "InvalidIdentifier", "suggest": "", @@ -705,19 +533,19 @@ "severity": "ERROR" }, { - "line": 62, + "line": 61, "column": 5, - "endLine": 62, + "endLine": 61, "endColumn": 21, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1729, - "end": 1745, + "start": 1701, + "end": 1717, "replacementText": "wiki.getPropertyByName('name').typeOf()", - "line": 62, + "line": 61, "column": 5, - "endLine": 62, + "endLine": 61, "endColumn": 21 } ], @@ -726,61 +554,19 @@ "severity": "ERROR" }, { - "line": 62, - "column": 12, - "endLine": 62, - "endColumn": 21, - "problem": "InteropObjectProperty", - "autofix": [ - { - "start": 1736, - "end": 1745, - "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": 1736, - "end": 1745, - "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, + "line": 65, "column": 28, - "endLine": 66, + "endLine": 65, "endColumn": 47, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1834, - "end": 1853, + "start": 1806, + "end": 1825, "replacementText": "ClassA.instantiate().typeOf()", - "line": 66, + "line": 65, "column": 28, - "endLine": 66, + "endLine": 65, "endColumn": 47 } ], @@ -789,19 +575,19 @@ "severity": "ERROR" }, { - "line": 66, + "line": 65, "column": 35, - "endLine": 66, + "endLine": 65, "endColumn": 47, "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1841, - "end": 1853, + "start": 1813, + "end": 1825, "replacementText": "ClassA.instantiate()", - "line": 66, + "line": 65, "column": 35, - "endLine": 66, + "endLine": 65, "endColumn": 47 } ], @@ -810,19 +596,19 @@ "severity": "ERROR" }, { - "line": 70, + "line": 69, "column": 1, - "endLine": 70, + "endLine": 69, "endColumn": 13, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1874, - "end": 1886, + "start": 1846, + "end": 1858, "replacementText": "myAaa.typeOf()", - "line": 70, + "line": 69, "column": 1, - "endLine": 70, + "endLine": 69, "endColumn": 13 } ], @@ -831,19 +617,19 @@ "severity": "ERROR" }, { - "line": 71, + "line": 70, "column": 1, - "endLine": 71, + "endLine": 70, "endColumn": 25, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1896, - "end": 1920, + "start": 1868, + "end": 1892, "replacementText": "Person.instantiate().getPropertyByName('name').typeOf()", - "line": 71, + "line": 70, "column": 1, - "endLine": 71, + "endLine": 70, "endColumn": 25 } ], @@ -852,45 +638,45 @@ "severity": "ERROR" }, { - "line": 71, + "line": 70, "column": 8, - "endLine": 71, - "endColumn": 25, - "problem": "InteropObjectProperty", + "endLine": 70, + "endColumn": 20, + "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1903, - "end": 1920, - "replacementText": "new Person().getPropertyByName(\"name\")", - "line": 71, + "start": 1875, + "end": 1887, + "replacementText": "Person.instantiate()", + "line": 70, "column": 8, - "endLine": 71, - "endColumn": 25 + "endLine": 70, + "endColumn": 20 } ], "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", + "rule": "ArkTS directly instantiated JS objects is not supported (arkts-interop-js2s-create-js-instance)", "severity": "ERROR" }, { "line": 71, - "column": 8, + "column": 1, "endLine": 71, - "endColumn": 25, - "problem": "InteropJsObjectUsage", + "endColumn": 30, + "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "replacementText": "new Person().getPropertyByName('name').toString()", - "start": 1903, - "end": 1920, + "start": 1902, + "end": 1931, + "replacementText": "Person.instantiate().invokeMethod(\"getName\").typeOf()", "line": 71, - "column": 8, + "column": 1, "endLine": 71, - "endColumn": 25 + "endColumn": 30 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "The \"typeof\" expression can't be used with interop JS objects (arkts-interop-js2s-typeof-js-type)", "severity": "ERROR" }, { @@ -901,8 +687,8 @@ "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1903, - "end": 1915, + "start": 1909, + "end": 1921, "replacementText": "Person.instantiate()", "line": 71, "column": 8, @@ -918,17 +704,17 @@ "line": 72, "column": 1, "endLine": 72, - "endColumn": 30, + "endColumn": 31, "problem": "InterOpImportJsForTypeOf", "autofix": [ { - "start": 1930, - "end": 1959, - "replacementText": "Person.instantiate().getPropertyByName('getName').invoke().typeOf()", + "start": 1940, + "end": 1970, + "replacementText": "Person.instantiate().invokeMethod(\"setAge\", ESValue.wrap(22)).typeOf()", "line": 72, "column": 1, "endLine": 72, - "endColumn": 30 + "endColumn": 31 } ], "suggest": "", @@ -939,20 +725,10 @@ "line": 72, "column": 8, "endLine": 72, - "endColumn": 30, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 72, - "column": 8, - "endLine": 72, - "endColumn": 30, - "problem": "InteropCallObjectMethods", + "endColumn": 31, + "problem": "LimitedVoidType", "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", + "rule": "Type \"void\" has no instances.(arkts-limited-void-type)", "severity": "ERROR" }, { @@ -963,8 +739,8 @@ "problem": "InstantiatedJsOjbect", "autofix": [ { - "start": 1937, - "end": 1949, + "start": 1947, + "end": 1959, "replacementText": "Person.instantiate()", "line": 72, "column": 8, @@ -977,87 +753,19 @@ "severity": "ERROR" }, { - "line": 73, - "column": 1, - "endLine": 73, - "endColumn": 31, - "problem": "InterOpImportJsForTypeOf", - "autofix": [ - { - "start": 1968, - "end": 1998, - "replacementText": "Person.instantiate().getPropertyByName('setAge').invoke(ESValue.wrap(22)).typeOf()" - } - ], - "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": 31, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 31, - "problem": "InteropCallObjectMethods", - "suggest": "", - "rule": "Calling methods of JS Object directly in interop is not allowed (arkts-interop-js2s-call-js-method)", - "severity": "ERROR" - }, - { - "line": 73, - "column": 8, - "endLine": 73, - "endColumn": 20, - "problem": "InstantiatedJsOjbect", - "autofix": [ - { - "start": 1975, - "end": 1987, - "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, + "line": 72, "column": 28, - "endLine": 73, + "endLine": 72, "endColumn": 30, "problem": "NumericSemantics", "autofix": [ { - "start": 1995, - "end": 1997, + "start": 1967, + "end": 1969, "replacementText": "22.0", - "line": 73, + "line": 72, "column": 28, - "endLine": 73, + "endLine": 72, "endColumn": 30 } ], 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 b61974a218a0379e953f24d569b9397beafd431a..ca88f857e960b437dcf767c0ac40be998c8f1236 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 59463414d2e4d40608f09d277d36fe666ba744bd..71c8bd394670f9d6baad57f261111a5083b672a7 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 @@ -13,7 +13,6 @@ * limitations under the License. */ -'use static' let GeneratedImportVar_3 = ESValue.load('./interop_import_js_js'); @@ -29,7 +28,7 @@ let Wiki = GeneratedImportVar_1.getPropertyByName('Wiki'); myAaa.invoke().typeOf(); //error -let fun = myAaa(); +let fun = myAaa.invoke(); typeof fun; Dog.typeOf(); //error Dog.invoke(ESValue.wrap('doge')).typeOf(); //error @@ -43,19 +42,19 @@ const aClass:ClassA = ClassA.instantiate() ClassA.instantiate().typeOf() //error typeof aClass; let person:Person = Person.instantiate(); -let name =person.getPropertyByName("name") -let name2 =person.getName() +let name =person.name +let name2 =person.invokeMethod("getName") function getPersonInfo(){ - typeof person; - typeof person.getName(); - typeof name2; - typeof name; - typeof person.setAge(111.0); - typeof person; - Person.instantiate().typeOf(); //error + typeof person; + typeof person.getName(); + typeof name2; + typeof name; + typeof person.setAge(111.0); + typeof person; + Person.instantiate().typeOf(); //error } -const age = typeof person.setAge(111.0); +const age = typeof person.setAge(111.0); let person2 = typeof person class Object { code: string = "www" @@ -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 ba16f9d3073df377c8f4b32fff3d875826ff1f40..221ab454949758144537fe7b13407a4f511890ed 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 @@ -14,11 +14,21 @@ "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": 66, + "endColumn": 58, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -28,7 +38,7 @@ "line": 20, "column": 5, "endLine": 20, - "endColumn": 58, + "endColumn": 66, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -38,7 +48,7 @@ "line": 21, "column": 5, "endLine": 21, - "endColumn": 66, + "endColumn": 57, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -48,7 +58,7 @@ "line": 22, "column": 5, "endLine": 22, - "endColumn": 57, + "endColumn": 66, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -58,7 +68,7 @@ "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)", @@ -68,7 +78,7 @@ "line": 24, "column": 5, "endLine": 24, - "endColumn": 58, + "endColumn": 62, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -78,7 +88,7 @@ "line": 25, "column": 5, "endLine": 25, - "endColumn": 62, + "endColumn": 56, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -88,7 +98,7 @@ "line": 26, "column": 5, "endLine": 26, - "endColumn": 56, + "endColumn": 62, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", @@ -98,16 +108,6 @@ "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": "", @@ -115,19 +115,19 @@ "severity": "ERROR" }, { - "line": 32, + "line": 31, "column": 5, - "endLine": 32, - "endColumn": 18, + "endLine": 31, + "endColumn": 25, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, { - "line": 40, + "line": 39, "column": 5, - "endLine": 40, + "endLine": 39, "endColumn": 41, "problem": "AnyType", "suggest": "", @@ -135,29 +135,29 @@ "severity": "ERROR" }, { - "line": 46, + "line": 45, "column": 5, - "endLine": 46, - "endColumn": 43, + "endLine": 45, + "endColumn": 22, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, { - "line": 47, + "line": 46, "column": 5, - "endLine": 47, - "endColumn": 28, + "endLine": 46, + "endColumn": 42, "problem": "AnyType", "suggest": "", "rule": "Use explicit types instead of \"any\", \"unknown\" (arkts-no-any-unknown)", "severity": "ERROR" }, { - "line": 60, + "line": 59, "column": 7, - "endLine": 60, + "endLine": 59, "endColumn": 13, "problem": "InvalidIdentifier", "suggest": "", @@ -165,4 +165,4 @@ "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 70554e5a8f408495ef89c1f78df89a93c90820b2..ad6fbcab7df3ac3917d11ae32b41a1cc05091219 --- a/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets +++ b/ets2panda/linter/test/interop/interop_not_have_property_arkts2.ets @@ -12,11 +12,11 @@ * 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" foo.name foo.name = "456" person.age = 23 -person.male = [2, 3] \ No newline at end of file +person.male = [2, 3] +foo.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 old mode 100755 new mode 100644 index f46b7b42fb49192a0c1bc401550cf11175318230..cb366b21c4bd6e8660ffc56660b9a0d3d0e15370 --- 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,17 +38,17 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 9, - "problem": "InteropJsObjectUsage", + "endColumn": 17, + "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": 1, "endLine": 20, - "endColumn": 17, + "endColumn": 16, "problem": "InteropObjectProperty", "suggest": "", "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", @@ -66,19 +56,19 @@ }, { "line": 20, - "column": 1, + "column": 14, "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", + "endColumn": 16, + "problem": "NumericSemantics", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { "line": 21, "column": 1, "endLine": 21, - "endColumn": 16, + "endColumn": 21, "problem": "InteropObjectProperty", "suggest": "", "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", @@ -86,19 +76,19 @@ }, { "line": 21, - "column": 1, + "column": 16, "endLine": 21, - "endColumn": 11, - "problem": "InteropJsObjectUsage", + "endColumn": 17, + "problem": "NumericSemantics", "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { "line": 21, - "column": 14, + "column": 19, "endLine": 21, - "endColumn": 16, + "endColumn": 20, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", @@ -108,7 +98,7 @@ "line": 22, "column": 1, "endLine": 22, - "endColumn": 21, + "endColumn": 13, "problem": "InteropObjectProperty", "suggest": "", "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", @@ -116,29 +106,9 @@ }, { "line": 22, - "column": 1, + "column": 11, "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, - "column": 16, - "endLine": 22, - "endColumn": 17, - "problem": "NumericSemantics", - "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 19, - "endLine": 22, - "endColumn": 20, + "endColumn": 13, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", 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 282314af7878a663ad46f7ba5e4ed752ae037af0..bc3b0d40f581733d3d0e8e607abf2fba86ebe8fb --- 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,35 +15,29 @@ ], "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, - "replacementText": "let GeneratedImportVar_1 = ESValue.load('./interop_not_have_property_js');\nlet foo = GeneratedImportVar_1.getPropertyByName('foo');\nlet person = GeneratedImportVar_1.getPropertyByName('person');\n" + "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": 16, + "column": 1, + "endLine": 16, + "endColumn": 59 } ], "suggest": "", @@ -51,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 } ], @@ -75,34 +69,38 @@ "line": 19, "column": 1, "endLine": 19, - "endColumn": 9, - "problem": "InteropJsObjectUsage", + "endColumn": 17, + "problem": "InteropObjectProperty", "autofix": [ { - "replacementText": "foo.getPropertyByName('name').toString()", - "start": 678, - "end": 686, + "start": 674, + "end": 690, + "replacementText": "foo.setPropertyByName(\"name\", ESValue.wrap(\"456\"))", "line": 19, "column": 1, "endLine": 19, - "endColumn": 9 + "endColumn": 17 } ], "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": 1, "endLine": 20, - "endColumn": 17, + "endColumn": 16, "problem": "InteropObjectProperty", "autofix": [ { - "start": 687, - "end": 703, - "replacementText": "foo.setPropertyByName(\"name\", ESValue.wrap(\"456\"))" + "start": 691, + "end": 706, + "replacementText": "person.setPropertyByName(\"age\", ESValue.wrap(23))", + "line": 20, + "column": 1, + "endLine": 20, + "endColumn": 16 } ], "suggest": "", @@ -111,36 +109,40 @@ }, { "line": 20, - "column": 1, + "column": 14, "endLine": 20, - "endColumn": 9, - "problem": "InteropJsObjectUsage", + "endColumn": 16, + "problem": "NumericSemantics", "autofix": [ { - "replacementText": "foo.getPropertyByName('name').toString()", - "start": 687, - "end": 695, + "start": 704, + "end": 706, + "replacementText": "23.0", "line": 20, - "column": 1, + "column": 14, "endLine": 20, - "endColumn": 9 + "endColumn": 16 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { "line": 21, "column": 1, "endLine": 21, - "endColumn": 16, + "endColumn": 21, "problem": "InteropObjectProperty", "autofix": [ { - "start": 704, - "end": 719, - "replacementText": "person.setPropertyByName(\"age\", ESValue.wrap(23))" + "start": 707, + "end": 727, + "replacementText": "person.setPropertyByName(\"male\", ESValue.wrap([2, 3]))", + "line": 21, + "column": 1, + "endLine": 21, + "endColumn": 21 } ], "suggest": "", @@ -149,40 +151,40 @@ }, { "line": 21, - "column": 1, + "column": 16, "endLine": 21, - "endColumn": 11, - "problem": "InteropJsObjectUsage", + "endColumn": 17, + "problem": "NumericSemantics", "autofix": [ { - "replacementText": "person.getPropertyByName('age').toNumber()", - "start": 704, - "end": 714, + "start": 722, + "end": 723, + "replacementText": "2.0", "line": 21, - "column": 1, + "column": 16, "endLine": 21, - "endColumn": 11 + "endColumn": 17 } ], "suggest": "", - "rule": "Direct usage of interop JS objects is not supported (arkts-interop-js-object-usage)", + "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" }, { "line": 21, - "column": 14, + "column": 19, "endLine": 21, - "endColumn": 16, + "endColumn": 20, "problem": "NumericSemantics", "autofix": [ { - "start": 717, - "end": 719, - "replacementText": "23.0", + "start": 725, + "end": 726, + "replacementText": "3.0", "line": 21, - "column": 14, + "column": 19, "endLine": 21, - "endColumn": 16 + "endColumn": 20 } ], "suggest": "", @@ -193,76 +195,38 @@ "line": 22, "column": 1, "endLine": 22, - "endColumn": 21, + "endColumn": 13, "problem": "InteropObjectProperty", "autofix": [ { - "start": 720, + "start": 728, "end": 740, - "replacementText": "person.setPropertyByName(\"male\", ESValue.wrap([2, 3]))" - } - ], - "suggest": "", - "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", - "severity": "ERROR" - }, - { - "line": 22, - "column": 1, - "endLine": 22, - "endColumn": 12, - "problem": "InteropJsObjectUsage", - "autofix": [ - { - "replacementText": "person.getPropertyByName('male')", - "start": 720, - "end": 731, + "replacementText": "foo.setPropertyByName(\"age\", ESValue.wrap(12))", "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, - "column": 16, - "endLine": 22, - "endColumn": 17, - "problem": "NumericSemantics", - "autofix": [ - { - "start": 735, - "end": 736, - "replacementText": "2.0", - "line": 22, - "column": 16, - "endLine": 22, - "endColumn": 17 + "endColumn": 13 } ], "suggest": "", - "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", + "rule": "Properties of interop objects can't be accessed directly (arkts-interop-js2s-access-js-prop)", "severity": "ERROR" }, { "line": 22, - "column": 19, + "column": 11, "endLine": 22, - "endColumn": 20, + "endColumn": 13, "problem": "NumericSemantics", "autofix": [ { "start": 738, - "end": 739, - "replacementText": "3.0", + "end": 740, + "replacementText": "12.0", "line": 22, - "column": 19, + "column": 11, "endLine": 22, - "endColumn": 20 + "endColumn": 13 } ], "suggest": "", 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 838a0500a51da618680219ad2074df304e1eff66..ca88f857e960b437dcf767c0ac40be998c8f1236 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 9fbd2c1ac2222f4c70a0532aa13ae588219f954f..cfddb44b00e1972729c9aa3c44be5394f0008a16 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'); @@ -22,4 +21,5 @@ let person = GeneratedImportVar_1.getPropertyByName('person'); 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])) \ No newline at end of file +person.setPropertyByName("male", ESValue.wrap([2.0, 3.0])) +foo.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 17bc19346aae749d288ae9fe18ae878cdee8d9ef..ae940558e7e1ab2f0a58b276731285e5dc330ab3 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 1049aac0f00e701d6e1ad108fcc92ab88dcf7933..8c41ae41820260ad9b446e203c8ebc8c7c096e4e --- 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 414d9f77210b68d5546e3d261c39852de9ee43a0..622761b380a175be670c7374af4cafe45e881106 --- 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 4452cefcfd558d981573f96c553799bb22d28897..fc4732acc47bc4af5e2f97cf2cfaad248fe51d35 --- 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 456612d680838522a6a4843c38b2df4fa326df96..ca88f857e960b437dcf767c0ac40be998c8f1236 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 1a22e1418c9a3fbf82d7e96e9db282d67d53e8e9..09086d9892f81603449fdd0498a3b3ce220b336c 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 01cf629ed9743d2f465bfce367539feebf811ed4..ef4a1a04e1196434b864ff249bcd12d37a9d92b8 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 9247c363b44ed65bb043a4311584031f31e6d8fd..124f7b4daba7134bcd6d05ab95a36653ec7cfd43 --- 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.args.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.args.json index 66fb88f85945924e8be0e83d90123507033f4c5d..6958168fef2a70000342107f7d5f2b5805c14fae 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 old mode 100755 new mode 100644 index 54dff3eb9234b3f09d0902f6ebbac8ea91691542..13cd6170a9d06c8a69cbf75fe8f5d7207f3d3e86 --- 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,33 +1,9 @@ { - "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, + "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 +11,9 @@ "severity": "ERROR" }, { - "line": 20, + "line": 19, "column": 10, - "endLine": 20, + "endLine": 19, "endColumn": 17, "problem": "NoAwaitJsPromise", "suggest": "", @@ -45,9 +21,9 @@ "severity": "ERROR" }, { - "line": 24, + "line": 23, "column": 10, - "endLine": 24, + "endLine": 23, "endColumn": 21, "problem": "NoAwaitJsPromise", "suggest": "", @@ -55,29 +31,9 @@ "severity": "ERROR" }, { - "line": 24, - "column": 16, - "endLine": 24, - "endColumn": 21, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "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": "", @@ -85,39 +41,9 @@ "severity": "ERROR" }, { - "line": 32, - "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": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "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, + "line": 35, "column": 10, - "endLine": 36, + "endLine": 35, "endColumn": 26, "problem": "NoAwaitJsPromise", "suggest": "", @@ -125,9 +51,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 40, "column": 12, - "endLine": 41, + "endLine": 40, "endColumn": 19, "problem": "NoAwaitJsPromise", "suggest": "", @@ -135,9 +61,9 @@ "severity": "ERROR" }, { - "line": 45, + "line": 44, "column": 12, - "endLine": 45, + "endLine": 44, "endColumn": 27, "problem": "NoAwaitJsPromise", "suggest": "", @@ -145,9 +71,9 @@ "severity": "ERROR" }, { - "line": 49, + "line": 48, "column": 20, - "endLine": 49, + "endLine": 48, "endColumn": 21, "problem": "ObjectLiteralNoContextType", "suggest": "", @@ -155,9 +81,9 @@ "severity": "ERROR" }, { - "line": 50, + "line": 49, "column": 3, - "endLine": 52, + "endLine": 51, "endColumn": 4, "problem": "ObjectLiteralProperty", "suggest": "", @@ -165,9 +91,9 @@ "severity": "ERROR" }, { - "line": 51, + "line": 50, "column": 12, - "endLine": 51, + "endLine": 50, "endColumn": 28, "problem": "NoAwaitJsPromise", "suggest": "", @@ -175,9 +101,9 @@ "severity": "ERROR" }, { - "line": 55, + "line": 54, "column": 12, - "endLine": 55, + "endLine": 54, "endColumn": 23, "problem": "NoAwaitJsPromise", "suggest": "", @@ -185,29 +111,9 @@ "severity": "ERROR" }, { - "line": 55, - "column": 18, - "endLine": 55, - "endColumn": 23, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "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": "", @@ -215,44 +121,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": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "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.autofix.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.autofix.json new file mode 100644 index 0000000000000000000000000000000000000000..5254337c77defbb125385c93025cd3cba914a1f2 --- /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.json b/ets2panda/linter/test/interop/no_await_js_promise.ets.json index 5285bc41f634a1abbb69521c2609a6c4aebd006d..02889dfd82b7eb15ba30b481cd8ee682c9a19ea9 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_await_js_promise.ets.migrate.ets b/ets2panda/linter/test/interop/no_await_js_promise.ets.migrate.ets new file mode 100644 index 0000000000000000000000000000000000000000..a89d3e58d376f0943d007c87f0d69510a8f00e0a --- /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 0000000000000000000000000000000000000000..5d4c781348cc18bbed693d732d73a9621736bf9e --- /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 b/ets2panda/linter/test/interop/no_js_instanceof.ets old mode 100755 new mode 100644 index f3e57eeee88a4fecf7bfddc410314089fdd77036..9c7c1b645398c89753dbdb8fdf9af53f2f160a57 --- 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.args.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.args.json index 3ef4496a819a201892114d1c90f78ae32053c334..571ee6bb76b0cad72a9443db47c2f9d7db474bd0 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.arkts2.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.arkts2.json old mode 100755 new mode 100644 index 7f34d1cc41501add68494e07069933e98c42e852..616006bedfa5985d09e37f9e6ad479315039b548 --- 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,19 +55,9 @@ "severity": "ERROR" }, { - "line": 39, - "column": 28, - "endLine": 39, - "endColumn": 50, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 39, + "line": 38, "column": 28, - "endLine": 39, + "endLine": 38, "endColumn": 50, "problem": "CallJSFunction", "suggest": "", @@ -85,9 +65,9 @@ "severity": "ERROR" }, { - "line": 39, + "line": 38, "column": 47, - "endLine": 39, + "endLine": 38, "endColumn": 49, "problem": "NumericSemantics", "suggest": "", @@ -95,9 +75,9 @@ "severity": "ERROR" }, { - "line": 41, + "line": 40, "column": 4, - "endLine": 41, + "endLine": 40, "endColumn": 34, "problem": "InteropJsInstanceof", "suggest": "", @@ -105,9 +85,9 @@ "severity": "ERROR" }, { - "line": 46, + "line": 45, "column": 8, - "endLine": 46, + "endLine": 45, "endColumn": 38, "problem": "InteropJsInstanceof", "suggest": "", @@ -115,9 +95,9 @@ "severity": "ERROR" }, { - "line": 52, + "line": 51, "column": 8, - "endLine": 52, + "endLine": 51, "endColumn": 38, "problem": "InteropJsInstanceof", "suggest": "", @@ -125,9 +105,9 @@ "severity": "ERROR" }, { - "line": 59, + "line": 58, "column": 12, - "endLine": 59, + "endLine": 58, "endColumn": 42, "problem": "InteropJsInstanceof", "suggest": "", @@ -135,9 +115,9 @@ "severity": "ERROR" }, { - "line": 65, + "line": 64, "column": 4, - "endLine": 65, + "endLine": 64, "endColumn": 22, "problem": "InteropJsInstanceof", "suggest": "", @@ -145,9 +125,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 68, "column": 4, - "endLine": 69, + "endLine": 68, "endColumn": 24, "problem": "InteropJsInstanceof", "suggest": "", @@ -155,19 +135,9 @@ "severity": "ERROR" }, { - "line": 69, + "line": 68, "column": 4, - "endLine": 69, - "endColumn": 7, - "problem": "InteropJsObjectCallStaticFunc", - "suggest": "", - "rule": "Direct usage of interop JS functions is not supported (arkts-interop-js2s-js-call-static-function)", - "severity": "ERROR" - }, - { - "line": 69, - "column": 4, - "endLine": 69, + "endLine": 68, "endColumn": 7, "problem": "CallJSFunction", "suggest": "", @@ -175,9 +145,9 @@ "severity": "ERROR" }, { - "line": 73, + "line": 72, "column": 36, - "endLine": 73, + "endLine": 72, "endColumn": 51, "problem": "DynamicCtorCall", "suggest": "", @@ -185,19 +155,9 @@ "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": "", @@ -205,9 +165,9 @@ "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.autofix.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.autofix.json new file mode 100644 index 0000000000000000000000000000000000000000..c1c3153c902ced5a24f5c3e25aa1c7c191e5ef51 --- /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.json b/ets2panda/linter/test/interop/no_js_instanceof.ets.json index e6955adae6bac5e78b91f1b2779d27117f1fde2f..ca88f857e960b437dcf767c0ac40be998c8f1236 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/no_js_instanceof.ets.migrate.ets b/ets2panda/linter/test/interop/no_js_instanceof.ets.migrate.ets new file mode 100644 index 0000000000000000000000000000000000000000..729ddeb90e7e63268dd5dabbbe8942f6f65f7249 --- /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 0000000000000000000000000000000000000000..992f388c81b589589fd96d52e0ea0603ba4c6188 --- /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" + } + ] +} diff --git a/ets2panda/linter/test/interop/object_built_in.ets b/ets2panda/linter/test/interop/object_built_in.ets index 7797930ffdc48c71b861f8f690b58f811efd2319..3170f3f087929ed9725c116545ec115437d88e83 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 07296c65fcf827975765e901537551ce63c21858..aea5d55ddb15b333934bc86eb79cd04096e9f178 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 582a700d940a62a7f8b6fae343ed7bf79d4da05e..d756197f15700b6f96caf8e023ffe8537cfcd193 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 7c15e1bf64f1cfa040ef5ebaf62e84285eba0321..c66bdfabca6b8b748cc4c5f004e3f5a32b7521ff 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 6a51dd80b2384cb85784952c10f738f84aaa2cbd..7fe4087dbb650d0fbaf0a53aa3712ff6f2692c8d 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 bafc2e9e5484c606da27a671a0708fcec32cba92..b242a6c5b974b13690bc5e6c8b116ae383f40ff7 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 f57fd51379483dadc616f4982de7a53d521c2656..2e730940c353d44edcde943baabc3cbe84d96937 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 5c02f0cb4d9911bc2709610266b70dc0caf4d404..4b9be812e45c1e79e4d5a1eab9e65a5f8a05af61 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 25154ac0c6605dd88492da69d54ca7d7a2cda0d5..ca88f857e960b437dcf767c0ac40be998c8f1236 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 dad32c88bac85147e6236659ba62ac53ecb691ea..81c8a334d4028ca4afe793d13a1cdae8e730ac59 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 4fd2894dd8489f827482c493f3d1782ef57e0d1a..418b723cf91853fba46d93ca52b7934df77ed6ae 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 2191e0197101822d16e3f3af4bc71f7162305b9b..540539ec6b9b475b6a7adcff5c4da0e6fb871e43 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 96b0800185e89fcc3bdf12c6ce9ac7dfd106ec0e..63eb6869e286dacf17910c0e1f44dc2feab1b3fa 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 f16e3c2498d6026be25ace4fff06b3a1efb26bde..e874522c3461ed3f99cfdaba2eb5321e4fed2062 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 0ee87e87fb38c2290a997111c093fa85d4809a32..ca88f857e960b437dcf767c0ac40be998c8f1236 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 index 2e2c993747bc431db12fcf5270cafc3ce7f20974..7eec28c4196a920c4c209ae4e9daf2ffaea7f188 100644 --- a/ets2panda/linter/test/interop/static_dynamic_import.ets +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -'use static' let arkTsMod = await import('./test_files/dummy_arkts1_file'); let tsModule = await import('./test_files/dummy_ts_file'); diff --git a/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json b/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json index 3b87fbdb1f540ab4bde448b1dbc5fb9749cd30d7..dc7f9e0521f966339a23226da90cd2184faf4677 100644 --- a/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets.arkts2.json @@ -15,9 +15,9 @@ ], "result": [ { - "line": 17, + "line": 16, "column": 16, - "endLine": 17, + "endLine": 16, "endColumn": 62, "problem": "InteropDynamicImport", "suggest": "", @@ -25,9 +25,9 @@ "severity": "ERROR" }, { - "line": 17, + "line": 16, "column": 22, - "endLine": 17, + "endLine": 16, "endColumn": 62, "problem": "DynamicImport", "suggest": "", @@ -35,9 +35,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 17, - "endLine": 18, + "endLine": 17, "endColumn": 59, "problem": "InteropDynamicImportTs", "suggest": "", @@ -45,9 +45,9 @@ "severity": "ERROR" }, { - "line": 18, + "line": 17, "column": 23, - "endLine": 18, + "endLine": 17, "endColumn": 59, "problem": "DynamicImport", "suggest": "", @@ -55,9 +55,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 16, - "endLine": 19, + "endLine": 18, "endColumn": 58, "problem": "InteropDynamicImportJs", "suggest": "", @@ -65,9 +65,9 @@ "severity": "ERROR" }, { - "line": 19, + "line": 18, "column": 22, - "endLine": 19, + "endLine": 18, "endColumn": 58, "problem": "DynamicImport", "suggest": "", @@ -75,9 +75,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 3, - "endLine": 22, + "endLine": 21, "endColumn": 44, "problem": "InteropDynamicImportTs", "suggest": "", @@ -85,9 +85,9 @@ "severity": "ERROR" }, { - "line": 22, + "line": 21, "column": 3, - "endLine": 22, + "endLine": 21, "endColumn": 39, "problem": "DynamicImport", "suggest": "", @@ -95,4 +95,4 @@ "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 index ca88f857e960b437dcf767c0ac40be998c8f1236..999000f1d0ecd378bb5189265cc4d871ecc8d227 100644 --- a/ets2panda/linter/test/interop/static_dynamic_import.ets.json +++ b/ets2panda/linter/test/interop/static_dynamic_import.ets.json @@ -13,5 +13,46 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "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 12d46c0860e9c1e8e2b8ea429ab13cae1448e3da..ca88f857e960b437dcf767c0ac40be998c8f1236 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/unary_operation_js_obj.ets b/ets2panda/linter/test/interop/unary_operation_js_obj.ets new file mode 100644 index 0000000000000000000000000000000000000000..a6d66fee062a7f2ee2f4822230e873f306f7e903 --- /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 0000000000000000000000000000000000000000..a89d885810708ad03d96e3e14bb6590efd1a7547 --- /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 0000000000000000000000000000000000000000..c935900b7d1d21c644eeee800720f6856bb53686 --- /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 0000000000000000000000000000000000000000..f9cba0c86385e77bfab4a5d927efed836a9f886f --- /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 0000000000000000000000000000000000000000..43cb4a27bcc78710d4aa5130c22ee053f66c3fbc --- /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 0000000000000000000000000000000000000000..5448d6f5f0aab231985e877f6d12ed9a37b69299 --- /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 0000000000000000000000000000000000000000..4d448e180c8d4e4bb1569a75f3db5f5f85ffb1c2 --- /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/test_files/dummy_js_file.js b/ets2panda/linter/test/interop/unary_operation_js_obj_js.js similarity index 95% rename from ets2panda/linter/test/interop/test_files/dummy_js_file.js rename to ets2panda/linter/test/interop/unary_operation_js_obj_js.js index fa09fbb12c4a5fa47c104c1173cb88dafe4b78b0..6787c967843fb9f771355c300ca676850b9bd3f6 100644 --- a/ets2panda/linter/test/interop/test_files/dummy_js_file.js +++ b/ets2panda/linter/test/interop/unary_operation_js_obj_js.js @@ -13,4 +13,4 @@ * limitations under the License. */ -export {} +export let foo = {num: 0}; \ 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 35f8bae39116bc89fb0ff43ffec5b8c810c399a3..da2c034f53dbd05f0044a1aa2bc0338138269c49 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 3c2bcf66a72cc5310f800eb87ad21c0a03a8d0cd..46c7e599251bb639a1baaa126c0edf24636fc8b7 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 5f1b6e40b9633eca99cf4f49bf543f25cd3118c7..bf760d1cf6aa852407507a04b3e7f8939b97ce40 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 3e8e488310b0cc25d757e85c0dad6e55c2c622c1..ca88f857e960b437dcf767c0ac40be998c8f1236 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 86dd5f4ed051b0282bcfb8c8cfe7d67a1c107233..884003da2478dc331ef9a4f6dde7bcee9fda2c4c 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 4eb8c2c72d3dad88d8e0550785ad1a4a133a9f98..47c591c577564449d20ae831cd168cb729bf4e87 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/arkts-array-type-immutable.ets.arkts2.json b/ets2panda/linter/test/main/arkts-array-type-immutable.ets.arkts2.json index 15d79307bb68b8182c9ef5e1327c95dec8bbb60a..50fb25efbd4e185ee01f34994c9860a16d181cac 100644 --- a/ets2panda/linter/test/main/arkts-array-type-immutable.ets.arkts2.json +++ b/ets2panda/linter/test/main/arkts-array-type-immutable.ets.arkts2.json @@ -31,7 +31,7 @@ "endColumn": 31, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -51,7 +51,7 @@ "endColumn": 7, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -71,7 +71,7 @@ "endColumn": 9, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -81,7 +81,7 @@ "endColumn": 54, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -121,7 +121,7 @@ "endColumn": 8, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" } ] diff --git a/ets2panda/linter/test/main/arkts-primitive-type-normalization.ets.arkts2.json b/ets2panda/linter/test/main/arkts-primitive-type-normalization.ets.arkts2.json index 72037700d54618305266ad3de86224130a079b0e..fc8bfe9fd884d40b45f2e95f6a6869ef1b3d4937 100644 --- a/ets2panda/linter/test/main/arkts-primitive-type-normalization.ets.arkts2.json +++ b/ets2panda/linter/test/main/arkts-primitive-type-normalization.ets.arkts2.json @@ -21,7 +21,7 @@ "endColumn": 21, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -41,7 +41,7 @@ "endColumn": 14, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -61,7 +61,7 @@ "endColumn": 31, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -81,7 +81,7 @@ "endColumn": 23, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -91,7 +91,7 @@ "endColumn": 26, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -101,7 +101,7 @@ "endColumn": 12, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -111,7 +111,7 @@ "endColumn": 11, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -121,7 +121,7 @@ "endColumn": 11, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" } ] diff --git a/ets2panda/linter/test/main/arktsutils_module.ets b/ets2panda/linter/test/main/arktsutils_module.ets index 3bfeec6005331e400a16972a240767cc9f567293..4e81dea82b9caa9f42f8000a32557894ad38463d 100644 --- a/ets2panda/linter/test/main/arktsutils_module.ets +++ b/ets2panda/linter/test/main/arktsutils_module.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { utils } from './oh_modules/@arkts.utils'; import { utils as ArkTSUtilsAlias } from './oh_modules/@arkts.utils'; @@ -32,4 +31,8 @@ function tesCollectionsUsage() { const utils3 = kitArkTSUtils.ASON.stringify(1); const utils4: string = ArkTSUtilsAlias.ASON.stringify(1); -} \ No newline at end of file + + type CreatedType = ArkTSUtils.ASON.SomeType; + + const someType: CreatedType = ArkTSUtils.ASON.SomeType; +} diff --git a/ets2panda/linter/test/main/arktsutils_module.ets.arkts2.json b/ets2panda/linter/test/main/arktsutils_module.ets.arkts2.json index a090d23f5e12cfc98c611c61defab3c6495f7f74..6da6e6ae1588b4a7791270d2b02b227b7b9cf6eb 100644 --- a/ets2panda/linter/test/main/arktsutils_module.ets.arkts2.json +++ b/ets2panda/linter/test/main/arktsutils_module.ets.arkts2.json @@ -15,19 +15,19 @@ ], "result": [ { - "line": 28, - "column": 32, - "endLine": 28, - "endColumn": 36, + "line": 27, + "column": 26, + "endLine": 27, + "endColumn": 31, "problem": "LimitedStdLibNoASON", "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 47, - "endLine": 28, + "endLine": 27, "endColumn": 48, "problem": "NumericSemantics", "suggest": "", @@ -35,19 +35,19 @@ "severity": "ERROR" }, { - "line": 30, - "column": 34, - "endLine": 30, - "endColumn": 38, + "line": 29, + "column": 18, + "endLine": 29, + "endColumn": 33, "problem": "LimitedStdLibNoASON", "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 49, - "endLine": 30, + "endLine": 29, "endColumn": 50, "problem": "NumericSemantics", "suggest": "", @@ -55,19 +55,19 @@ "severity": "ERROR" }, { - "line": 32, - "column": 32, - "endLine": 32, - "endColumn": 36, + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 31, "problem": "LimitedStdLibNoASON", "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 32, + "line": 31, "column": 47, - "endLine": 32, + "endLine": 31, "endColumn": 48, "problem": "NumericSemantics", "suggest": "", @@ -75,24 +75,44 @@ "severity": "ERROR" }, { - "line": 34, - "column": 42, - "endLine": 34, - "endColumn": 46, + "line": 33, + "column": 26, + "endLine": 33, + "endColumn": 41, "problem": "LimitedStdLibNoASON", "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 57, - "endLine": 34, + "endLine": 33, "endColumn": 58, "problem": "NumericSemantics", "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 32, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 33, + "endLine": 37, + "endColumn": 43, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/arktsutils_module.ets.autofix.json b/ets2panda/linter/test/main/arktsutils_module.ets.autofix.json index 77b0d7cec92bf2d147a1e34daeb265c53c1d0f0d..d6868a9cbf4f513be46a17011c04913690564267 100644 --- a/ets2panda/linter/test/main/arktsutils_module.ets.autofix.json +++ b/ets2panda/linter/test/main/arktsutils_module.ets.autofix.json @@ -15,40 +15,29 @@ ], "result": [ { - "line": 28, - "column": 32, - "endLine": 28, - "endColumn": 36, + "line": 27, + "column": 26, + "endLine": 27, + "endColumn": 31, "problem": "LimitedStdLibNoASON", - "autofix": [ - { - "start": 981, - "end": 991, - "replacementText": "JSON", - "line": 28, - "column": 32, - "endLine": 28, - "endColumn": 36 - } - ], "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 28, + "line": 27, "column": 47, - "endLine": 28, + "endLine": 27, "endColumn": 48, "problem": "NumericSemantics", "autofix": [ { - "start": 1002, - "end": 1003, + "start": 1001, + "end": 1002, "replacementText": "1.0", - "line": 28, + "line": 27, "column": 47, - "endLine": 28, + "endLine": 27, "endColumn": 48 } ], @@ -57,40 +46,29 @@ "severity": "ERROR" }, { - "line": 30, - "column": 34, - "endLine": 30, - "endColumn": 38, + "line": 29, + "column": 18, + "endLine": 29, + "endColumn": 33, "problem": "LimitedStdLibNoASON", - "autofix": [ - { - "start": 1024, - "end": 1044, - "replacementText": "JSON", - "line": 30, - "column": 34, - "endLine": 30, - "endColumn": 38 - } - ], "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 30, + "line": 29, "column": 49, - "endLine": 30, + "endLine": 29, "endColumn": 50, "problem": "NumericSemantics", "autofix": [ { - "start": 1055, - "end": 1056, + "start": 1054, + "end": 1055, "replacementText": "1.0", - "line": 30, + "line": 29, "column": 49, - "endLine": 30, + "endLine": 29, "endColumn": 50 } ], @@ -99,40 +77,29 @@ "severity": "ERROR" }, { - "line": 32, - "column": 32, - "endLine": 32, - "endColumn": 36, + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 31, "problem": "LimitedStdLibNoASON", - "autofix": [ - { - "start": 1077, - "end": 1095, - "replacementText": "JSON", - "line": 32, - "column": 32, - "endLine": 32, - "endColumn": 36 - } - ], "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 32, + "line": 31, "column": 47, - "endLine": 32, + "endLine": 31, "endColumn": 48, "problem": "NumericSemantics", "autofix": [ { - "start": 1106, - "end": 1107, + "start": 1105, + "end": 1106, "replacementText": "1.0", - "line": 32, + "line": 31, "column": 47, - "endLine": 32, + "endLine": 31, "endColumn": 48 } ], @@ -141,46 +108,55 @@ "severity": "ERROR" }, { - "line": 34, - "column": 42, - "endLine": 34, - "endColumn": 46, + "line": 33, + "column": 26, + "endLine": 33, + "endColumn": 41, "problem": "LimitedStdLibNoASON", - "autofix": [ - { - "start": 1136, - "end": 1156, - "replacementText": "JSON", - "line": 34, - "column": 42, - "endLine": 34, - "endColumn": 46 - } - ], "suggest": "", "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", "severity": "ERROR" }, { - "line": 34, + "line": 33, "column": 57, - "endLine": 34, + "endLine": 33, "endColumn": 58, "problem": "NumericSemantics", "autofix": [ { - "start": 1167, - "end": 1168, + "start": 1166, + "end": 1167, "replacementText": "1.0", - "line": 34, + "line": 33, "column": 57, - "endLine": 34, + "endLine": 33, "endColumn": 58 } ], "suggest": "", "rule": "Numeric semantics is different for integer values (arkts-numeric-semantic)", "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 32, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 33, + "endLine": 37, + "endColumn": 43, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/main/arktsutils_module.ets.migrate.ets b/ets2panda/linter/test/main/arktsutils_module.ets.migrate.ets index b2a00452ad60169918db38c4092f2036bce562ba..3b1d7e17b6e5f116f3051c61fe671e0dee13327e 100644 --- a/ets2panda/linter/test/main/arktsutils_module.ets.migrate.ets +++ b/ets2panda/linter/test/main/arktsutils_module.ets.migrate.ets @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import { utils } from './oh_modules/@arkts.utils'; import { utils as ArkTSUtilsAlias } from './oh_modules/@arkts.utils'; @@ -25,11 +24,15 @@ export { utils } from './oh_modules/@arkts.utils'; function tesCollectionsUsage() { - const utils1: string = JSON.stringify(1.0); + const utils1: string = utils.ASON.stringify(1.0); + + const utils2 = ArkTSUtilsAlias.ASON.stringify(1.0); + + const utils3 = kitArkTSUtils.ASON.stringify(1.0); - const utils2 = JSON.stringify(1.0); + const utils4: string = ArkTSUtilsAlias.ASON.stringify(1.0); - const utils3 = JSON.stringify(1.0); + type CreatedType = ArkTSUtils.ASON.SomeType; - const utils4: string = JSON.stringify(1.0); -} \ No newline at end of file + const someType: CreatedType = ArkTSUtils.ASON.SomeType; +} diff --git a/ets2panda/linter/test/main/arktsutils_module.ets.migrate.json b/ets2panda/linter/test/main/arktsutils_module.ets.migrate.json index 9f305c86d7ff705098b1e480818e125d5e6e3a4a..1b597eff5b8579d13d203bafc99002f5f4b2ce85 100644 --- a/ets2panda/linter/test/main/arktsutils_module.ets.migrate.json +++ b/ets2panda/linter/test/main/arktsutils_module.ets.migrate.json @@ -13,5 +13,66 @@ "See the License for the specific language governing permissions and", "limitations under the License." ], - "result": [] + "result": [ + { + "line": 27, + "column": 26, + "endLine": 27, + "endColumn": 31, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 29, + "column": 18, + "endLine": 29, + "endColumn": 33, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 18, + "endLine": 31, + "endColumn": 31, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 33, + "column": 26, + "endLine": 33, + "endColumn": 41, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 35, + "column": 22, + "endLine": 35, + "endColumn": 32, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 33, + "endLine": 37, + "endColumn": 43, + "problem": "LimitedStdLibNoASON", + "suggest": "", + "rule": "ASON is not supported. (arkts-no-need-stdlib-ason)", + "severity": "ERROR" + } + ] } 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 40493eb17563e97e8f44bded1361261fa9b00f25..3643204633f2584747bd4fde01082b4531dcfbb4 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 ec4168139c9bca5ac69a6316b4577582c358b1b6..f3c413339478654d0f37c17c2569396314f8e316 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 8407a76e0f1a39a6b7313c0ba4b4143b441bb8ad..12700705c3a2aa039dfe0008091dbab9028f7bdf 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/avoid_using_union_types.ets b/ets2panda/linter/test/main/avoid_using_union_types.ets index 907449c2fa6cf690316687315692376de55b20bf..4b633916d9b3e45a0a9abcb39b92ebda00f9abe4 100644 --- a/ets2panda/linter/test/main/avoid_using_union_types.ets +++ b/ets2panda/linter/test/main/avoid_using_union_types.ets @@ -33,4 +33,7 @@ function foo(a: A | B | C) { a.x; // No error here, since TypeScript already checks this case and reports an error. No need to duplicate this logic a.y; // Report error here, type of `y` is different: 'number' in A, C and 'string' in B a.z; // No error, the code is valid -} \ No newline at end of file +} + +let data: Uint8Array = new Uint8Array(); +let reqPb = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset); \ 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 3bf41adaebabc702af23e7f93af0ad0ce71cc015..40f9e25a1146514fe90eb5be83555b9e9a7ea182 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/dynamic_ctor_call.ets.arkts2.json b/ets2panda/linter/test/main/dynamic_ctor_call.ets.arkts2.json index 0ef26c352d653b6c6e8fd73f0070ea28f6847bbe..b4ee74500e610e14150f1907769481521dccf99e 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 6c7ca94b922852b39dbb8edf11e8a67856b34ea0..d79abde569bf4dd85df92241a96cba0118cc695a 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 6f0f0a04818feb1bc8998c01eb4f2dae5cefcabc..d3870c4c8f88782bc29409f986e4660d79c7b1d2 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 ca5758bca29ec3547fa2ecf15a3320655747c97b..b4e8db486eeaedea242edff205286dd79e155a9f 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 8332379fa7ccc19ab8c5ff0b28b5ca38417e962e..10523de7b5e1276e0e5c2da57fadc4ae7c4b59b4 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 773fea5ff8c4e90cfc4e962f87f7eb24ea4edf71..08fe89b9bc8a0dafe7c366644d88f0da1e2b61b5 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 a3d92d0d965596b23b8e137b426e01275b3f7847..27185a830cab2f5ec8e9e1151f2cf63f4593cd4b 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 d1daebd5f8a021b6d2daa1afa892f0a62a28f0c9..d8c630fa30f60f14820cf5d891bb906638523cc3 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 2999205f9565c7610abab7a3471711f09e29ea9f..df7367f9debfe680b03a61f933d6da4292479f7d 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 39d24845a6e49fd2f89e45c2a5ef8279dc72e0b6..5a91df9df0075858aa94533bc5b79e47a6ced5dc 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 286fd756ff7265880cbb18d4dfc3e7848bae06e8..79102a9b706cd894b386530ef2168b94c6c28c25 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, @@ -294,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, @@ -354,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, @@ -364,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, @@ -384,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 282458e4e5bf09a939b7369e09cc839049e7466c..82e0ac288a827ad33167618e6e7dca7020656324 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, @@ -687,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, @@ -831,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, @@ -852,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, @@ -903,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 7756bd53973f3ae465790f9582ab044fb5879ed4..97c0791cc5086137c8680a4f3ef9882562a14456 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, @@ -84,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/no_enum_prop_as_type.ets.arkts2.json b/ets2panda/linter/test/main/no_enum_prop_as_type.ets.arkts2.json index 5974b151459cc560e541b4b565b58b1bbfc11d17..be0d1b9493001b13e588a2405cc082e6429ec87e 100644 --- a/ets2panda/linter/test/main/no_enum_prop_as_type.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_enum_prop_as_type.ets.arkts2.json @@ -21,7 +21,7 @@ "endColumn": 20, "problem": "NoEnumPropAsType", "suggest": "", - "rule": "Enum prop as type are not supported (arkts-no-enum-prop-as-type)", + "rule": "Enum elements cannot be types in ArkTS1.2 (arkts-no-enum-prop-as-type)", "severity": "ERROR" }, { @@ -31,7 +31,7 @@ "endColumn": 11, "problem": "NoEnumPropAsType", "suggest": "", - "rule": "Enum prop as type are not supported (arkts-no-enum-prop-as-type)", + "rule": "Enum elements cannot be types in ArkTS1.2 (arkts-no-enum-prop-as-type)", "severity": "ERROR" } ] 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 f34010f03c1c62657b7858be3941d57c50546b92..2a8c937e9f90ac9a473715b3abeaa83c114917ad 100644 --- a/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_sparse_array.ets.arkts2.json @@ -21,7 +21,7 @@ "endColumn": 12, "problem": "NosparseArray", "suggest": "", - "rule": "Sparse array are not supported (arkts-no-sparse-array)", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", "severity": "ERROR" }, { @@ -31,7 +31,7 @@ "endColumn": 14, "problem": "NosparseArray", "suggest": "", - "rule": "Sparse array are not supported (arkts-no-sparse-array)", + "rule": "Sparse array is not supported in ArkTS1.2 (arkts-no-sparse-array)", "severity": "ERROR" }, { diff --git a/ets2panda/linter/test/main/no_ts_like_smart_type.ets b/ets2panda/linter/test/main/no_ts_like_smart_type.ets index 01a023bc1fb85ad7b5d4f8c352dd8ef27e1beb15..fd197a3772e0976efc1467aee1646a8bb1d8f35b 100755 --- a/ets2panda/linter/test/main/no_ts_like_smart_type.ets +++ b/ets2panda/linter/test/main/no_ts_like_smart_type.ets @@ -31,4 +31,15 @@ class AA2 { } return this.instance; // Error } +} +class A { + private static instance:A = new A(); + static get():A { + return A.instance; + } +}class A { + private static instance:A = new A(); + static get():A { + return A.instance; + } } \ No newline at end of file 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 f0089549bc3a12ec6d0f3114a9e8a97159b0d7e9..a3ca4dc49beb75905f735b3abcfa3c6742e5e755 100644 --- a/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json +++ b/ets2panda/linter/test/main/no_tuples_arrays.ets.arkts2.json @@ -71,7 +71,7 @@ "endColumn": 59, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -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, @@ -121,7 +131,7 @@ "endColumn": 62, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -161,7 +171,7 @@ "endColumn": 42, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -181,7 +191,7 @@ "endColumn": 53, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -201,7 +211,7 @@ "endColumn": 53, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -221,7 +231,7 @@ "endColumn": 53, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -241,7 +251,7 @@ "endColumn": 43, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -261,7 +271,7 @@ "endColumn": 48, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { @@ -281,7 +291,7 @@ "endColumn": 50, "problem": "ArrayTypeImmutable", "suggest": "", - "rule": "Array types follow the principle of invariance (arkts-array-type-immutable)", + "rule": "Array type is immutable in ArkTS1.2 (arkts-array-type-immutable)", "severity": "ERROR" }, { diff --git a/ets2panda/linter/test/main/numeric_bigint_compare.ets b/ets2panda/linter/test/main/numeric_bigint_compare.ets index 74f1bf97da9e34c1f36711bb6468ee900ae9664f..a8479c4635e10285b980707d889cd92f6e7f0088 100755 --- a/ets2panda/linter/test/main/numeric_bigint_compare.ets +++ b/ets2panda/linter/test/main/numeric_bigint_compare.ets @@ -31,4 +31,53 @@ n1 + n2 n1 - n2 n1 * n2 n1 / n2 -n1 % n2 \ No newline at end of file +n1 % n2 + +function parFunPar(params: boolean) {} +parFunPar(1n > 1.0); +parFunPar(1n < 1.0); +parFunPar(1n >= 1.0); +parFunPar(1n <= 1.0); +parFunPar(1n == 1.0); + +function parFunReturn() : boolean { + return 1n > 1.0; +} +function parFunReturn1() : boolean { + return 1n < 1.0; +} +function parFunReturn2() : boolean { + return 1n >= 1.0; +} +function parFunReturn3() : boolean { + return 1n <= 1.0; +} +function parFunReturn4() : boolean { + return 1n == 1.0; +} + +if (1n > 1.0) { + console.log('1n > 1.0'); +} +if (1n < 1.0) { + console.log('1n < 1.0'); +} +if (1n >= 1.0) { + console.log('1n >= 1.0'); +} +if (1n <= 1.0) { + console.log('1n <= 1.0'); +} +if (1n == 1.0) { + console.log('1n == 1.0'); +} + +let compareA6:boolean = true; +compareA6 = 2n > 1.0 && 1n > 1.5 || 2n >= 2.0; + +const condition = true +compareA6 = ((1n > 1.0) ? (1n < 1.0) : (1n >= 1.0)); +compareA6 = ((1n <= 1.0) ? (1n == 1.0) : (1n > 1.5)); +function comparePar2() { + return 5n > 5.0 || 5n < 5.0 || 5n >= 5.0 || 5n <= 5.0 || 5n == 5.0; +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/numeric_bigint_compare.ets.arkts2.json b/ets2panda/linter/test/main/numeric_bigint_compare.ets.arkts2.json index 09a668e7ce727bac3773cf1a8b9cbe0315ed5cbd..9368614ceed5b359c8064110287393341f32a23b 100755 --- a/ets2panda/linter/test/main/numeric_bigint_compare.ets.arkts2.json +++ b/ets2panda/linter/test/main/numeric_bigint_compare.ets.arkts2.json @@ -103,6 +103,356 @@ "suggest": "", "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", "severity": "ERROR" + }, + { + "line": 29, + "column": 1, + "endLine": 29, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 30, + "column": 1, + "endLine": 30, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 31, + "column": 1, + "endLine": 31, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 32, + "column": 1, + "endLine": 32, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 33, + "column": 1, + "endLine": 33, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 34, + "column": 1, + "endLine": 34, + "endColumn": 8, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 37, + "column": 11, + "endLine": 37, + "endColumn": 19, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 38, + "column": 11, + "endLine": 38, + "endColumn": 19, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 39, + "column": 11, + "endLine": 39, + "endColumn": 20, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 40, + "column": 11, + "endLine": 40, + "endColumn": 20, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 41, + "column": 11, + "endLine": 41, + "endColumn": 20, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 44, + "column": 10, + "endLine": 44, + "endColumn": 18, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 47, + "column": 10, + "endLine": 47, + "endColumn": 18, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 50, + "column": 10, + "endLine": 50, + "endColumn": 19, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 53, + "column": 10, + "endLine": 53, + "endColumn": 19, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 56, + "column": 10, + "endLine": 56, + "endColumn": 19, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 59, + "column": 5, + "endLine": 59, + "endColumn": 13, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 62, + "column": 5, + "endLine": 62, + "endColumn": 13, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 65, + "column": 5, + "endLine": 65, + "endColumn": 14, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 68, + "column": 5, + "endLine": 68, + "endColumn": 14, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 71, + "column": 5, + "endLine": 71, + "endColumn": 14, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 13, + "endLine": 76, + "endColumn": 21, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 25, + "endLine": 76, + "endColumn": 33, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 76, + "column": 37, + "endLine": 76, + "endColumn": 46, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 15, + "endLine": 79, + "endColumn": 23, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 28, + "endLine": 79, + "endColumn": 36, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 79, + "column": 41, + "endLine": 79, + "endColumn": 50, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 15, + "endLine": 80, + "endColumn": 24, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 29, + "endLine": 80, + "endColumn": 38, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 80, + "column": 43, + "endLine": 80, + "endColumn": 51, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 10, + "endLine": 82, + "endColumn": 18, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 22, + "endLine": 82, + "endColumn": 30, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 34, + "endLine": 82, + "endColumn": 43, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 47, + "endLine": 82, + "endColumn": 56, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" + }, + { + "line": 82, + "column": 60, + "endLine": 82, + "endColumn": 69, + "problem": "NumericBigintCompare", + "suggest": "", + "rule": "Not supporting comparison between number type and bigint type (arkts-numeric-bigint-compare)", + "severity": "ERROR" } ] } \ No newline at end of file diff --git a/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json b/ets2panda/linter/test/main/numeric_semantics.ets.arkts2.json index d8d76c5ce87c4221590181e6ea52baac523f6e38..d7c46831b14d25e64f496f10c4261b2b9f132733 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 148d39bc8276e8eda806b5d3325102c8b6e58239..5045e3f3cb2e3b1e3277ea34162c1b85a723a673 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 c86c2373e15de875d2b44d53c7a5dc66cf1713bf..e61c55a40d4fc588a8198f34b1efaf9c10b06728 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 0b572f009af85043603d7fd6254a8a4ff384c34f..f7e900af40abfb93cd87f7510a395c41301531ae 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 e649323550046bb28030db18baa72b90cdfdd326..2a6aa3c53193e0f8f4003a1b85b5b1a39ec1aa29 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 2b4699fa61f8fc34e602920f4759be0300caa0ae..6d6b2576f7863fe6e819a3e25e396fdafc2be4ae 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 cc12e25c14161a7519fb9115fec3540ee4a842d2..ac48689e304276e2328248afd7d21a6e67131e8b 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 8e5ca8740328ce6d6ff6e2c7106760e138b5718d..706c09bb349b3b143c9bc367d7acbc5c014eeb8e 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 9143d0676d166e6b9291a69bf5f6a0bbf880a2b3..972e1c73e2711c3ce1974702ac64b4cf7125523d 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_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 0000000000000000000000000000000000000000..4f8c44b2269e78ee952f21c78af4d88ffe23815e --- /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/interop/static_dynamic_import.ets.args.json b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json similarity index 97% rename from ets2panda/linter/test/interop/static_dynamic_import.ets.args.json rename to ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json index d8d3390ad9befeca9b595017d9eea0f5ada3d049..4acc088d1da62353e56ced57f16b342de413cb78 100644 --- a/ets2panda/linter/test/interop/static_dynamic_import.ets.args.json +++ b/ets2panda/linter/test/main/prop_decorators_and_interfaces_4.ets.args.json @@ -14,6 +14,6 @@ "limitations under the License." ], "mode": { - "arkts2": "" + "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 0000000000000000000000000000000000000000..552209810c02f8d5c445215949809e7ba09e0007 --- /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 0000000000000000000000000000000000000000..ca88f857e960b437dcf767c0ac40be998c8f1236 --- /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 diff --git a/ets2panda/linter/test/main/prop_name_from_value.ets b/ets2panda/linter/test/main/prop_name_from_value.ets index bdfdc1a80d5529ad17bdec94f11f1a0e7e493de8..d511b494ee584fc16dd2ce5c2e4d2a7f1c279865 100644 --- a/ets2panda/linter/test/main/prop_name_from_value.ets +++ b/ets2panda/linter/test/main/prop_name_from_value.ets @@ -22,4 +22,11 @@ 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 arrVal = arr[1]; //legal +let a = 1; +let b = 2.3; +let c = "str"; +let d3 = TEST[TEST.A]; +let d4 = TEST[a]; +let d5 = TEST[b]; +let d2 = TEST['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 4218268d314b5d23e17b0cb47ab709da3f410059..60d761a98ee1621b8579dbcbdf3b323d42aa1278 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,96 @@ "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" + }, + { + "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": 29, + "column": 10, + "endLine": 29, + "endColumn": 22, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "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 2505d44ef896812a12606f6913efcc4792763d22..574d747586c6583c0d0e6cc13c51346e0b256267 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,226 @@ "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": 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": 101, + "column": 1, + "endLine": 101, + "endColumn": 26, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 102, + "column": 1, + "endLine": 102, + "endColumn": 25, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, + { + "line": 103, + "column": 1, + "endLine": 103, + "endColumn": 25, + "problem": "UnsupportPropNameFromValue", + "suggest": "", + "rule": "Enum cannot get member name by member value (arkts-unsupport-prop-name-from-value)", + "severity": "ERROR" + }, { "line": 105, "column": 31, @@ -631,7 +881,7 @@ "endColumn": 31, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { @@ -674,6 +924,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 071dffbe54d7b371f9c3d04390e1ea8bff75b602..f7b6b0c4e8884b33423b670eb5fd2bbea6c10068 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 b/ets2panda/linter/test/main/structural_identity.ets index eae4133097d265060b89928949fb24982901a27b..406a7fee8edd059aa887b3e5d1f5e2eed7c97258 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 1a9ca3c7cfd29082482d0da6d3c02b04726fdfde..89cd070221de4abd16abf56e37ba1cec76a7c1be 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, @@ -1583,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 diff --git a/ets2panda/linter/test/main/swicth_expr.ets.arkts2.json b/ets2panda/linter/test/main/swicth_expr.ets.arkts2.json index 29b100aba1877bd1022c6fa33b014a9d04edb9b5..5ce55a54ac3b3b4b94d6b10bf24348f2a15a4a24 100755 --- a/ets2panda/linter/test/main/swicth_expr.ets.arkts2.json +++ b/ets2panda/linter/test/main/swicth_expr.ets.arkts2.json @@ -621,7 +621,7 @@ "endColumn": 32, "problem": "CreatingPrimitiveTypes", "suggest": "", - "rule": "ArkTS creating primitive types is not supported (arkts-primitive-type-normalization)", + "rule": "Primitive types are normalized with their boxed type (arkts-primitive-type-normalization)", "severity": "ERROR" }, { diff --git a/ets2panda/linter/test/main/ts_overload.ets b/ets2panda/linter/test/main/ts_overload.ets index 40fc4f8024538c335a635959fa461f831bb70fd9..d6a903fb5b31ca585cdefe3e5a95fefb02c3629d 100644 --- a/ets2panda/linter/test/main/ts_overload.ets +++ b/ets2panda/linter/test/main/ts_overload.ets @@ -13,9 +13,9 @@ * limitations under the License. */ -function makeDate(timestamp: number): Date; -function makeDate(m: number, d: number, y: number): Date; -function makeDate(mOrTimestamp: number, d?: number, y?: number): Date { +function makeDate(timestamp: number): Date; //error +function makeDate(m: number, d: number, y: number): Date; //error +function makeDate(mOrTimestamp: number, d?: number, y?: number): Date { //error if (d !== undefined && y !== undefined) { return new Date(y, mOrTimestamp, d); } else { @@ -27,15 +27,15 @@ const d2 = makeDate(5, 5, 5); const d3 = makeDate(1, 3); class Vector { - abstract foo(): void - abstract foo(x: string): void - abstract foo(x?: string): void { + abstract foo(): void //error + abstract foo(x: string): void //error + abstract foo(x?: string): void { //error /body/ } - public fun(): void - public fun(x: string): void - public fun(x?: string): void { + public fun(): void //error + public fun(x: string): void //error + public fun(x?: string): void { //error /body/ } } @@ -47,11 +47,11 @@ abstract class absClass { /body/ } - constructor(x: number, y: number); + constructor(x: number, y: number); //error - constructor(magnitude: number); + constructor(magnitude: number); //error - constructor(...args: number[]) { + constructor(...args: number[]) { //error /* ... */ } } @@ -59,4 +59,30 @@ function func(){ console.log("ArkTs foo4") } -func.val = "0xff"; \ No newline at end of file +func.val = "0xff"; + +@Component +struct B{ + constructor() { + super() + } + build() { + } +} + +struct C{ + constructor() { //error + super() + } + constructor(x:number) //error +} + +class A{ + constructor() { + } +} +class D{ + constructor() { //error + } + constructor(x:number) //error +} \ No newline at end of file diff --git a/ets2panda/linter/test/main/ts_overload.ets.arkts2.json b/ets2panda/linter/test/main/ts_overload.ets.arkts2.json index cd9bd6a42cd4866538aa090bd2d9d0daf5911c47..3f46c402c29de60fc616890530c45d2daddab902 100644 --- a/ets2panda/linter/test/main/ts_overload.ets.arkts2.json +++ b/ets2panda/linter/test/main/ts_overload.ets.arkts2.json @@ -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, @@ -233,6 +253,56 @@ "suggest": "", "rule": "Declaring properties on functions is not supported (arkts-no-func-props)", "severity": "ERROR" + }, + { + "line": 74, + "column": 3, + "endLine": 76, + "endColumn": 4, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 77, + "column": 3, + "endLine": 77, + "endColumn": 24, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 85, + "column": 3, + "endLine": 86, + "endColumn": 4, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 87, + "column": 3, + "endLine": 87, + "endColumn": 24, + "problem": "TsOverload", + "suggest": "", + "rule": "Class TS overloading is not supported(arkts-no-ts-overload)", + "severity": "ERROR" + }, + { + "line": 64, + "column": 2, + "endLine": 64, + "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/rules/rule37.ets.migrate.json b/ets2panda/linter/test/rules/rule37.ets.migrate.json index ca88f857e960b437dcf767c0ac40be998c8f1236..0a1c7ec09788dc01f74297d811e3c342a1e47d88 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 f2d125c5784100f6d7f32f00cfe38427f50a997b..84106d351ab25809f282d4840cec7be3e42bdfe5 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, diff --git a/ets2panda/linter/test/sdkwhite/return_new_interface.ets.arkts2.json b/ets2panda/linter/test/sdkwhite/return_new_interface.ets.arkts2.json index 92f597960e2eead0bfad0cdde65d9981dff2b182..7b974d3450d22c88c7a7dedab6df6e5722470b8d 100644 --- a/ets2panda/linter/test/sdkwhite/return_new_interface.ets.arkts2.json +++ b/ets2panda/linter/test/sdkwhite/return_new_interface.ets.arkts2.json @@ -49,9 +49,9 @@ "column": 14, "endLine": 26, "endColumn": 15, - "problem": "ConstructorIface", + "problem": "ConstructorIfaceFromSdk", "suggest": "", - "rule": "Construct signatures are not supported in interfaces (arkts-no-ctor-signatures-iface)", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", "severity": "ERROR" }, { @@ -79,9 +79,9 @@ "column": 14, "endLine": 30, "endColumn": 15, - "problem": "ConstructorIface", + "problem": "ConstructorIfaceFromSdk", "suggest": "", - "rule": "Construct signatures are not supported in interfaces (arkts-no-ctor-signatures-iface)", + "rule": "Construct signatures are not supported in interfaces.(sdk-ctor-signatures-iface)", "severity": "ERROR" }, { @@ -95,4 +95,4 @@ "severity": "ERROR" } ] -} \ No newline at end of file +} diff --git a/ets2panda/lsp/BUILD.gn b/ets2panda/lsp/BUILD.gn index 74d79eb907fc43edb89e5cfcdac2011797a3092c..94fcff39bac361fc01a4053e509578148d87b9fe 100644 --- a/ets2panda/lsp/BUILD.gn +++ b/ets2panda/lsp/BUILD.gn @@ -47,41 +47,50 @@ ohos_source_set("libes2panda_lsp_static") { "src/class_hierarchy.cpp", "src/class_hierarchy_info.cpp", "src/classifier.cpp", + "src/code_fix_provider.cpp", "src/completions.cpp", "src/completions_details.cpp", "src/create_type_help_items.cpp", - "src/find_safe_delete_location.cpp", "src/find_references.cpp", "src/find_rename_locations.cpp", + "src/find_safe_delete_location.cpp", + "src/formatting/formatting.cpp", "src/formatting/formatting_context.cpp", "src/formatting/formatting_settings.cpp", - "src/formatting/formatting.cpp", - "src/formatting/rules_map.cpp", "src/formatting/rules.cpp", + "src/formatting/rules_map.cpp", + "src/generate_constructor.cpp", "src/get_adjusted_location.cpp", + "src/get_class_property_info.cpp", "src/get_definition_and_bound_span.cpp", - "src/inlay_hints.cpp", "src/get_safe_delete_info.cpp", + "src/inlay_hints.cpp", "src/internal_api.cpp", "src/isolated_declaration.cpp", "src/line_column_offset.cpp", + "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/generate_constructor.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", + "src/register_code_fix/forgetten_this_property_access.cpp", + "src/register_code_fix/import_fixes.cpp", "src/rename.cpp", "src/script_element_kind.cpp", "src/services/services.cpp", + "src/services/text_change/change_tracker.cpp", "src/services/utilities.cpp", "src/signature_help.cpp", "src/signature_help_items.cpp", - "src/get_class_property_info.cpp", "src/string_completions.cpp", "src/suggestion_diagnostics.cpp", "src/todo_comments.cpp", "src/types.cpp", - "src/navigate_to.cpp", ] configs = [ "$ark_root/assembler:arkassembler_public_config", diff --git a/ets2panda/lsp/CMakeLists.txt b/ets2panda/lsp/CMakeLists.txt index 70e7152b2f83ea4661061eeff0de79d48159affb..41272e7af7e9cc293fbe41a3831284aa79fa051f 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 @@ -44,7 +46,8 @@ set(ES2PANDA_LSP_SRC ./src/services/services.cpp ./src/services/utilities.cpp ./src/line_column_offset.cpp - ./src/text_change/change_tracker.cpp + ./src/services/text_change/change_tracker.cpp + ./src/code_fix_provider.cpp ./src/inlay_hints.cpp ./src/get_class_property_info.cpp ./src/create_type_help_items.cpp @@ -55,6 +58,12 @@ set(ES2PANDA_LSP_SRC ./src/get_definition_and_bound_span.cpp ./src/types.cpp ./src/navigate_to.cpp + ./src/code_fix_provider.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 + ./src/register_code_fix/forgetten_this_property_access.cpp + ./src/register_code_fix/import_fixes.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 aeee5e477281963987bf1060a3f011a86362fe0b..424200a26f9ead0311d556562872872b431580a7 100644 --- a/ets2panda/lsp/include/api.h +++ b/ets2panda/lsp/include/api.h @@ -28,14 +28,18 @@ #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" +#include "formatting/formatting_settings.h" +#include "user_preferences.h" #ifdef __cplusplus extern "C" { @@ -67,18 +71,6 @@ typedef struct References { std::vector referenceInfos; } References; -struct TextChange { - TextSpan span; - std::string newText; - TextChange(TextSpan s, const std::string &t) : span(s), newText(t) {} -}; - -struct FileTextChanges { - std::string fileName; - std::vector textChanges; - FileTextChanges(const std::string &f, const std::vector &t) : fileName(f), textChanges(t) {} -}; - typedef struct Position { size_t line_; // Line number size_t character_; // Character position in the line @@ -227,6 +219,13 @@ struct FieldsInfo { { return name < other.name; } + FieldsInfo() = default; + FieldsInfo(const FieldsInfo &fi) : name(fi.name), properties(fi.properties) {} +}; + +struct LspClassPropertyInfo { + FieldsInfo fieldsInfo; + LspClassPropertyInfo(FieldsInfo f) : fieldsInfo(std::move(f)) {} }; typedef struct DocumentHighlightsReferences { @@ -262,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_; @@ -474,17 +457,46 @@ struct TypeHierarchiesInfo { TypeHierarchies subHierarchies; }; +struct InstallPackageActionInfo { + std::string type_; + std::optional file; + std::optional packageName; +}; + +struct CodeActionInfo { + std::string description_; + std::vector changes_; + std::vector commands_; +}; + +struct CombinedCodeActionsInfo { + std::vector changes_; + std::vector commands_; +}; + +struct CodeFixActionInfo : CodeActionInfo { + std::string fixName_; + std::string fixId_ = {}; + std::string fixAllDescription_ = {}; +}; + +struct CodeFixOptions { + ark::es2panda::lsp::CancellationToken token; + ark::es2panda::lsp::FormatCodeSettings options; + ark::es2panda::lsp::UserPreferences preferences; +}; + 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); References (*getFileReferences)(char const *fileName, es2panda_Context *context, bool isPackageModule); DeclInfo (*getDeclInfo)(es2panda_Context *context, size_t position); std::vector (*getClassHierarchiesImpl)(es2panda_Context *context, - const std::string &fileName, + const char *fileName, size_t pos); bool (*getSafeDeleteInfo)(es2panda_Context *context, size_t position, const char *path); References (*getReferencesAtPosition)(es2panda_Context *context, DeclInfo *declInfo); @@ -517,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)( @@ -526,14 +538,15 @@ 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, + size_t end_position, std::vector &errorCodes, + CodeFixOptions &codeFixOptions); + CombinedCodeActionsInfo (*getCombinedCodeFix)(const char *fileName, const std::string &fixId, + CodeFixOptions &codeFixOptions); } LSPAPI; - CAPI_EXPORT LSPAPI const *GetImpl(); - // NOLINTEND - #ifdef __cplusplus } #endif - -#endif +#endif \ No newline at end of file diff --git a/ets2panda/lsp/include/applicable_refactors.h b/ets2panda/lsp/include/applicable_refactors.h index 3329f8891f2f4a3ef31fd613789fd4cb9e541f3a..9d736ddbf8f6f000991cfad4f016c39650a0aa7a 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/class_hierarchy_info.h b/ets2panda/lsp/include/class_hierarchy_info.h index 9bec05817b847666682e1fe77f74a83a332f1929..f7730151ede001b7006a22b2b6df3ba85a471e43 100644 --- a/ets2panda/lsp/include/class_hierarchy_info.h +++ b/ets2panda/lsp/include/class_hierarchy_info.h @@ -52,7 +52,7 @@ enum class AccessModifierStyle { PUBLIC = 0, PROTECTED, PRIVATE }; class ClassMethodItem { public: ClassMethodItem(std::string detail, SetterStyle setter, AccessModifierStyle access) - : detail_(std::move(detail)), setter_(setter), accessMoodifier_(access) + : detail_(std::move(detail)), setter_(setter), accessModifier_(access) { } @@ -88,14 +88,14 @@ public: AccessModifierStyle GetAccessModifierStyle() const { - return accessMoodifier_; + return accessModifier_; } private: std::string funcName_; std::string detail_; SetterStyle setter_; - AccessModifierStyle accessMoodifier_; + AccessModifierStyle accessModifier_; }; class ClassHierarchyInfo { diff --git a/ets2panda/lsp/include/code_fix_provider.h b/ets2panda/lsp/include/code_fix_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..7d18b2d7c4166d209d831d8fa0ef82d90c37821f --- /dev/null +++ b/ets2panda/lsp/include/code_fix_provider.h @@ -0,0 +1,85 @@ +/** + * 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 CODE_FIX_PROVIDER_H +#define CODE_FIX_PROVIDER_H +#include +#include +#include +#include +#include "services/text_change/change_tracker.h" +#include "code_fixes/code_fix_types.h" +#include "es2panda.h" + +namespace ark::es2panda::lsp { + +class CodeFixProvider { +private: + std::unordered_map> errorCodeToFixes_; + std::unordered_map> fixIdToRegistration_; + +public: + std::unordered_map> GetErrorCodeToFixes() const + { + return errorCodeToFixes_; + } + std::unordered_map> GetFixIdToRegistration() const + { + return fixIdToRegistration_; + } + + void RegisterCodeFix(const std::string &aliasName, std::unique_ptr registration); + static CodeFixProvider &Instance(); + + std::string FormatWithArgs(const std::string &text); + std::string DiagnosticToString(const DiagnosticAndArguments &diag); + CodeFixAction CreateCodeFixActionWorker(std::string &fixName, std::string &description, + std::vector &changes, std::string &fixId, + std::string &fixAllDescription, std::vector command); + + CodeFixAction CreateCodeFixActionWithoutFixAll(std::string &fixName, std::vector &changes, + DiagnosticAndArguments &description); + CodeFixAction CreateCodeFixAction(std::string fixName, std::vector changes, + DiagnosticAndArguments &description, std::string fixId, + DiagnosticAndArguments &fixAllDescription, + std::vector &command); + std::string GetFileName(const std::string &filePath); + std::vector GetSupportedErrorCodes(); + DiagnosticReferences *GetDiagnostics(const CodeFixContextBase &context); + + bool ShouldIncludeFixAll(const CodeFixRegistration ®istration, const std::vector &diagnostics); + std::vector GetFixes(const CodeFixContext &context); + void EachDiagnostic(const CodeFixAllContext &context, const std::vector &errorCodes, + const std::function &cb); + CombinedCodeActions CodeFixAll(const CodeFixAllContext &context, const std::vector &errorCodes, + std::function use); + FileTextChanges CreateFileTextChanges(const std::string &fileName, const std::vector &textChanges); + + CombinedCodeActions GetAllFixes(const CodeFixAllContext &context); +}; + +template +struct AutoCodeFixRegister { + constexpr explicit AutoCodeFixRegister(const std::string &name, std::unique_ptr registration) + { + CodeFixProvider::Instance().RegisterCodeFix(name, std::move(registration)); + } + + constexpr explicit AutoCodeFixRegister(const std::string &name) : AutoCodeFixRegister(name, std::make_unique()) + { + } +}; +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/include/code_fixes/code_fix_types.h b/ets2panda/lsp/include/code_fixes/code_fix_types.h new file mode 100644 index 0000000000000000000000000000000000000000..1e38c16cb7165ebe86e051f26c6f880188052c83 --- /dev/null +++ b/ets2panda/lsp/include/code_fixes/code_fix_types.h @@ -0,0 +1,120 @@ +/** + * 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 CODE_FIX_TYPES_H +#define CODE_FIX_TYPES_H + +#include +#include +#include +#include +#include +#include "../user_preferences.h" +#include "../cancellation_token.h" +#include "../types.h" +#include "../api.h" +#include "es2panda.h" +#include "public/es2panda_lib.h" +#include "public/public.h" +#include "../get_class_property_info.h" + +namespace ark::es2panda::lsp { + +enum DiagnosticCategory { WARNING, ERROR, SUGGESTION, MESSAGE }; + +struct DiagnosticMessage { + std::string key; + DiagnosticCategory category; + size_t code; + std::string message; + std::string reportsUnnecessary = {}; + std::string reportsDeprecated = {}; + bool elidedInCompatabilityPyramid; +}; +struct DiagnosticAndArguments { + DiagnosticMessage message; + std::vector arguments; +}; + +struct CodeAction { + std::string description; + std::vector changes; + std::vector commands; +}; +struct CombinedCodeActions { + std::vector changes; + std::vector commands; +}; +struct CodeFixAction : CodeAction { + std::string fixName; + std::string fixId = {}; + std::string fixAllDescription = {}; +}; + +struct CodeFixContextBase : TextChangesContext { + es2panda_Context *context; + CancellationToken cancellationToken; +}; + +struct CodeFixAllContext : CodeFixContextBase { + std::string fixId = {}; +}; + +struct DiagnosticWithLocation : Diagnostic { + SourceFile file; + size_t start = 0; + size_t length = 0; +}; + +struct CodeFixContext : CodeFixContextBase { + int errorCode = 0; + TextSpan span = {0, 0}; +}; + +class CodeFixRegistration { +private: + std::vector errorCodes_; + std::vector fixIds_; + +public: + std::vector GetErrorCodes() const + { + return errorCodes_; + } + std::vector GetFixIds() const + { + return fixIds_; + } + void SetErrorCodes(const std::vector &codes) + { + errorCodes_ = codes; + } + void SetFixIds(const std::vector &ids) + { + fixIds_ = ids; + } + virtual std::vector GetCodeActions(const CodeFixContext &) = 0; + virtual CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &) = 0; + CodeFixRegistration() = default; + CodeFixRegistration(const CodeFixRegistration &) = delete; + CodeFixRegistration &operator=(const CodeFixRegistration &) = delete; + CodeFixRegistration(CodeFixRegistration &&) = delete; + CodeFixRegistration &operator=(CodeFixRegistration &&) = delete; + virtual ~CodeFixRegistration() = default; +}; + +} // namespace ark::es2panda::lsp + +#endif diff --git a/ets2panda/lsp/include/get_class_property_info.h b/ets2panda/lsp/include/get_class_property_info.h index c73cd691655e7213d281033d5430ff6e7239a1da..5dcc804ef0f68d68cc07f71540452c2ed9ce5db5 100644 --- a/ets2panda/lsp/include/get_class_property_info.h +++ b/ets2panda/lsp/include/get_class_property_info.h @@ -28,15 +28,16 @@ #include "api.h" #include "internal_api.h" #include "public/public.h" +#include "types.h" namespace ark::es2panda::lsp { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) struct InstallPackageAction { - const std::string type_; + std::string type; std::optional file; std::optional packageName; - InstallPackageAction() : type_("install package") {} + InstallPackageAction() : type("install package") {} }; using CodeActionCommand = InstallPackageAction; diff --git a/ets2panda/lsp/include/internal_api.h b/ets2panda/lsp/include/internal_api.h index 0ee6acab8fbf2f7267cee83cca9991f948ba129c..9d1f8ff9b669def2e1c67fc8f40f65fad351df29 100644 --- a/ets2panda/lsp/include/internal_api.h +++ b/ets2panda/lsp/include/internal_api.h @@ -88,6 +88,11 @@ std::string GetOwnerId(ir::AstNode *node); std::string GetIdentifierName(ir::AstNode *node); bool NodeHasTokens(const ir::AstNode *node); void FindAllChild(const ir::AstNode *ast, const ir::NodePredicate &cb, ArenaVector &results); +std::vector GetCodeFixesAtPositionImpl(es2panda_Context *context, size_t startPosition, + size_t endPosition, std::vector &errorCodes, + CodeFixOptions &codeFixOptions); +CombinedCodeActionsInfo GetCombinedCodeFixImpl(es2panda_Context *context, const std::string &fixId, + CodeFixOptions &codeFixOptions); } // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/include/refactor_provider.h b/ets2panda/lsp/include/refactor_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..dbd529c2c2ef5579f156d61d4456c4dc6a432e69 --- /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 2b9767164bc3209a865ff62c93337bc295354924..5581ab3dd52ded479126c416070681b49c9007f3 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 0000000000000000000000000000000000000000..72e3dd74ea783ce9bd5ad063c226788b5cedb81c --- /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/register_code_fix/add_missing_declare_property.h b/ets2panda/lsp/include/register_code_fix/add_missing_declare_property.h new file mode 100644 index 0000000000000000000000000000000000000000..304f15ee4cbf075ba0a7b47dc929ba7b2177c224 --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/add_missing_declare_property.h @@ -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. + */ + +#ifndef ADD_MISSING_DECLARE_PROPERTY_H +#define ADD_MISSING_DECLARE_PROPERTY_H + +#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 { + +void MakeChange(ChangeTracker changeTracker, es2panda_Context *context, size_t pos, + std::vector &fixedNodes); + +std::vector GetCodeActionsToAddMissingDeclareOnProperty(const CodeFixContext &context); + +class AddMissingDeclareProperty : public CodeFixRegistration { +public: + AddMissingDeclareProperty(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; +}; + +} // namespace ark::es2panda::lsp + +#endif \ No newline at end of file diff --git a/ets2panda/lsp/include/register_code_fix/fix_missing_call_parantheses.h b/ets2panda/lsp/include/register_code_fix/fix_missing_call_parantheses.h new file mode 100644 index 0000000000000000000000000000000000000000..c2c50e1dde12c3e57939fda73a7be0de8d5bb572 --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/fix_missing_call_parantheses.h @@ -0,0 +1,37 @@ +/** + * 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_MISSING_CALL_PARANTHESES_H +#define FIX_MISSING_CALL_PARANTHESES_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 FixMissingCallParantheses : public CodeFixRegistration { +public: + FixMissingCallParantheses(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; +}; + +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/include/register_code_fix/fix_nan_equality.h b/ets2panda/lsp/include/register_code_fix/fix_nan_equality.h new file mode 100644 index 0000000000000000000000000000000000000000..b88fbe5287806bca9e808ccb43a4834ae5df2997 --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/fix_nan_equality.h @@ -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. + */ + +#ifndef FIX_NAN_EQUALITY_H +#define FIX_NAN_EQUALITY_H + +#include +#include +#include "code_fixes/code_fix_types.h" +#include "services/text_change/change_tracker.h" +#include "lsp/include/types.h" + +namespace ark::es2panda::lsp { + +class FixNaNEquality : public CodeFixRegistration { +public: + FixNaNEquality(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; + +private: + void MakeChangeForNaNEquality(ChangeTracker &changeTracker, es2panda_Context *context, size_t pos, + std::vector &fixedNodes); + + std::vector GetCodeActionsToFixNaNEquality(const CodeFixContext &context); +}; + +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/include/register_code_fix/forgetten_this_property_access.h b/ets2panda/lsp/include/register_code_fix/forgetten_this_property_access.h new file mode 100644 index 0000000000000000000000000000000000000000..d5ea48b3195fad2cff697cf846cecb0af4919067 --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/forgetten_this_property_access.h @@ -0,0 +1,37 @@ +/** + * 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 FORGOTTEN_THIS_PROPERTY_ACCESS_H +#define FORGOTTEN_THIS_PROPERTY_ACCESS_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 ForgettenThisPropertyAccess : public CodeFixRegistration { +public: + ForgettenThisPropertyAccess(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; +}; + +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/include/register_code_fix/import_fixes.h b/ets2panda/lsp/include/register_code_fix/import_fixes.h new file mode 100644 index 0000000000000000000000000000000000000000..97da8872f2b60bdd7a5d1567171b827b3565c62a --- /dev/null +++ b/ets2panda/lsp/include/register_code_fix/import_fixes.h @@ -0,0 +1,37 @@ +/** + * 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 "code_fixes/code_fix_types.h" +#include "services/text_change/change_tracker.h" +#include "types.h" + +namespace ark::es2panda::lsp { + +class ImportFixes : public CodeFixRegistration { +public: + ImportFixes(); + + std::vector GetCodeActions(const CodeFixContext &context) override; + + CombinedCodeActions GetAllCodeActions(const CodeFixAllContext &codeFixAll) override; +}; + +} // namespace ark::es2panda::lsp +#endif diff --git a/ets2panda/lsp/include/text_change/change_tracker.h b/ets2panda/lsp/include/services/text_change/change_tracker.h similarity index 91% rename from ets2panda/lsp/include/text_change/change_tracker.h rename to ets2panda/lsp/include/services/text_change/change_tracker.h index 326e7c3bf54c025db0761ea7bff1562e4f44f5d4..d7d6d1042b99312fa3aa452a34ffbc7e54f5a2e8 100644 --- a/ets2panda/lsp/include/text_change/change_tracker.h +++ b/ets2panda/lsp/include/services/text_change/change_tracker.h @@ -34,12 +34,10 @@ namespace ark::es2panda::lsp { -// Trivia Options -enum class LeadingTriviaOption { EXCLUDE, INCLUDEALL, JSDOC, STARTLINE }; +enum class LeadingTriviaOption { EXCLUDE, INCLUDEALL, STARTLINE }; enum class TrailingTriviaOption { EXCLUDE, EXCLUDEWHITESPACE, INCLUDE }; -// Configurable Trivia Options struct ConfigurableStart { std::optional leadingTriviaOption; }; @@ -48,17 +46,11 @@ struct ConfigurableEnd { std::optional trailingTriviaOption; }; -struct TextRange { - size_t pos; - size_t end; -}; - struct ConfigurableStartEnd { std::optional leadingTriviaOption; std::optional trailingTriviaOption; }; -// InsertNodeOptions & Extensions struct InsertNodeOptions { std::optional prefix; std::optional suffix; @@ -75,7 +67,6 @@ struct ChangeNodeOptions { std::optional insertNodeOptions; }; -// ChangeKind Enum enum class ChangeKind { REMOVE, REPLACEWITHSINGLENODE, REPLACEWITHMULTIPLENODES, TEXT }; struct ChangeText { @@ -85,7 +76,6 @@ struct ChangeText { std::string text; }; -// Change Variants struct ReplaceWithSingleNode { const SourceFile *sourceFile; TextRange range; @@ -105,31 +95,16 @@ struct RemoveNode { const SourceFile *sourceFile; TextRange range; ChangeKind kind = ChangeKind::REMOVE; - // node and options are "never", so not present -}; - -struct FileTextChanges { - std::string fileName; - std::vector textChanges; - bool isNewFile = false; }; -// Union Type: Change - struct NewFile { std::optional oldFile; std::string fileName; - std::vector statements; // int for NewLineTrivia + std::vector statements; }; using Change = std::variant; -// Public constructor -struct LanguageServiceHost {}; -struct TextChangesContext { - LanguageServiceHost host = {}; - FormatContext formatContext; - UserPreferences preferences; -}; + struct DeletedNode { const SourceFile *sourceFile; const std::variant> &node; @@ -138,13 +113,13 @@ struct DeletedNode { struct NewFileStruct { std::optional oldFile; std::string fileName; - std::vector> statements; // int for NewLineTrivia + std::vector> statements; }; using ValidateNonFormattedText = std::function; struct ClassInsertInfo { - ir::AstNode *node; // Could be ClassLikeDeclaration, InterfaceDeclaration, or ObjectLiteralExpression + ir::AstNode *node; SourceFile *sourceFile; }; @@ -177,6 +152,8 @@ private: InsertNodeOptions GetInsertNodeAfterOptionsWorker(const ir::AstNode *node); void InsertNodeInListAfterMultiLine(bool multilineList, es2panda_Context *context, const SourceFile *sourceFile, size_t end, const ir::AstNode *newNode); + std::vector GetTextChangesFromChanges(std::vector &changes, std::string &newLineCharacter, + const FormatCodeSettings &formatCodeSettings); std::vector deletedNodes_; std::vector changes_; std::vector newFiles_; @@ -201,11 +178,12 @@ public: } static ChangeTracker FromContext(TextChangesContext &context); - static std::vector With(TextChangesContext &context, const std::function &cb); + static std::vector With(TextChangesContext &context, + const std::function &cb); void PushRaw(const SourceFile *sourceFile, const FileTextChanges &change); void DeleteRange(const SourceFile *sourceFile, TextRange range); - std::vector GetChanges(); + std::vector GetChanges(); void Delete(const SourceFile *sourceFile, std::variant> &node); TextRange GetAdjustedRange(es2panda_Context *context, ir::AstNode *startNode, ir::AstNode *endNode); diff --git a/ets2panda/lsp/include/types.h b/ets2panda/lsp/include/types.h index 73ddbc65a65341b3f32b9320e7bc160f80cdf416..438144e733adeacb158b09c643bef25431661f35 100644 --- a/ets2panda/lsp/include/types.h +++ b/ets2panda/lsp/include/types.h @@ -19,6 +19,8 @@ #include #include #include +#include "formatting/formatting.h" +#include "user_preferences.h" // NOLINTBEGIN @@ -78,6 +80,19 @@ public: } }; +struct TextChange { + TextSpan span; + std::string newText; + TextChange(TextSpan s, const std::string &t) : span(s), newText(t) {} +}; + +struct FileTextChanges { + std::string fileName; + std::vector textChanges; + FileTextChanges(const std::string &f, const std::vector &t) : fileName(f), textChanges(t) {} + FileTextChanges() = default; +}; + enum class InlayHintKind { TYPE, PARAMETER, @@ -207,6 +222,16 @@ public: } }; +struct LanguageServiceHost { + std::string name = "lsp"; +}; + +struct TextChangesContext { + LanguageServiceHost host = {}; + ark::es2panda::lsp::FormatContext formatContext; + ark::es2panda::lsp::UserPreferences preferences; +}; + struct SignatureHelpItems { private: std::vector items_; diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index f3b669a7dd89e4d8d1704c250620d1aeb08c7313..38f34cb0d292b8e1175e0af2cbd60e8b96b6e3f6 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -101,10 +101,9 @@ DeclInfo GetDeclInfo(es2panda_Context *context, size_t position) return result; } -std::vector GetClassHierarchies(es2panda_Context *context, const std::string &fileName, - size_t pos) +std::vector GetClassHierarchies(es2panda_Context *context, const char *fileName, size_t pos) { - return GetClassHierarchiesImpl(context, fileName, pos); + return GetClassHierarchiesImpl(context, std::string(fileName), pos); } bool GetSafeDeleteInfo(es2panda_Context *context, size_t position, const char *path) @@ -339,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; } @@ -372,6 +371,26 @@ 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) +{ + 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; +} + +CombinedCodeActionsInfo GetCombinedCodeFix(const char *fileName, const std::string &fixId, + CodeFixOptions &codeFixOptions) +{ + Initializer initializer = Initializer(); + auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED); + auto result = ark::es2panda::lsp::GetCombinedCodeFixImpl(context, fixId, codeFixOptions); + initializer.DestroyContext(context); + return result; +} LSPAPI g_lspImpl = {GetDefinitionAtPosition, GetApplicableRefactors, @@ -408,7 +427,9 @@ LSPAPI g_lspImpl = {GetDefinitionAtPosition, ToLineColumnOffsetWrapper, GetTodoComments, ProvideInlayHints, - GetSignatureHelpItems}; + GetSignatureHelpItems, + GetCodeFixesAtPosition, + GetCombinedCodeFix}; } // namespace ark::es2panda::lsp CAPI_EXPORT LSPAPI const *GetImpl() diff --git a/ets2panda/lsp/src/applicable_refactors.cpp b/ets2panda/lsp/src/applicable_refactors.cpp index 20a8994900bba09f10a938eacc52b96b9e5ab99a..602cfeb76c8a38fd3139a3abc190aa102847003c 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/class_hierarchy.cpp b/ets2panda/lsp/src/class_hierarchy.cpp index 7022639d66af7b6a25c7686724a7ddf2bb71c857..368a3ac5a5826d1138e601210bf7cfa4afe7fbac 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/lsp/src/class_hierarchy_info.cpp b/ets2panda/lsp/src/class_hierarchy_info.cpp index 1363ee9b88dc43f885126220b48a65aa644bfc90..6534cd30d9335201bfa4f3a73712978181aae7ed 100644 --- a/ets2panda/lsp/src/class_hierarchy_info.cpp +++ b/ets2panda/lsp/src/class_hierarchy_info.cpp @@ -261,29 +261,31 @@ void ProcessClassHierarchy(const ir::AstNode *token, const ClassHierarchyInfo &b ProcessClassHierarchy(superClass, baseInfo, result); } -ClassHierarchyInfo GetCurrentTokenClassHierarchyInfo(const ir::AstNode *token) +ir::AstNode *GetTargetClassDeclarationByPosition(es2panda_Context *context, size_t position) { - ClassHierarchyInfo currentInfo; - auto classDefinition = GetClassDefinitionFromIdentifierNode(token); - if (classDefinition == nullptr) { - return currentInfo; + if (context == nullptr) { + return nullptr; + } + auto token = GetTouchingToken(context, position, false); + auto tmp = token; + while (tmp != nullptr) { + if (tmp->IsClassDeclaration()) { + return tmp; + } + tmp = tmp->Parent(); } - auto className = GetNameFromIdentifierNode(token); - return CreateClassHierarchyInfoFromBody(classDefinition, className, true); + return nullptr; } ClassHierarchy GetClassHierarchyInfoImpl(es2panda_Context *context, size_t position) { ClassHierarchy result; - if (context == nullptr) { - return result; - } - auto token = GetTouchingToken(context, position, false); - if (token == nullptr || !token->IsIdentifier()) { + auto classDeclaration = GetTargetClassDeclarationByPosition(context, position); + if (classDeclaration == nullptr) { return result; } - auto currentInfo = GetCurrentTokenClassHierarchyInfo(token); - auto classDefinition = GetClassDefinitionFromIdentifierNode(token); + auto classDefinition = classDeclaration->AsClassDeclaration()->Definition(); + auto currentInfo = CreateClassHierarchyInfoFromBody(classDefinition, "", true); auto superClass = GetSuperClassNode(classDefinition); if (superClass == nullptr) { return result; diff --git a/ets2panda/lsp/src/code_fix_provider.cpp b/ets2panda/lsp/src/code_fix_provider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..184391276794fd48e7cc179c37b4d68d515d62f7 --- /dev/null +++ b/ets2panda/lsp/src/code_fix_provider.cpp @@ -0,0 +1,234 @@ +/* + * 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/code_fix_provider.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { + +void CodeFixProvider::RegisterCodeFix(const std::string &aliasName, std::unique_ptr registration) +{ + if (aliasName.empty()) { + ASSERT("Alias name cannot be empty"); + } + auto shared = std::shared_ptr(std::move(registration)); + + for (auto error : shared->GetErrorCodes()) { + errorCodeToFixes_.emplace(std::to_string(error), shared); + } + if (!shared->GetFixIds().empty()) { + for (const auto &fixId : shared->GetFixIds()) { + fixIdToRegistration_.emplace(fixId, shared); + } + } +} + +CodeFixProvider &CodeFixProvider::Instance() +{ + static CodeFixProvider instance; + return instance; +} + +std::string CodeFixProvider::FormatWithArgs(const std::string &text) +{ + std::string result = text; + const std::string regExp = R"(\{(\d+)\})"; + std::regex pattern(regExp); + std::smatch match; + return result; +} + +std::string CodeFixProvider::DiagnosticToString(const DiagnosticAndArguments &diag) +{ + std::string message; + if (diag.arguments.empty()) { + message = diag.message.message; + } else { + message = FormatWithArgs(diag.message.message); + } + return message; +} + +CodeFixAction CodeFixProvider::CreateCodeFixActionWorker(std::string &fixName, std::string &description, + std::vector &changes, std::string &fixId, + std::string &fixAllDescription, + std::vector command = {}) +{ + CodeAction codeAction; + codeAction.description = description; + codeAction.changes = changes; + codeAction.commands = std::move(command); + return {codeAction, fixName, fixId, fixAllDescription}; +} + +CodeFixAction CodeFixProvider::CreateCodeFixActionWithoutFixAll(std::string &fixName, + std::vector &changes, + DiagnosticAndArguments &description) +{ + std::string fixId; + std::string descriptionMessage = DiagnosticToString(description); + std::string fixAllDescription; + return CreateCodeFixActionWorker(fixName, descriptionMessage, changes, fixId, fixAllDescription); +} + +CodeFixAction CodeFixProvider::CreateCodeFixAction(std::string fixName, std::vector changes, + DiagnosticAndArguments &description, std::string fixId, + DiagnosticAndArguments &fixAllDescription, + std::vector &command) +{ + std::string descriptionMessage = DiagnosticToString(description); + std::string fixAllDescriptionMessage = DiagnosticToString(fixAllDescription); + return CreateCodeFixActionWorker(fixName, descriptionMessage, changes, fixId, fixAllDescriptionMessage, + std::move(command)); +} + +std::string CodeFixProvider::GetFileName(const std::string &filePath) +{ + if (filePath.empty()) { + return ""; + } + + std::size_t pos = filePath.find_last_of('/'); + if (pos != std::string::npos) { + return filePath.substr(pos + 1); + } + + pos = filePath.find_last_of('\\'); + if (pos != std::string::npos) { + return filePath.substr(pos + 1); + } + + return filePath; +} + +std::vector CodeFixProvider::GetSupportedErrorCodes() +{ + std::vector result; + for (const auto &kv : errorCodeToFixes_) { + result.push_back(kv.first); + } + return result; +} + +DiagnosticReferences *CodeFixProvider::GetDiagnostics(const CodeFixContextBase &context) +{ + DiagnosticReferences *result = nullptr; + LSPAPI const *lspApi = GetImpl(); + Initializer initializer = Initializer(); + auto it = reinterpret_cast(context.context); + std::string fileNameStr(GetFileName(std::string(it->sourceFile->filePath))); + std::string sourceStr(it->sourceFile->source); + const auto ctx = initializer.CreateContext(fileNameStr.c_str(), ES2PANDA_STATE_CHECKED, sourceStr.c_str()); + DiagnosticReferences semantic = lspApi->getSemanticDiagnostics(ctx); + DiagnosticReferences syntactic = lspApi->getSyntacticDiagnostics(ctx); + DiagnosticReferences suggestions = lspApi->getSuggestionDiagnostics(ctx); + + for (const auto &d : semantic.diagnostic) { + result->diagnostic.push_back(d); + } + for (const auto &d : syntactic.diagnostic) { + result->diagnostic.push_back(d); + } + for (const auto &d : suggestions.diagnostic) { + result->diagnostic.push_back(d); + } + initializer.DestroyContext(ctx); + return result; +} + +bool CodeFixProvider::ShouldIncludeFixAll(const CodeFixRegistration ®istration, + const std::vector &diagnostics) +{ + int maybeFixableDiagnostics = 0; + const int minFixableDiagnostics = 1; + for (size_t i = 0; i <= diagnostics.size(); i++) { + if (std::find(registration.GetErrorCodes().begin(), registration.GetErrorCodes().end(), i) != + registration.GetErrorCodes().end()) { + ++maybeFixableDiagnostics; + if (maybeFixableDiagnostics > minFixableDiagnostics) { + break; + } + } + } + return maybeFixableDiagnostics > minFixableDiagnostics; +} + +CombinedCodeActions CodeFixProvider::GetAllFixes(const CodeFixAllContext &context) +{ + auto it = fixIdToRegistration_.find(context.fixId); + if (it == fixIdToRegistration_.end() || !it->second) { + return CombinedCodeActions(); + } + const std::shared_ptr ®istration = it->second; + return registration->GetAllCodeActions(context); +} + +void CodeFixProvider::EachDiagnostic(const CodeFixAllContext &context, const std::vector &errorCodes, + const std::function &cb) +{ + if (errorCodes.empty()) { + } + if (cb) { + } + auto diagnostics = GetDiagnostics(context); + if (diagnostics != nullptr) { + for (size_t i = 0; i <= diagnostics->diagnostic.size(); i++) { + } + } +} + +std::vector CodeFixProvider::GetFixes(const CodeFixContext &context) +{ + std::vector result; + auto it = errorCodeToFixes_.find(std::to_string(context.errorCode)); + if (it != errorCodeToFixes_.end()) { + const auto ®istrations = it->second; + if (registrations) { + auto actions = registrations->GetCodeActions(context); + for (auto &action : actions) { + result.push_back(action); + } + } + } + return result; +} + +CombinedCodeActions CodeFixProvider::CodeFixAll( + const CodeFixAllContext &context, const std::vector &errorCodes, + std::function use) +{ + std::vector commands; + TextChangesContext textChangesContext {context.host, context.formatContext, context.preferences}; + auto changes = ChangeTracker::With(textChangesContext, [&](ChangeTracker &tracker) { + EachDiagnostic(context, errorCodes, [&](const DiagnosticWithLocation &diag) { use(tracker, diag); }); + }); + return {changes, commands}; +} + +FileTextChanges CodeFixProvider::CreateFileTextChanges(const std::string &fileName, + const std::vector &textChanges) +{ + return {fileName, textChanges}; +} + +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/completions.cpp b/ets2panda/lsp/src/completions.cpp index fc0e486bf6fb59eaf424608bdf51a6fae79b5179..cc8bda93246fb41cffd852d5ce797da567f5306e 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/completions_details.cpp b/ets2panda/lsp/src/completions_details.cpp index 54b46cc2240225f8d0b19af4f1bfc2182f456c1c..f82c5f40a4c1b828d566a3a4b0c755799bf71d36 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/get_class_property_info.cpp b/ets2panda/lsp/src/get_class_property_info.cpp index e0228eea95e8a63370d7227d3d6bc5cee28c9e91..750d24fd84f4b49791d7adb62b786f544bea7554 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/lsp/src/internal_api.cpp b/ets2panda/lsp/src/internal_api.cpp index d6c459647d02f9084e1471e6dc1c9efc882f2106..05c9922c143daca85f149f7c0fc423e7337c8743 100644 --- a/ets2panda/lsp/src/internal_api.cpp +++ b/ets2panda/lsp/src/internal_api.cpp @@ -27,6 +27,10 @@ #include "public/es2panda_lib.h" #include "public/public.h" #include "utils/arena_containers.h" +#include "formatting/formatting.h" +#include "code_fix_provider.h" +#include "get_class_property_info.h" +#include "code_fixes/code_fix_types.h" namespace ark::es2panda::lsp { @@ -701,4 +705,72 @@ DocumentHighlights GetDocumentHighlightsImpl(es2panda_Context *context, size_t p return GetSemanticDocumentHighlights(context, position); } +std::vector CreateInstallPackageActionInfos(std::vector &commands) +{ + std::vector infos; + for (const auto &command : commands) { + InstallPackageActionInfo info {command.type, command.file, command.packageName}; + infos.push_back(info); + } + + return infos; +} + +CodeFixActionInfo CreateCodeFixActionInfo(CodeFixAction &codeFixAction) +{ + auto infos = CreateInstallPackageActionInfos(codeFixAction.commands); + + CodeActionInfo codeActionInfo {codeFixAction.description, codeFixAction.changes, infos}; + + return CodeFixActionInfo {codeActionInfo, codeFixAction.fixName, codeFixAction.fixId, + codeFixAction.fixAllDescription}; +} + +CombinedCodeActionsInfo CreateCombinedCodeActionsInfo(CombinedCodeActions &combinedCodeActions) +{ + auto infos = CreateInstallPackageActionInfos(combinedCodeActions.commands); + + return CombinedCodeActionsInfo {combinedCodeActions.changes, infos}; +} + +std::vector GetCodeFixesAtPositionImpl(es2panda_Context *context, size_t startPosition, + size_t endPosition, std::vector &errorCodes, + CodeFixOptions &codeFixOptions) +{ + TextSpan textspan = TextSpan(startPosition, endPosition); + std::vector actions; + auto formatContext = GetFormatContext(codeFixOptions.options); + + for (auto errorCode : errorCodes) { + if (codeFixOptions.token.IsCancellationRequested()) { + return actions; + } + + TextChangesContext textChangesContext {LanguageServiceHost(), formatContext, codeFixOptions.preferences}; + CodeFixContextBase codeFixContextBase {textChangesContext, context, codeFixOptions.token}; + CodeFixContext codeFixContent {codeFixContextBase, errorCode, textspan}; + + auto fixes = CodeFixProvider::Instance().GetFixes(codeFixContent); + for (auto fix : fixes) { + auto codeFixes = CreateCodeFixActionInfo(fix); + actions.push_back(codeFixes); + } + } + + return actions; +} + +CombinedCodeActionsInfo GetCombinedCodeFixImpl(es2panda_Context *context, const std::string &fixId, + CodeFixOptions &codeFixOptions) +{ + auto formatContext = GetFormatContext(codeFixOptions.options); + TextChangesContext textChangesContext {LanguageServiceHost(), formatContext, codeFixOptions.preferences}; + CodeFixContextBase codeFixContextBase {textChangesContext, context, codeFixOptions.token}; + CodeFixAllContext codeFixAllContent {codeFixContextBase, fixId}; + + auto fixes = CodeFixProvider::Instance().GetAllFixes(codeFixAllContent); + + return CreateCombinedCodeActionsInfo(fixes); +} + } // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/organize_imports.cpp b/ets2panda/lsp/src/organize_imports.cpp index aacf38ab477d6ec4b92d514bbd871f2915afaf18..c91ebd45bdda8dd9f3e33807b60aef7a30f098ea 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/lsp/src/quick_info.cpp b/ets2panda/lsp/src/quick_info.cpp index 1205f9ac5b2ce873ff273ec01bd485d9ce88a415..e79b26420d378b07003937494081192fa2acdcd2 100644 --- a/ets2panda/lsp/src/quick_info.cpp +++ b/ets2panda/lsp/src/quick_info.cpp @@ -680,6 +680,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(); @@ -946,9 +950,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))); @@ -978,6 +990,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; @@ -990,7 +1008,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 { @@ -1005,6 +1023,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/lsp/src/refactor_provider.cpp b/ets2panda/lsp/src/refactor_provider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6e8e598ff5a354a28f1632e82d77a8e40b16ba2 --- /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 d5996360f3b097fb797942c414311021f49e59a3..e594fa230ac2e27c99c5b73b06ee18f20ba44a1a 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 0000000000000000000000000000000000000000..4a9c1a1980ea54739c968e77aa90539f0c460961 --- /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/lsp/src/register_code_fix/add_missing_declare_property.cpp b/ets2panda/lsp/src/register_code_fix/add_missing_declare_property.cpp new file mode 100644 index 0000000000000000000000000000000000000000..600252a8b0a4769ae7a4b05ac7b6069c80eda1a1 --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/add_missing_declare_property.cpp @@ -0,0 +1,93 @@ +/** + * 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/add_missing_declare_property.h" +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { + +const int G_ADD_MISSING_DECLARE_PROPERTY_CODE = 1001; // change this to the error code you want to handle + +void MakeChange(ChangeTracker changeTracker, es2panda_Context *context, size_t pos, + std::vector &fixedNodes) +{ + const auto token = GetTouchingToken(context, pos, false); + if (token == nullptr || !token->IsIdentifier()) { + return; + } + const auto declaration = token->Parent(); + if (declaration->IsProperty()) { + fixedNodes.push_back(declaration); + changeTracker.InsertModifierBefore(context, token, declaration); + } +} + +std::vector GetCodeActionsToAddMissingDeclareOnProperty(const CodeFixContext &context) +{ + TextChangesContext textChangesContext = {context.host, context.formatContext, context.preferences}; + std::vector fixedNodes; + + auto fileTextChanges = ChangeTracker::With( + textChangesContext, [&](ChangeTracker &tracker) { MakeChange(tracker, context.context, 3, fixedNodes); }); + return fileTextChanges; +} + +AddMissingDeclareProperty::AddMissingDeclareProperty() +{ + const char *addMissingDeclarationPropertyId = "AddMissingDeclareProperty"; + SetErrorCodes({G_ADD_MISSING_DECLARE_PROPERTY_CODE}); + SetFixIds({addMissingDeclarationPropertyId}); +} + +std::vector AddMissingDeclareProperty::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + auto changes = GetCodeActionsToAddMissingDeclareOnProperty(context); + if (!changes.empty()) { + CodeFixAction codeAction; + codeAction.fixName = "Fix"; + codeAction.description = "Fix Description"; + codeAction.changes = changes; + codeAction.fixId = "AddMissingDeclareProperty"; + codeAction.fixAllDescription = "Fix All Description"; + InstallPackageAction codeActionCommand; + codeActionCommand.file = "addMissingDeclareProperty.ets"; + codeActionCommand.packageName = "dummy-package"; + codeAction.commands.push_back(codeActionCommand); + returnedActions.push_back(codeAction); + } + return returnedActions; +} + +CombinedCodeActions AddMissingDeclareProperty::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + std::vector fixedNodes; + CodeFixProvider provider; + + const auto changes = provider.CodeFixAll(codeFixAll, GetErrorCodes(), + [&](ChangeTracker &tracker, const DiagnosticWithLocation &diag) { + MakeChange(tracker, codeFixAll.context, diag.start, fixedNodes); + }); + + CombinedCodeActions combinedCodeActions; + combinedCodeActions.changes = changes.changes; + combinedCodeActions.commands = changes.commands; + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_addMissingDeclareProperty("AddMissingDeclareProperty"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/register_code_fix/fix_missing_call_parantheses.cpp b/ets2panda/lsp/src/register_code_fix/fix_missing_call_parantheses.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c414f7f7e86bbdbd5b864d4dafffd1cf14d5f1c --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/fix_missing_call_parantheses.cpp @@ -0,0 +1,50 @@ +/** + * 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/fix_missing_call_parantheses.h" +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { +const int G_FIX_MISSING_CALL_PARANTHESES_CODE = 1002; // change this to the error code you want to handle + +FixMissingCallParantheses::FixMissingCallParantheses() +{ + const char *fixMissingCallParanthesesId = "FixMissingCallParantheses"; + + SetErrorCodes({G_FIX_MISSING_CALL_PARANTHESES_CODE}); // change this to the error code you want to handle + SetFixIds({fixMissingCallParanthesesId}); +} + +std::vector FixMissingCallParantheses::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + if (context.errorCode == G_FIX_MISSING_CALL_PARANTHESES_CODE) { + } + return returnedActions; +} + +CombinedCodeActions FixMissingCallParantheses::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + CombinedCodeActions combinedCodeActions; + if (codeFixAll.fixId == "FixMissingCallParantheses") { + } + + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_fixMissingCallParantheses("FixMissingCallParantheses"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/register_code_fix/fix_nan_equality.cpp b/ets2panda/lsp/src/register_code_fix/fix_nan_equality.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11080e91fb7ddc088fbeef974c9bc786ae1c7abd --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/fix_nan_equality.cpp @@ -0,0 +1,125 @@ + +/** + * 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/fix_nan_equality.h" +#include +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { + +const int G_FIX_NAN_EQUALITY_CODE = 1003; // change this to the error code you want to handle + +void FixNaNEquality::MakeChangeForNaNEquality(ChangeTracker &changeTracker, es2panda_Context *context, size_t pos, + std::vector &fixedNodes) +{ + auto *token = GetTouchingToken(context, pos, false); + if (token == nullptr || !token->IsBinaryExpression()) { + return; + } + + const auto *binaryExpr = token->AsBinaryExpression(); + if (binaryExpr->Left() == nullptr || binaryExpr->Right() == nullptr) { + return; + } + + auto isLeftNaN = binaryExpr->Left()->IsIdentifier() && binaryExpr->Left()->AsIdentifier()->Name() == "NaN"; + auto isRightNaN = binaryExpr->Right()->IsIdentifier() && binaryExpr->Right()->AsIdentifier()->Name() == "NaN"; + if (!isLeftNaN && !isRightNaN) { + return; + } + + auto *expr = isLeftNaN ? binaryExpr->Right() : binaryExpr->Left(); + std::string exprText = expr->ToString(); + std::string newText; + + if (binaryExpr->Type() == ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION) { + newText = "Number.isNaN(" + exprText + ")"; + } else { + return; + } + + // auto *ctx = reinterpret_cast(context); + + fixedNodes.push_back(const_cast(token)); + // ark::es2panda::ir::AstNode *bClone = token->Clone(ctx->allocator, nullptr); + + ChangeNodeOptions changeNodeOptions; + changeNodeOptions.insertNodeOptions->prefix = ""; + changeNodeOptions.insertNodeOptions->suffix = ""; + changeNodeOptions.insertNodeOptions->delta = 0; + + ark::es2panda::lsp::ChangeNodeOptions options = {}; + changeTracker.ReplaceNode(context, token, token, changeNodeOptions); +} + +std::vector FixNaNEquality::GetCodeActionsToFixNaNEquality(const CodeFixContext &context) +{ + TextChangesContext textChangesContext = {context.host, context.formatContext, context.preferences}; + std::vector fixedNodes; + auto fileTextChanges = ChangeTracker::With(textChangesContext, [&](ChangeTracker &tracker) { + MakeChangeForNaNEquality(tracker, context.context, context.span.start, fixedNodes); + }); + + return fileTextChanges; +} + +FixNaNEquality::FixNaNEquality() +{ + const char *fixNanEqualityId = "FixNaNEquality"; + SetErrorCodes({G_FIX_NAN_EQUALITY_CODE}); // "NaN comparison" error code + SetFixIds({fixNanEqualityId}); // "fixNaNEquality" fix ID +} + +std::vector FixNaNEquality::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + auto changes = GetCodeActionsToFixNaNEquality(context); + if (!changes.empty()) { + CodeFixAction codeAction; + codeAction.fixName = "fixNaNEquality"; + codeAction.description = "Use Number.isNaN instead of comparing with NaN"; + codeAction.changes = changes; + codeAction.fixId = "FixNaNEquality"; + codeAction.fixAllDescription = "Replace all NaN equality comparisons"; + returnedActions.push_back(codeAction); + } + return returnedActions; +} + +CombinedCodeActions FixNaNEquality::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + const std::vector fixedNodes; + CodeFixProvider provider; + + const auto changes = provider.CodeFixAll( + codeFixAll, GetErrorCodes(), [&](ChangeTracker &tracker, const DiagnosticWithLocation &diag) { + Initializer initializer = Initializer(); + auto ctx = + initializer.CreateContext(diag.file.source.data(), ES2PANDA_STATE_CHECKED, diag.file.source.data()); + MakeChangeForNaNEquality(tracker, ctx, diag.start, const_cast &>(fixedNodes)); + initializer.DestroyContext(ctx); + }); + + CombinedCodeActions combinedCodeActions; + combinedCodeActions.changes = changes.changes; + combinedCodeActions.commands = changes.commands; + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_fixNaNEquality("FixNaNEquality"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/register_code_fix/forgetten_this_property_access.cpp b/ets2panda/lsp/src/register_code_fix/forgetten_this_property_access.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1bda5b238ae79e836cacf9dcebb4062e51f84b1 --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/forgetten_this_property_access.cpp @@ -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. + */ + +#include "lsp/include/register_code_fix/forgetten_this_property_access.h" +#include +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { + +const int G_FORGETTEN_THIS_PROPERTY_ACCESS_CODE = 1004; // change this to the error code you want to handle + +ForgettenThisPropertyAccess::ForgettenThisPropertyAccess() +{ + const char *forgottenThisPropertAccesId = "ForgettenThisPropertyAccess"; + SetErrorCodes({G_FORGETTEN_THIS_PROPERTY_ACCESS_CODE}); // change this to the error code you want to handle + SetFixIds({forgottenThisPropertAccesId}); +} + +std::vector ForgettenThisPropertyAccess::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + if (context.errorCode == G_FORGETTEN_THIS_PROPERTY_ACCESS_CODE) { + } + return returnedActions; +} + +CombinedCodeActions ForgettenThisPropertyAccess::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + CombinedCodeActions combinedCodeActions; + if (codeFixAll.fixId == "ForgettenThisPropertyAccess") { + } + + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_forgettenThisPropertyAccess("ForgettenThisPropertyAccess"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/register_code_fix/import_fixes.cpp b/ets2panda/lsp/src/register_code_fix/import_fixes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22a12042fa2593313171f5479dc08b3f3b78493a --- /dev/null +++ b/ets2panda/lsp/src/register_code_fix/import_fixes.cpp @@ -0,0 +1,50 @@ +/** + * 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/import_fixes.h" +#include +#include +#include "lsp/include/code_fix_provider.h" +#include "lsp/include/internal_api.h" + +namespace ark::es2panda::lsp { +const int G_IMPORT_FIXES_CODE = 1005; // change this to the error code you want to handle + +ImportFixes::ImportFixes() +{ + const char *importFixesId = "ImportFixes"; + SetErrorCodes({G_IMPORT_FIXES_CODE}); // change this to the error code you want to handle + SetFixIds({importFixesId}); +} + +std::vector ImportFixes::GetCodeActions(const CodeFixContext &context) +{ + std::vector returnedActions; + if (context.errorCode == G_IMPORT_FIXES_CODE) { + } + return returnedActions; +} + +CombinedCodeActions ImportFixes::GetAllCodeActions(const CodeFixAllContext &codeFixAll) +{ + CombinedCodeActions combinedCodeActions; + if (codeFixAll.fixId == "ImportFixes") { + } + + return combinedCodeActions; +} +// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, cert-err58-cpp) +AutoCodeFixRegister g_importFixes("ImportFixes"); +} // namespace ark::es2panda::lsp diff --git a/ets2panda/lsp/src/rename.cpp b/ets2panda/lsp/src/rename.cpp index 10f812d813b73e92ec59d79c872fac920fdcb301..e836fb4858a2e21712155eef08dd868bf3905e15 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/lsp/src/text_change/change_tracker.cpp b/ets2panda/lsp/src/services/text_change/change_tracker.cpp similarity index 94% rename from ets2panda/lsp/src/text_change/change_tracker.cpp rename to ets2panda/lsp/src/services/text_change/change_tracker.cpp index 2729d2cec7017ab13ac0851551c7f96106cbb0f7..5b4aca7e1efd28cba77837fbe1be9308434ca70f 100644 --- a/ets2panda/lsp/src/text_change/change_tracker.cpp +++ b/ets2panda/lsp/src/services/text_change/change_tracker.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "lsp/include/text_change/change_tracker.h" +#include "lsp/include/services/text_change/change_tracker.h" #include #include #include @@ -30,7 +30,8 @@ ChangeTracker ChangeTracker::FromContext(TextChangesContext &context) return ChangeTracker(context.formatContext, context.formatContext.GetFormatCodeSettings().GetNewLineCharacter()); } -std::vector ChangeTracker::With(TextChangesContext &context, const std::function &cb) +std::vector ChangeTracker::With(TextChangesContext &context, + const std::function &cb) { auto tracker = FromContext(context); cb(tracker); @@ -290,7 +291,7 @@ void ChangeTracker::FinishDeleteDeclarations() { // its about delete declarations // will develop next version - std::cout << deletedNodes_.size() << std::endl; + // its about delete declarations } /* createTextrangeFromSpan did not developed. it will develop next version.it should be gotten from utılıtıes * createTextTangeFromSpan method. pls check it from ts side*/ @@ -790,6 +791,33 @@ std::vector GetTextChangesFromChanges( return {}; } +std::vector ChangeTracker::GetTextChangesFromChanges(std::vector &changes, + std::string &newLineCharacter, + const FormatCodeSettings &formatCodeSettings) +{ + (void)newLineCharacter; + (void)formatCodeSettings; + + std::unordered_map fileChangesMap; + for (const auto &change : changes) { + if (const auto *textChange = std::get_if(&change)) { + TextChange c = {{textChange->range.pos, textChange->range.end - textChange->range.pos}, textChange->text}; + const std::string &filePath = std::string(textChange->sourceFile->filePath); + if (fileChangesMap.find(filePath) == fileChangesMap.end()) { + fileChangesMap[filePath].fileName = filePath; + } + fileChangesMap[filePath].textChanges.push_back(c); + } + } + + std::vector fileTextChanges; + fileTextChanges.reserve(fileChangesMap.size()); + for (auto &pair : fileChangesMap) { + fileTextChanges.push_back(std::move(pair.second)); + } + + return fileTextChanges; +} /** * Note: after calling this, the TextChanges object must be discarded! @@ -798,11 +826,14 @@ std::vector GetTextChangesFromChanges( * `getNonFormattedText` changes the node's positions, so we can only call this * once and can't get the non-formatted text separately. */ -std::vector ChangeTracker::GetChanges() // should add ValidateNonFormattedText +std::vector ChangeTracker::GetChanges() // should add ValidateNonFormattedText { + FinishDeleteDeclarations(); FinishClassesWithNodesInsertedAtStart(); + auto textChangesList = + GetTextChangesFromChanges(changes_, newLineCharacter_, formatContext_.GetFormatCodeSettings()); - return changes_; + return textChangesList; } void ChangeTracker::CreateNewFile(SourceFile *oldFile, const std::string &fileName, diff --git a/ets2panda/parser/ETSFormattedParser.cpp b/ets2panda/parser/ETSFormattedParser.cpp index 93fac4b3e5590269a1692b433c089510359e52bc..d0b01fdad556ca202f89738c1de968e4313372a7 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 6a1ca88c8ba51e4efcefd264f849c93a809e9a62..71fd3ae93938a12a0a607146c1b4d4f994e9902b 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); @@ -1634,6 +1668,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/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 6c905bafe65715c395e3d9e7a1b05d968b8dec95..6ca2d6d6c8c09d7b66be307381d10bbf303eb358 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 c1dc7c92e0533b4e90189b4face6ecfb071cfe32..0876670671b173530cbb9ac165104505fbe085ef 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); @@ -1338,6 +1337,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/parser/ETSparserEnums.cpp b/ets2panda/parser/ETSparserEnums.cpp index bcd59d4ec5d7aca460f667b7f25e1a0ed8b1cf42..b38077398cc5b70edba573d32ea6928b9ff8dbd3 100644 --- a/ets2panda/parser/ETSparserEnums.cpp +++ b/ets2panda/parser/ETSparserEnums.cpp @@ -160,11 +160,6 @@ ir::TSEnumDeclaration *ETSParser::ParseEnumMembers(ir::Identifier *const key, co Lexer()->NextToken(lexer::NextTokenFlags::KEYWORD_TO_IDENT); // eat '{' - if (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { - LogError(diagnostic::ENUM_MUST_HAVE_ONE_CONST); - return nullptr; // Error processing. - } - ArenaVector members(Allocator()->Adapter()); lexer::SourcePosition enumEnd = ParseEnumMember(members); diff --git a/ets2panda/parser/ETSparserExpressions.cpp b/ets2panda/parser/ETSparserExpressions.cpp index 3882cf5b2bf8085f9caa38b5fe7e37dd0edb29f7..7c0bd342e97a317106119b561437caf824eb9ed6 100644 --- a/ets2panda/parser/ETSparserExpressions.cpp +++ b/ets2panda/parser/ETSparserExpressions.cpp @@ -220,6 +220,16 @@ ir::Expression *ETSParser::ParsePropertyDefinition(ExpressionParseFlags flags) return returnProperty; } +bool CheckNextTokenOfTypeof(const lexer::Token &token) +{ + bool pretendTypeof = token.KeywordType() == lexer::TokenType::KEYW_TYPEOF; + bool pretendIdent = token.IsLiteral(); + bool pretendOperator = token.IsUpdate(); + bool pretendUnary = token.IsUnary(); + bool pretendPuctuator = token.IsTsParamToken(token.Type()); + return (pretendTypeof || pretendIdent || pretendOperator || pretendUnary || pretendPuctuator); +} + // NOLINTNEXTLINE(google-default-arguments) ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags flags) { @@ -251,8 +261,13 @@ ir::Expression *ETSParser::ParseDefaultPrimaryExpression(ExpressionParseFlags fl Lexer()->NextToken(); bool pretendArrow = Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_ARROW; + bool checkNextTokenOfTypeof = CheckNextTokenOfTypeof(Lexer()->GetToken()); Lexer()->Rewind(savedPos); + if (Lexer()->GetToken().KeywordType() == lexer::TokenType::KEYW_TYPEOF && checkNextTokenOfTypeof) { + return ParseUnaryOrPrefixUpdateExpression(); + } + if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT) { if (pretendArrow) { return ParseArrowFunctionExpression(); diff --git a/ets2panda/parser/ETSparserNamespaces.cpp b/ets2panda/parser/ETSparserNamespaces.cpp index ea4a8feb4bad30cdaf3ca8bfcbcf73f4ac6995d2..50240599974741629a8b0ec7b6ceb6b993125256 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 c88b813839c23e8add2f6c176521551081589d0f..1ee35142fd8a792cb1383957cba1115dde960053 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 d64de90591844ae65634a889dd50971c16c1b197..c71ad06628d3c17756b408eace5e79973cf7e316 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 3d6ecb19e6e96a79eeb47ad641980a8f4874f6c7..572ce976dc019b2b7e56d904c9303874ed1e8ce9 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 b06f0f6470295c038e7d5e0c9b20615c57ba6733..c29543942cadcf88358a2ac9db0e08e8f34a4169 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 }; @@ -57,7 +62,6 @@ enum class ProgramFlags : uint32_t { AST_CHECK_PROCESSED = 1U << 1U, AST_ENUM_LOWERED = 1U << 2U, AST_BOXED_TYPE_LOWERED = 1U << 3U, - AST_CONST_STRING_TO_CHAR_LOWERED = 1U << 4U, AST_CONSTANT_EXPRESSION_LOWERED = 1U << 5U, AST_STRING_CONSTANT_LOWERED = 1U << 6U, AST_IDENTIFIER_ANALYZED = 1U << 7U, @@ -99,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 { @@ -191,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() { @@ -290,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 @@ -316,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); @@ -368,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_ {}; @@ -383,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 37cbb764e9bf6ff4064fd66f19e144e40f1519d4..10e1650666a4751492058c9f438720b80251668d 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 68c404993fe37dbe0d4d8bd25d9457fb5ad5ad9e..8df91d24aff6942c01c70ef14542a277129967cd 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 b331f5682953c8da1608024a26a68d4458fd4b91..cf927443b4f8927ae3bde32e4da2d471051bb38c 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/compiler/lowering/ets/constStringToCharLowering.h b/ets2panda/public/public.cpp similarity index 53% rename from ets2panda/compiler/lowering/ets/constStringToCharLowering.h rename to ets2panda/public/public.cpp index e1ac39e53ced136a1009fc3af85c0a936a1ff957..3b3754328b24bec031f0deeb8d601690722e2dca 100644 --- a/ets2panda/compiler/lowering/ets/constStringToCharLowering.h +++ b/ets2panda/public/public.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 @@ -13,19 +13,19 @@ * limitations under the License. */ -#ifndef ES2PANDA_COMPILER_LOWERING_CONST_STRING_TO_CHAR_LOWERING_H -#define ES2PANDA_COMPILER_LOWERING_CONST_STRING_TO_CHAR_LOWERING_H - +#include "public/public.h" #include "compiler/lowering/phase.h" -namespace ark::es2panda::compiler { +namespace ark::es2panda::public_lib { -class ConstStringToCharLowering : public PhaseForBodies { -public: - std::string_view Name() const override; - bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; -}; +checker::Checker *Context::GetChecker() const +{ + return checkers_[compiler::GetPhaseManager()->GetCurrentMajor()]; +} -} // namespace ark::es2panda::compiler +checker::SemanticAnalyzer *Context::GetAnalyzer() const +{ + return analyzers_[compiler::GetPhaseManager()->GetCurrentMajor()]; +} -#endif // ES2PANDA_COMPILER_LOWERING_CONST_STRING_TO_CHAR_LOWERING_H +} // namespace ark::es2panda::public_lib diff --git a/ets2panda/public/public.h b/ets2panda/public/public.h index fdb18d9ca659365353d1def34bb4d84939b6e5d6..46ddf91b4cf5295d74d5a601958c7b5ac833a853 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 170649f36e0bec15baf5dd0f417f3f7e7fcd0132..c2bf21da691329d79896559019bb72c5d47eb9d9 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/compiler/ets/boxingConversion1.ets b/ets2panda/test/ast/compiler/ets/boxingConversion1.ets index c4d703e4a25f9c17408d978147e9471016b71002..656ce82e1ba4b0967f0c894a649cbc255b0304d0 100644 --- a/ets2panda/test/ast/compiler/ets/boxingConversion1.ets +++ b/ets2panda/test/ast/compiler/ets/boxingConversion1.ets @@ -18,4 +18,6 @@ function main() : void { let b: Byte = /* @@ label */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 219921314be7d2169d4de6cd525622a94fefc1ed..ff64829de2438ffcabd1b87b2bccb1b4f584f0df 100644 --- a/ets2panda/test/ast/compiler/ets/boxingConversion4.ets +++ b/ets2panda/test/ast/compiler/ets/boxingConversion4.ets @@ -23,6 +23,8 @@ function main() : void { refInt(b); // primitive widening before boxing is not allowed } +/* @@@ 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' */ diff --git a/ets2panda/test/ast/compiler/ets/func_as_param.ets b/ets2panda/test/ast/compiler/ets/func_as_param.ets index e78a161c811a95e6622a5d3a1448c51ead6bd841..43f1c47d80e957c7619da2512f1e419be36ac96f 100644 --- a/ets2panda/test/ast/compiler/ets/func_as_param.ets +++ b/ets2panda/test/ast/compiler/ets/func_as_param.ets @@ -16,7 +16,7 @@ function getFuncWithArgsZero(func: (() => void) | (() => Promise)) { return new Promise(async (resolve: (value: PromiseLike) => void) => { await (func as () => Promise)(); - const funcStr = (func as object).toString() + const funcStr = Type.of(func as object).getLiteral() const argsCount = getFunctionArgumentsCount(funcStr) const isAsync = checkIsAsyncFunction(funcStr) resolve(Promise.resolve()); @@ -26,7 +26,8 @@ function getFuncWithArgsZero(func: (() => void) | (() => Promise)) { function getFunctionArgumentsCount(funcStr: string): number { const regex = new RegExp("^[0123456789]$", "g") let count = "" - for(let str of funcStr) { + for(let ch of funcStr) { + let str = new Char(ch).toString(); if(regex.test(str)) { count = str } @@ -47,4 +48,69 @@ function checkIsAsyncFunction(funcStr: string): boolean { } } +async function testAsyncGetFuncWithArgsZeroSafe() { + let success = false; + try { + await getFuncWithArgsZero( async () => {}); + success = true; + } catch (e) { + success = false; + } + assertEQ(success, true, "getFuncWithArgsZero with async should not throw"); +} + +function testGetFuncWithArgsZeroSafe() { + let success = false; + try { + getFuncWithArgsZero(() => {}); + success = true; + } catch (e) { + success = false; + } + assertEQ(success, true, "getFuncWithArgsZero should not throw"); +} + +function main(): void { + const func1 = (a: number, b: number): number => { + return a + b; + }; + + const func2 = async (): Promise => {}; + + const func3 = (): number => { + return 42; + }; + + const func4 = async (x: number, y: number, z: number): Promise => {}; + + const funcStr1: string = Type.of(func1 as object).getLiteral(); + const funcStr2: string = Type.of(func2 as object).getLiteral(); + const funcStr3: string = Type.of(func3 as object).getLiteral(); + const funcStr4: string = Type.of(func4 as object).getLiteral(); + + // Test getLiteral() + assertEQ(funcStr1, "(1: std.core.Double, 2: std.core.Double): std.core.Double", "func1 literal check"); + assertEQ(funcStr2, "(): std.core.Promise", "func2 literal check"); + assertEQ(funcStr3, "(): std.core.Double", "func3 literal check"); + assertEQ(funcStr4, "(1: std.core.Double, 2: std.core.Double, 3: std.core.Double): std.core.Promise", "func4 literal check"); + + // Test getFunctionArgumentsCount + assertEQ(getFunctionArgumentsCount(funcStr1), 2, "func1 should have 2 arguments"); + assertEQ(getFunctionArgumentsCount(funcStr2), 0, "func2 should have 0 arguments"); + assertEQ(getFunctionArgumentsCount(funcStr3), 0, "func3 should have 0 arguments"); + assertEQ(getFunctionArgumentsCount(funcStr4), 3, "func4 should have 3 arguments"); + + // Test checkIsAsyncFunction + assertEQ(checkIsAsyncFunction(funcStr1), false, "func1 should not be async"); + assertEQ(checkIsAsyncFunction(funcStr2), true, "func2 should be async"); + assertEQ(checkIsAsyncFunction(funcStr3), false, "func3 should not be async"); + assertEQ(checkIsAsyncFunction(funcStr4), true, "func4 should be async"); + + // execute getFuncWithArgsZero with async + testAsyncGetFuncWithArgsZeroSafe() + + // execute getFuncWithArgsZero with sync + testGetFuncWithArgsZeroSafe() +} + diff --git a/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets b/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets index 5856063ea2e162016e81d70f12f2e953976bc615..7ccba2d83e8e9f611c7bf8c9fe5ca2eb6c42e95b 100644 --- a/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets +++ b/ets2panda/test/ast/compiler/ets/inferTypeOfArrayNegative3.ets @@ -17,4 +17,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: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/invalidPrivateAccess3.ets b/ets2panda/test/ast/compiler/ets/invalidPrivateAccess3.ets index 25579258e19ebe54785d73f2ecdf31e2b1c30453..511ee961f9e200c9f2b685f6f2ab8297c7f5fa23 100644 --- a/ets2panda/test/ast/compiler/ets/invalidPrivateAccess3.ets +++ b/ets2panda/test/ast/compiler/ets/invalidPrivateAccess3.ets @@ -35,5 +35,6 @@ function main(): void { klass.foo(); } +/* @@? 35:5 Error TypeError: Expected 1 arguments, got 0. */ /* @@? 35:5 Error TypeError: Signature foo(): void is not visible here. */ /* @@? 35:5 Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/compiler/ets/invalidProtectedAccess3.ets b/ets2panda/test/ast/compiler/ets/invalidProtectedAccess3.ets index d943387afb5bc572b61cee0ae0dec20303425d5e..eeaa22daaa3be3ac557d17a03cd89c106fbbd1c4 100644 --- a/ets2panda/test/ast/compiler/ets/invalidProtectedAccess3.ets +++ b/ets2panda/test/ast/compiler/ets/invalidProtectedAccess3.ets @@ -35,5 +35,6 @@ function main(): void { klass.foo(); } +/* @@? 35:5 Error TypeError: Expected 1 arguments, got 0. */ /* @@? 35:5 Error TypeError: Signature foo(): void is not visible here. */ /* @@? 35:5 Error TypeError: No matching call signature */ 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 61acb173f6c4f7637e2e3033e6e6cbf5fa815909..43dba88366d7689ba0df603127b3152e737a3e09 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 @@ -17,4 +17,6 @@ function main() : void { let a: Byte = /* @@ label */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 2727c5fe2cd30fa543645706d3ee1ce8aae15318..d918e3e7d3ef1c2fbb1d9d73a122a4e029d8f444 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 @@ -17,4 +17,6 @@ function main() : void { let e: Float = /* @@ label */new Float(6,"3"); } +/* @@@ 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") */ diff --git a/ets2panda/test/ast/parser/ets/default_parameter2.ets b/ets2panda/test/ast/parser/ets/default_parameter2.ets index de4e98af760ec414fc3a9890b6756dddb154d5a1..be81d6ef8449081a84985e1bb611a482fc3de737 100644 --- a/ets2panda/test/ast/parser/ets/default_parameter2.ets +++ b/ets2panda/test/ast/parser/ets/default_parameter2.ets @@ -15,7 +15,7 @@ function main() : void { - foo(); + /* @@ label */foo(); } function foo(a : int, b : int = 10) : int @@ -28,4 +28,5 @@ function foo(a : int) : int return a; } -/* @@? 18:5 Error TypeError: No matching call signature */ +/* @@@ label Error TypeError: Expected 1 arguments, got 0. */ +/* @@@ label Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/parser/ets/enum3.ets b/ets2panda/test/ast/parser/ets/enum3.ets index ce66860a394a77b50009d303513023789bf27695..553b552a78aa95b2cef021ee43f4a83eb9f0af10 100644 --- a/ets2panda/test/ast/parser/ets/enum3.ets +++ b/ets2panda/test/ast/parser/ets/enum3.ets @@ -16,6 +16,3 @@ enum EmptyEnum { } - -/* @@? 18:1 Error SyntaxError: An enum must have at least one enum constant. */ -/* @@? 18:1 Error SyntaxError: Unexpected token '}'. */ 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 0000000000000000000000000000000000000000..7dc0bbfcc8fef31455835e3c8a417e11b8d73aba --- /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/test/ast/parser/ets/keyof_array_tuple.ets b/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets index 9ccb1e71d583365cb44c56f35ffe7b0d6fef433e..9284175d61779263c20e9ff49a3dcb6f0ae46f9e 100644 --- a/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets +++ b/ets2panda/test/ast/parser/ets/keyof_array_tuple.ets @@ -37,5 +37,13 @@ function main():void{ /* @@? 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) */ +/* @@? 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) */ +/* @@? 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/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 3190aa7e6ef9dd4d0766796b826bdb4aa141ebfa..7ab996094754f44c3e03556b42c2769bb1d4c004 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 47da757660366c0f4be55075d4b511a3bc98c0da..36a1540c411d2201827b16032f1d8b1fd6d2b043 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 3ef1125541bbd29788940eb132d3b67562c95008..8d51ff1d62025a5cfc0b3d4e6238d47b79f6204c 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/re_export/re_export_4.ets b/ets2panda/test/ast/parser/ets/re_export/re_export_4.ets index 32c944833ab27798b576ce6fcf3b87e56c1506a9..399324e4b7989207edba240d77f1c2145da64717 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/ast/parser/ets/rest_parameter_05.ets b/ets2panda/test/ast/parser/ets/rest_parameter_05.ets index 07cdd8b2dfe5dcd52d4b3033bcc865b0a1286e1b..53d71208a0886248013a2c68ab4204e05f1e5f78 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_05.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_05.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -19,4 +19,5 @@ function sum(...numbers: [number, number, number]): number { /* @@ label */sum() +/* @@@ label Error TypeError: Expected 3 arguments, got 0. */ /* @@@ label Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_06.ets b/ets2panda/test/ast/parser/ets/rest_parameter_06.ets index 969c4fc10f95b3c5e3bc5e20d0f24d1a8fc1e208..7759de0401912ca488db242b55e868581d32f78b 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_06.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_06.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -19,4 +19,5 @@ 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) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_07.ets b/ets2panda/test/ast/parser/ets/rest_parameter_07.ets index 922f5eeac935f299b0d4ffedf6ade63efe010a42..f1373852fb56c61480e240df1f947cc4031adf7e 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_07.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_07.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -17,6 +17,7 @@ function sum(...numbers: [number, number, number]): number { return numbers[0] + numbers[1] + numbers[2] } -/* @@ label1 */sum(10, 20, /* @@ label2 */"one") +/* @@ label1 */sum(/* @@ label2 */10, 20, "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 */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_08.ets b/ets2panda/test/ast/parser/ets/rest_parameter_08.ets index 9d882858460e1591c26af2644159a13cb207de4c..9abafc61d90340842ba9af5ce6712ccf06af91fa 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_08.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_08.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -22,7 +22,12 @@ function sum(a: int, ...numbers: [number, number, number]): number { /* @@ label3 */sum(11,12,13) /* @@ label4 */sum(11,12,13,15,16) +/* @@@ label1 Error TypeError: Expected 1 arguments, got 0. */ +/* @@@ 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) */ +/* @@@ label3 Error TypeError: Expected 4 arguments, got 3. */ /* @@@ 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) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_09.ets b/ets2panda/test/ast/parser/ets/rest_parameter_09.ets index db49515272580f195352d5fc6fbf43f1372a47eb..c958b2efe1158870f943ef205ec0ea298cf49f8f 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_09.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_09.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -22,4 +22,5 @@ class C { /* @@ label */(new C()).foo() +/* @@@ label Error TypeError: Expected 2 arguments, got 0. */ /* @@@ label Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_10.ets b/ets2panda/test/ast/parser/ets/rest_parameter_10.ets index 29860c344939e6d29e8c8f667ce7367eaa50b69a..db95f4b9b072594eeaef434067e33c86eee8179a 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_10.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_10.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -22,4 +22,5 @@ class C { /* @@ label */(new C()).foo(new A) +/* @@@ label Error TypeError: Expected 2 arguments, got 1. */ /* @@@ label Error TypeError: No matching call signature for foo(A) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_11.ets b/ets2panda/test/ast/parser/ets/rest_parameter_11.ets index 2d79df71a7415f37d2bcc309e759a9c4c9a82038..5750476b45c61d017f30953572399f04db80f51d 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_11.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_11.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -22,4 +22,5 @@ class C { /* @@ label */(new C()).foo(new A, new B, new B) +/* @@@ label Error TypeError: Expected 2 arguments, got 3. */ /* @@@ label Error TypeError: No matching call signature for foo(A, B, B) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_12.ets b/ets2panda/test/ast/parser/ets/rest_parameter_12.ets index 7f8d2e5e4da93675c8dca1545f5dfa460fcf7171..5b519005961a3ddb39329fe51fa1de4cec476a01 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_12.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_12.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -24,6 +24,9 @@ class C { /* @@ label2 */C.foo(new A) /* @@ label3 */C.foo(new A, new B, new B) +/* @@@ label1 Error TypeError: Expected 2 arguments, got 0. */ /* @@@ label1 Error TypeError: No matching call signature */ +/* @@@ label2 Error TypeError: Expected 2 arguments, got 1. */ /* @@@ label2 Error TypeError: No matching call signature for foo(A) */ +/* @@@ label3 Error TypeError: Expected 2 arguments, got 3. */ /* @@@ label3 Error TypeError: No matching call signature for foo(A, B, B) */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets index 70ae141ee79208fc4d760a6faa832d4ced30bb5d..8b8c8cdbc278be0553a1451210d4c53ddd8357c8 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets @@ -2,10 +2,10 @@ * 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 -* +* 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. @@ -22,7 +22,7 @@ class C { constructor(...p: [A, B]) { this.field = p[0] == p[1] } - + constructor(a: int, ...p: [A, B]) { this.field = p[0] == p[1] } @@ -34,6 +34,14 @@ function main() { /* @@ label3 */new C(new A, new B, new B) } +/* @@@ label1 Error TypeError: Expected 1 arguments, got 0. */ +/* @@@ label1 Error TypeError: Expected 2 arguments, got 0. */ +/* @@@ label1 Error TypeError: Expected 3 arguments, got 0. */ /* @@@ label1 Error TypeError: No matching construct signature */ +/* @@@ 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 */ +/* @@@ 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 */ diff --git a/ets2panda/test/ast/parser/ets/too_many_expression.ets b/ets2panda/test/ast/parser/ets/too_many_expression.ets index 813cdecc0051526625189ce67adef53e3a4dce36..e9649de766bc77c7344570f5f227aac15247073f 100644 --- a/ets2panda/test/ast/parser/ets/too_many_expression.ets +++ b/ets2panda/test/ast/parser/ets/too_many_expression.ets @@ -1,471 +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. - */ +/* + * 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. + */ -/new Uint8Array[let [-9] = ([((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= . 7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .$7 = + >>> 0O5.25657e9)]((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= .7 = + >>> 0O5.25657e9)][((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((({Symbol: [ceil(h: b= . +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( -/* @@? 16:1 Error SyntaxError: Unexpected token '/'. */ -/* @@? 16:2 Error SyntaxError: Unexpected token 'new'. */ -/* @@? 16:17 Error SyntaxError: Unexpected token 'let'. */ -/* @@? 16:17 Error TypeError: Indexed access is not supported for such expression type. */ -/* @@? 16:28 Error SyntaxError: Unexpected token '<'. */ -/* @@? 16:29 Error SyntaxError: Expected ']', got 'identification literal'. */ -/* @@? 16:29 Error SyntaxError: Unexpected token 'missing'. */ -/* @@? 16:29 Error TypeError: Unresolved reference missing */ -/* @@? 16:37 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:42 Error SyntaxError: Unexpected token '<'. */ -/* @@? 16:43 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 16:51 Error SyntaxError: Unexpected token ')'. */ -/* @@? 16:56 Error TypeError: need to specify target type for class composite */ -/* @@? 16:189 Error SyntaxError: Unexpected token. */ -/* @@? 16:189 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:189 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:191 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:194 Error SyntaxError: Unexpected token '.'. */ -/* @@? 16:196 Error SyntaxError: Unexpected token. */ -/* @@? 16:198 Error SyntaxError: Unexpected token. */ -/* @@? 16:200 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:202 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:206 Error SyntaxError: Unexpected token. */ -/* @@? 16:217 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:218 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:353 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:353 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:353 Error SyntaxError: Unexpected token. */ -/* @@? 16:355 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:361 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:365 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:369 Error SyntaxError: Unexpected token. */ -/* @@? 16:380 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:381 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:516 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:516 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:516 Error SyntaxError: Unexpected token. */ -/* @@? 16:518 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:524 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:528 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:532 Error SyntaxError: Unexpected token. */ -/* @@? 16:543 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:544 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:679 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:679 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:679 Error SyntaxError: Unexpected token. */ -/* @@? 16:681 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:687 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:691 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:695 Error SyntaxError: Unexpected token. */ -/* @@? 16:706 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:707 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:842 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:842 Error SyntaxError: Unexpected token. */ -/* @@? 16:842 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:844 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:850 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:854 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:858 Error SyntaxError: Unexpected token. */ -/* @@? 16:869 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:870 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1005 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1005 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1005 Error SyntaxError: Unexpected token. */ -/* @@? 16:1007 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1013 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1017 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1021 Error SyntaxError: Unexpected token. */ -/* @@? 16:1032 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1033 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1168 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1168 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1168 Error SyntaxError: Unexpected token. */ -/* @@? 16:1170 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1176 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1180 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1184 Error SyntaxError: Unexpected token. */ -/* @@? 16:1195 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1196 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1331 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1331 Error SyntaxError: Unexpected token. */ -/* @@? 16:1331 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1333 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1339 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1343 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1347 Error SyntaxError: Unexpected token. */ -/* @@? 16:1358 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1359 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1494 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1494 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1494 Error SyntaxError: Unexpected token. */ -/* @@? 16:1496 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1502 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1506 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1510 Error SyntaxError: Unexpected token. */ -/* @@? 16:1521 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1522 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1657 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1657 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1657 Error SyntaxError: Unexpected token. */ -/* @@? 16:1659 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1665 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1669 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1673 Error SyntaxError: Unexpected token. */ -/* @@? 16:1684 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1685 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1820 Error SyntaxError: Unexpected token. */ -/* @@? 16:1820 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1820 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1822 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1828 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1832 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1836 Error SyntaxError: Unexpected token. */ -/* @@? 16:1847 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:1848 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:1983 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:1983 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:1983 Error SyntaxError: Unexpected token. */ -/* @@? 16:1985 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:1991 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:1995 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:1999 Error SyntaxError: Unexpected token. */ -/* @@? 16:2010 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2011 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2146 Error SyntaxError: Unexpected token. */ -/* @@? 16:2146 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2146 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2148 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2154 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2158 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2162 Error SyntaxError: Unexpected token. */ -/* @@? 16:2173 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2174 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2309 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2309 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2309 Error SyntaxError: Unexpected token. */ -/* @@? 16:2311 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2317 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2321 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2325 Error SyntaxError: Unexpected token. */ -/* @@? 16:2336 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2337 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2472 Error SyntaxError: Unexpected token. */ -/* @@? 16:2472 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2472 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2474 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2480 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2484 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2488 Error SyntaxError: Unexpected token. */ -/* @@? 16:2499 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2500 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2635 Error SyntaxError: Unexpected token. */ -/* @@? 16:2635 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2635 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2637 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2643 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2647 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2651 Error SyntaxError: Unexpected token. */ -/* @@? 16:2662 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2663 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2798 Error SyntaxError: Unexpected token. */ -/* @@? 16:2798 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2798 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2800 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2806 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2810 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2814 Error SyntaxError: Unexpected token. */ -/* @@? 16:2825 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2826 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:2961 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:2961 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:2961 Error SyntaxError: Unexpected token. */ -/* @@? 16:2963 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:2969 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:2973 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:2977 Error SyntaxError: Unexpected token. */ -/* @@? 16:2988 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:2989 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3124 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3124 Error SyntaxError: Unexpected token. */ -/* @@? 16:3124 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3126 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3132 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3136 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3140 Error SyntaxError: Unexpected token. */ -/* @@? 16:3151 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3152 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3287 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3287 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3287 Error SyntaxError: Unexpected token. */ -/* @@? 16:3289 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3295 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3299 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3303 Error SyntaxError: Unexpected token. */ -/* @@? 16:3314 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3315 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3450 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3450 Error SyntaxError: Unexpected token. */ -/* @@? 16:3450 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3452 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3458 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3462 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3466 Error SyntaxError: Unexpected token. */ -/* @@? 16:3477 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3478 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3613 Error SyntaxError: Unexpected token. */ -/* @@? 16:3613 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3613 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3615 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3621 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3625 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3629 Error SyntaxError: Unexpected token. */ -/* @@? 16:3640 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3641 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3776 Error SyntaxError: Unexpected token. */ -/* @@? 16:3776 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3776 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3778 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3784 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3788 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3792 Error SyntaxError: Unexpected token. */ -/* @@? 16:3803 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3804 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:3939 Error SyntaxError: Unexpected token. */ -/* @@? 16:3939 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:3939 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:3941 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:3947 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:3951 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:3955 Error SyntaxError: Unexpected token. */ -/* @@? 16:3966 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:3967 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4102 Error SyntaxError: Unexpected token. */ -/* @@? 16:4102 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4102 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4104 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4110 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4114 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4118 Error SyntaxError: Unexpected token. */ -/* @@? 16:4129 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4130 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4265 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4265 Error SyntaxError: Unexpected token. */ -/* @@? 16:4265 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4267 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4273 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4277 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4281 Error SyntaxError: Unexpected token. */ -/* @@? 16:4292 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4293 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4428 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4428 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4428 Error SyntaxError: Unexpected token. */ -/* @@? 16:4430 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4436 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4440 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4444 Error SyntaxError: Unexpected token. */ -/* @@? 16:4455 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4456 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4591 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4591 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4591 Error SyntaxError: Unexpected token. */ -/* @@? 16:4593 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4599 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4603 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4607 Error SyntaxError: Unexpected token. */ -/* @@? 16:4618 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4619 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4754 Error SyntaxError: Unexpected token. */ -/* @@? 16:4754 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4754 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4756 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4762 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4766 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4770 Error SyntaxError: Unexpected token. */ -/* @@? 16:4781 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4782 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:4917 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:4917 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:4917 Error SyntaxError: Unexpected token. */ -/* @@? 16:4919 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:4925 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:4929 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:4933 Error SyntaxError: Unexpected token. */ -/* @@? 16:4944 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:4945 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:5080 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:5080 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:5080 Error SyntaxError: Unexpected token. */ -/* @@? 16:5082 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:5088 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:5092 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:5096 Error SyntaxError: Unexpected token. */ -/* @@? 16:5107 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:5108 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:5243 Error SyntaxError: Unexpected token. */ -/* @@? 16:5243 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:5243 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:5245 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:5251 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:5255 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:5259 Error SyntaxError: Unexpected token. */ -/* @@? 16:5270 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:5271 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:5406 Error SyntaxError: Unexpected token. */ -/* @@? 16:5406 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:5406 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:5408 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:5414 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:5418 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:5422 Error SyntaxError: Unexpected token. */ -/* @@? 16:5433 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:5434 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:5569 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:5569 Error SyntaxError: Unexpected token. */ -/* @@? 16:5569 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:5571 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:5577 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:5581 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:5585 Error SyntaxError: Unexpected token. */ -/* @@? 16:5596 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:5597 Error SyntaxError: Unexpected token ']'. */ -/* @@? 16:5732 Error SyntaxError: Unexpected token, expected ',' or ')'. */ -/* @@? 16:5732 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 16:5732 Error SyntaxError: Unexpected token. */ -/* @@? 16:5734 Error SyntaxError: Invalid shorthand property initializer. */ -/* @@? 16:5740 Error SyntaxError: Invalid left-hand side in assignment expression. */ -/* @@? 16:5744 Error SyntaxError: Unexpected token '>>>'. */ -/* @@? 16:5748 Error SyntaxError: Unexpected token. */ -/* @@? 16:5759 Error SyntaxError: Unexpected token, expected ':'. */ -/* @@? 16:5760 Error SyntaxError: Unexpected token ']'. */ - -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ',' or ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ']'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ -/* @@? 472:1 Error SyntaxError: Unexpected token. */ -/* @@? 472:1 Error SyntaxError: Unexpected token, expected ')'. */ +/* @@? 16:1025 Error SyntaxError: Maximum allowed nesting level exceeded. */ +/* @@? 19:67 Error SyntaxError: Unexpected token, expected ')'. */ \ 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 a5017ce1b8d99159045bb88bcbed7e28d811438c..556f4484e1776aca2f29c671170fc48615c8c4d5 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/test/parser/ets/getterOverride-expected.txt b/ets2panda/test/parser/ets/getterOverride-expected.txt index e223479634015a073306b06ad469b143ac9ffac0..64aef4f75fb0189142e8f69b1c6e06addc5ebc4d 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 186322d784b0eb15320378f9d779ce0a4f9d08f7..21522024230d4c9763450a7899c86c5129758d31 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 74a1b2496b3ba75e68186ffddbc65591fb299940..23266085b04a3b8123302cca339ef97225492d25 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/AnnotationOfClassPropertyInherit.ets b/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.ets new file mode 100644 index 0000000000000000000000000000000000000000..f7f39edabb87d52a23d71d18bb2eba8e5f0be4a5 --- /dev/null +++ b/ets2panda/test/runtime/ets/AnnotationOfClassPropertyInherit.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. + */ + +@interface JSONRename { + name:string = "" +} + +class A { + @JSONRename("ID") + name2: string = "" + pwd2: string = "" +} + +class B extends A {} diff --git a/ets2panda/test/runtime/ets/charToStringCast.ets b/ets2panda/test/runtime/ets/charToStringCast.ets index 0d4ed953f3633279c5b9522616397b5f4031a430..1226d3c2843bbe2d1777f904cbc807463b8036c1 100644 --- a/ets2panda/test/runtime/ets/charToStringCast.ets +++ b/ets2panda/test/runtime/ets/charToStringCast.ets @@ -14,7 +14,6 @@ */ function main(): void { - let s:string = c'X' as string; - + let s:string = new Char(c'X').toString(); assertEQ(s, "X") -} \ No newline at end of file +} diff --git a/ets2panda/linter/test/interop/test_files/dummy_arkts1_file.ets b/ets2panda/test/runtime/ets/class_implements_interface_export.ets similarity index 87% rename from ets2panda/linter/test/interop/test_files/dummy_arkts1_file.ets rename to ets2panda/test/runtime/ets/class_implements_interface_export.ets index 5aad017834822967ec7249e5db93b39b94750059..585718a5fa356c33eaf2f6c05836597e798ed9cc 100644 --- a/ets2panda/linter/test/interop/test_files/dummy_arkts1_file.ets +++ b/ets2panda/test/runtime/ets/class_implements_interface_export.ets @@ -13,4 +13,13 @@ * limitations under the License. */ -export module arkts {} +export class A{} + +interface I { + a: boolean +} + +class B implements I { + a = false +} + diff --git a/ets2panda/linter/test/interop/test_files/dummy_ts_file.ts b/ets2panda/test/runtime/ets/class_implements_interface_import.ets similarity index 91% rename from ets2panda/linter/test/interop/test_files/dummy_ts_file.ts rename to ets2panda/test/runtime/ets/class_implements_interface_import.ets index e2f4a0e44b486d7a8c9ba88bb4c7d9dd933145be..e779066f3cace24871b5147abf0176e5623c4d1a 100644 --- a/ets2panda/linter/test/interop/test_files/dummy_ts_file.ts +++ b/ets2panda/test/runtime/ets/class_implements_interface_import.ets @@ -13,4 +13,4 @@ * limitations under the License. */ -export module tsModule {} +import { A } from "./class_implements_interface_export" \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/enum_empty.ets b/ets2panda/test/runtime/ets/enum_empty.ets new file mode 100644 index 0000000000000000000000000000000000000000..3b7accba5095a1741e7888a435267f30ba722885 --- /dev/null +++ b/ets2panda/test/runtime/ets/enum_empty.ets @@ -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. + */ + +enum Empty { } + +class TestClass { } + +function main() { + let a: Empty | undefined = undefined; + let c: Empty | string | TestClass = "123" + foo(a); + foo2(c) +} + +function foo(a?: Empty) { } + +function foo2(a?: Empty | string | TestClass) { + assertEQ(a, "123") +} diff --git a/ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets b/ets2panda/test/runtime/ets/interfaceMethodWithDefaultParameter.ets new file mode 100644 index 0000000000000000000000000000000000000000..7efbf745fc190e2fd399fca9e3ee15bfa118c702 --- /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 diff --git a/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields1.ets b/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields1.ets new file mode 100644 index 0000000000000000000000000000000000000000..9b3a86d87093754ba337b026968a65fafd7689c6 --- /dev/null +++ b/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields1.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. + */ + +// lambda with receiver is used as fields + +class A { + f = (this: A): string => { return "instance A" } + + static f = (this: A): string => { return "static A" } +} + +function main() { + let a: A = new A() + assertEQ(a.f(a), "instance A") + assertEQ(A.f(a), "static A") +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields2.ets b/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields2.ets new file mode 100644 index 0000000000000000000000000000000000000000..1f304be5ac8142965188a728a02edb0315d3e64e --- /dev/null +++ b/ets2panda/test/runtime/ets/lambda_with_receiver/lambda_with_receiver_as_class_fields2.ets @@ -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. + */ + +class A { + f(): string { return "A" } +} +class B { + a:A + constructor(a:A){ + this.a = a + } + f = (this: A): string => { return "A ex" } +} + +function main() { + let a: A = new A() + let b: B = new B(a) + assertEQ(b.a.f(), "A") +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/multiple_typeof_operator.ets b/ets2panda/test/runtime/ets/multiple_typeof_operator.ets new file mode 100644 index 0000000000000000000000000000000000000000..6a891f640d3021dc7337034fb3d998252d252fac --- /dev/null +++ b/ets2panda/test/runtime/ets/multiple_typeof_operator.ets @@ -0,0 +1,36 @@ +/* + * 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 Y {} + +function main() { + let a : Int = 5 + + assertEQ(typeof typeof 1, "string") + assertEQ(typeof typeof typeof typeof typeof 5, "string") + assertEQ(typeof typeof typeof typeof typeof typeof 1, "string") + assertEQ(typeof typeof typeof typeof typeof typeof ++a, "string") + assertEQ(typeof typeof typeof typeof typeof typeof a++, "string") + + let y = new Y(); + + assertEQ(typeof y, "object") + + let typeof: int = 0; + let x = typeof + 1 + ++typeof; + + assertEQ(typeof typeof, "number"); +} diff --git a/ets2panda/test/runtime/ets/overload-primitive-and-object.ets b/ets2panda/test/runtime/ets/overload-primitive-and-object.ets new file mode 100644 index 0000000000000000000000000000000000000000..0ac7c992a695ded3de698a970f89ba2865463e2b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload-primitive-and-object.ets @@ -0,0 +1,35 @@ +/* + * 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 res: number = 0; +function foo(i: int, j: int): void { + res = 19; +} +function foo(i: number, j: Number): void { + res = 21; +} +function boo(x: Number, y: number) { + res = 34; +} +function boo(x: number, y: Number) { + res = 47; +} +function main(): void { + let n: Number = new Number(); + foo(1, n); + assertEQ(res, 21); + boo(6 as Number, 8); + assertEQ(res, 34); +} diff --git a/ets2panda/test/runtime/ets/stringliteral_to_char.ets b/ets2panda/test/runtime/ets/stringliteral_to_char.ets index 12a4d5723fd2b738a0bce33c12a459b82e8e2744..54c125597040571d9ed3c8d192043f85c1688f82 100644 --- a/ets2panda/test/runtime/ets/stringliteral_to_char.ets +++ b/ets2panda/test/runtime/ets/stringliteral_to_char.ets @@ -14,7 +14,7 @@ */ function foo() : Char { - return 'c' + return c'c' } function foo1(a: Char) : Char { @@ -26,11 +26,11 @@ function foo2() : Char { } function main() { - let c : Char = 'c'; + let c : Char = c'c'; let val : Char = foo() assertEQ(val, c) - let val1 : Char = foo1("c") + let val1 : Char = foo1("c"[0]) assertEQ(val1, c) let val2 : Char = foo2() diff --git a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt index 3888be099f06c2f41a1d1aefc8f37af562268910..2e165ab582113b71ccda1812e0ba2be2fe70ea00 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 b22bc81fde9a9281cf2a42f66b48860ae25d3b44..218f40820457e3d35cead6f6e3f96a73df23a911 100644 --- a/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt +++ b/ets2panda/test/test-lists/srcdumper/srcdumper-ets-ignored.txt @@ -63,8 +63,6 @@ ast/parser/ets/re_export/re_export_15.ets ast/parser/ets/re_export/re_export_16.ets parser/ets/ambient_indexer_1.ets parser/ets/ambient_indexer_6.ets -parser/ets/class_init.ets -parser/ets/class_static_initializer.ets parser/ets/conversions.ets parser/ets/declare_namespace.ets runtime/ets/namespace_tests/namespace_import_type_test/namespace_export.ets @@ -100,7 +98,6 @@ 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/localClassIsPermitted.ets parser/ets/promiseCasting.ets parser/ets/re_export/diamond/B.ets parser/ets/re_export/diamond/B2.ets @@ -156,8 +153,6 @@ 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_static_block_multi_files/P1/P1_0.ets -ast/compiler/ets/package_static_block_multi_files/P1/P1_1.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 @@ -194,6 +189,7 @@ 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 c3b982aa63f37c06a973606c199c648cf3014966..8a8e6911a8048bac1f53c8fe6b9f8345a3a0eae8 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 472da09d9329ca691410ca30ae0c73809329f96a..1c82aeed87a9433ae34306838724b64a7aea4296 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/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index 7dbd8024a75bfd6c60df69fbedc8aa5ea548473c..82d3f067648b2d1f95c98e205042cefd98deb241 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 ) @@ -207,3 +207,6 @@ ets2panda_add_gtest(lsp_api_test_todo_comments CPP_SOURCES ets2panda_add_gtest(lsp_api_test_navigate_to CPP_SOURCES navigate_to_test.cpp ) +ets2panda_add_gtest(lsp_api_test_code_fix_registration CPP_SOURCES + code_fix_registration_test.cpp +) diff --git a/ets2panda/test/unit/lsp/change_tracker_test.cpp b/ets2panda/test/unit/lsp/change_tracker_test.cpp index d20c3f551a23f98f4d5694b423f92f83919e40ef..1726d6b4563b6c66ac88352ab5ce6c8e7a3d80ff 100644 --- a/ets2panda/test/unit/lsp/change_tracker_test.cpp +++ b/ets2panda/test/unit/lsp/change_tracker_test.cpp @@ -24,7 +24,7 @@ #include "lsp_api_test.h" #include "lsp/include/class_hierarchy.h" #include "lsp/include/internal_api.h" -#include "lsp/include/text_change/change_tracker.h" +#include "lsp/include/services/text_change/change_tracker.h" #include "public/es2panda_lib.h" #include @@ -44,7 +44,7 @@ ark::es2panda::lsp::ChangeTracker GetTracker() const std::string defaultNewLine = "\n"; ark::es2panda::lsp::FormatCodeSettings settings; auto formatContext = ark::es2panda::lsp::GetFormatContext(settings); - ark::es2panda::lsp::TextChangesContext changeText {{}, formatContext, {}}; + TextChangesContext changeText {{}, formatContext, {}}; auto tracker = ark::es2panda::lsp::ChangeTracker::FromContext(changeText); return tracker; } @@ -69,12 +69,9 @@ function add(a: number, b: number) { auto spanStart = returnNode->Start().index; auto spanLength = strlen("return a + b;"); TextSpan span = {spanStart, spanLength}; - ark::es2panda::lsp::FileTextChanges fileChange; - fileChange.fileName = "pushRaw_AddsChangeCorrectly.ets"; - fileChange.isNewFile = false; std::string retStr = "return a - b;"; TextChange change = {span, retStr}; - fileChange.textChanges.push_back(change); + FileTextChanges fileChange = {"pushRaw_AddsChangeCorrectly.ets", {change}}; auto tracker = GetTracker(); tracker.PushRaw(sourceFile, fileChange); @@ -82,14 +79,14 @@ function add(a: number, b: number) { EXPECT_FALSE(list.empty()); EXPECT_EQ(list.size(), 1); - const auto &variant = list[0]; - const auto *changeText = std::get_if(&variant); - ASSERT_NE(changeText, nullptr); + const auto variant = list[0]; + const auto changeText = variant.textChanges; + ASSERT_EQ(changeText[0].newText, retStr); - EXPECT_EQ(changeText->sourceFile->filePath, fileChange.fileName); + EXPECT_EQ(variant.fileName, fileChange.fileName); - const auto &textChange = changeText->range; - EXPECT_EQ(textChange.pos, spanStart); + const auto &textChange = changeText; + EXPECT_EQ(textChange[0].span.start, spanStart); } TEST_F(LspClassChangeTracker, DeleteMethods_BasicTest1) diff --git a/ets2panda/test/unit/lsp/class_hierarchys_test.cpp b/ets2panda/test/unit/lsp/class_hierarchys_test.cpp index e946aed4748d29a5aad81ac0bc0b56fc109230f8..5a4647aeb98ebb02979f089090cedaa9cf1f897d 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) { diff --git a/ets2panda/test/unit/lsp/code_fix_registration_test.cpp b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c493453dba112e9a73e873418e4155888bd1b250 --- /dev/null +++ b/ets2panda/test/unit/lsp/code_fix_registration_test.cpp @@ -0,0 +1,30 @@ +/** + * 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/code_fix_provider.h" +#include "gtest/gtest.h" + +namespace { + +TEST(RefactorProviderRegistrationTest, RegistersConvertFunctionRefactor) +{ + const auto &provider = ark::es2panda::lsp::CodeFixProvider::Instance(); + const auto &errors = provider.GetErrorCodeToFixes(); + const auto &fixIdToRegistration = provider.GetFixIdToRegistration(); + EXPECT_FALSE(errors.empty()); + EXPECT_FALSE(fixIdToRegistration.empty()); + EXPECT_EQ(errors.size(), 5); +} +} // namespace \ No newline at end of file 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 b6d8c37e24a78850931124f9ab47a23d587b0d28..039281bfc6db5d7408e822bb87d579da42dc822c 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 diff --git a/ets2panda/test/unit/lsp/get_completions_entry_details.cpp b/ets2panda/test/unit/lsp/get_completions_entry_details.cpp index d55b0df0f4ba992aba6c303dd63ef955c8e83075..1bb64d6bbab1f18d0a4adddb10fb21cf04a8d247 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 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 536122486fde7fc6c0d54260bedaf6b05ad8a067..cfbac8e4199b2e536d3e4336d5119b8d42efda12 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 d230e67a2e4e94e7460f2527bbf5692212c316d9..5a0f1c776bba96cd364449bdb9ba54003c83cd59 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 ea1af27659e22815bacc7be14489e5eb31b38aca..39ad9d38870fac53c5e9301794ffaf4090bc5902 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/lsp/organize_imports_test.cpp b/ets2panda/test/unit/lsp/organize_imports_test.cpp index 573c3dc35b3be0e08e7fc924a38f0646b8637089..137fea4d9d3b2f93db700a6edba1fb7a998e7f2a 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); } 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 0000000000000000000000000000000000000000..b033fa469d9dcdaa4eeea047b1feff68bda94cc0 --- /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 2688b3b2c5605f574b5afb34393d4f0a1177651c..0000000000000000000000000000000000000000 --- 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 diff --git a/ets2panda/test/unit/lsp/script_element_kind_test.cpp b/ets2panda/test/unit/lsp/script_element_kind_test.cpp index 71aedf5f4efe9ea7ee7eafa918b0fdfdcfe86c76..dd461cd45da89973984963bd060d30022cf78eb5 100644 --- a/ets2panda/test/unit/lsp/script_element_kind_test.cpp +++ b/ets2panda/test/unit/lsp/script_element_kind_test.cpp @@ -32,7 +32,7 @@ TEST_F(LSPAPITests, GetAliasScriptElementKind_1) Initializer initializer = Initializer(); es2panda_Context *context = initializer.CreateContext( - "script_element_kind.ets", ES2PANDA_STATE_CHECKED, + "script_element_kind_1.ets", ES2PANDA_STATE_CHECKED, "let number_literal: number = 1234;\nlet string_literal: string = \"hello\";\nconst str_property = " "\"foo\";\n"); @@ -52,7 +52,7 @@ TEST_F(LSPAPITests, GetAliasScriptElementKind_2) LSPAPI const *lspApi = GetImpl(); Initializer initializer = Initializer(); es2panda_Context *context = - initializer.CreateContext("script_element_kind.ets", ES2PANDA_STATE_CHECKED, + initializer.CreateContext("script_element_kind_2.ets", ES2PANDA_STATE_CHECKED, " \nfunction f() {\n let a = 123;\n}\nconst s = \"hello\";\n"); size_t const startOfFile = 0; // 0: position of start of file, first space @@ -74,7 +74,8 @@ TEST_F(LSPAPITests, GetAliasScriptElementKind_3) const char *statement = R"(let empty: null = null; let notAssigned: undefined = undefined;)"; - es2panda_Context *context = initializer.CreateContext("script_element_kind.ets", ES2PANDA_STATE_CHECKED, statement); + es2panda_Context *context = + initializer.CreateContext("script_element_kind_3.ets", ES2PANDA_STATE_CHECKED, statement); size_t const nullLiteral = 19; // 19:position of the second null. size_t const etsNullType = 25; // 25: position of the second let. diff --git a/ets2panda/test/unit/plugin/CMakeLists.txt b/ets2panda/test/unit/plugin/CMakeLists.txt index 91cf3d297b6beefbc449bf27392ca1080b4afe91..672aff08e47fc7bb6d04a499fb451dc6d7bcff1e 100644 --- a/ets2panda/test/unit/plugin/CMakeLists.txt +++ b/ets2panda/test/unit/plugin/CMakeLists.txt @@ -110,6 +110,7 @@ set(PLUGIN_TESTS "plugin_proceed_to_state_test_global_func_call_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_interface_duplicate_setter compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_case_block_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" + "plugin_proceed_to_state_function_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" ) set(RUNTIME_ARGUMENTS diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state.cpp index aa95c1230462a62b1470ceaad0825d555a9573f5..b700c046a91a6e21bd812c47bcf96d1afc9fd211 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 2efc5c36d56c243078a5bf2cc3c686c83919b66d..d7953251363888edd9d08f7f54812ceba7388633 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 3cbc8d25db12c56f0a19fa25c741c252882f40c3..7d7f575528f3c2992d9ff13dd471bf470cb1c3bb 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/plugin_proceed_to_state_function_dump.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_function_dump.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b04f4e7b42499db679f80b3da671c60437757c15 --- /dev/null +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_function_dump.cpp @@ -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. + */ + +#include +#include "public/es2panda_lib.h" +#include "util.h" + +static es2panda_Impl *g_impl = nullptr; +static const char *const G_SOURCE = "export function foo(x?: int) {}"; +static std::string *g_dumpedSource = nullptr; + +int main(int argc, char **argv) +{ + auto dumpTest = [](es2panda_Context *context) -> bool { + const char *dumpedSourceInArenaMemory = + g_impl->AstNodeDumpEtsSrcConst(context, g_impl->ProgramAst(context, g_impl->ContextProgram(context))); + g_dumpedSource = new std::string(dumpedSourceInArenaMemory); + return g_dumpedSource->find(G_SOURCE) != std::string::npos; + }; + + std::map>> testFunctions1; + testFunctions1[ES2PANDA_STATE_CHECKED] = {dumpTest}; + ProccedToStatePluginTestData data1 = {argc, argv, &g_impl, testFunctions1, true, G_SOURCE, ES2PANDA_STATE_CHECKED}; + int result = RunAllStagesWithTestFunction(data1); + if (result != 0) { + delete g_dumpedSource; + return result; + } + + std::map>> testFunctions2; + ProccedToStatePluginTestData data2 = {argc, argv, &g_impl, testFunctions2, true, *g_dumpedSource}; + result = RunAllStagesWithTestFunction(data2); + delete g_dumpedSource; + g_dumpedSource = nullptr; + return result; +} diff --git a/ets2panda/test/unit/plugin/util.cpp b/ets2panda/test/unit/plugin/util.cpp index ee42c4879b4f98765ede5eb3f51958b1b10c3b77..e5709c5b75bff83da4e8214af53f6a76d584c81b 100644 --- a/ets2panda/test/unit/plugin/util.cpp +++ b/ets2panda/test/unit/plugin/util.cpp @@ -137,10 +137,11 @@ static bool IsAllowedStage(es2panda_ContextState state) } } -static void DestroyTest(es2panda_Context *context, es2panda_Config *config) +static int DestroyTest(es2panda_Context *context, es2panda_Config *config, const int exitCode) { g_implPtr->DestroyContext(context); g_implPtr->DestroyConfig(config); + return exitCode; } int RunAllStagesWithTestFunction(ProccedToStatePluginTestData &data) @@ -169,8 +170,7 @@ int RunAllStagesWithTestFunction(ProccedToStatePluginTestData &data) for (auto [testStage, _] : data.testFunctions) { if (!IsAllowedStage(testStage)) { - DestroyTest(context, config); - return TEST_ERROR_CODE; + return DestroyTest(context, config, TEST_ERROR_CODE); } } @@ -183,18 +183,16 @@ int RunAllStagesWithTestFunction(ProccedToStatePluginTestData &data) CheckForErrors(GetPhaseName(state), context); for (const auto &testFunc : data.testFunctions[state]) { if (!testFunc(context)) { - DestroyTest(context, config); - return TEST_ERROR_CODE; + return DestroyTest(context, config, TEST_ERROR_CODE); } } + if (state == data.exitAfterState) { + break; + } } - if (g_implPtr->ContextState(context) == ES2PANDA_STATE_ERROR) { - DestroyTest(context, config); - return PROCEED_ERROR_CODE; - } - DestroyTest(context, config); - return 0; + int result = g_implPtr->ContextState(context) == ES2PANDA_STATE_ERROR ? PROCEED_ERROR_CODE : 0; + return DestroyTest(context, config, result); } int Test(es2panda_Context *context, es2panda_Impl *impl, int stage, diff --git a/ets2panda/test/unit/plugin/util.h b/ets2panda/test/unit/plugin/util.h index 4bfae76fbac8b47c42c63628c5e6f741729105a3..515f89b105bd02b3155f3658e172b7fd02788d7a 100644 --- a/ets2panda/test/unit/plugin/util.h +++ b/ets2panda/test/unit/plugin/util.h @@ -44,6 +44,7 @@ struct ProccedToStatePluginTestData { std::map>> testFunctions; bool fromSource; std::string source; + es2panda_ContextState exitAfterState = ES2PANDA_STATE_ERROR; }; void CheckForErrors(const std::string &stateName, es2panda_Context *context); 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 35f7374b7b19ba0bdd94fc171e5425d610a6af4c..7e88eff58069a34f01ac3ba0abc2ed237d37e9c3 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 d6f9e1b2820481ee809bf898384cd9ffa1f7d503..eee97381aa92785d2a7f9622fdb8c9bff839ce26 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 8eb1282e8cd57206baca8071d10c9004b14e86fc..1b4c7be1d7115e28a79a197d3f1a15554b92e3df 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 4564a46588737aec56e7d886b7c7bc1f7f81723a..7814d7f261bf2ede5137cefe7217592859b56161 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 51b3a9e2cfa67f1d3a5cfc22de33bcb5822e853e..2652cdfe6fe8bd1e178704da2bde225731af52f2 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 288cafaf20f616c57cc4089b17d851b65fc31973..dbdd1b433c20cd6034af0c1074360b797b1c39e2 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 b8d0e4960490b31aa08f7d9f85341080a4eeda5c..651b6ab840ed182055a63a6627d43f64c3f841db 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 7ee4731ed7ff27114ecf4f2338e56762487f4851..542d91ddf755197429d7945a23a9a83e8faa5785 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 c5cf75fa2b30ab3ca9619ba20581f2c0e225b9f0..4a20d2a0540dbc26ed29e1649e1400191036df99 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 5cf5263917e9da8538a71822044520fc5af37a2d..3d964e211d995e0d0cf41aa5e7967d71b8bea03b 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_); @@ -138,6 +139,7 @@ size_t SizeOfNodeTest::SizeOf() sizeof(node->anonClass_) + Align(sizeof(node->localIndex_)) + sizeof(node->localPrefix_) + + sizeof(node->functionalReferenceReferencedMethod_) + sizeof(node->exportedClasses_); // clang-format on } @@ -587,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 0a7312aa666b947aa427c947d87dfdc2a9789320..36b345f6c3940552772d8cb0cc84326e2ec7ed83 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/asm_test.cpp b/ets2panda/test/utils/asm_test.cpp index 230cb5cd58309db59228b59f0f3d71f11665d05e..53fb2a8dcf1e4258b5c3b2826a3a882c931fe8df 100644 --- a/ets2panda/test/utils/asm_test.cpp +++ b/ets2panda/test/utils/asm_test.cpp @@ -225,7 +225,7 @@ void AsmTest::CheckFunctionParameterAnnotations(ark::pandasm::Program *program, ASSERT_LT(paramIndex, found->second.params.size()); for (const auto &expected : expectedAnnotations) { - auto annotations = found->second.params.at(paramIndex).metadata->GetAnnotations(); + auto annotations = found->second.params.at(paramIndex).GetOrCreateMetadata().GetAnnotations(); auto it = std::find_if(annotations.begin(), annotations.end(), [&expected](const ark::pandasm::AnnotationData &annotation) { return annotation.GetName() == expected.first; @@ -246,7 +246,7 @@ void AsmTest::CheckFunctionParameterWithoutAnnotations(ark::pandasm::Program *pr auto found = functionTable.find(functionName); ASSERT_NE(found, functionTable.end()); ASSERT_LT(paramIndex, found->second.params.size()); - ASSERT(found->second.params.at(paramIndex).metadata->GetAnnotations().empty()); + ASSERT(found->second.params.at(paramIndex).GetOrCreateMetadata().GetAnnotations().empty()); } void AsmTest::CheckClassFieldAnnotations(ark::pandasm::Program *program, const std::string &recordName, diff --git a/ets2panda/test/utils/ast_verifier_test.cpp b/ets2panda/test/utils/ast_verifier_test.cpp index 96fc2c38f97a1d95cd8db36cf3b1828505333825..2175041ca7925aa23384e1a5f9cb1c3ddc7ac662 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 68ccb22ecb1b9769f01705ae9a8c2fbcbfbff1bc..0d4d9fd9550e911860cda8aa30cf36d617a12ced 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 cd41db0d661cbc2f25eb74df4f8e162ea795bbcb..79259abbadaa30314635362e73d5b21792a83a71 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 ce8df944bac418aedcb6a0ded16ce672310dec65..2529a908f57a0244d753db39bd5dbe91fcaa361b 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/diagnostic/fatal.yaml b/ets2panda/util/diagnostic/fatal.yaml index c8e64913cc1cf4e59d2d4907a855e3d0018c8ea6..0bc08c8af6333a592a341bc1fb90e149fa76ba21 100644 --- a/ets2panda/util/diagnostic/fatal.yaml +++ b/ets2panda/util/diagnostic/fatal.yaml @@ -111,7 +111,3 @@ fatal: - name: MISSING_OUTPUT_FILE id: 25 message: "Output file path must be specified." - -- name: DEEP_NESTING - id: 26 - message: "Maximum allowed nesting level exceeded." diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 302489098a9dc43b3dc23b6cded42765acf6cdd2..e61143986bcf695abdb9aa0c4020ed3b1e3d0d43 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -260,7 +260,7 @@ semantic: id: 62 message: "need to specify target type for class composite" -- name: CKASS_COMPOSITE_INVALID_TARGET +- name: CLASS_COMPOSITE_INVALID_TARGET id: 63 message: "Target type for class composite needs to be an object type, found '{}'" diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index eeafa8b76d20336d478313d800822298ea56da5b..bb3bcb5a839bceeb48d13c63c29b2ff43e5f3914 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -516,9 +516,9 @@ syntax: id: 126 message: "Variable declaration expected." -- name: ENUM_MUST_HAVE_ONE_CONST +- name: CONFLICTING_FIELD_MODIFIERS id: 127 - message: "An enum must have at least one enum constant." + message: "Conflicting modifiers '!' and '?' on field." - name: VALUE_IS_NOT_SET id: 128 @@ -1228,6 +1228,14 @@ syntax: id: 304 message: "Late-initialized field cannot have default value." -- name: CONFLICTING_FIELD_MODIFIERS +- name: DEEP_NESTING id: 305 - message: "Conflicting modifiers '!' and '?' on field." \ 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." + +- name: ERROR_ARKTS_NO_EXPORT_ASSIGNMENT + id: 307 + message: "'export = ...' syntax is not supported, use regular import/export instead!" diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 131ca76cf853ad72d7bea3b41d85bb1e7e4c47fe..9660f1f160f0261e55eee8caa904972c4c70247f 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 0562a1cb453f1188dd5d0c7973e034f99b1ae7d5..a013fc7a71296a28d869b92a28d67a00afe02e86 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 46a95feeb13deec32a36e70db739689d02203b04..b22f3325b19332835b92a5e03e3faea22018be79 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 cc0990c7b5768973d1159ca7af31193b5bcfa31d..6764fadf6a481d4e5a58a42b249cceed57169ad3 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 21095663b0dadb9d8a4d27077784a065678d3360..9e011a215919850377801f2c805284ab4e50a03d 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/util/recursiveGuard.h b/ets2panda/util/recursiveGuard.h index ad89f5a8e5ef34905ade1d0fe228ac09c726371e..34b57989b1ec5ec1c1ec112c1a01ccb641901e54 100644 --- a/ets2panda/util/recursiveGuard.h +++ b/ets2panda/util/recursiveGuard.h @@ -18,7 +18,7 @@ namespace ark::es2panda::parser { -constexpr unsigned int MAX_RECURSION_DEPTH = 4096; +constexpr unsigned int MAX_RECURSION_DEPTH = 1024; struct RecursiveContext { unsigned depth = 0; diff --git a/ets2panda/util/ustring.cpp b/ets2panda/util/ustring.cpp index 7a8d1ace6d23afd00f7bcc4c95c9e673a2dcbb88..90cf82ad7718209eebd29408a5b6421bb2617765 100644 --- a/ets2panda/util/ustring.cpp +++ b/ets2panda/util/ustring.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 @@ -80,14 +80,6 @@ void StringView::Iterator::SkipCp() } } -bool StringView::IsConvertibleToChar() const -{ - Iterator it(*this); - size_t size = 0; - char32_t ch = it.PeekCp(&size); - return size == Length() && ch != Iterator::INVALID_CP; -} - } // namespace ark::es2panda::util // NOLINTNEXTLINE(cert-dcl58-cpp) diff --git a/ets2panda/util/ustring.h b/ets2panda/util/ustring.h index 4437014055c8c3cf2873810ad2c69c7605c6fcf8..be6a745d60eeb58ac60b8e767f1bb344cc9cf59f 100644 --- a/ets2panda/util/ustring.h +++ b/ets2panda/util/ustring.h @@ -156,8 +156,6 @@ public: template static void Mutf8Encode(T *str, char32_t cu); - bool IsConvertibleToChar() const; - class Iterator { public: static char32_t constexpr INVALID_CP = std::numeric_limits::max(); diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0f9ae6db10eb045584fc07219f3d5e52f561d4bc..3c1b368ce7d2fe7a0da0d81285a47f1c0bd200fd 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 6d24b0f3c70a02b79922da2a2016018cfcf53eef..140596eccdc48348626616e97dcf9b436d0b61b9 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 1b3c9bd10c98555613327fa05b3ac7b8e8f766a3..437a2ffb79dd259f21257e6901141194fc991930 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 0504029b7be6471f8ede3cfadc766d7e0d78e2e5..83750a64247d1fa390960df5d42edf312e0cb6d4 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 7005e55370513706478b8932f632e9e7082b0072..ff674f639bedec5df0df93fdecf5d21aab8b3379 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 ba937f6b0135da8607f155b9bdd9cb9a045fae43..be95eb82d3fd27bc765b38cb42380c925f96502d 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 {