More simple prefix matching in ParameterNameAndTypeCompletion

This commit is contained in:
Valentin Kipyatkov
2015-10-08 19:54:12 +03:00
parent 9b4070b881
commit aa0a68b4be
@@ -49,38 +49,36 @@ import java.util.*
class ParameterNameAndTypeCompletion( class ParameterNameAndTypeCompletion(
private val collector: LookupElementsCollector, private val collector: LookupElementsCollector,
private val lookupElementFactory: LookupElementFactory, private val lookupElementFactory: LookupElementFactory,
defaultPrefixMatcher: PrefixMatcher, private val prefixMatcher: PrefixMatcher,
private val resolutionFacade: ResolutionFacade private val resolutionFacade: ResolutionFacade
) { ) {
private val modifiedPrefixMatcher = MyPrefixMatcher(defaultPrefixMatcher.prefix) private val userPrefixes: List<String>
private val classNamePrefixMatchers: List<PrefixMatcher>
private val prefixWords: Array<String>
private val nameSuggestionPrefixes: List<String> // prefixes to use to generate parameter names from class names
init { init {
val prefix = defaultPrefixMatcher.getPrefix() val prefix = prefixMatcher.prefix
prefixWords = NameUtil.splitNameIntoWords(prefix) val prefixWords = NameUtil.splitNameIntoWords(prefix)
nameSuggestionPrefixes = if (prefix.isEmpty() || prefix[0].isUpperCase()) // prefixes to use to generate parameter names from class names
val nameSuggestionPrefixes = if (prefix.isEmpty() || prefix[0].isUpperCase())
emptyList() emptyList()
else else
prefixWords.indices.map { index -> if (index == 0) prefix else prefixWords.drop(index).join("") } prefixWords.indices.map { index -> if (index == 0) prefix else prefixWords.drop(index).join("") }
userPrefixes = nameSuggestionPrefixes.indices.map { prefixWords.take(it).join("") }
classNamePrefixMatchers = nameSuggestionPrefixes.map { CamelHumpMatcher(it.capitalize(), false) }
} }
private val nameSuggestionPrefixMatchers = nameSuggestionPrefixes.map { MyPrefixMatcher(it) }
private val userPrefixes = nameSuggestionPrefixes.indices.map { prefixWords.take(it).join("") }
private val suggestionsByTypesAdded = HashSet<Type>() private val suggestionsByTypesAdded = HashSet<Type>()
public fun addFromImportedClasses(position: PsiElement, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) { public fun addFromImportedClasses(position: PsiElement, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
for ((prefixMatcher, userPrefix) in nameSuggestionPrefixMatchers.zip(userPrefixes)) { for ((classNameMatcher, userPrefix) in classNamePrefixMatchers.zip(userPrefixes)) {
val resolutionScope = position.getResolutionScope(bindingContext, resolutionFacade) val resolutionScope = position.getResolutionScope(bindingContext, resolutionFacade)
val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, prefixMatcher.toClassifierNamePrefixMatcher().asNameFilter()) val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, classNameMatcher.asNameFilter())
for (classifier in classifiers) { for (classifier in classifiers) {
if (visibilityFilter(classifier)) { if (visibilityFilter(classifier)) {
addSuggestionsForClassifier(classifier, userPrefix, prefixMatcher, notImported = false) addSuggestionsForClassifier(classifier, userPrefix, notImported = false)
} }
} }
@@ -89,20 +87,18 @@ class ParameterNameAndTypeCompletion(
} }
public fun addFromAllClasses(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) { public fun addFromAllClasses(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) {
for ((prefixMatcher, userPrefix) in nameSuggestionPrefixMatchers.zip(userPrefixes)) { for ((classNameMatcher, userPrefix) in classNamePrefixMatchers.zip(userPrefixes)) {
AllClassesCompletion( AllClassesCompletion(
parameters, indicesHelper, prefixMatcher.toClassifierNamePrefixMatcher(), resolutionFacade, { !it.isSingleton() } parameters, indicesHelper, classNameMatcher, resolutionFacade, { !it.isSingleton() }
).collect( ).collect(
{ addSuggestionsForClassifier(it, userPrefix, prefixMatcher, notImported = true) }, { addSuggestionsForClassifier(it, userPrefix, notImported = true) },
{ addSuggestionsForJavaClass(it, userPrefix, prefixMatcher, notImported = true) } { addSuggestionsForJavaClass(it, userPrefix, notImported = true) }
) )
collector.flushToResultSet() collector.flushToResultSet()
} }
} }
private fun PrefixMatcher.toClassifierNamePrefixMatcher() = cloneWithPrefix(getPrefix().capitalize())
public fun addFromParametersInFile(position: PsiElement, resolutionFacade: ResolutionFacade, visibilityFilter: (DeclarationDescriptor) -> Boolean) { public fun addFromParametersInFile(position: PsiElement, resolutionFacade: ResolutionFacade, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
val lookupElementToCount = LinkedHashMap<LookupElement, Int>() val lookupElementToCount = LinkedHashMap<LookupElement, Int>()
position.getContainingFile().forEachDescendantOfType<JetParameter>( position.getContainingFile().forEachDescendantOfType<JetParameter>(
@@ -111,7 +107,7 @@ class ParameterNameAndTypeCompletion(
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
val name = parameter.getName() val name = parameter.getName()
if (name != null && modifiedPrefixMatcher.prefixMatches(name)) { if (name != null && prefixMatcher.isStartMatch(name)) {
val descriptor = resolutionFacade.analyze(parameter)[BindingContext.VALUE_PARAMETER, parameter] val descriptor = resolutionFacade.analyze(parameter)[BindingContext.VALUE_PARAMETER, parameter]
if (descriptor != null) { if (descriptor != null) {
val parameterType = descriptor.getType() val parameterType = descriptor.getType()
@@ -126,29 +122,30 @@ class ParameterNameAndTypeCompletion(
for ((lookupElement, count) in lookupElementToCount) { for ((lookupElement, count) in lookupElementToCount) {
lookupElement.putUserData(PRIORITY_KEY, -count) lookupElement.putUserData(PRIORITY_KEY, -count)
collector.addElement(lookupElement, modifiedPrefixMatcher) collector.addElement(lookupElement)
} }
} }
private fun addSuggestionsForClassifier(classifier: DeclarationDescriptor, userPrefix: String, prefixMatcher: PrefixMatcher, notImported: Boolean) { private fun addSuggestionsForClassifier(classifier: DeclarationDescriptor, userPrefix: String, notImported: Boolean) {
addSuggestions(classifier.getName().asString(), userPrefix, prefixMatcher, DescriptorType(classifier as ClassifierDescriptor), notImported) addSuggestions(classifier.getName().asString(), userPrefix, DescriptorType(classifier as ClassifierDescriptor), notImported)
} }
private fun addSuggestionsForJavaClass(psiClass: PsiClass, userPrefix: String, prefixMatcher: PrefixMatcher, notImported: Boolean) { private fun addSuggestionsForJavaClass(psiClass: PsiClass, userPrefix: String, notImported: Boolean) {
addSuggestions(psiClass.getName()!!, userPrefix, prefixMatcher, JavaClassType(psiClass), notImported) addSuggestions(psiClass.getName()!!, userPrefix, JavaClassType(psiClass), notImported)
} }
private fun addSuggestions(className: String, userPrefix: String, prefixMatcher: PrefixMatcher, type: Type, notImported: Boolean) { private fun addSuggestions(className: String, userPrefix: String, type: Type, notImported: Boolean) {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
if (suggestionsByTypesAdded.contains(type)) return // don't add suggestions for the same with longer user prefix if (suggestionsByTypesAdded.contains(type)) return // don't add suggestions for the same with longer user prefix
val nameSuggestions = KotlinNameSuggester.getCamelNames(className, { true }, userPrefix.isEmpty()) val nameSuggestions = KotlinNameSuggester.getCamelNames(className, { true }, userPrefix.isEmpty())
for (name in nameSuggestions) { for (name in nameSuggestions) {
if (prefixMatcher.prefixMatches(name)) { val parameterName = userPrefix + name
val lookupElement = MyLookupElement.create(userPrefix + name, type, lookupElementFactory) if (prefixMatcher.isStartMatch(parameterName)) {
val lookupElement = MyLookupElement.create(parameterName, type, lookupElementFactory)
if (lookupElement != null) { if (lookupElement != null) {
lookupElement.putUserData(PRIORITY_KEY, userPrefix.length()) // suggestions with longer user prefix get lower priority lookupElement.putUserData(PRIORITY_KEY, userPrefix.length()) // suggestions with longer user prefix get lower priority
collector.addElement(lookupElement, modifiedPrefixMatcher, notImported = notImported) collector.addElement(lookupElement, notImported = notImported)
suggestionsByTypesAdded.add(type) suggestionsByTypesAdded.add(type)
} }
} }
@@ -208,7 +205,7 @@ class ParameterNameAndTypeCompletion(
} }
override fun handleInsert(context: InsertionContext) { override fun handleInsert(context: InsertionContext) {
val settings = CodeStyleSettingsManager.getInstance(context.getProject()).getCurrentSettings().getCustomSettings(javaClass<JetCodeStyleSettings>()) val settings = CodeStyleSettingsManager.getInstance(context.getProject()).getCurrentSettings().getCustomSettings(JetCodeStyleSettings::class.java)
val spaceBefore = if (settings.SPACE_BEFORE_TYPE_COLON) " " else "" val spaceBefore = if (settings.SPACE_BEFORE_TYPE_COLON) " " else ""
val spaceAfter = if (settings.SPACE_AFTER_TYPE_COLON) " " else "" val spaceAfter = if (settings.SPACE_AFTER_TYPE_COLON) " " else ""
val text = parameterName + spaceBefore + ":" + spaceAfter val text = parameterName + spaceBefore + ":" + spaceAfter
@@ -233,10 +230,4 @@ class ParameterNameAndTypeCompletion(
object Weigher : LookupElementWeigher("kotlin.parameterNameAndTypePriority") { object Weigher : LookupElementWeigher("kotlin.parameterNameAndTypePriority") {
override fun weigh(element: LookupElement, context: WeighingContext): Int = element.getUserData(PRIORITY_KEY) ?: 0 override fun weigh(element: LookupElement, context: WeighingContext): Int = element.getUserData(PRIORITY_KEY) ?: 0
} }
private class MyPrefixMatcher(prefix: String) : CamelHumpMatcher(prefix, false) {
override fun prefixMatches(element: LookupElement) = isStartMatch(element)
override fun cloneWithPrefix(prefix: String) = MyPrefixMatcher(prefix)
}
} }