diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt index dace95ae9b1..b6ec042d557 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/extensions/FirExtensionDeclarationsSymbolProvider.kt @@ -68,7 +68,7 @@ class FirExtensionDeclarationsSymbolProvider private constructor( cachesFactory.createLazyValue { computeNamesGroupedByPackage( FirDeclarationGenerationExtension::getTopLevelClassIds, - ClassId::getPackageFqName + ClassId::packageFqName ) { it.shortClassName.asString() } } diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest.kt index 5fc572fc4c6..0ad511a9467 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest.kt @@ -31,7 +31,7 @@ class KotlinOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() { fun testSimpleClass() { val sourceFile = getSourceFile("testSimpleClass", "com/example/SimpleClass.kt") val actualSnapshot = sourceFile.compileAndSnapshot().toGson() - val expectedSnapshot = sourceFile.getExpectedSnapshotFile().readText() + val expectedSnapshot = sourceFile.getExpectedSnapshotText() assertEquals(expectedSnapshot, actualSnapshot) @@ -55,7 +55,7 @@ class KotlinOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() { val sourceFile = getSourceFile("testSimpleClass", "com/example/SimpleClass.kt") val classFile = sourceFile.compileSingle() val actualSnapshot = classFile.snapshot(ClassSnapshotGranularity.CLASS_LEVEL).toGson() - val expectedSnapshot = sourceFile.getExpectedSnapshotFile(ClassSnapshotGranularity.CLASS_LEVEL).readText() + val expectedSnapshot = sourceFile.getExpectedSnapshotText(ClassSnapshotGranularity.CLASS_LEVEL) assertEquals(expectedSnapshot, actualSnapshot) @@ -103,7 +103,7 @@ class JavaOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() { fun testSimpleClass() { val sourceFile = getSourceFile("testSimpleClass", "com/example/SimpleClass.java") val actualSnapshot = sourceFile.compileAndSnapshot().toGson() - val expectedSnapshot = sourceFile.getExpectedSnapshotFile().readText() + val expectedSnapshot = sourceFile.getExpectedSnapshotText() assertEquals(expectedSnapshot, actualSnapshot) @@ -126,7 +126,7 @@ class JavaOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() { val sourceFile = getSourceFile("testSimpleClass", "com/example/SimpleClass.java") val classFile = sourceFile.compileSingle() val actualSnapshot = classFile.snapshot(ClassSnapshotGranularity.CLASS_LEVEL).toGson() - val expectedSnapshot = sourceFile.getExpectedSnapshotFile(ClassSnapshotGranularity.CLASS_LEVEL).readText() + val expectedSnapshot = sourceFile.getExpectedSnapshotText(ClassSnapshotGranularity.CLASS_LEVEL) assertEquals(expectedSnapshot, actualSnapshot) @@ -135,10 +135,10 @@ class JavaOnlyClasspathSnapshotterTest : ClasspathSnapshotTestCommon() { } } -private fun TestSourceFile.getExpectedSnapshotFile(granularity: ClassSnapshotGranularity? = null): File { +private fun TestSourceFile.getExpectedSnapshotText(granularity: ClassSnapshotGranularity? = null): String { val relativePath = sourceFile.unixStyleRelativePath.substringBeforeLast(".") + ".json" val expectedSnapshotDirName = if (granularity == null) "expected-snapshot" else "expected-snapshot-${granularity.name}" - return sourceFile.baseDir.resolve("../$expectedSnapshotDirName/$relativePath") + return sourceFile.baseDir.resolve("../$expectedSnapshotDirName/$relativePath").readText().trimEnd() } private fun String.assertContains(vararg elements: String) { diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json index bdfdee03cd7..e1078e3dae9 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json @@ -10,7 +10,7 @@ "fqName": "SimpleClass" } }, - "local": false + "isLocal": false }, "classAbiHash": -6515999856905133685, "supertypes": [ @@ -18,4 +18,4 @@ "internalName": "java/lang/Object" } ] -} \ No newline at end of file +} diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot/com/example/SimpleClass.json b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot/com/example/SimpleClass.json index 59d878d78f3..7d6b5ba0d35 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot/com/example/SimpleClass.json +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/java/testSimpleClass/expected-snapshot/com/example/SimpleClass.json @@ -10,7 +10,7 @@ "fqName": "SimpleClass" } }, - "local": false + "isLocal": false }, "classAbiHash": 2881075740228300324, "classMemberLevelSnapshot": { @@ -40,4 +40,4 @@ "internalName": "java/lang/Object" } ] -} \ No newline at end of file +} diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json index c2b4a9ae022..d3ed0fe304a 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot-CLASS_LEVEL/com/example/SimpleClass.json @@ -10,7 +10,7 @@ "fqName": "SimpleClass" } }, - "local": false + "isLocal": false }, "classAbiHash": 8283317449409255124, "supertypes": [ @@ -18,4 +18,4 @@ "internalName": "java/lang/Object" } ] -} \ No newline at end of file +} diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json index 9b9fb6060e1..89647aa58c1 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json @@ -10,7 +10,7 @@ "fqName": "SimpleClass" } }, - "local": false + "isLocal": false }, "classAbiHash": 8283317449409255124, "classMemberLevelSnapshot": { @@ -25,7 +25,7 @@ "fqName": "SimpleClass" } }, - "local": false + "isLocal": false }, "classKind": "CLASS", "classHeaderData": [ @@ -74,4 +74,4 @@ "internalName": "java/lang/Object" } ] -} \ No newline at end of file +} diff --git a/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt b/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt index 318f9a1e568..933775764e3 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/name/ClassId.kt @@ -13,14 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.jetbrains.kotlin.name; - -import kotlin.text.StringsKt; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; +package org.jetbrains.kotlin.name /** * A class name which is used to uniquely identify a Kotlin class. @@ -31,145 +24,106 @@ import java.util.List; * the package, separated by dollar signs. If a class is an inner of local, relativeClassName would consist of two names, * the second one being the class' short name. */ -public final class ClassId { - @NotNull - public static ClassId topLevel(@NotNull FqName topLevelFqName) { - return new ClassId(topLevelFqName.parent(), topLevelFqName.shortName()); +class ClassId(val packageFqName: FqName, relativeClassName: FqName, local: Boolean) { + val relativeClassName: FqName + val isLocal: Boolean + + init { + assert(!relativeClassName.isRoot) { "Class name must not be root: " + packageFqName + if (local) " (local)" else "" } + this.relativeClassName = relativeClassName + isLocal = local } - private final FqName packageFqName; - private final FqName relativeClassName; - private final boolean local; + constructor(packageFqName: FqName, topLevelName: Name) : this(packageFqName, FqName.topLevel(topLevelName), false) - public ClassId(@NotNull FqName packageFqName, @NotNull FqName relativeClassName, boolean local) { - this.packageFqName = packageFqName; - assert !relativeClassName.isRoot() : - "Class name must not be root: " + packageFqName + (local ? " (local)" : ""); - this.relativeClassName = relativeClassName; - this.local = local; + val parentClassId: ClassId? + get() = if (!isNestedClass) null else ClassId( + packageFqName, + relativeClassName.parent(), + isLocal + ) + val shortClassName: Name + get() = relativeClassName.shortName() + + fun createNestedClassId(name: Name): ClassId { + return ClassId(packageFqName, relativeClassName.child(name), isLocal) } - public ClassId(@NotNull FqName packageFqName, @NotNull Name topLevelName) { - this(packageFqName, FqName.topLevel(topLevelName), false); - } - - @NotNull - public FqName getPackageFqName() { - return packageFqName; - } - - @NotNull - public FqName getRelativeClassName() { - return relativeClassName; - } - - @Nullable - public ClassId getParentClassId() { - if (!isNestedClass()) return null; - return new ClassId(packageFqName, relativeClassName.parent(), isLocal()); - } - - @NotNull - public Name getShortClassName() { - return relativeClassName.shortName(); - } - - public boolean isLocal() { - return local; - } - - @NotNull - public ClassId createNestedClassId(@NotNull Name name) { - return new ClassId(getPackageFqName(), relativeClassName.child(name), local); - } - - @Nullable - public ClassId getOuterClassId() { - FqName parent = relativeClassName.parent(); - return parent.isRoot() ? null : new ClassId(getPackageFqName(), parent, local); - } - - @NotNull - public ClassId getOutermostClassId() { - FqName name = relativeClassName; - while (!name.parent().isRoot()) name = name.parent(); - return new ClassId(packageFqName, name, false); - } - - public boolean isNestedClass() { - return !relativeClassName.parent().isRoot(); - } - - @NotNull - public FqName asSingleFqName() { - if (packageFqName.isRoot()) return relativeClassName; - return new FqName(packageFqName.asString() + "." + relativeClassName.asString()); - } - - public boolean startsWith(@NotNull Name segment) { - return packageFqName.startsWith(segment); - } - - /** - * @param string a string where packages are delimited by '/' and classes by '.', e.g. "kotlin/Map.Entry" - */ - @NotNull - public static ClassId fromString(@NotNull String string) { - return fromString(string, false); - } - - @NotNull - public static ClassId fromString(@NotNull String string, boolean isLocal) { - int lastSlashIndex = string.lastIndexOf("/"); - String packageName; - String className; - if (lastSlashIndex == -1) { - packageName = ""; - className = string; - } else { - packageName = string.substring(0, lastSlashIndex).replace('/', '.'); - className = string.substring(lastSlashIndex + 1); + val outerClassId: ClassId? + get() { + val parent = relativeClassName.parent() + return if (parent.isRoot) null else ClassId(packageFqName, parent, isLocal) } - return new ClassId(new FqName(packageName), new FqName(className), isLocal); + val outermostClassId: ClassId + get() { + var name = relativeClassName + while (!name.parent().isRoot) name = name.parent() + return ClassId(packageFqName, name, false) + } + val isNestedClass: Boolean + get() = !relativeClassName.parent().isRoot + + fun asSingleFqName(): FqName { + return if (packageFqName.isRoot) relativeClassName else FqName(packageFqName.asString() + "." + relativeClassName.asString()) + } + + fun startsWith(segment: Name): Boolean { + return packageFqName.startsWith(segment) } /** * @return a string where packages are delimited by '/' and classes by '.', e.g. "kotlin/Map.Entry" */ - @NotNull - public String asString() { - if (packageFqName.isRoot()) return relativeClassName.asString(); - return packageFqName.asString().replace('.', '/') + "/" + relativeClassName.asString(); + fun asString(): String { + return if (packageFqName.isRoot) relativeClassName.asString() else packageFqName.asString() + .replace('.', '/') + "/" + relativeClassName.asString() } - @NotNull - public String asFqNameString() { - if (packageFqName.isRoot()) return relativeClassName.asString(); - return packageFqName.asString() + "." + relativeClassName.asString(); + fun asFqNameString(): String { + return if (packageFqName.isRoot) relativeClassName.asString() else packageFqName.asString() + "." + relativeClassName.asString() } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ClassId id = (ClassId) o; - - return packageFqName.equals(id.packageFqName) && - relativeClassName.equals(id.relativeClassName) && - local == id.local; + override fun equals(o: Any?): Boolean { + if (this === o) return true + if (o == null || javaClass != o.javaClass) return false + val id = o as ClassId + return packageFqName == id.packageFqName && relativeClassName == id.relativeClassName && isLocal == id.isLocal } - @Override - public int hashCode() { - int result = packageFqName.hashCode(); - result = 31 * result + relativeClassName.hashCode(); - result = 31 * result + Boolean.valueOf(local).hashCode(); - return result; + override fun hashCode(): Int { + var result = packageFqName.hashCode() + result = 31 * result + relativeClassName.hashCode() + result = 31 * result + isLocal.hashCode() + return result } - @Override - public String toString() { - return packageFqName.isRoot() ? "/" + asString() : asString(); + override fun toString(): String { + return if (packageFqName.isRoot) "/" + asString() else asString() + } + + companion object { + @JvmStatic + fun topLevel(topLevelFqName: FqName): ClassId { + return ClassId(topLevelFqName.parent(), topLevelFqName.shortName()) + } + + /** + * @param string a string where packages are delimited by '/' and classes by '.', e.g. "kotlin/Map.Entry" + */ + @JvmOverloads + @JvmStatic + fun fromString(string: String, isLocal: Boolean = false): ClassId { + val lastSlashIndex = string.lastIndexOf("/") + val packageName: String + val className: String + if (lastSlashIndex == -1) { + packageName = "" + className = string + } else { + packageName = string.substring(0, lastSlashIndex).replace('/', '.') + className = string.substring(lastSlashIndex + 1) + } + return ClassId(FqName(packageName), FqName(className), isLocal) + } } } diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/findClassInModule.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/findClassInModule.kt index 5a32f5fd964..5bb721bd8fa 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/findClassInModule.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/findClassInModule.kt @@ -54,7 +54,7 @@ fun ModuleDescriptor.findNonGenericClassAcrossDependencies(classId: ClassId, not if (existingClass != null) return existingClass // Take a list of N zeros, where N is the number of class names in the given ClassId - val typeParametersCount = generateSequence(classId, ClassId::getOuterClassId).map { 0 }.toList() + val typeParametersCount = generateSequence(classId, ClassId::outerClassId).map { 0 }.toList() return notFoundClasses.getClass(classId, typeParametersCount) } diff --git a/core/deserialization.common/src/org/jetbrains/kotlin/serialization/deserialization/MetadataUtil.kt b/core/deserialization.common/src/org/jetbrains/kotlin/serialization/deserialization/MetadataUtil.kt index 3bb6609369d..24c6c87d624 100644 --- a/core/deserialization.common/src/org/jetbrains/kotlin/serialization/deserialization/MetadataUtil.kt +++ b/core/deserialization.common/src/org/jetbrains/kotlin/serialization/deserialization/MetadataUtil.kt @@ -15,7 +15,7 @@ import java.io.InputStream class MetadataClassDataFinder(val finder: KotlinMetadataFinder) : ClassDataFinder { override fun findClassData(classId: ClassId): ClassData? { - val topLevelClassId = generateSequence(classId, ClassId::getOuterClassId).last() + val topLevelClassId = generateSequence(classId, ClassId::outerClassId).last() val stream = finder.findMetadata(topLevelClassId) ?: return null val (message, nameResolver, version) = readProto(stream) return message.class_List.firstOrNull { classProto -> @@ -41,4 +41,4 @@ fun readProto(stream: InputStream): Triple