[LT] ~ Rewrite big `when` expressions to branch over integers but not over types

It forces JVM to generate fast lookup/table switch bytecode
diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/AbstractLightTreeRawFirBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/AbstractLightTreeRawFirBuilder.kt
index a955362..4b05212 100644
--- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/AbstractLightTreeRawFirBuilder.kt
+++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/AbstractLightTreeRawFirBuilder.kt
@@ -18,6 +18,7 @@
 import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter
 import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
 import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImplWithoutSource
+import org.jetbrains.kotlin.kdoc.lexer.KDocTokens.KDOC_INDEX
 import org.jetbrains.kotlin.lexer.KtToken
 import org.jetbrains.kotlin.lexer.KtTokens.*
 import org.jetbrains.kotlin.name.Name
@@ -168,11 +169,24 @@
         for (kid in kidsArray) {
             if (kid == null) break
             val tokenType = kid.tokenType
-            if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON || tokenType in skipTokens ||
-                tokenType == TokenType.ERROR_ELEMENT || tokenType == TokenType.BAD_CHARACTER
-            ) {
+
+            when (kid.index) {
+                EOL_COMMENT_INDEX,
+                BLOCK_COMMENT_INDEX,
+                KDOC_INDEX,
+                SHEBANG_COMMENT_INDEX,
+                CommonTokens.WHITE_SPACE_INDEX,
+                SEMICOLON_INDEX,
+                CommonTokens.ERROR_ELEMENT_INDEX,
+                CommonTokens.BAD_CHARACTER_INDEX -> {
+                    continue
+                }
+            }
+
+            if (tokenType in skipTokens) {
                 continue
             }
+
             f(kid)
         }
     }
@@ -183,11 +197,24 @@
         val container = mutableListOf<T>()
         for (kid in kidsArray) {
             if (kid == null) break
-            val tokenType = kid.tokenType
-            if (COMMENTS.contains(tokenType) || tokenType == WHITE_SPACE || tokenType == SEMICOLON || tokenType == TokenType.ERROR_ELEMENT) continue
+            when (kid.index) {
+                EOL_COMMENT_INDEX,
+                BLOCK_COMMENT_INDEX,
+                KDOC_INDEX,
+                SHEBANG_COMMENT_INDEX,
+                CommonTokens.WHITE_SPACE_INDEX,
+                SEMICOLON_INDEX,
+                CommonTokens.ERROR_ELEMENT_INDEX -> {
+                    continue
+                }
+            }
+
             f(kid, container)
         }
 
         return container
     }
+
+    protected val LighterASTNode?.index: Int
+        get() = this?.tokenType?.index?.toInt() ?: NULL_ELEMENT_TYPE_INDEX
 }
diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt
index adadf1b..a02c07e 100644
--- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt
+++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt
@@ -55,6 +55,42 @@
 import org.jetbrains.kotlin.lexer.KtTokens.*
 import org.jetbrains.kotlin.name.*
 import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.BACKING_FIELD_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CLASS_BODY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CLASS_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CLASS_INITIALIZER_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CONTEXT_RECEIVER_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CONTRACT_EFFECT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.DELEGATED_SUPER_TYPE_ENTRY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.DOT_QUALIFIED_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.DYNAMIC_TYPE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.ENUM_ENTRY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FILE_ANNOTATION_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FUNCTION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FUNCTION_TYPE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FUNCTION_TYPE_RECEIVER_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.IMPORT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.INTERSECTION_TYPE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.MODIFIER_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.NULLABLE_TYPE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.OBJECT_DECLARATION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PACKAGE_DIRECTIVE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PRIMARY_CONSTRUCTOR_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PROPERTY_ACCESSOR_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PROPERTY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.REFERENCE_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SCRIPT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SECONDARY_CONSTRUCTOR_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_CALL_ENTRY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_ENTRY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SUPER_TYPE_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPEALIAS_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_ARGUMENT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_CONSTRAINT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_PARAMETER_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_REFERENCE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.USER_TYPE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.VALUE_PARAMETER_LIST_INDEX
 import org.jetbrains.kotlin.util.getChildren
 import org.jetbrains.kotlin.utils.addToStdlib.runIf
 import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
