From 8ad9718310e3cc32a31b38a86bb7c46b1cc74a21 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 29 Aug 2023 18:20:42 +0900 Subject: [PATCH] [LL API] Check the class file is in a conventional place Although 'VirtualFile's are typically inside the containing package directory, e.g. 'foo/bar/Baz.class' for 'foo.bar.Baz', there might be classes with files in unexpected places. Sources of such classes may include broken stubs, or just classes from misbehaving IDE plugins. As we are yet to identity such cases, here we treat them as 'other' candidates. --- ...braryScopeAwareConeCallConflictResolver.kt | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLLibraryScopeAwareConeCallConflictResolver.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLLibraryScopeAwareConeCallConflictResolver.kt index 5a3ec70b918..d249950b2b3 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLLibraryScopeAwareConeCallConflictResolver.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/resolve/extensions/LLLibraryScopeAwareConeCallConflictResolver.kt @@ -96,7 +96,29 @@ private class LLLibraryScopeAwareConeCallConflictResolver( } private fun getSymbolRootFile(virtualFile: VirtualFile, packageFqName: FqName): VirtualFile? { - val nestingLevel = packageFqName.pathSegments().size - return generateSequence(virtualFile) { it.parent }.drop(nestingLevel + 1).firstOrNull() + val packageFqNameSegments = packageFqName.pathSegments().asReversed() + val nestingLevel = packageFqNameSegments.size + + var current = virtualFile + var index = 0 + + while (true) { + assert(index <= nestingLevel) + + val parent = current.parent ?: return null + + if (index == nestingLevel) { + // Parent containing the root package is a class file root + return parent + } + + if (parent.name != packageFqNameSegments[index].asString()) { + // Unexpected directory structure, the class is in a non-conventional root + return null + } + + current = parent + index += 1 + } } } \ No newline at end of file