[stub] simplify ClassId creation

We can create nested ClassId just from the parent stub instead of calculation by tree.
This commit simplified the complexity of ClassId building to liner.
Example:
```kotlin
package one
class A {
  class B {
    class C {
      class D
    }
  }
}
```
Previously, we had to create ClassId by traverse parents for each class.
Now we will visit each class only once.
It should improve performance and memory consumption during indexing.

^KTIJ-26848
This commit is contained in:
Dmitrii Gridin
2023-09-04 16:01:03 +02:00
committed by Space Team
parent 2421d3cdf1
commit 0701da6c59
5 changed files with 34 additions and 61 deletions
@@ -23,7 +23,7 @@ object KotlinStubVersions {
// Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version
// if you are not 100% sure it can be avoided.
// Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version.
const val SOURCE_STUB_VERSION = 155
const val SOURCE_STUB_VERSION = 156
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
@@ -1,13 +1,17 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 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.psi.stubs
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClassLikeDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
object StubUtils {
@JvmStatic
@@ -20,4 +24,19 @@ object StubUtils {
fun serializeClassId(dataStream: StubOutputStream, classId: ClassId?) {
dataStream.writeName(classId?.asString())
}
}
@JvmStatic
fun createNestedClassId(parentStub: StubElement<*>, currentDeclaration: KtClassLikeDeclaration): ClassId? = when {
parentStub is KotlinFileStub -> ClassId(parentStub.getPackageFqName(), currentDeclaration.nameAsSafeName)
parentStub is KotlinScriptStub -> createNestedClassId(parentStub.parentStub, currentDeclaration)
parentStub is KotlinPlaceHolderStub<*> && parentStub.stubType == KtStubElementTypes.CLASS_BODY -> {
val containingClassStub = parentStub.parentStub as? KotlinClassifierStub
if (containingClassStub != null && currentDeclaration !is KtEnumEntry) {
containingClassStub.getClassId()?.createNestedClassId(currentDeclaration.nameAsSafeName)
} else {
null
}
}
else -> null
}
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 2010-2023 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.psi.stubs.elements;
@@ -60,9 +49,10 @@ public class KtClassElementType extends KtStubElementType<KotlinClassStub, KtCla
FqName fqName = KtPsiUtilKt.safeFqNameForLazyResolve(psi);
boolean isEnumEntry = psi instanceof KtEnumEntry;
List<String> superNames = KtPsiUtilKt.getSuperNames(psi);
ClassId classId = StubUtils.createNestedClassId(parentStub, psi);
return new KotlinClassStubImpl(
getStubType(isEnumEntry), (StubElement<?>) parentStub,
StringRef.fromString(fqName != null ? fqName.asString() : null), psi.getClassId(),
StringRef.fromString(fqName != null ? fqName.asString() : null), classId,
StringRef.fromString(psi.getName()),
Utils.INSTANCE.wrapStrings(superNames),
psi.isInterface(), isEnumEntry, psi.isLocal(), psi.isTopLevel()
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 2010-2023 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.psi.stubs.elements;
@@ -46,8 +35,9 @@ public class KtObjectElementType extends KtStubElementType<KotlinObjectStub, KtO
String name = psi.getName();
FqName fqName = KtPsiUtilKt.safeFqNameForLazyResolve(psi);
List<String> superNames = KtPsiUtilKt.getSuperNames(psi);
ClassId classId = StubUtils.createNestedClassId(parentStub, psi);
return new KotlinObjectStubImpl(
(StubElement<?>) parentStub, StringRef.fromString(name), fqName, psi.getClassId(), Utils.INSTANCE.wrapStrings(superNames),
(StubElement<?>) parentStub, StringRef.fromString(name), fqName, classId, Utils.INSTANCE.wrapStrings(superNames),
psi.isTopLevel(), psi.isCompanion(), psi.isLocal(), psi.isObjectLiteral()
);
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT 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 2010-2023 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.psi.stubs.elements
@@ -21,11 +10,8 @@ import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import com.intellij.util.io.StringRef
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.psi.psiUtil.safeFqNameForLazyResolve
import org.jetbrains.kotlin.psi.stubs.KotlinClassStub
import org.jetbrains.kotlin.psi.stubs.KotlinFileStub
import org.jetbrains.kotlin.psi.stubs.KotlinTypeAliasStub
import org.jetbrains.kotlin.psi.stubs.StubUtils
import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
@@ -33,26 +19,14 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
class KtTypeAliasElementType(debugName: String) :
KtStubElementType<KotlinTypeAliasStub, KtTypeAlias>(debugName, KtTypeAlias::class.java, KotlinTypeAliasStub::class.java) {
override fun createStub(psi: KtTypeAlias, parentStub: StubElement<*>?): KotlinTypeAliasStub {
override fun createStub(psi: KtTypeAlias, parentStub: StubElement<*>): KotlinTypeAliasStub {
val name = StringRef.fromString(psi.name)
val fqName = StringRef.fromString(psi.safeFqNameForLazyResolve()?.asString())
val classId = parentStub?.let { createNestedClassId(it, psi) }
val classId = StubUtils.createNestedClassId(parentStub, psi)
val isTopLevel = psi.isTopLevel()
return KotlinTypeAliasStubImpl(parentStub, name, fqName, classId, isTopLevel)
}
private fun createNestedClassId(parentStub: StubElement<*>, typeAlias: KtTypeAlias): ClassId? {
val typeAliasName = typeAlias.nameAsName ?: return null
return when {
parentStub.stubType == KtStubElementTypes.CLASS_BODY -> {
val parentClass = parentStub.parentStub as? KotlinClassStub
parentClass?.getClassId()?.createNestedClassId(typeAliasName)
}
parentStub is KotlinFileStub -> ClassId(parentStub.getPackageFqName(), typeAliasName)
else -> null
}
}
override fun serialize(stub: KotlinTypeAliasStub, dataStream: StubOutputStream) {
dataStream.writeName(stub.name)
dataStream.writeName(stub.getFqName()?.asString())