@@ -86,29 +122,29 @@
         context.packageFqName = FqName.ROOT
         var packageDirective: FirPackageDirective? = null
         file.forEachChildren { child ->
-            when (child.tokenType) {
-                FILE_ANNOTATION_LIST -> {
+            when (child.index) {
+                FILE_ANNOTATION_LIST_INDEX -> {
                     withContainerSymbol(fileSymbol) {
                         convertAnnotationsOnlyTo(child, fileAnnotations)
                     }
                 }
-                PACKAGE_DIRECTIVE -> {
+                PACKAGE_DIRECTIVE_INDEX -> {
                     packageDirective = convertPackageDirective(child).also { context.packageFqName = it.packageFqName }
                 }
-                IMPORT_LIST -> importList += convertImportDirectives(child)
-                CLASS -> firDeclarationList += convertClass(child)
-                FUN -> firDeclarationList += convertFunctionDeclaration(child) as FirDeclaration
-                KtNodeTypes.PROPERTY -> firDeclarationList += convertPropertyDeclaration(child)
-                TYPEALIAS -> firDeclarationList += convertTypeAlias(child)
-                OBJECT_DECLARATION -> firDeclarationList += convertClass(child)
-                DESTRUCTURING_DECLARATION -> {
+                IMPORT_LIST_INDEX -> importList += convertImportDirectives(child)
+                CLASS_INDEX -> firDeclarationList += convertClass(child)
+                FUNCTION_INDEX -> firDeclarationList += convertFunctionDeclaration(child) as FirDeclaration
+                PROPERTY_INDEX -> firDeclarationList += convertPropertyDeclaration(child)
+                TYPEALIAS_INDEX -> firDeclarationList += convertTypeAlias(child)
+                OBJECT_DECLARATION_INDEX -> firDeclarationList += convertClass(child)
+                DESTRUCTURING_DECLARATION_INDEX -> {
                     val initializer = buildFirDestructuringDeclarationInitializer(child)
                     firDeclarationList += buildErrorTopLevelDestructuringDeclaration(child.toFirSourceElement(), initializer)
                 }
-                SCRIPT -> {
+                SCRIPT_INDEX -> {
                     // TODO: scripts aren't supported yet
                 }
-                MODIFIER_LIST -> modifierList += child
+                MODIFIER_LIST_INDEX -> modifierList += child
             }
         }
 
@@ -140,14 +176,14 @@
 
     fun convertBlockExpressionWithoutBuilding(block: LighterASTNode, kind: KtFakeSourceElementKind? = null): FirBlockBuilder {
         val firStatements = block.forEachChildrenReturnList<FirStatement> { node, container ->
-            when (node.tokenType) {
-                CLASS, OBJECT_DECLARATION -> container += convertClass(node) as FirStatement
-                FUN -> container += convertFunctionDeclaration(node)
-                KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node) as FirStatement
-                DESTRUCTURING_DECLARATION -> container +=
+            when (node.index) {
+                CLASS_INDEX, OBJECT_DECLARATION_INDEX -> container += convertClass(node) as FirStatement
+                FUNCTION_INDEX -> container += convertFunctionDeclaration(node)
+                PROPERTY_INDEX -> container += convertPropertyDeclaration(node) as FirStatement
+                DESTRUCTURING_DECLARATION_INDEX -> container +=
                     convertDestructingDeclaration(node).toFirDestructingDeclaration(this, baseModuleData)
-                TYPEALIAS -> container += convertTypeAlias(node) as FirStatement
-                CLASS_INITIALIZER -> shouldNotBeCalled("CLASS_INITIALIZER expected to be processed during class body conversion")
+                TYPEALIAS_INDEX -> container += convertTypeAlias(node) as FirStatement
+                CLASS_INITIALIZER_INDEX -> shouldNotBeCalled("CLASS_INITIALIZER expected to be processed during class body conversion")
                 else -> if (node.isExpression()) container += expressionConverter.getAsFirStatement(node)
             }
         }
@@ -171,9 +207,9 @@
     private fun convertPackageDirective(packageNode: LighterASTNode): FirPackageDirective {
         var packageName: FqName = FqName.ROOT
         packageNode.forEachChildren {
-            when (it.tokenType) {
+            when (it.index) {
                 //TODO separate logic for both expression types
-                DOT_QUALIFIED_EXPRESSION, REFERENCE_EXPRESSION -> packageName = parsePackageName(it)
+                DOT_QUALIFIED_EXPRESSION_INDEX, REFERENCE_EXPRESSION_INDEX -> packageName = parsePackageName(it)
             }
         }
         return buildPackageDirective {
@@ -377,17 +413,17 @@
     private fun convertAnnotationTarget(annotationUseSiteTarget: LighterASTNode): AnnotationUseSiteTarget {
         lateinit var annotationTarget: AnnotationUseSiteTarget
         annotationUseSiteTarget.forEachChildren {
-            when (it.tokenType) {
-                ALL_KEYWORD -> annotationTarget = ALL
-                FIELD_KEYWORD -> annotationTarget = FIELD
-                FILE_KEYWORD -> annotationTarget = FILE
-                PROPERTY_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.PROPERTY
-                GET_KEYWORD -> annotationTarget = PROPERTY_GETTER
-                SET_KEYWORD -> annotationTarget = PROPERTY_SETTER
-                RECEIVER_KEYWORD -> annotationTarget = RECEIVER
-                PARAM_KEYWORD -> annotationTarget = CONSTRUCTOR_PARAMETER
-                SETPARAM_KEYWORD -> annotationTarget = SETTER_PARAMETER
-                DELEGATE_KEYWORD -> annotationTarget = PROPERTY_DELEGATE_FIELD
+            when (it.index) {
+                ALL_KEYWORD_INDEX -> annotationTarget = ALL
+                FIELD_KEYWORD_INDEX -> annotationTarget = FIELD
+                FILE_KEYWORD_INDEX -> annotationTarget = FILE
+                PROPERTY_KEYWORD_INDEX -> annotationTarget = AnnotationUseSiteTarget.PROPERTY
+                GET_KEYWORD_INDEX -> annotationTarget = PROPERTY_GETTER
+                SET_KEYWORD_INDEX -> annotationTarget = PROPERTY_SETTER
+                RECEIVER_KEYWORD_INDEX -> annotationTarget = RECEIVER
+                PARAM_KEYWORD_INDEX -> annotationTarget = CONSTRUCTOR_PARAMETER
+                SETPARAM_KEYWORD_INDEX -> annotationTarget = SETTER_PARAMETER
+                DELEGATE_KEYWORD_INDEX -> annotationTarget = PROPERTY_DELEGATE_FIELD
             }
         }
 
@@ -482,15 +518,15 @@
             val classSymbol = FirRegularClassSymbol(context.currentClassId)
             withContainerSymbol(classSymbol) {
                 classNode.forEachChildren {
-                    when (it.tokenType) {
-                        CLASS_KEYWORD -> classKind = ClassKind.CLASS
-                        INTERFACE_KEYWORD -> classKind = ClassKind.INTERFACE
-                        OBJECT_KEYWORD -> classKind = ClassKind.OBJECT
-                        TYPE_PARAMETER_LIST -> typeParameterList = it
-                        PRIMARY_CONSTRUCTOR -> primaryConstructor = it
-                        SUPER_TYPE_LIST -> superTypeList = it
-                        TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
-                        CLASS_BODY -> classBody = it
+                    when (it.index) {
+                        CLASS_KEYWORD_INDEX -> classKind = ClassKind.CLASS
+                        INTERFACE_KEYWORD_INDEX -> classKind = ClassKind.INTERFACE
+                        OBJECT_KEYWORD_INDEX -> classKind = ClassKind.OBJECT
+                        TYPE_PARAMETER_LIST_INDEX -> typeParameterList = it
+                        PRIMARY_CONSTRUCTOR_INDEX -> primaryConstructor = it
+                        SUPER_TYPE_LIST_INDEX -> superTypeList = it
+                        TYPE_CONSTRAINT_LIST_INDEX -> typeConstraints += convertTypeConstraints(it)
+                        CLASS_BODY_INDEX -> classBody = it
                     }
                 }
 
@@ -911,17 +947,17 @@
     private fun convertClassBody(classBody: LighterASTNode, classWrapper: ClassWrapper): List<FirDeclaration> {
         val modifierLists = mutableListOf<LighterASTNode>()
         var firDeclarations = classBody.forEachChildrenReturnList { node, container ->
-            when (node.tokenType) {
-                ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
-                CLASS -> container += convertClass(node)
-                FUN -> container += convertFunctionDeclaration(node) as FirDeclaration
-                KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
-                TYPEALIAS -> container += convertTypeAlias(node)
-                OBJECT_DECLARATION -> container += convertClass(node)
-                CLASS_INITIALIZER -> container += convertAnonymousInitializer(node, classWrapper) //anonymousInitializer
-                SECONDARY_CONSTRUCTOR -> container += convertSecondaryConstructor(node, classWrapper)
-                MODIFIER_LIST -> modifierLists += node
-                DESTRUCTURING_DECLARATION -> {
+            when (node.index) {
+                ENUM_ENTRY_INDEX -> container += convertEnumEntry(node, classWrapper)
+                CLASS_INDEX -> container += convertClass(node)
+                FUNCTION_INDEX -> container += convertFunctionDeclaration(node) as FirDeclaration
+                PROPERTY_INDEX -> container += convertPropertyDeclaration(node, classWrapper)
+                TYPEALIAS_INDEX -> container += convertTypeAlias(node)
+                OBJECT_DECLARATION_INDEX -> container += convertClass(node)
+                CLASS_INITIALIZER_INDEX -> container += convertAnonymousInitializer(node, classWrapper) //anonymousInitializer
+                SECONDARY_CONSTRUCTOR_INDEX -> container += convertSecondaryConstructor(node, classWrapper)
+                MODIFIER_LIST_INDEX -> modifierLists += node
+                DESTRUCTURING_DECLARATION_INDEX -> {
                     val initializer = buildFirDestructuringDeclarationInitializer(node)
                     container += buildErrorTopLevelDestructuringDeclaration(node.toFirSourceElement(), initializer)
                 }
@@ -984,13 +1020,11 @@
         withContainerSymbol(constructorSymbol) {
             var modifiersIfPresent: ModifierList? = null
             val valueParameters = mutableListOf<ValueParameter>()
-            var hasConstructorKeyword = false
             primaryConstructor?.forEachChildren {
                 when (it.tokenType) {
                     MODIFIER_LIST -> {
                         modifiersIfPresent = convertModifierList(it)
                     }
-                    CONSTRUCTOR_KEYWORD -> hasConstructorKeyword = true
                     VALUE_PARAMETER_LIST -> valueParameters += convertValueParameters(
                         it,
                         constructorSymbol,
@@ -1267,11 +1301,11 @@
         var typeParametersNode: LighterASTNode? = null
 
         typeAlias.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> modifiers = convertModifierList(it)
-                IDENTIFIER -> identifier = it.asText
-                TYPE_REFERENCE -> typeRefNode = it
-                TYPE_PARAMETER_LIST -> typeParametersNode = it
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> modifiers = convertModifierList(it)
+                IDENTIFIER_INDEX -> identifier = it.asText
+                TYPE_REFERENCE_INDEX -> typeRefNode = it
+                TYPE_PARAMETER_LIST_INDEX -> typeParametersNode = it
             }
         }
 
@@ -1347,20 +1381,20 @@
         withContainerSymbol(propertySymbol, isLocal) {
             val propertySource = property.toFirSourceElement()
             property.forEachChildren {
-                when (it.tokenType) {
-                    MODIFIER_LIST -> {
+                when (it.index) {
+                    MODIFIER_LIST_INDEX -> {
                         modifiers = convertModifierList(it)
                     }
-                    TYPE_PARAMETER_LIST -> typeParameterList = it
-                    COLON -> isReturnType = true
-                    TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverTypeNode = it
-                    TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
-                    PROPERTY_DELEGATE -> delegate = it
-                    VAR_KEYWORD -> isVar = true
-                    PROPERTY_ACCESSOR -> {
+                    TYPE_PARAMETER_LIST_INDEX -> typeParameterList = it
+                    COLON_INDEX -> isReturnType = true
+                    TYPE_REFERENCE_INDEX -> if (isReturnType) returnType = convertType(it) else receiverTypeNode = it
+                    TYPE_CONSTRAINT_LIST_INDEX -> typeConstraints += convertTypeConstraints(it)
+                    PROPERTY_DELEGATE_INDEX -> delegate = it
+                    VAR_KEYWORD_INDEX -> isVar = true
+                    PROPERTY_ACCESSOR_INDEX -> {
                         accessors += it
                     }
-                    BACKING_FIELD -> fieldDeclaration = it
+                    BACKING_FIELD_INDEX -> fieldDeclaration = it
                     else -> if (it.isExpression()) {
                         context.calleeNamesForLambda += null
                         propertyInitializer = withForcedLocalContext {
@@ -1527,12 +1561,12 @@
         val source = destructingDeclaration.toFirSourceElement()
         var firExpression: FirExpression? = null
         destructingDeclaration.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> convertAnnotationsOnlyTo(it, annotations)
-                VAR_KEYWORD -> isVar = true
-                DESTRUCTURING_DECLARATION_ENTRY -> entries += convertDestructingDeclarationEntry(it)
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> convertAnnotationsOnlyTo(it, annotations)
+                VAR_KEYWORD_INDEX -> isVar = true
+                DESTRUCTURING_DECLARATION_ENTRY_INDEX -> entries += convertDestructingDeclarationEntry(it)
                 // Property delegates should be ignored as they aren't a valid initializers
-                PROPERTY_DELEGATE -> {}
+                PROPERTY_DELEGATE_INDEX -> {}
                 else -> if (it.isExpression()) firExpression =
                     expressionConverter.getAsFirExpression(it, "Initializer required for destructuring declaration")
             }
@@ -1558,10 +1592,10 @@
         var identifier: String? = null
         var firType: FirTypeRef? = null
         entry.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> convertAnnotationsOnlyTo(it, annotations)
-                IDENTIFIER -> identifier = it.asText
-                TYPE_REFERENCE -> firType = convertType(it)
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> convertAnnotationsOnlyTo(it, annotations)
+                IDENTIFIER_INDEX -> identifier = it.asText
+                TYPE_REFERENCE_INDEX -> firType = convertType(it)
             }
         }
 
@@ -1609,13 +1643,13 @@
 
         getterOrSetter.forEachChildren {
             if (it.asText == "set") isGetter = false
-            when (it.tokenType) {
-                SET_KEYWORD -> isGetter = false
-                MODIFIER_LIST -> {
+            when (it.index) {
+                SET_KEYWORD_INDEX -> isGetter = false
+                MODIFIER_LIST_INDEX -> {
                     modifiers = convertModifierList(it)
                 }
-                TYPE_REFERENCE -> returnType = convertType(it)
-                VALUE_PARAMETER_LIST -> {
+                TYPE_REFERENCE_INDEX -> returnType = convertType(it)
+                VALUE_PARAMETER_LIST_INDEX -> {
                     // getter can have an empty value parameter list
                     if (!isGetter) {
                         firValueParameters = convertSetterParameter(
@@ -1623,8 +1657,8 @@
                         )
                     }
                 }
-                CONTRACT_EFFECT_LIST -> outerContractDescription = obtainContractDescription(it)
-                BLOCK -> block = it
+                CONTRACT_EFFECT_LIST_INDEX -> outerContractDescription = obtainContractDescription(it)
+                BLOCK_INDEX -> block = it
                 else -> if (it.isExpression()) expression = it
             }
         }
@@ -1875,18 +1909,18 @@
         withContainerSymbol(functionSymbol, isLocal) {
             val target: FirFunctionTarget
             functionDeclaration.forEachChildren {
-                when (it.tokenType) {
-                    MODIFIER_LIST -> {
+                when (it.index) {
+                    MODIFIER_LIST_INDEX -> {
                         modifiers = convertModifierList(it)
                     }
-                    TYPE_PARAMETER_LIST -> typeParameterList = it
-                    VALUE_PARAMETER_LIST -> valueParametersList = it //must convert later, because it can contains "return"
-                    COLON -> isReturnType = true
-                    TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverTypeNode = it
-                    TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
-                    CONTRACT_EFFECT_LIST -> outerContractDescription = obtainContractDescription(it)
-                    BLOCK -> block = it
-                    EQ -> hasEqToken = true
+                    TYPE_PARAMETER_LIST_INDEX -> typeParameterList = it
+                    VALUE_PARAMETER_LIST_INDEX -> valueParametersList = it //must convert later, because it can contains "return"
+                    COLON_INDEX -> isReturnType = true
+                    TYPE_REFERENCE_INDEX -> if (isReturnType) returnType = convertType(it) else receiverTypeNode = it
+                    TYPE_CONSTRAINT_LIST_INDEX -> typeConstraints += convertTypeConstraints(it)
+                    CONTRACT_EFFECT_LIST_INDEX -> outerContractDescription = obtainContractDescription(it)
+                    BLOCK_INDEX -> block = it
+                    EQ_INDEX -> hasEqToken = true
                     else -> if (it.isExpression()) expression = it
                 }
             }
@@ -2094,17 +2128,17 @@
         val delegateFieldsMap = mutableMapOf<Int, FirFieldSymbol>()
         var index = 0
         delegationSpecifiers.forEachChildren {
-            when (it.tokenType) {
-                SUPER_TYPE_ENTRY -> {
+            when (it.index) {
+                SUPER_TYPE_ENTRY_INDEX -> {
                     superTypeRefs += convertType(it)
                     index++
                 }
-                SUPER_TYPE_CALL_ENTRY -> convertConstructorInvocation(it).apply {
+                SUPER_TYPE_CALL_ENTRY_INDEX -> convertConstructorInvocation(it).apply {
                     superTypeCalls += DelegatedConstructorWrapper(first, second, it.toFirSourceElement())
                     superTypeRefs += first
                     index++
                 }
-                DELEGATED_SUPER_TYPE_ENTRY -> {
+                DELEGATED_SUPER_TYPE_ENTRY_INDEX -> {
                     superTypeRefs += convertExplicitDelegation(it, delegateFieldsMap, index)
                     index++
                 }
@@ -2252,10 +2286,10 @@
         var identifier: String? = null
         var firType: FirTypeRef? = null
         typeParameter.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> typeParameterModifiers = convertTypeParameterModifiers(it)
-                IDENTIFIER -> identifier = it.asText
-                TYPE_REFERENCE -> firType = convertType(it)
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> typeParameterModifiers = convertTypeParameterModifiers(it)
+                IDENTIFIER_INDEX -> identifier = it.asText
+                TYPE_REFERENCE_INDEX -> firType = convertType(it)
             }
         }
 
@@ -2304,18 +2338,18 @@
 
         var firType: FirTypeRef? = null
         type.forEachChildren {
-            when (it.tokenType) {
-                TYPE_REFERENCE -> firType = convertType(it)
-                MODIFIER_LIST -> allTypeModifiers += convertModifierList(it)
-                USER_TYPE -> firType = convertUserType(typeRefSource, it)
-                NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
-                FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, allTypeModifiers)
-                DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
+            when (it.index) {
+                TYPE_REFERENCE_INDEX -> firType = convertType(it)
+                MODIFIER_LIST_INDEX -> allTypeModifiers += convertModifierList(it)
+                USER_TYPE_INDEX -> firType = convertUserType(typeRefSource, it)
+                NULLABLE_TYPE_INDEX -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
+                FUNCTION_TYPE_INDEX -> firType = convertFunctionType(typeRefSource, it, allTypeModifiers)
+                DYNAMIC_TYPE_INDEX -> firType = buildDynamicTypeRef {
                     source = typeRefSource
                     isMarkedNullable = false
                 }
-                INTERSECTION_TYPE -> firType = convertIntersectionType(typeRefSource, it, false)
-                CONTEXT_RECEIVER_LIST, TokenType.ERROR_ELEMENT -> firType =
+                INTERSECTION_TYPE_INDEX -> firType = convertIntersectionType(typeRefSource, it, false)
+                CONTEXT_RECEIVER_LIST_INDEX, CommonTokens.ERROR_ELEMENT_INDEX -> firType =
                     buildErrorTypeRef {
                         source = typeRefSource
                         diagnostic = ConeSyntaxDiagnostic("Unwrapped type is null")
@@ -2382,16 +2416,16 @@
     ): FirTypeRef {
         lateinit var firType: FirTypeRef
         nullableType.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> allTypeModifiers += convertModifierList(it)
-                USER_TYPE -> firType = convertUserType(typeRefSource, it, isNullable)
-                FUNCTION_TYPE -> firType = convertFunctionType(typeRefSource, it, allTypeModifiers, isNullable)
-                NULLABLE_TYPE -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
-                DYNAMIC_TYPE -> firType = buildDynamicTypeRef {
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> allTypeModifiers += convertModifierList(it)
+                USER_TYPE_INDEX -> firType = convertUserType(typeRefSource, it, isNullable)
+                FUNCTION_TYPE_INDEX -> firType = convertFunctionType(typeRefSource, it, allTypeModifiers, isNullable)
+                NULLABLE_TYPE_INDEX -> firType = convertNullableType(typeRefSource, it, allTypeModifiers)
+                DYNAMIC_TYPE_INDEX -> firType = buildDynamicTypeRef {
                     source = typeRefSource
                     isMarkedNullable = true
                 }
-                INTERSECTION_TYPE -> firType = convertIntersectionType(typeRefSource, it, isNullable)
+                INTERSECTION_TYPE_INDEX -> firType = convertIntersectionType(typeRefSource, it, isNullable)
             }
         }
 
@@ -2412,13 +2446,13 @@
         val firTypeArguments = mutableListOf<FirTypeProjection>()
         var typeArgumentsSource: KtSourceElement? = null
         userType.forEachChildren {
-            when (it.tokenType) {
-                USER_TYPE -> simpleFirUserType = convertUserType(typeRefSource, it) as? FirUserTypeRef //simple user type
-                REFERENCE_EXPRESSION -> {
+            when (it.index) {
+                USER_TYPE_INDEX -> simpleFirUserType = convertUserType(typeRefSource, it) as? FirUserTypeRef //simple user type
+                REFERENCE_EXPRESSION_INDEX -> {
                     identifierSource = it.toFirSourceElement()
                     identifier = it.asText
                 }
-                TYPE_ARGUMENT_LIST -> {
+                TYPE_ARGUMENT_LIST_INDEX -> {
                     typeArgumentsSource = it.toFirSourceElement()
                     firTypeArguments += convertTypeArguments(it, allowedUnderscoredTypeArgument = false)
                 }
@@ -2476,10 +2510,10 @@
         lateinit var firType: FirTypeRef
         var isStarProjection = false
         typeProjection.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> modifiers = convertTypeArgumentModifierList(it)
-                TYPE_REFERENCE -> firType = convertType(it)
-                MUL -> isStarProjection = true
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> modifiers = convertTypeArgumentModifierList(it)
+                TYPE_REFERENCE_INDEX -> firType = convertType(it)
+                MUL_INDEX -> isStarProjection = true
             }
         }
 
@@ -2518,11 +2552,11 @@
         val parameters = mutableListOf<FirFunctionTypeParameter>()
         var contextList: LighterASTNode? = null
         functionType.forEachChildren {
-            when (it.tokenType) {
-                FUNCTION_TYPE_RECEIVER -> receiverTypeReference = convertReceiverType(it)
-                VALUE_PARAMETER_LIST -> parameters += convertFunctionTypeParameters(it)
-                TYPE_REFERENCE -> returnTypeReference = convertType(it)
-                CONTEXT_RECEIVER_LIST -> contextList = it
+            when (it.index) {
+                FUNCTION_TYPE_RECEIVER_INDEX -> receiverTypeReference = convertReceiverType(it)
+                VALUE_PARAMETER_LIST_INDEX -> parameters += convertFunctionTypeParameters(it)
+                TYPE_REFERENCE_INDEX -> returnTypeReference = convertType(it)
+                CONTEXT_RECEIVER_LIST_INDEX -> contextList = it
             }
         }
 
@@ -2610,13 +2644,13 @@
         var firExpression: FirExpression? = null
         var destructuringDeclaration: DestructuringDeclaration? = null
         valueParameter.forEachChildren {
-            when (it.tokenType) {
-                MODIFIER_LIST -> modifiers = convertModifierList(it)
-                VAL_KEYWORD -> isVal = true
-                VAR_KEYWORD -> isVar = true
-                IDENTIFIER -> identifier = it.asText
-                TYPE_REFERENCE -> {}
-                DESTRUCTURING_DECLARATION -> destructuringDeclaration = convertDestructingDeclaration(it)
+            when (it.index) {
+                MODIFIER_LIST_INDEX -> modifiers = convertModifierList(it)
+                VAL_KEYWORD_INDEX -> isVal = true
+                VAR_KEYWORD_INDEX -> isVar = true
+                IDENTIFIER_INDEX -> identifier = it.asText
+                TYPE_REFERENCE_INDEX -> {}
+                DESTRUCTURING_DECLARATION_INDEX -> destructuringDeclaration = convertDestructingDeclaration(it)
                 else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it, "Should have default value")
             }
         }
diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
index 70f6877..4cef050 100644
--- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
+++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt
@@ -50,8 +50,31 @@
 import org.jetbrains.kotlin.name.CallableId
 import org.jetbrains.kotlin.name.SpecialNames
 import org.jetbrains.kotlin.psi.psiUtil.UNWRAPPABLE_TOKEN_TYPES
-import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
 import org.jetbrains.kotlin.psi.stubs.elements.KtNameReferenceExpressionElementType
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.ANNOTATION_ENTRY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.ANNOTATION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.BOOLEAN_CONSTANT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CHARACTER_CONSTANT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CLASS_INITIALIZER_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.CLASS_LITERAL_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.COLLECTION_LITERAL_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.DOT_QUALIFIED_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FLOAT_CONSTANT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.FUNCTION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.INTEGER_CONSTANT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.LAMBDA_ARGUMENT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.NULL_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PROPERTY_ACCESSOR_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.PROPERTY_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.REFERENCE_EXPRESSION_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.SECONDARY_CONSTRUCTOR_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.STRING_TEMPLATE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_ARGUMENT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.TYPE_REFERENCE_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.VALUE_ARGUMENT_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.VALUE_ARGUMENT_LIST_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.VALUE_ARGUMENT_NAME_INDEX
+import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes.VALUE_PARAMETER_LIST_INDEX
 import org.jetbrains.kotlin.types.expressions.OperatorConventions
 import org.jetbrains.kotlin.util.OperatorNameConventions
 import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -120,49 +143,49 @@
 
     /*****    EXPRESSIONS    *****/
     fun convertExpression(expression: LighterASTNode, errorReason: String): FirElement {
-        return when (expression.tokenType) {
-            LAMBDA_EXPRESSION -> convertLambdaExpression(expression)
-            BINARY_EXPRESSION -> convertBinaryExpression(expression)
-            BINARY_WITH_TYPE -> convertBinaryWithTypeRHSExpression(expression) {
+        return when (expression.index) {
+            LAMBDA_EXPRESSION_INDEX -> convertLambdaExpression(expression)
+            BINARY_EXPRESSION_INDEX -> convertBinaryExpression(expression)
+            BINARY_WITH_TYPE_INDEX -> convertBinaryWithTypeRHSExpression(expression) {
                 this.getOperationSymbol().toFirOperation()
             }
-            IS_EXPRESSION -> convertBinaryWithTypeRHSExpression(expression) {
+            IS_EXPRESSION_INDEX -> convertBinaryWithTypeRHSExpression(expression) {
                 if (this == "is") FirOperation.IS else FirOperation.NOT_IS
             }
-            LABELED_EXPRESSION -> convertLabeledExpression(expression)
-            PREFIX_EXPRESSION, POSTFIX_EXPRESSION -> convertUnaryExpression(expression)
-            ANNOTATED_EXPRESSION -> convertAnnotatedExpression(expression)
-            CLASS_LITERAL_EXPRESSION -> convertClassLiteralExpression(expression)
-            CALLABLE_REFERENCE_EXPRESSION -> convertCallableReferenceExpression(expression)
-            DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> convertQualifiedExpression(expression)
-            CALL_EXPRESSION -> convertCallExpression(expression)
-            WHEN -> convertWhenExpression(expression)
-            ARRAY_ACCESS_EXPRESSION -> convertArrayAccessExpression(expression)
-            COLLECTION_LITERAL_EXPRESSION -> convertCollectionLiteralExpression(expression)
-            STRING_TEMPLATE -> convertStringTemplate(expression)
-            is KtConstantExpressionElementType -> convertConstantExpression(expression)
-            REFERENCE_EXPRESSION -> convertSimpleNameExpression(expression)
-            DO_WHILE -> convertDoWhile(expression)
-            WHILE -> convertWhile(expression)
-            FOR -> convertFor(expression)
-            TRY -> convertTryExpression(expression)
-            IF -> convertIfExpression(expression)
-            BREAK, CONTINUE -> convertLoopJump(expression)
-            RETURN -> convertReturn(expression)
-            THROW -> convertThrow(expression)
-            PARENTHESIZED -> {
+            LABELED_EXPRESSION_INDEX -> convertLabeledExpression(expression)
+            PREFIX_EXPRESSION_INDEX, POSTFIX_EXPRESSION_INDEX -> convertUnaryExpression(expression)
+            ANNOTATED_EXPRESSION_INDEX -> convertAnnotatedExpression(expression)
+            CLASS_LITERAL_EXPRESSION_INDEX -> convertClassLiteralExpression(expression)
+            CALLABLE_REFERENCE_EXPRESSION_INDEX -> convertCallableReferenceExpression(expression)
+            DOT_QUALIFIED_EXPRESSION_INDEX, SAFE_ACCESS_EXPRESSION_INDEX -> convertQualifiedExpression(expression)
+            CALL_EXPRESSION_INDEX -> convertCallExpression(expression)
+            WHEN_INDEX -> convertWhenExpression(expression)
+            ARRAY_ACCESS_EXPRESSION_INDEX -> convertArrayAccessExpression(expression)
+            COLLECTION_LITERAL_EXPRESSION_INDEX -> convertCollectionLiteralExpression(expression)
+            STRING_TEMPLATE_INDEX -> convertStringTemplate(expression)
+            NULL_INDEX, BOOLEAN_CONSTANT_INDEX, FLOAT_CONSTANT_INDEX, CHARACTER_CONSTANT_INDEX, INTEGER_CONSTANT_INDEX -> convertConstantExpression(expression)
+            REFERENCE_EXPRESSION_INDEX -> convertSimpleNameExpression(expression)
+            DO_WHILE_INDEX -> convertDoWhile(expression)
+            WHILE_INDEX -> convertWhile(expression)
+            FOR_INDEX -> convertFor(expression)
+            TRY_INDEX -> convertTryExpression(expression)
+            IF_INDEX -> convertIfExpression(expression)
+            BREAK_INDEX, CONTINUE_INDEX -> convertLoopJump(expression)
+            RETURN_INDEX -> convertReturn(expression)
+            THROW_INDEX -> convertThrow(expression)
+            PARENTHESIZED_INDEX -> {
                 val content = expression.getExpressionInParentheses()
                 context.forwardLabelUsagePermission(expression, content)
                 getAsFirExpression(content, "Empty parentheses", sourceWhenInvalidExpression = expression)
             }
-            PROPERTY_DELEGATE, INDICES, CONDITION, LOOP_RANGE ->
+            PROPERTY_DELEGATE_INDEX, INDICES_INDEX, CONDITION_INDEX, LOOP_RANGE_INDEX ->
                 getAsFirExpression(expression.getChildExpression(), errorReason, sourceWhenInvalidExpression = expression)
-            THIS_EXPRESSION -> convertThisExpression(expression)
-            SUPER_EXPRESSION -> convertSuperExpression(expression)
+            THIS_EXPRESSION_INDEX -> convertThisExpression(expression)
+            SUPER_EXPRESSION_INDEX -> convertSuperExpression(expression)
 
-            OBJECT_LITERAL -> declarationBuilder.convertObjectLiteral(expression)
-            FUN -> declarationBuilder.convertFunctionDeclaration(expression)
-            DESTRUCTURING_DECLARATION -> declarationBuilder.convertDestructingDeclaration(expression)
+            OBJECT_LITERAL_INDEX -> declarationBuilder.convertObjectLiteral(expression)
+            FUNCTION_INDEX -> declarationBuilder.convertFunctionDeclaration(expression)
+            DESTRUCTURING_DECLARATION_INDEX -> declarationBuilder.convertDestructingDeclaration(expression)
                 .toFirDestructingDeclaration(this, baseModuleData)
             else -> buildErrorExpression(
                 expression.toFirSourceElement(KtFakeSourceElementKind.ErrorTypeRef),
@@ -182,14 +205,14 @@
 
         val functionSymbol = FirAnonymousFunctionSymbol()
         lambdaExpression.getChildNodesByType(FUNCTION_LITERAL).first().forEachChildren {
-            when (it.tokenType) {
-                VALUE_PARAMETER_LIST -> valueParameterList += declarationBuilder.convertValueParameters(
+            when (it.index) {
+                VALUE_PARAMETER_LIST_INDEX -> valueParameterList += declarationBuilder.convertValueParameters(
                     valueParameters = it,
                     functionSymbol,
                     ValueParameterDeclaration.LAMBDA
                 )
-                BLOCK -> block = it
-                ARROW -> hasArrow = true
+                BLOCK_INDEX -> block = it
+                ARROW_INDEX -> hasArrow = true
             }
         }
 
@@ -302,9 +325,9 @@
         val output = mutableListOf<LighterASTNode?>()
         input.add(binaryExpression)
         while (input.isNotEmpty()) {
-            var node = input.pop()
-            when (node?.tokenType) {
-                BINARY_EXPRESSION -> {
+            val node = input.pop()
+            when (node?.index) {
+                BINARY_EXPRESSION_INDEX -> {
                     val (leftNode, opNode, rightNode) = extractBinaryExpression(node)
 
                     if (opNode.asText.getOperationSymbol() != PLUS) {
@@ -314,7 +337,7 @@
                     input.add(leftNode)
                     input.add(rightNode)
                 }
-                PARENTHESIZED -> {
+                PARENTHESIZED_INDEX -> {
                     val content = node.getExpressionInParentheses()
                     input.add(content)
                 }
@@ -391,14 +414,14 @@
         // No need for the callee name since arguments are already generated
         context.calleeNamesForLambda.removeLast()
 
-        when (operationToken) {
-            ELVIS ->
+        when (operationToken.index.toInt()) {
+            ELVIS_INDEX ->
                 return leftArgAsFir.generateNotNullOrOther(rightArgAsFir, baseSource)
-            ANDAND, OROR ->
+            ANDAND_INDEX, OROR_INDEX ->
                 return leftArgAsFir.generateLazyLogicalOperation(rightArgAsFir, operationToken == ANDAND, baseSource)
-            in OperatorConventions.IN_OPERATIONS ->
+            IN_KEYWORD_INDEX, NOT_IN_INDEX ->
                 return rightArgAsFir.generateContainsOperation(leftArgAsFir, operationToken == NOT_IN, baseSource, operationReferenceSource)
-            in OperatorConventions.COMPARISON_OPERATIONS ->
+            LT_INDEX, GT_INDEX, LTEQ_INDEX, GTEQ_INDEX ->
                 return leftArgAsFir.generateComparisonExpression(rightArgAsFir, operationToken, baseSource, operationReferenceSource)
         }
         val conventionCallName = operationToken.toBinaryName()
@@ -455,9 +478,9 @@
         var leftArgAsFir: FirExpression? = null
         lateinit var firType: FirTypeRef
         binaryExpression.forEachChildren {
-            when (it.tokenType) {
-                OPERATION_REFERENCE -> operationTokenName = it.asText
-                TYPE_REFERENCE -> firType = declarationBuilder.convertType(it)
+            when (it.index) {
+                OPERATION_REFERENCE_INDEX -> operationTokenName = it.asText
+                TYPE_REFERENCE_INDEX -> firType = declarationBuilder.convertType(it)
                 else -> if (it.isExpression()) leftArgAsFir = getAsFirExpression(it, "No left operand")
             }
         }
@@ -485,15 +508,15 @@
 
         labeledExpression.forEachChildren {
             context.setNewLabelUserNode(it)
-            when (it.tokenType) {
-                LABEL_QUALIFIER -> {
+            when (it.index) {
+                LABEL_QUALIFIER_INDEX -> {
                     val name = it.asText.dropLast(1)
                     labelSource = it.getChildNodesByType(LABEL).single().toFirSourceElement()
                     context.addNewLabel(buildLabel(name, labelSource!!))
                     forbiddenLabelKind = getForbiddenLabelKind(name, isRepetitiveLabel)
                 }
-                BLOCK -> firExpression = declarationBuilder.convertBlock(it)
-                PROPERTY -> firExpression = declarationBuilder.convertPropertyDeclaration(it)
+                BLOCK_INDEX -> firExpression = declarationBuilder.convertBlock(it)
+                PROPERTY_INDEX -> firExpression = declarationBuilder.convertPropertyDeclaration(it)
                 else -> if (it.isExpression()) firExpression = getAsFirStatement(it)
             }
         }
@@ -572,10 +595,10 @@
         var firExpression: FirElement? = null
         val firAnnotationList = mutableListOf<FirAnnotation>()
         annotatedExpression.forEachChildren {
-            when (it.tokenType) {
-                ANNOTATION -> declarationBuilder.convertAnnotationTo(it, firAnnotationList)
-                ANNOTATION_ENTRY -> firAnnotationList += declarationBuilder.convertAnnotationEntry(it)
-                BLOCK -> firExpression = declarationBuilder.convertBlockExpression(it)
+            when (it.index) {
+                ANNOTATION_INDEX -> declarationBuilder.convertAnnotationTo(it, firAnnotationList)
+                ANNOTATION_ENTRY_INDEX -> firAnnotationList += declarationBuilder.convertAnnotationEntry(it)
+                BLOCK_INDEX -> firExpression = declarationBuilder.convertBlockExpression(it)
                 else -> if (it.isExpression()) {
                     context.forwardLabelUsagePermission(annotatedExpression, it)
                     firExpression = getAsFirStatement(it)
@@ -729,24 +752,24 @@
         var superNode: LighterASTNode? = null
         callSuffix.forEachChildren { child ->
             fun process(node: LighterASTNode) {
-                when (node.tokenType) {
-                    REFERENCE_EXPRESSION -> {
+                when (node.index) {
+                    REFERENCE_EXPRESSION_INDEX -> {
                         name = node.asText
                     }
-                    SUPER_EXPRESSION -> {
+                    SUPER_EXPRESSION_INDEX -> {
                         superNode = node
                     }
-                    PARENTHESIZED -> if (node.tokenType != TokenType.ERROR_ELEMENT) {
+                    PARENTHESIZED_INDEX -> if (node.tokenType != TokenType.ERROR_ELEMENT) {
                         additionalArgument = getAsFirExpression(node.getExpressionInParentheses(), "Incorrect invoke receiver", sourceWhenInvalidExpression = node)
                     }
-                    TYPE_ARGUMENT_LIST -> {
+                    TYPE_ARGUMENT_LIST_INDEX -> {
                         firTypeArguments += declarationBuilder.convertTypeArguments(node, allowedUnderscoredTypeArgument = true)
                     }
-                    VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> {
+                    VALUE_ARGUMENT_LIST_INDEX, LAMBDA_ARGUMENT_INDEX -> {
                         hasArguments = true
                         valueArguments += node
                     }
-                    else -> if (node.tokenType != TokenType.ERROR_ELEMENT) {
+                    else -> if (node.index != CommonTokens.ERROR_ELEMENT_INDEX) {
                         additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver")
                     }
                 }
@@ -958,21 +981,21 @@
         var guard: FirExpression? = null
         var shouldBindSubject = false
         whenEntry.forEachChildren {
-            when (it.tokenType) {
-                WHEN_CONDITION_EXPRESSION -> conditions += convertWhenConditionExpression(it, subjectVariable)
-                WHEN_CONDITION_IN_RANGE -> {
+            when (it.index) {
+                WHEN_CONDITION_EXPRESSION_INDEX -> conditions += convertWhenConditionExpression(it, subjectVariable)
+                WHEN_CONDITION_IN_RANGE_INDEX -> {
                     val (condition, shouldBind) = convertWhenConditionInRange(it, subjectVariable)
                     conditions += condition
                     shouldBindSubject = shouldBindSubject || shouldBind
                 }
-                WHEN_CONDITION_IS_PATTERN -> {
+                WHEN_CONDITION_IS_PATTERN_INDEX -> {
                     val (condition, shouldBind) = convertWhenConditionIsPattern(it, subjectVariable)
                     conditions += condition
                     shouldBindSubject = shouldBindSubject || shouldBind
                 }
-                WHEN_ENTRY_GUARD -> guard = getAsFirExpression(it.getFirstChildExpressionUnwrapped(), "No expression in guard", sourceWhenInvalidExpression = it)
-                ELSE_KEYWORD -> isElse = true
-                BLOCK -> firBlock = declarationBuilder.convertBlock(it)
+                WHEN_ENTRY_GUARD_INDEX -> guard = getAsFirExpression(it.getFirstChildExpressionUnwrapped(), "No expression in guard", sourceWhenInvalidExpression = it)
+                ELSE_KEYWORD_INDEX -> isElse = true
+                BLOCK_INDEX -> firBlock = declarationBuilder.convertBlock(it)
                 else -> if (it.isExpression()) firBlock = declarationBuilder.convertBlock(it)
             }
         }
@@ -1023,12 +1046,11 @@
         var conditionSource: KtLightSourceElement? = null
         whenCondition.forEachChildren {
             when {
-                it.tokenType == OPERATION_REFERENCE && it.asText == NOT_IN.value -> {
-                    conditionSource = it.toFirSourceElement()
-                    isNegate = true
-                }
                 it.tokenType == OPERATION_REFERENCE -> {
                     conditionSource = it.toFirSourceElement()
+                    if (it.asText == NOT_IN.value) {
+                        isNegate = true
+                    }
                 }
                 else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "No range in condition with range")
             }
@@ -1482,10 +1504,10 @@
         var thenBlock: LighterASTNode? = null
         var elseBlock: LighterASTNode? = null
         ifExpression.forEachChildren {
-            when (it.tokenType) {
-                CONDITION -> firCondition = getAsFirExpression(it, "If statement should have condition")
-                THEN -> thenBlock = it
-                ELSE -> elseBlock = it
+            when (it.index) {
+                CONDITION_INDEX -> firCondition = getAsFirExpression(it, "If statement should have condition")
+                THEN_INDEX -> thenBlock = it
+                ELSE_INDEX -> elseBlock = it
             }
         }
         return IfNodeComponents(firCondition, thenBlock, elseBlock)
@@ -1499,15 +1521,14 @@
             ) {
                 parent = parent.getParent() ?: return true
             }
-            val parentTokenType = parent.tokenType
-            return when (parentTokenType) {
-                BLOCK -> parent.getLastChildExpression() == this && parent.usedAsExpression
-                TRY, CATCH -> parent.usedAsExpression
-                THEN, ELSE, WHEN_ENTRY -> parent.getParent()?.usedAsExpression ?: true
-                CLASS_INITIALIZER, SCRIPT_INITIALIZER, SECONDARY_CONSTRUCTOR, FUNCTION_LITERAL, FINALLY -> false
-                FUN, PROPERTY_ACCESSOR -> parent.getChildrenAsArray().any { it?.tokenType == EQ }
-                DOT_QUALIFIED_EXPRESSION -> parent.getFirstChild() == this
-                BODY -> when (parent.getParent()?.tokenType) {
+            return when (parent.index) {
+                BLOCK_INDEX -> parent.getLastChildExpression() == this && parent.usedAsExpression
+                TRY_INDEX, CATCH_INDEX -> parent.usedAsExpression
+                THEN_INDEX, ELSE_INDEX, WHEN_ENTRY_INDEX -> parent.getParent()?.usedAsExpression ?: true
+                CLASS_INITIALIZER_INDEX, SCRIPT_INITIALIZER_INDEX, SECONDARY_CONSTRUCTOR_INDEX, FUNCTION_LITERAL_INDEX, FINALLY_INDEX -> false
+                FUNCTION_INDEX, PROPERTY_ACCESSOR_INDEX -> parent.getChildrenAsArray().any { it?.tokenType == EQ }
+                DOT_QUALIFIED_EXPRESSION_INDEX -> parent.getFirstChild() == this
+                BODY_INDEX -> when (parent.getParent()?.tokenType) {
                     FOR, WHILE, DO_WHILE -> false
                     else -> true
                 }
@@ -1621,12 +1642,12 @@
      */
     fun convertValueArguments(valueArguments: LighterASTNode): List<FirExpression> {
         return valueArguments.forEachChildrenReturnList { node, container ->
-            when (node.tokenType) {
-                VALUE_ARGUMENT -> container += convertValueArgument(node)
-                LAMBDA_EXPRESSION,
-                LABELED_EXPRESSION,
-                ANNOTATED_EXPRESSION,
-                -> container += getAsFirExpression<FirAnonymousFunctionExpression>(node).apply {
+            when (node.index) {
+                VALUE_ARGUMENT_INDEX -> container += convertValueArgument(node)
+                LAMBDA_EXPRESSION_INDEX,
+                LABELED_EXPRESSION_INDEX,
+                ANNOTATED_EXPRESSION_INDEX,
+                    -> container += getAsFirExpression<FirAnonymousFunctionExpression>(node).apply {
                     // TODO(KT-66553) remove and set in builder
                     @OptIn(RawFirApi::class)
                     replaceIsTrailingLambda(newIsTrailingLambda = true)
@@ -1644,11 +1665,11 @@
         var isSpread = false
         var firExpression: FirExpression? = null
         valueArgument.forEachChildren {
-            when (it.tokenType) {
-                VALUE_ARGUMENT_NAME -> identifier = it.asText
-                MUL -> isSpread = true
-                STRING_TEMPLATE -> firExpression = convertStringTemplate(it)
-                is KtConstantExpressionElementType -> firExpression = convertConstantExpression(it)
+            when (it.index) {
+                VALUE_ARGUMENT_NAME_INDEX -> identifier = it.asText
+                MUL_INDEX -> isSpread = true
+                STRING_TEMPLATE_INDEX -> firExpression = convertStringTemplate(it)
+                NULL_INDEX, BOOLEAN_CONSTANT_INDEX, FLOAT_CONSTANT_INDEX, CHARACTER_CONSTANT_INDEX, INTEGER_CONSTANT_INDEX -> firExpression = convertConstantExpression(it)
                 else -> if (it.isExpression()) firExpression = getAsFirExpression(it, "Argument is absent")
             }
         }
diff --git a/compiler/psi/src/org/jetbrains/kotlin/CommonTokens.java b/compiler/psi/src/org/jetbrains/kotlin/CommonTokens.java
new file mode 100644
index 0000000..e3d068e
--- /dev/null
+++ b/compiler/psi/src/org/jetbrains/kotlin/CommonTokens.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin;
+
+import com.intellij.lang.java.JavaParserDefinition;
+import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
+import com.intellij.psi.TokenType;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.kotlin.psi.stubs.elements.KtFileElementType;
+
+@SuppressWarnings({"WeakerAccess", "unused"}) // Let all static identifiers be public as well as corresponding elements
+public class CommonTokens {
+    public final static IElementType PLAIN_FILE_ELEMENT_TYPE = new PlainTextParserDefinition().getFileNodeType();
+    public final static IElementType JAVA_FILE = JavaParserDefinition.JAVA_FILE;
+    public final static IElementType FILE_ELEMENT_TYPE =  KtFileElementType.INSTANCE;
+
+    public final static IElementType WHITE_SPACE = TokenType.WHITE_SPACE;
+    public final static IElementType BAD_CHARACTER = TokenType.BAD_CHARACTER;
+    public final static IElementType NEW_LINE_INDENT = TokenType.NEW_LINE_INDENT;
+    public final static IElementType ERROR_ELEMENT = TokenType.ERROR_ELEMENT;
+    public final static IElementType CODE_FRAGMENT = TokenType.CODE_FRAGMENT;
+    public final static IElementType DUMMY_HOLDER = TokenType.DUMMY_HOLDER;
+
+    public final static int PLAIN_FILE_ELEMENT_TYPE_INDEX = IElementType.FIRST_TOKEN_INDEX;
+    public final static int JAVA_FILE_INDEX = PLAIN_FILE_ELEMENT_TYPE_INDEX + 1;
+    public final static int FILE_ELEMENT_TYPE_INDEX = JAVA_FILE_INDEX + 1;
+
+    public final static int WHITE_SPACE_INDEX = FILE_ELEMENT_TYPE_INDEX + 1;
+    public final static int BAD_CHARACTER_INDEX = WHITE_SPACE_INDEX + 1;
+    public final static int NEW_LINE_INDENT_INDEX = BAD_CHARACTER_INDEX + 1;
+    public final static int ERROR_ELEMENT_INDEX = NEW_LINE_INDENT_INDEX + 1;
+    public final static int CODE_FRAGMENT_INDEX = ERROR_ELEMENT_INDEX + 1;
+    public final static int DUMMY_HOLDER_INDEX = CODE_FRAGMENT_INDEX + 1;
+
+    static {
+        ElementTypeChecker.checkExplicitStaticIndexesMatchImplicit(CommonTokens.class);
+    }
+}
diff --git a/compiler/psi/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java b/compiler/psi/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java
index 0d3efe6..d5f1f45 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/kdoc/lexer/KDocTokens.java
@@ -22,11 +22,11 @@
 import com.intellij.lang.PsiParser;
 import com.intellij.openapi.project.Project;
 import com.intellij.psi.PsiElement;
-import com.intellij.psi.TokenType;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.ILazyParseableElementType;
 import com.intellij.psi.tree.TokenSet;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.kotlin.CommonTokens;
 import org.jetbrains.kotlin.ElementTypeChecker;
 import org.jetbrains.kotlin.idea.KotlinLanguage;
 import org.jetbrains.kotlin.kdoc.parser.KDocLinkParser;
@@ -38,12 +38,10 @@
     static {
         // It forces initializing tokens in strict order that provides possibility to match indexes and static identifiers
         @SuppressWarnings("unused")
-        IElementType dependentTokensInit = TokenType.WHITE_SPACE;
+        IElementType dependentTokensInit = CommonTokens.WHITE_SPACE;
     }
 
-    private final static int START_OFFSET = 9; // The specific value is calculated based on already initialized internal elements
-
-    public final static int KDOC_INDEX = START_OFFSET + 1;
+    public final static int KDOC_INDEX = CommonTokens.DUMMY_HOLDER_INDEX + 1;
     public final static int START_INDEX = KDOC_INDEX + 1;
     public final static int END_INDEX = START_INDEX + 1;
     public final static int LEADING_ASTERISK_INDEX = END_INDEX + 1;
diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
index cde45e2..dca112d 100644
--- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
+++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java
@@ -5,6 +5,7 @@
 
 package org.jetbrains.kotlin.psi.stubs.elements;
 
+import com.intellij.psi.stubs.PsiFileStubImpl;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.tree.TokenSet;
 import org.jetbrains.kotlin.ElementTypeChecker;
@@ -21,7 +22,10 @@
         IElementType dependentTokensInit = KtTokens.EOF;
     }
 
-    public static final int CLASS_INDEX = ACTUAL_KEYWORD_INDEX + 1;
+    public static final IElementType PSI_FILE_STUB = PsiFileStubImpl.TYPE;
+
+    public static final int PSI_FILE_STUB_INDEX = ACTUAL_KEYWORD_INDEX + 1;
+    public static final int CLASS_INDEX = PSI_FILE_STUB_INDEX + 1;
     public static final int FUNCTION_INDEX = CLASS_INDEX + 1;
     public static final int PROPERTY_INDEX = FUNCTION_INDEX + 1;
     public static final int PROPERTY_ACCESSOR_INDEX = PROPERTY_INDEX + 1;