From f59e7f946a7dca53e0f39149e88cf3a6409ddf2e Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Tue, 2 Sep 2025 18:43:19 +0300 Subject: [PATCH 1/3] Enums --- .../main/kotlin/org/jacodb/ets/dto/Convert.kt | 4 +- .../main/kotlin/org/jacodb/ets/dto/Types.kt | 4 +- .../main/kotlin/org/jacodb/ets/model/Type.kt | 10 +- .../kotlin/org/jacodb/ets/test/EnumTest.kt | 148 ++++++++++++ .../samples/source/lang/enum-edge-cases.ts | 193 +++++++++++++++ .../samples/source/lang/enum-modules.ts | 190 +++++++++++++++ .../resources/samples/source/lang/enum.ts | 227 +++++++++++++++++- 7 files changed, 766 insertions(+), 10 deletions(-) create mode 100644 jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EnumTest.kt create mode 100644 jacodb-ets/src/test/resources/samples/source/lang/enum-edge-cases.ts create mode 100644 jacodb-ets/src/test/resources/samples/source/lang/enum-modules.ts diff --git a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt index 75fb62326..d071751f7 100644 --- a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt +++ b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt @@ -529,8 +529,8 @@ fun TypeDto.toEtsType(): EtsType = when (this) { is ClassTypeDto -> toEtsClassType() is EnumValueTypeDto -> EtsEnumValueType( - signature = signature.toEtsFieldSignature(), - constant = constant?.toEtsConstant(), + signature = signature.toEtsClassSignature(), + name = name, ) is FunctionTypeDto -> EtsFunctionType( diff --git a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Types.kt b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Types.kt index 5e9fb8fd8..511db7ac3 100644 --- a/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Types.kt +++ b/jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Types.kt @@ -71,8 +71,8 @@ data class LexicalEnvTypeDto( @Serializable @SerialName("EnumValueType") data class EnumValueTypeDto( - val signature: FieldSignatureDto, - val constant: ConstantDto? = null, + val signature: ClassSignatureDto, + val name: String? = null, ) : TypeDto @Serializable diff --git a/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Type.kt b/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Type.kt index d6dda2ae2..d78bfdbd7 100644 --- a/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Type.kt +++ b/jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Type.kt @@ -428,11 +428,15 @@ data class EtsLexicalEnvType( } data class EtsEnumValueType( - val signature: EtsFieldSignature, - val constant: EtsConstant? = null, + val signature: EtsClassSignature, + val name: String? = null, ) : EtsType { override val typeName: String - get() = signature.name + get() = if (name != null) { + "${signature.name}.$name" + } else { + signature.name + } override fun toString(): String = typeName diff --git a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EnumTest.kt b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EnumTest.kt new file mode 100644 index 000000000..921cf8c57 --- /dev/null +++ b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EnumTest.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2022 UnitTestBot contributors (utbot.org) + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jacodb.ets.test + +import org.jacodb.ets.model.EtsClassCategory +import org.jacodb.ets.test.utils.getResourcePath +import org.jacodb.ets.utils.loadEtsFileAutoConvert +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue + +class EnumTest { + + @Test + fun testEnum() { + val path = "/samples/source/lang/enum.ts" + val res = getResourcePath(path) + val file = loadEtsFileAutoConvert(res) + + // Count enum classes + val enumClasses = file.allClasses.filter { it.category == EtsClassCategory.ENUM } + assertTrue(enumClasses.size >= 5, "File should have multiple enums") + + // Check for specific enum types + val basicEnum = enumClasses.find { it.name == "BasicEnum" } + val stringEnum = enumClasses.find { it.name == "StringEnum" } + val mixedEnum = enumClasses.find { it.name == "MixedEnum" } + + assertNotNull(basicEnum, "Should find BasicEnum") + assertNotNull(stringEnum, "Should find StringEnum") + assertNotNull(mixedEnum, "Should find MixedEnum") + + // Verify field counts + assertEquals(3, basicEnum.fields.size, "BasicEnum should have 3 fields") + assertEquals(3, stringEnum.fields.size, "StringEnum should have 3 fields") + assertEquals(3, mixedEnum.fields.size, "MixedEnum should have 3 fields") + } + + @Test + fun testEnumEdgeCases() { + val path = "/samples/source/lang/enum-edge-cases.ts" + val res = getResourcePath(path) + val file = loadEtsFileAutoConvert(res) + + val enumClasses = file.allClasses.filter { it.category == EtsClassCategory.ENUM } + assertTrue(enumClasses.isNotEmpty(), "Edge cases file should have enums") + + // Check for specific edge case enums + val emptyEnum = enumClasses.find { it.name == "EmptyEnum" } + val singleEnum = enumClasses.find { it.name == "SingleEnum" } + val floatEnum = enumClasses.find { it.name == "FloatEnum" } + + assertNotNull(emptyEnum, "Should find EmptyEnum") + assertNotNull(singleEnum, "Should find SingleEnum") + assertNotNull(floatEnum, "Should find FloatEnum") + + // Verify edge case properties + assertEquals(0, emptyEnum.fields.size, "EmptyEnum should have no fields") + assertEquals(1, singleEnum.fields.size, "SingleEnum should have 1 field") + assertEquals(3, floatEnum.fields.size, "FloatEnum should have 3 fields") + } + + @Test + fun testEnumModules() { + val path = "/samples/source/lang/enum-modules.ts" + val res = getResourcePath(path) + val file = loadEtsFileAutoConvert(res) + + val enumClasses = file.allClasses.filter { it.category == EtsClassCategory.ENUM } + assertTrue(enumClasses.isNotEmpty(), "Modules file should have enums") + + // Check for exported enums + val publicEnum = enumClasses.find { it.name == "PublicEnum" } + val constExportEnum = enumClasses.find { it.name == "ConstExportEnum" } + + assertNotNull(publicEnum, "Should find PublicEnum") + assertNotNull(constExportEnum, "Should find ConstExportEnum") + + // Verify exported enum properties + assertEquals(3, publicEnum.fields.size, "PublicEnum should have 3 fields") + assertEquals(3, constExportEnum.fields.size, "ConstExportEnum should have 3 fields") + } + + @Test + fun testEnumUsageInClasses() { + val path = "/samples/source/lang/enum.ts" + val res = getResourcePath(path) + val file = loadEtsFileAutoConvert(res) + + // Find class that uses enums + val usageClass = file.allClasses.find { it.name == "EnumUsageExamples" } + assertNotNull(usageClass, "Should find EnumUsageExamples class") + + // Verify the class has methods that work with enums + val methods = usageClass.methods + assertTrue(methods.any { it.name == "setColor" }, "Should have setColor method") + assertTrue(methods.any { it.name == "getDirection" }, "Should have getDirection method") + assertTrue(methods.any { it.name == "handleDirection" }, "Should have handleDirection method") + + // Check method parameter counts + val setColorMethod = methods.find { it.name == "setColor" } + assertNotNull(setColorMethod, "setColor method should exist") + assertEquals(1, setColorMethod.parameters.size, "setColor should have 1 parameter") + + val getDirectionMethod = methods.find { it.name == "getDirection" } + assertNotNull(getDirectionMethod, "getDirection method should exist") + assertEquals(0, getDirectionMethod.parameters.size, "getDirection should have no parameters") + } + + @Test + fun testEnumVsClassDistinction() { + val path = "/samples/source/lang/enum.ts" + val res = getResourcePath(path) + val file = loadEtsFileAutoConvert(res) + + // Count different class categories + val enumCount = file.allClasses.count { it.category == EtsClassCategory.ENUM } + val classCount = file.allClasses.count { it.category == EtsClassCategory.CLASS } + + assertTrue(enumCount > 0, "Should have enum classes") + assertTrue(classCount > 0, "Should have regular classes") + + // Verify proper categorization + val basicEnum = file.allClasses.find { it.name == "BasicEnum" } + val usageClass = file.allClasses.find { it.name == "EnumUsageExamples" } + + assertNotNull(basicEnum, "Should find BasicEnum") + assertNotNull(usageClass, "Should find EnumUsageExamples") + + assertEquals(EtsClassCategory.ENUM, basicEnum.category, "BasicEnum should be categorized as ENUM") + assertEquals(EtsClassCategory.CLASS, usageClass.category, "EnumUsageExamples should be categorized as CLASS") + } +} diff --git a/jacodb-ets/src/test/resources/samples/source/lang/enum-edge-cases.ts b/jacodb-ets/src/test/resources/samples/source/lang/enum-edge-cases.ts new file mode 100644 index 000000000..02e85d9fa --- /dev/null +++ b/jacodb-ets/src/test/resources/samples/source/lang/enum-edge-cases.ts @@ -0,0 +1,193 @@ +// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +// Empty enum (edge case) +enum EmptyEnum { + // No members +} + +// Single member enum +enum SingleEnum { + OnlyOne +} + +// Enum with float values +enum FloatEnum { + Pi = 3.14, + E = 2.71, + Phi = 1.618 +} + +// Enum with very long names +enum VeryLongNameEnum { + ThisIsAVeryLongEnumMemberNameThatTestsTheParsingCapability, + AnotherExtremelyLongEnumMemberNameForTestingPurposes, + ShortName +} + +// Enum with special characters in string values +enum SpecialCharEnum { + NewLine = "line1\nline2", + Tab = "col1\tcol2", + Quote = "He said \"Hello\"", + Backslash = "path\\to\\file", + Unicode = "café 🚀 ñoño" +} + +// Enum with duplicate values (different keys, same values) +enum DuplicateValueEnum { + Primary = 1, + Secondary = 1, // Same value as Primary + Tertiary = 2 +} + +// Enum members that look like reserved words +enum ReservedWordLikeEnum { + class = "class_value", + function = "function_value", + var = "var_value", + let = "let_value", + const = "const_value" +} + +// Enum with number-like string values +enum NumberStringEnum { + Zero = "0", + One = "1", + Two = "2", + NotANumber = "NaN" +} + +// Nested enum access patterns +namespace NestedAccess { + export enum InnerEnum { + Value1 = "inner1", + Value2 = "inner2" + } + + export function useInnerEnum(): InnerEnum { + return InnerEnum.Value1; + } +} + +// Enum used in generic constraints +interface EnumConstraint { + value: T; + + process(input: T): void; +} + +// Enum with computed values using other enums +enum CrossReferenceEnum { + Base = DuplicateValueEnum.Primary, + Extended = Base + 10, + Combined = FloatEnum.Pi + Base +} + +// Enum used in type unions +type ColorOrNumber = StringEnum | NumericEnum; + +// Enum used as object key type +type EnumAsKey = { + [K in StringEnum]: boolean; +}; + +// Enum with function call values +enum FunctionCallEnum { + Random = Math.random(), + Length = "hello".length, + Parsed = parseInt("42") +} + +// Enum access through different patterns +class EnumAccessPatterns { + // Bracket notation access + getBracketAccess(): string { + return StringEnum["Red"]; + } + + // Dynamic access + getDynamicAccess(key: keyof typeof StringEnum): string { + return StringEnum[key]; + } + + // Computed property access + getComputedAccess(): string { + const prop = "Red" as keyof typeof StringEnum; + return StringEnum[prop]; + } + + // Enum used in array + getEnumArray(): StringEnum[] { + return [StringEnum.Red, StringEnum.Green, StringEnum.Blue]; + } + + // Enum used in object literal + getEnumObject(): { color: StringEnum } { + return { color: StringEnum.Red }; + } + + // Enum used in ternary operator + getConditionalEnum(condition: boolean): StringEnum { + return condition ? StringEnum.Red : StringEnum.Blue; + } +} + +// Enum with getter-like access +namespace EnumWithGetters { + export enum Status { + Active = "ACTIVE", + Inactive = "INACTIVE" + } + + export function isActive(status: Status): boolean { + return status === Status.Active; + } +} + +// Enum value used in calculations +function calculateWithEnum(): number { + return NumericEnum.Ten * 2 + NumericEnum.One; +} + +// Enum used in template literals +function createMessage(status: StringEnum): string { + return `The color is ${status} today`; +} + +// Enum comparison with different patterns +function compareEnumValues(): boolean[] { + return [ + // Direct comparison + StringEnum.Red === StringEnum.Red, + // Comparison with variable + StringEnum.Red === StringEnum["Red"], + // Type coercion comparison + NumericEnum.One == 1, + // Strict comparison + NumericEnum.One === 1, + ]; +} + +// Enum used in class inheritance/implementation patterns +abstract class EnumProcessor { + abstract process(value: T): string; +} + +class StringEnumProcessor extends EnumProcessor { + process(value: StringEnum): string { + return `Processing: ${value}`; + } +} + +// Inline enums from other files for testing +enum StringEnum { + Red = "red", + Green = "green", + Blue = "blue" +} + +enum NumericEnum { + One = 1, + Two = 2, + Ten = 10 +} diff --git a/jacodb-ets/src/test/resources/samples/source/lang/enum-modules.ts b/jacodb-ets/src/test/resources/samples/source/lang/enum-modules.ts new file mode 100644 index 000000000..5e8eea649 --- /dev/null +++ b/jacodb-ets/src/test/resources/samples/source/lang/enum-modules.ts @@ -0,0 +1,190 @@ +// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +// Exported enum for external use +export enum PublicEnum { + Public1 = "public1", + Public2 = "public2", + Public3 = "public3" +} + +// Default exported enum +enum DefaultExportedEnum { + Default1, + Default2, + Default3 +} + +export default DefaultExportedEnum; + +// Const enum export +export const enum ConstExportEnum { + Small = "small", + Medium = "medium", + Large = "large" +} + +// Enum with re-export pattern +export enum ReExportEnum { + Option1 = 1, + Option2 = 2 +} + +// Re-export with alias +export { ReExportEnum as AliasedEnum }; + +// Enum used in exported function +export function processEnum(value: PublicEnum): string { + return `Processing ${value}`; +} + +// Enum used in exported class +export class EnumConsumer { + private status: PublicEnum = PublicEnum.Public1; + + constructor(initialStatus: PublicEnum) { + this.status = initialStatus; + } + + getStatus(): PublicEnum { + return this.status; + } + + setStatus(status: PublicEnum): void { + this.status = status; + } +} + +// Enum used in exported interface +export interface EnumInterface { + type: PublicEnum; + + process(input: PublicEnum): PublicEnum; +} + +// Exported enum with namespace merging +export enum MergedEnum { + Value1 = "value1", + Value2 = "value2", +} + +export namespace MergedEnum { + export function helper(value: MergedEnum): boolean { + return value === MergedEnum.Value1; + } + + export const metadata = { + version: "1.0", + description: "Merged enum with namespace", + }; +} + +// Enum used in type exports +export type EnumUnion = PublicEnum | DefaultExportedEnum; +export type EnumRecord = Record; +export type EnumKeys = keyof typeof PublicEnum; + +// Conditional enum export +const isDevelopment = process.env.NODE_ENV === 'development'; + +export enum ConditionalEnum { + Always = "always", + Sometimes = isDevelopment ? "debug" : "production" +} + +// Enum with computed exports +export enum ComputedExportEnum { + Base = 10, + Computed = Base * 2, + Dynamic = Math.floor(Math.random() * 100) +} + +// Multiple enum exports in one statement +enum LocalEnum1 { + A = "a", B = "b" +} + +enum LocalEnum2 { + X = 1, Y = 2 +} + +export { LocalEnum1, LocalEnum2 }; + +// Enum used in exported generic +export class GenericWithEnum { + constructor(private value: T) { + } + + getValue(): T { + return this.value; + } +} + +// Enum used in exported decorator (if supported) +export function enumValidator(validValues: PublicEnum[]) { + return function (target: any, propertyName: string, descriptor: PropertyDescriptor) { + // Decorator logic would go here + }; +} + +// Enum with barrel export pattern +export enum Feature1Enum { + Option1 = "feature1_option1", + Option2 = "feature1_option2" +} + +export enum Feature2Enum { + Option1 = "feature2_option1", + Option2 = "feature2_option2" +} + +// Would typically be in an index.ts file +export * from './enum-modules'; // Self-reference for testing + +// Enum with side effects on export +let sideEffectCounter = 0; + +export enum SideEffectEnum { + First = ++sideEffectCounter, + Second = ++sideEffectCounter, + Third = ++sideEffectCounter +} + +// Enum used in async context +export async function getAsyncEnum(): Promise { + // Simulate async operation + await new Promise(resolve => setTimeout(resolve, 0)); + return PublicEnum.Public1; +} + +// Enum used in generator function +export function* enumGenerator(): Generator { + yield PublicEnum.Public1; + yield PublicEnum.Public2; + yield PublicEnum.Public3; +} + +// Enum with complex module patterns +export namespace EnumModule { + export enum InternalEnum { + Internal1 = "internal1", + Internal2 = "internal2" + } + + export function useInternal(value: InternalEnum): string { + return `Using ${value}`; + } + + export namespace Nested { + export enum DeepEnum { + Deep1 = 1, + Deep2 = 2 + } + } +} + +// Import-like patterns (simulated for testing) +import type { PublicEnum as ImportedEnum } from './enum-modules'; + +export function useImportedEnum(value: ImportedEnum): string { + return `Imported: ${value}`; +} diff --git a/jacodb-ets/src/test/resources/samples/source/lang/enum.ts b/jacodb-ets/src/test/resources/samples/source/lang/enum.ts index 093c834b1..fe6b6c0d5 100644 --- a/jacodb-ets/src/test/resources/samples/source/lang/enum.ts +++ b/jacodb-ets/src/test/resources/samples/source/lang/enum.ts @@ -1,4 +1,225 @@ -enum Animal { - Cat, - Dog, +// noinspection JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +// Basic numeric enum (auto-incrementing from 0) +enum BasicEnum { + First, + Second, + Third } + +// Numeric enum with explicit values +enum NumericEnum { + One = 1, + Two = 2, + Three = 3, + Ten = 10, + Eleven // auto-increment from 10, becomes 11 +} + +// String enum +enum StringEnum { + Red = "red", + Green = "green", + Blue = "blue" +} + +// Mixed enum (heterogeneous) +enum MixedEnum { + No = 0, + Yes = "YES", + Maybe = 1 +} + +// Computed enum values +enum ComputedEnum { + A = 1, + B = A * 2, + C = B + A, + D = Math.floor(3.14) +} + +// Enum with negative values +enum NegativeEnum { + Below = -1, + Zero = 0, + Above = 1 +} + +// Const enum (compile-time constants) +const enum ConstEnum { + Small = 1, + Medium = 2, + Large = 3 +} + +// Enum with string and template literal values +enum TemplateEnum { + Start = "start", + Process = `process_${Date.now()}`, + End = "end" +} + +// Enum as namespace (with additional properties/methods) +enum Direction { + Up = "UP", + Down = "DOWN", + Left = "LEFT", + Right = "RIGHT" +} + +namespace Direction { + export function opposite(dir: Direction): Direction { + switch (dir) { + case Direction.Up: + return Direction.Down; + case Direction.Down: + return Direction.Up; + case Direction.Left: + return Direction.Right; + case Direction.Right: + return Direction.Left; + } + } +} + +// Enum with large values +enum LargeEnum { + Small = 1, + Medium = 1000, + Large = 1000000, + Huge = Number.MAX_SAFE_INTEGER +} + +// Enum usage scenarios +class EnumUsageExamples { + // Property with enum type + private status: BasicEnum = BasicEnum.First; + + // Method parameter with enum + setColor(color: StringEnum): void { + console.log(`Setting color to ${color}`); + } + + // Method returning enum + getDirection(): Direction.Up { + return Direction.Up; + } + + // Switch on enum + handleDirection(dir: Direction): string { + switch (dir) { + case Direction.Up: + return "Going up"; + case Direction.Down: + return "Going down"; + case Direction.Left: + return "Going left"; + case Direction.Right: + return "Going right"; + default: + return "Unknown direction"; + } + } + + // Enum as object key + getEnumValues(): Record { + return { + [StringEnum.Red]: 1, + [StringEnum.Green]: 2, + [StringEnum.Blue]: 3, + }; + } + + // Enum comparison + compareEnums(): boolean { + return BasicEnum.First === BasicEnum.First; + } + + // Enum to string conversion + enumToString(value: BasicEnum): string { + return BasicEnum[value]; + } + + // String to enum conversion + stringToEnum(str: string): BasicEnum | undefined { + return (BasicEnum as any)[str]; + } +} + +// Enum with bit flags pattern +enum FilePermission { + None = 0, + Read = 1 << 0, // 1 + Write = 1 << 1, // 2 + Execute = 1 << 2, // 4 + All = Read | Write | Execute // 7 +} + +// Enum iteration and introspection +function iterateEnum() { + // Get all numeric enum keys + const basicKeys = Object.keys(BasicEnum).filter(key => isNaN(Number(key))); + + // Get all numeric enum values + const basicValues = Object.values(BasicEnum).filter(value => typeof value === 'number'); + + // Get all string enum entries + const stringEntries = Object.entries(StringEnum); + + return { basicKeys, basicValues, stringEntries }; +} + +// Enum as array index +const enumArray: string[] = []; +enumArray[BasicEnum.First] = "first item"; +enumArray[BasicEnum.Second] = "second item"; + +// Enum with JSDoc comments +/** + * HTTP status code categories + */ +enum HttpStatus { + /** Informational responses */ + Continue = 100, + /** Success responses */ + OK = 200, + /** Client error responses */ + NotFound = 404, + /** Server error responses */ + InternalServerError = 500 +} + +// Reverse mapping usage (for numeric enums) +function useReverseMapping() { + const enumValue = BasicEnum.Second; + const enumName = BasicEnum[enumValue]; // "Second" + return { enumValue, enumName }; +} + +// Enum with complex expressions +enum ComplexEnum { + Base = 10, + Derived = Base * 2 + 5, // 25 + Complex = Math.max(Base, Derived) + 1 // 26 +} + +// Function using multiple enum types +function processMultipleEnums( + basic: BasicEnum, + str: StringEnum, + dir: Direction, +): { basic: number | string, str: string, dir: string } { + return { + basic: basic, + str: str, + dir: dir, + }; +} + +// Enum destructuring +const { Red, Green } = StringEnum; +const [first, second] = [BasicEnum.First, BasicEnum.Second]; + +// Enum with default export/import patterns (for module testing) +export { BasicEnum as DefaultBasicEnum }; +export default StringEnum; From 9490a5d4b1c4ce38ca78bc236d0278d5b8d46126 Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Wed, 3 Sep 2025 13:47:22 +0300 Subject: [PATCH 2/3] Bump ArkAnalyzer --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 806575354..9b1c150d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,7 @@ jobs: DEST_DIR="arkanalyzer" MAX_RETRIES=10 RETRY_DELAY=3 # Delay between retries in seconds - BRANCH="neo/2025-08-12" + BRANCH="neo/2025-09-03" for ((i=1; i<=MAX_RETRIES; i++)); do git clone --depth=1 --branch $BRANCH $REPO_URL $DEST_DIR && break From ae31fa932866b55fd9d39b8cb2e49f872a6e43fe Mon Sep 17 00:00:00 2001 From: Konstantin Chukharev Date: Wed, 3 Sep 2025 14:17:55 +0300 Subject: [PATCH 3/3] Fix test --- .../test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt index 7c920d504..990a6a8c7 100644 --- a/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt +++ b/jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt @@ -609,11 +609,12 @@ class EtsFromJsonTest { fun testClassCategory() { val path = "/samples/etsir/ast/lang/enum.ts.json" val file = loadEtsFileFromResource(path) - val cls = file.classes.first { it.name == "Animal" } + val cls = file.classes.first { it.name == "BasicEnum" } assertEquals(EtsClassCategory.ENUM, cls.category) - assertEquals(2, cls.fields.size) - assertEquals("Cat", cls.fields[0].name) - assertEquals("Dog", cls.fields[1].name) + assertEquals(3, cls.fields.size) + assertEquals("First", cls.fields[0].name) + assertEquals("Second", cls.fields[1].name) + assertEquals("Third", cls.fields[2].name) } @Test