Move name sanitization utilities to module 'descriptors'

This commit is contained in:
Alexander Udalov
2017-01-11 14:22:18 +03:00
parent f4d59304e2
commit 6ffa56b640
7 changed files with 63 additions and 38 deletions
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys;
import org.jetbrains.kotlin.config.CompilerConfiguration; import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.config.JVMConfigurationKeys; import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.idea.KotlinFileType; import org.jetbrains.kotlin.idea.KotlinFileType;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.NameUtils;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.test.*; import org.jetbrains.kotlin.test.*;
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase; import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase;
@@ -279,7 +279,7 @@ public class CodegenTestsOnAndroidGenerator extends KtUsefulTestCase {
} }
private String generateTestName(String fileName) { 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; int i = 0;
while (generatedTestNames.contains(result)) { while (generatedTestNames.contains(result)) {
@@ -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.java.lazy.descriptors.LazyJavaPackageFragment;
import org.jetbrains.kotlin.load.kotlin.*; import org.jetbrains.kotlin.load.kotlin.*;
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment; import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider.IncrementalMultifileClassPackageFragment;
import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.*;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.SpecialNames;
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap; import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
@@ -947,7 +944,7 @@ public class KotlinTypeMapper {
if (!(descriptor instanceof ConstructorDescriptor) && if (!(descriptor instanceof ConstructorDescriptor) &&
descriptor.getVisibility() == Visibilities.INTERNAL && descriptor.getVisibility() == Visibilities.INTERNAL &&
!descriptor.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)) { !descriptor.getAnnotations().hasAnnotation(KotlinBuiltIns.FQ_NAMES.publishedApi)) {
return name + "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName); return name + "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName);
} }
return name; return name;
@@ -134,7 +134,7 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String = private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
packageFqName.asString().replace('.', '/') + "/" + 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 = private fun getClassFilePath(classId: ClassId): String =
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
@@ -21,9 +21,9 @@ import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import java.util.* import java.util.*
@@ -33,20 +33,6 @@ object PackagePartClassUtils {
private val PART_CLASS_NAME_SUFFIX = "Kt" 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 = private @JvmStatic fun decapitalizeAsJavaClassName(str: String): String =
// NB use Locale.ENGLISH so that build is locale-independent. // NB use Locale.ENGLISH so that build is locale-independent.
// See Javadoc on java.lang.String.toUpperCase() for more details. // See Javadoc on java.lang.String.toUpperCase() for more details.
@@ -77,7 +63,7 @@ object PackagePartClassUtils {
} }
@JvmStatic fun getFilePartShortName(fileName: String): String = @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? { @JvmStatic fun getFileNameByFacadeName(facadeClassName: String): String? {
if (!facadeClassName.endsWith(PART_CLASS_NAME_SUFFIX)) return null if (!facadeClassName.endsWith(PART_CLASS_NAME_SUFFIX)) return null
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.load.java; package org.jetbrains.kotlin.load.java;
import kotlin.text.Regex;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.builtins.CompanionObjectMapping; import org.jetbrains.kotlin.builtins.CompanionObjectMapping;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; 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 DELEGATED_PROPERTIES_ARRAY_NAME = "$$delegatedProperties";
public static final String DELEGATE_SUPER_FIELD_PREFIX = "$$delegate_"; public static final String DELEGATE_SUPER_FIELD_PREFIX = "$$delegate_";
private static final String ANNOTATIONS_SUFFIX = "$annotations"; private static final String ANNOTATIONS_SUFFIX = "$annotations";
public static final String ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; private 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_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX;
public static final String INSTANCE_FIELD = "INSTANCE"; 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_ARGUMENT = "$i$a$";
public static final String LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION = "$i$f$"; 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 @NotNull
public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) { public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) {
return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX; return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX;
@@ -92,9 +89,10 @@ public final class JvmAbi {
@NotNull @NotNull
public static String setterName(@NotNull String propertyName) { public static String setterName(@NotNull String propertyName) {
return startsWithIsPrefix(propertyName) return SET_PREFIX +
? SET_PREFIX + propertyName.substring(IS_PREFIX.length()) (startsWithIsPrefix(propertyName)
: SET_PREFIX + CapitalizeDecapitalizeKt.capitalizeAsciiOnly(propertyName); ? propertyName.substring(IS_PREFIX.length())
: CapitalizeDecapitalizeKt.capitalizeAsciiOnly(propertyName));
} }
public static boolean startsWithIsPrefix(String name) { public static boolean startsWithIsPrefix(String name) {
@@ -104,11 +102,6 @@ public final class JvmAbi {
return !('a' <= c && c <= 'z'); 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) { public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration()); isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration());
@@ -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"
}
@@ -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.java.structure.reflect.*
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
@@ -126,7 +127,7 @@ internal sealed class JvmPropertySignature {
if (classProto.hasExtension(JvmProtoBuf.classModuleName)) if (classProto.hasExtension(JvmProtoBuf.classModuleName))
nameResolver.getString(classProto.getExtension(JvmProtoBuf.classModuleName)) nameResolver.getString(classProto.getExtension(JvmProtoBuf.classModuleName))
else JvmAbi.DEFAULT_MODULE_NAME else JvmAbi.DEFAULT_MODULE_NAME
return "$" + JvmAbi.sanitizeAsJavaIdentifier(moduleName) return "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName)
} }
if (descriptor.visibility == Visibilities.PRIVATE && containingDeclaration is PackageFragmentDescriptor) { if (descriptor.visibility == Visibilities.PRIVATE && containingDeclaration is PackageFragmentDescriptor) {
val packagePartSource = (descriptor as DeserializedPropertyDescriptor).containerSource val packagePartSource = (descriptor as DeserializedPropertyDescriptor).containerSource