diff --git a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/CodegenTestsOnAndroidGenerator.java b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/CodegenTestsOnAndroidGenerator.java index 3a9c1456574..448fea2b703 100644 --- a/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/CodegenTestsOnAndroidGenerator.java +++ b/compiler/android-tests/tests/org/jetbrains/kotlin/android/tests/CodegenTestsOnAndroidGenerator.java @@ -32,8 +32,8 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys; import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.JVMConfigurationKeys; import org.jetbrains.kotlin.idea.KotlinFileType; -import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.name.NameUtils; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase; @@ -279,7 +279,7 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase { } private String generateTestName(String fileName) { - String result = JvmAbi.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName))); + String result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName))); int i = 0; while (generatedTestNames.contains(result)) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index fbda7bed45a..83801272e7d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -53,10 +53,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment; import org.jetbrains.kotlin.load.kotlin.*; import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment; -import org.jetbrains.kotlin.name.ClassId; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.name.SpecialNames; +import org.jetbrains.kotlin.name.*; import org.jetbrains.kotlin.platform.JavaToKotlinClassMap; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtFile; @@ -947,7 +944,7 @@ public class KotlinTypeMapper { if (!(descriptor instanceof ConstructorDescriptor) && descriptor.getVisibility() == Visibilities.INTERNAL && !descriptor.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)) { - return name + "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName); + return name + "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName); } return name; diff --git a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt index cd08a3fe2e1..5371260dc7c 100644 --- a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt +++ b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt @@ -134,7 +134,7 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) { private fun getPackageFilePath(packageFqName: FqName, fileName: String): String = packageFqName.asString().replace('.', '/') + "/" + - PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + DOT_METADATA_FILE_EXTENSION + PackagePartClassUtils.getFilePartShortName(fileName) + DOT_METADATA_FILE_EXTENSION private fun getClassFilePath(classId: ClassId): String = classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt index 6be40b2f7c7..10b750a384a 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/PackagePartClassUtils.kt @@ -21,9 +21,9 @@ import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.psi.* import java.util.* @@ -33,20 +33,6 @@ object PackagePartClassUtils { private val PART_CLASS_NAME_SUFFIX = "Kt" - @JvmStatic fun getPartClassName(str: String): String = - if (str.isEmpty()) - "_$PART_CLASS_NAME_SUFFIX" - else - capitalizeAsJavaClassName(JvmAbi.sanitizeAsJavaIdentifier(str)) + PART_CLASS_NAME_SUFFIX - - private @JvmStatic fun capitalizeAsJavaClassName(str: String): String = - // NB use Locale.ENGLISH so that build is locale-independent. - // See Javadoc on java.lang.String.toUpperCase() for more details. - if (Character.isJavaIdentifierStart(str[0])) - str.substring(0, 1).toUpperCase(Locale.ENGLISH) + str.substring(1) - else - "_$str" - private @JvmStatic fun decapitalizeAsJavaClassName(str: String): String = // NB use Locale.ENGLISH so that build is locale-independent. // See Javadoc on java.lang.String.toUpperCase() for more details. @@ -77,7 +63,7 @@ object PackagePartClassUtils { } @JvmStatic fun getFilePartShortName(fileName: String): String = - getPartClassName(FileUtil.getNameWithoutExtension(fileName)) + NameUtils.getPackagePartClassNamePrefix(FileUtil.getNameWithoutExtension(fileName)) + PART_CLASS_NAME_SUFFIX @JvmStatic fun getFileNameByFacadeName(facadeClassName: String): String? { if (!facadeClassName.endsWith(PART_CLASS_NAME_SUFFIX)) return null diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index 6984ac27d44..ab3913eff31 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.load.java; -import kotlin.text.Regex; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.CompanionObjectMapping; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; @@ -51,8 +50,8 @@ public final class JvmAbi { public static final String DELEGATED_PROPERTIES_ARRAY_NAME = "$$delegatedProperties"; public static final String DELEGATE_SUPER_FIELD_PREFIX = "$$delegate_"; private static final String ANNOTATIONS_SUFFIX = "$annotations"; - public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; - public static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; + private static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; + private static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; public static final String INSTANCE_FIELD = "INSTANCE"; @@ -62,8 +61,6 @@ public final class JvmAbi { public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT = "$i$a$"; public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION = "$i$f$"; - private static final Regex SANITIZE_AS_JAVA_INVALID_CHARACTERS = new Regex("[^\\p{L}\\p{Digit}]"); - @NotNull public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) { return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX; @@ -92,9 +89,10 @@ public final class JvmAbi { @NotNull public static String setterName(@NotNull String propertyName) { - return startsWithIsPrefix(propertyName) - ? SET_PREFIX + propertyName.substring(IS_PREFIX.length()) - : SET_PREFIX + CapitalizeDecapitalizeKt.capitalizeAsciiOnly(propertyName); + return SET_PREFIX + + (startsWithIsPrefix(propertyName) + ? propertyName.substring(IS_PREFIX.length()) + : CapitalizeDecapitalizeKt.capitalizeAsciiOnly(propertyName)); } public static boolean startsWithIsPrefix(String name) { @@ -104,11 +102,6 @@ public final class JvmAbi { return !('a' <= c && c <= 'z'); } - @NotNull - public static String sanitizeAsJavaIdentifier(@NotNull String str) { - return SANITIZE_AS_JAVA_INVALID_CHARACTERS.replace(str, "_"); - } - public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration()); diff --git a/core/descriptors/src/org/jetbrains/kotlin/name/NameUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/name/NameUtils.kt new file mode 100644 index 00000000000..d0ce2b24c64 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/name/NameUtils.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2017 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. + */ + +package org.jetbrains.kotlin.name + +import java.util.* + +object NameUtils { + private val SANITIZE_AS_JAVA_INVALID_CHARACTERS = "[^\\p{L}\\p{Digit}]".toRegex() + + @JvmStatic + fun sanitizeAsJavaIdentifier(name: String): String { + return SANITIZE_AS_JAVA_INVALID_CHARACTERS.replace(name, "_") + } + + /** + * Capitalizes the short name of the file (without extension) and sanitizes it so that it's a valid Java identifier. + * E.g. "fileName" -> "FileName", "1" -> "_1", "" -> "_" + */ + @JvmStatic + fun getPackagePartClassNamePrefix(shortFileName: String): String = + if (shortFileName.isEmpty()) + "_" + else + capitalizeAsJavaClassName(sanitizeAsJavaIdentifier(shortFileName)) + + @JvmStatic + private fun capitalizeAsJavaClassName(str: String): String = + // NB use Locale.ENGLISH so that build is locale-independent. + // See Javadoc on java.lang.String.toUpperCase() for more details. + if (Character.isJavaIdentifierStart(str[0])) + str.substring(0, 1).toUpperCase(Locale.ENGLISH) + str.substring(1) + else + "_$str" +} diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt index 39540e2b265..72c2adc1359 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.reflect.* import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType @@ -126,7 +127,7 @@ internal sealed class JvmPropertySignature { if (classProto.hasExtension(JvmProtoBuf.classModuleName)) nameResolver.getString(classProto.getExtension(JvmProtoBuf.classModuleName)) else JvmAbi.DEFAULT_MODULE_NAME - return "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName) + return "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName) } if (descriptor.visibility == Visibilities.PRIVATE && containingDeclaration is PackageFragmentDescriptor) { val packagePartSource = (descriptor as DeserializedPropertyDescriptor).containerSource