Name suggester: Improve name suggestion strategy for type parameters
This commit is contained in:
+4
-1
@@ -330,17 +330,20 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||||
SourceElement.NO_SOURCE
|
SourceElement.NO_SOURCE
|
||||||
)
|
)
|
||||||
|
|
||||||
val validator = CollectingValidator { scope.getClassifier(Name.identifier(it)) == null }
|
val validator = CollectingValidator { scope.getClassifier(Name.identifier(it)) == null }
|
||||||
|
val parameterNames = JetNameSuggester.suggestNamesForTypeParameters(typeParameterCount, validator)
|
||||||
val typeParameters = typeParameterCount.indices.map {
|
val typeParameters = typeParameterCount.indices.map {
|
||||||
TypeParameterDescriptorImpl.createWithDefaultBound(
|
TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||||
fakeFunction,
|
fakeFunction,
|
||||||
Annotations.EMPTY,
|
Annotations.EMPTY,
|
||||||
false,
|
false,
|
||||||
Variance.INVARIANT,
|
Variance.INVARIANT,
|
||||||
Name.identifier(validator.validateName("T")),
|
Name.identifier(parameterNames[it]),
|
||||||
it
|
it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fakeFunction.initialize(null, null, typeParameters, Collections.emptyList(), null, null, Visibilities.INTERNAL)
|
return fakeFunction.initialize(null, null, typeParameters, Collections.emptyList(), null, null, Visibilities.INTERNAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.intellij.util.ArrayUtil;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
@@ -96,6 +97,16 @@ public class JetNameSuggester {
|
|||||||
return ArrayUtil.toStringArray(result);
|
return ArrayUtil.toStringArray(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String[] COMMON_TYPE_PARAMETER_NAMES = {"T", "U", "V", "W", "X", "Y", "Z"};
|
||||||
|
|
||||||
|
public static @NotNull String[] suggestNamesForTypeParameters(int count, @NotNull JetNameValidator validator) {
|
||||||
|
ArrayList<String> result = new ArrayList<String>();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
result.add(validator.validateNameWithVariants(COMMON_TYPE_PARAMETER_NAMES));
|
||||||
|
}
|
||||||
|
return ArrayUtil.toStringArray(result);
|
||||||
|
}
|
||||||
|
|
||||||
private static void addNamesForType(ArrayList<String> result, JetType jetType, JetNameValidator validator) {
|
private static void addNamesForType(ArrayList<String> result, JetType jetType, JetNameValidator validator) {
|
||||||
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
|
||||||
JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
|
JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
|
||||||
|
|||||||
@@ -35,6 +35,23 @@ public abstract class JetNameValidator {
|
|||||||
return name + i
|
return name + i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates name using set of variants which are tried in succession (and extended with suffixes if necessary)
|
||||||
|
* For example, when given sequence of a, b, c possible names are tried out in the following order: a, b, c, a1, b1, c1, a2, b2, c2, ...
|
||||||
|
* @param names to check it in scope
|
||||||
|
* @return name or nameI, where name is one of variants and I is a number
|
||||||
|
*/
|
||||||
|
public fun validateNameWithVariants(vararg names: String): String {
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
for (name in names) {
|
||||||
|
val candidate = if (i > 0) name + i else name
|
||||||
|
if (validateInner(candidate)) return candidate
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract fun validateInner(name: String): Boolean
|
protected abstract fun validateInner(name: String): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,12 +65,12 @@ public open class CollectingValidator(
|
|||||||
): JetNameValidator() {
|
): JetNameValidator() {
|
||||||
private val suggestedSet = HashSet(existingNames)
|
private val suggestedSet = HashSet(existingNames)
|
||||||
|
|
||||||
override fun validateInner(name: String): Boolean = name !in suggestedSet && filter(name)
|
override fun validateInner(name: String): Boolean {
|
||||||
|
if (name !in suggestedSet && filter(name)) {
|
||||||
override fun validateName(name: String): String {
|
suggestedSet.add(name)
|
||||||
val validatedName = super.validateName(name)
|
return true
|
||||||
suggestedSet.add(validatedName)
|
}
|
||||||
return validatedName
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// "Create function 'foo'" "true"
|
// "Create function 'foo'" "true"
|
||||||
|
|
||||||
class B<T>(val t: T) {
|
class B<T>(val t: T) {
|
||||||
fun <T1, T2> foo(arg: T1, arg1: T2): T1 {
|
fun <U, V> foo(arg: U, arg1: V): U {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// "Create function 'foo'" "true"
|
// "Create function 'foo'" "true"
|
||||||
|
|
||||||
class B<T>(val t: T) {
|
class B<T>(val t: T) {
|
||||||
fun <T1> foo(i: Int, arg: T1): Int {
|
fun <U> foo(i: Int, arg: U): Int {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
// "Create function 'foo'" "true"
|
// "Create function 'foo'" "true"
|
||||||
|
|
||||||
class B<T>(val t: T) {
|
class B<T>(val t: T) {
|
||||||
fun <T1, T2> foo(arg: T1, arg1: T2): T1 {
|
fun <U, V> foo(arg: U, arg1: V): U {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -6,6 +6,6 @@ class A<T>(val items: List<T>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <E, T, T1> List<E>.foo(arg: T, arg1: T1): T {
|
fun <E, T, U> List<E>.foo(arg: T, arg1: U): T {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
+1
-1
@@ -6,6 +6,6 @@ class A<T>(val items: List<T>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <E, T, T1> List<E>.foo(arg: T, arg1: T1): T {
|
fun <E, T, U> List<E>.foo(arg: T, arg1: U): T {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,6 +4,6 @@ fun test(): Int {
|
|||||||
return foo<String, Int>(2, "2")
|
return foo<String, Int>(2, "2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T, T1> foo(arg: T1, arg1: T): T1 {
|
fun <T, U> foo(arg: U, arg1: T): U {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,6 +4,6 @@ fun test(): Int {
|
|||||||
return foo<String, Int, Boolean>(2, "2")
|
return foo<String, Int, Boolean>(2, "2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T, T1, T2> foo(arg: T1, arg1: T): T1 {
|
fun <T, U, V> foo(arg: U, arg1: T): U {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,6 +4,6 @@ fun test(): Int {
|
|||||||
return foo<String, Int>(2, "2")
|
return foo<String, Int>(2, "2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T, T1> foo(arg: T1, arg1: T): T1 {
|
fun <T, U> foo(arg: U, arg1: T): U {
|
||||||
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user