KT-9418 Suggest name for new declaration basing on unresolved names in code
#KT-9418 Fixed
This commit is contained in:
@@ -28,6 +28,7 @@ import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.MultiRangeReference
|
||||
import com.intellij.psi.PsiElement
|
||||
@@ -44,10 +45,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
@@ -81,6 +79,12 @@ open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
|
||||
fun annotateElement(element: PsiElement, holder: AnnotationHolder, diagnostics: Diagnostics) {
|
||||
val diagnosticsForElement = diagnostics.forElement(element)
|
||||
|
||||
if (element is KtNameReferenceExpression) {
|
||||
val unresolved = diagnostics.any { it.factory == Errors.UNRESOLVED_REFERENCE }
|
||||
element.putUserData(UNRESOLVED_KEY, if (unresolved) Unit else null)
|
||||
}
|
||||
|
||||
if (diagnosticsForElement.isEmpty()) return
|
||||
|
||||
if (ProjectRootsUtil.isInProjectSource(element) || element.containingFile is KtCodeFragment) {
|
||||
@@ -98,6 +102,10 @@ open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
|
||||
fun createQuickFixes(diagnostic: Diagnostic): Collection<IntentionAction> =
|
||||
createQuickFixes(diagnostic.singletonOrEmptyList())[diagnostic]
|
||||
|
||||
private val UNRESOLVED_KEY = Key<Unit>("KotlinPsiChecker.UNRESOLVED_KEY")
|
||||
|
||||
fun wasUnresolved(element: KtNameReferenceExpression) = element.getUserData(UNRESOLVED_KEY) != null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+119
-49
@@ -46,16 +46,18 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.renderer.render
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.util.supertypesWithAny
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.util.*
|
||||
|
||||
class BasicCompletionSession(
|
||||
configuration: CompletionSessionConfiguration,
|
||||
parameters: CompletionParameters,
|
||||
toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
||||
private val toFromOriginalFileMapper: ToFromOriginalFileMapper,
|
||||
resultSet: CompletionResultSet
|
||||
) : CompletionSession(configuration, parameters, resultSet) {
|
||||
|
||||
@@ -88,14 +90,9 @@ class BasicCompletionSession(
|
||||
private fun detectCompletionKind(): CompletionKind {
|
||||
if (nameExpression == null) {
|
||||
return when {
|
||||
(position.parent as? KtParameter)?.nameIdentifier == position ->
|
||||
PARAMETER_NAME
|
||||
(position.parent as? KtNamedDeclaration)?.nameIdentifier == position -> DECLARATION_NAME
|
||||
|
||||
(position.parent as? KtClassOrObject)?.nameIdentifier == position && position.parent.parent is KtFile ->
|
||||
TOP_LEVEL_CLASS_NAME
|
||||
|
||||
else ->
|
||||
KEYWORDS_ONLY
|
||||
else -> KEYWORDS_ONLY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +155,20 @@ class BasicCompletionSession(
|
||||
}
|
||||
|
||||
override fun doComplete() {
|
||||
val declaration = isStartOfExtensionReceiverFor()
|
||||
if (declaration != null) {
|
||||
completeDeclarationNameFromUnresolved(declaration)
|
||||
|
||||
// no auto-popup on typing after "val", "var" and "fun" because it's likely the name of the declaration which is being typed by user
|
||||
if (parameters.invocationCount == 0) {
|
||||
val suppressOtherCompletion = when (declaration) {
|
||||
is KtNamedFunction -> prefixMatcher.prefix.let { it.isEmpty() || it[0].isLowerCase() /* function name usually starts with lower case letter */ }
|
||||
else -> true
|
||||
}
|
||||
if (suppressOtherCompletion) return
|
||||
}
|
||||
}
|
||||
|
||||
fun completeWithSmartCompletion(lookupElementFactory: LookupElementFactory) {
|
||||
if (smartCompletion != null) {
|
||||
val (additionalItems, @Suppress("UNUSED_VARIABLE") inheritanceSearcher) = smartCompletion.additionalItems(lookupElementFactory)
|
||||
@@ -276,6 +287,19 @@ class BasicCompletionSession(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isStartOfExtensionReceiverFor(): KtCallableDeclaration? {
|
||||
val userType = nameExpression!!.parent as? KtUserType ?: return null
|
||||
if (userType.qualifier != null) return null
|
||||
val typeRef = userType.parent as? KtTypeReference ?: return null
|
||||
if (userType != typeRef.typeElement) return null
|
||||
val parent = typeRef.parent
|
||||
return when (parent) {
|
||||
is KtNamedFunction -> parent.check { typeRef == it.receiverTypeReference }
|
||||
is KtProperty -> parent.check { typeRef == it.receiverTypeReference }
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val KEYWORDS_ONLY = object : CompletionKind {
|
||||
@@ -414,45 +438,42 @@ class BasicCompletionSession(
|
||||
}
|
||||
}
|
||||
|
||||
private val PARAMETER_NAME = object : CompletionKind {
|
||||
private val DECLARATION_NAME = object : CompletionKind {
|
||||
override val descriptorKindFilter: DescriptorKindFilter?
|
||||
get() = null
|
||||
|
||||
override fun doComplete() {
|
||||
val declaration = declaration()
|
||||
if (declaration is KtParameter && !shouldCompleteParameterNameAndType()) return // do not complete also keywords and from unresolved references in such case
|
||||
|
||||
collector.addLookupElementPostProcessor { lookupElement ->
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||
lookupElement
|
||||
}
|
||||
|
||||
KEYWORDS_ONLY.doComplete()
|
||||
|
||||
if (shouldCompleteParameterNameAndType()) {
|
||||
val parameterNameAndTypeCompletion = ParameterNameAndTypeCompletion(collector, basicLookupElementFactory, prefixMatcher, resolutionFacade)
|
||||
completeDeclarationNameFromUnresolved(declaration)
|
||||
|
||||
// if we are typing parameter name, restart completion each time we type an upper case letter because new suggestions will appear (previous words can be used as user prefix)
|
||||
val prefixPattern = StandardPatterns.string().with(object : PatternCondition<String>("Prefix ends with uppercase letter") {
|
||||
override fun accepts(prefix: String, context: ProcessingContext?) = prefix.isNotEmpty() && prefix.last().isUpperCase()
|
||||
})
|
||||
collector.restartCompletionOnPrefixChange(prefixPattern)
|
||||
when (declaration) {
|
||||
is KtParameter ->
|
||||
completeParameterNameAndType()
|
||||
|
||||
collector.addLookupElementPostProcessor { lookupElement ->
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.HIDE_LOOKUP_ON_COLON, Unit)
|
||||
lookupElement
|
||||
is KtClassOrObject -> {
|
||||
if (declaration.isTopLevel()) {
|
||||
completeTopLevelClassName()
|
||||
}
|
||||
}
|
||||
|
||||
parameterNameAndTypeCompletion.addFromParametersInFile(position, resolutionFacade, isVisibleFilterCheckAlways)
|
||||
flushToResultSet()
|
||||
|
||||
parameterNameAndTypeCompletion.addFromImportedClasses(position, bindingContext, isVisibleFilterCheckAlways)
|
||||
flushToResultSet()
|
||||
|
||||
parameterNameAndTypeCompletion.addFromAllClasses(parameters, indicesHelper(false))
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldDisableAutoPopup(): Boolean {
|
||||
if (!shouldCompleteParameterNameAndType() || TemplateManager.getInstance(project).getActiveTemplate(parameters.editor) != null) {
|
||||
return true
|
||||
}
|
||||
if (TemplateManager.getInstance(project).getActiveTemplate(parameters.editor) != null) return true
|
||||
|
||||
if (LookupCancelWatcher.getInstance(project).wasAutoPopupRecentlyCancelled(parameters.editor, position.startOffset)) {
|
||||
return true
|
||||
if (declaration() is KtParameter) {
|
||||
if (LookupCancelWatcher.getInstance(project).wasAutoPopupRecentlyCancelled(parameters.editor, position.startOffset)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -465,8 +486,41 @@ class BasicCompletionSession(
|
||||
return sorter
|
||||
}
|
||||
|
||||
private fun completeParameterNameAndType() {
|
||||
val parameterNameAndTypeCompletion = ParameterNameAndTypeCompletion(collector, basicLookupElementFactory, prefixMatcher, resolutionFacade)
|
||||
|
||||
// if we are typing parameter name, restart completion each time we type an upper case letter because new suggestions will appear (previous words can be used as user prefix)
|
||||
val prefixPattern = StandardPatterns.string().with(object : PatternCondition<String>("Prefix ends with uppercase letter") {
|
||||
override fun accepts(prefix: String, context: ProcessingContext?) = prefix.isNotEmpty() && prefix.last().isUpperCase()
|
||||
})
|
||||
collector.restartCompletionOnPrefixChange(prefixPattern)
|
||||
|
||||
collector.addLookupElementPostProcessor { lookupElement ->
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.HIDE_LOOKUP_ON_COLON, Unit)
|
||||
lookupElement
|
||||
}
|
||||
|
||||
parameterNameAndTypeCompletion.addFromParametersInFile(position, resolutionFacade, isVisibleFilterCheckAlways)
|
||||
flushToResultSet()
|
||||
|
||||
parameterNameAndTypeCompletion.addFromImportedClasses(position, bindingContext, isVisibleFilterCheckAlways)
|
||||
flushToResultSet()
|
||||
|
||||
parameterNameAndTypeCompletion.addFromAllClasses(parameters, indicesHelper(false))
|
||||
}
|
||||
|
||||
private fun completeTopLevelClassName() {
|
||||
val name = parameters.originalFile.virtualFile.nameWithoutExtension
|
||||
if (!(Name.isValidIdentifier(name) && Name.identifier(name).render() == name && name[0].isUpperCase())) return
|
||||
if ((parameters.originalFile as KtFile).declarations.any { it is KtClassOrObject && it.name == name }) return
|
||||
|
||||
collector.addElement(LookupElementBuilder.create(name))
|
||||
}
|
||||
|
||||
private fun declaration() = position.parent as KtNamedDeclaration
|
||||
|
||||
private fun shouldCompleteParameterNameAndType(): Boolean {
|
||||
val parameter = position.getNonStrictParentOfType<KtParameter>()!!
|
||||
val parameter = declaration() as? KtParameter ?: return false
|
||||
val list = parameter.parent as? KtParameterList ?: return false
|
||||
val owner = list.parent
|
||||
return when (owner) {
|
||||
@@ -478,21 +532,6 @@ class BasicCompletionSession(
|
||||
}
|
||||
}
|
||||
|
||||
private val TOP_LEVEL_CLASS_NAME = object : CompletionKind {
|
||||
override val descriptorKindFilter: DescriptorKindFilter?
|
||||
get() = null
|
||||
|
||||
override fun doComplete() {
|
||||
val name = parameters.originalFile.virtualFile.nameWithoutExtension
|
||||
if (!(Name.isValidIdentifier(name) && Name.identifier(name).render() == name && name[0].isUpperCase())) return
|
||||
if ((parameters.originalFile as KtFile).declarations.any { it is KtClassOrObject && it.name == name }) return
|
||||
|
||||
val lookupElement = LookupElementBuilder.create(name)
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||
collector.addElement(lookupElement)
|
||||
}
|
||||
}
|
||||
|
||||
private val SUPER_QUALIFIER = object : CompletionKind {
|
||||
override val descriptorKindFilter: DescriptorKindFilter?
|
||||
get() = DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS
|
||||
@@ -513,4 +552,35 @@ class BasicCompletionSession(
|
||||
.forEach { collector.addElement(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun completeDeclarationNameFromUnresolved(declaration: KtNamedDeclaration) {
|
||||
val referenceScope = referenceScope(declaration) ?: return
|
||||
val originalScope = toFromOriginalFileMapper.toOriginalFile(referenceScope) ?: return
|
||||
val afterOffset = if (referenceScope is KtBlockExpression) parameters.offset else null
|
||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration]
|
||||
FromUnresolvedNamesCompletion(collector, prefixMatcher).addNameSuggestions(originalScope, afterOffset, descriptor)
|
||||
}
|
||||
|
||||
private fun referenceScope(declaration: KtNamedDeclaration): KtElement? {
|
||||
val parent = declaration.parent
|
||||
when (parent) {
|
||||
is KtParameterList -> return parent.parent as KtElement
|
||||
|
||||
is KtClassBody -> {
|
||||
val classOrObject = parent.parent as KtClassOrObject
|
||||
if (classOrObject is KtObjectDeclaration && classOrObject.isCompanion()) {
|
||||
return classOrObject.containingClassOrObject
|
||||
}
|
||||
else {
|
||||
return classOrObject
|
||||
}
|
||||
}
|
||||
|
||||
is KtFile -> return parent
|
||||
|
||||
is KtBlockExpression -> return parent
|
||||
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@ tailrec fun <T : Any> LookupElement.getUserDataDeep(key: Key<T>): T? {
|
||||
|
||||
enum class ItemPriority {
|
||||
SUPER_METHOD_WITH_ARGUMENTS,
|
||||
FROM_UNRESOLVED_NAME_SUGGESTION,
|
||||
DEFAULT,
|
||||
IMPLEMENT,
|
||||
OVERRIDE,
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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.idea.completion
|
||||
|
||||
import com.intellij.codeInsight.completion.PrefixMatcher
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinPsiChecker
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import java.util.*
|
||||
|
||||
class FromUnresolvedNamesCompletion(
|
||||
private val collector: LookupElementsCollector,
|
||||
private val prefixMatcher: PrefixMatcher
|
||||
) {
|
||||
fun addNameSuggestions(scope: KtElement, afterOffset: Int?, sampleDescriptor: DeclarationDescriptor?) {
|
||||
val names = HashSet<String>()
|
||||
scope.forEachDescendantOfType<KtNameReferenceExpression> { refExpr ->
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (KotlinPsiChecker.wasUnresolved(refExpr)) {
|
||||
val callTypeAndReceiver = CallTypeAndReceiver.detect(refExpr)
|
||||
if (callTypeAndReceiver.receiver != null) return@forEachDescendantOfType
|
||||
if (sampleDescriptor != null) {
|
||||
if (!callTypeAndReceiver.callType.descriptorKindFilter.accepts(sampleDescriptor)) return@forEachDescendantOfType
|
||||
|
||||
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||
val isCall = refExpr.parent is KtCallExpression
|
||||
val canBeUsage = when (sampleDescriptor) {
|
||||
is FunctionDescriptor -> isCall // cannot use simply function name without arguments
|
||||
is VariableDescriptor -> true // variable can as well be used with arguments when it has invoke()
|
||||
is ClassDescriptor -> if (isCall) sampleDescriptor.kind == ClassKind.CLASS else sampleDescriptor.kind.isSingleton
|
||||
else -> false // what else it can be?
|
||||
}
|
||||
if (!canBeUsage) return@forEachDescendantOfType
|
||||
}
|
||||
}
|
||||
|
||||
val name = refExpr.getReferencedName()
|
||||
if (!prefixMatcher.prefixMatches(name)) return@forEachDescendantOfType
|
||||
|
||||
if (afterOffset != null && refExpr.startOffset < afterOffset) return@forEachDescendantOfType
|
||||
|
||||
if (refExpr.mainReference.resolveToDescriptors(refExpr.analyze(BodyResolveMode.PARTIAL)).isEmpty()) {
|
||||
names.add(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (name in names.sorted()) {
|
||||
val lookupElement = LookupElementBuilder.create(name)
|
||||
.suppressAutoInsertion()
|
||||
.assignPriority(ItemPriority.FROM_UNRESOLVED_NAME_SUGGESTION)
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||
collector.addElement(lookupElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
-25
@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
var KtFile.doNotComplete: Boolean? by UserDataProperty(Key.create("DO_NOT_COMPLETE"))
|
||||
@@ -365,33 +364,9 @@ class KotlinCompletionContributor : CompletionContributor() {
|
||||
// no completion auto-popup after integer and dot
|
||||
if (invocationCount == 0 && prefixMatcher.prefix.isEmpty() && AFTER_INTEGER_LITERAL_AND_DOT.accepts(position)) return true
|
||||
|
||||
// no auto-popup on typing after "val", "var" and "fun" because it's likely the name of the declaration which is being typed by user
|
||||
if (invocationCount == 0) {
|
||||
val callable = isInExtensionReceiverOf(position)
|
||||
if (callable != null) {
|
||||
return when (callable) {
|
||||
is KtNamedFunction -> prefixMatcher.prefix.let { it.isEmpty() || it[0].isLowerCase() /* function name usually starts with lower case letter */ }
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun isInExtensionReceiverOf(position: PsiElement): KtCallableDeclaration? {
|
||||
val nameRef = position.parent as? KtNameReferenceExpression ?: return null
|
||||
val userType = nameRef.parent as? KtUserType ?: return null
|
||||
val typeRef = userType.parent as? KtTypeReference ?: return null
|
||||
if (userType != typeRef.typeElement) return null
|
||||
val parent = typeRef.parent
|
||||
return when (parent) {
|
||||
is KtNamedFunction -> parent.check { typeRef == it.receiverTypeReference }
|
||||
is KtProperty -> parent.check { typeRef == it.receiverTypeReference }
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAtEndOfLine(offset: Int, document: Document): Boolean {
|
||||
var i = offset
|
||||
val chars = document.charsSequence
|
||||
|
||||
+10
-10
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.completion
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
class ToFromOriginalFileMapper(
|
||||
@@ -63,15 +63,15 @@ class ToFromOriginalFileMapper(
|
||||
}
|
||||
}
|
||||
|
||||
fun toOriginalFile(declaration: KtDeclaration): KtDeclaration? {
|
||||
if (declaration.containingFile != syntheticFile) return declaration
|
||||
val offset = toOriginalFile(declaration.startOffset) ?: return null
|
||||
return PsiTreeUtil.findElementOfClassAtOffset(originalFile, offset, KtDeclaration::class.java, true)
|
||||
fun <TElement : PsiElement> toOriginalFile(element: TElement): TElement? {
|
||||
if (element.containingFile != syntheticFile) return element
|
||||
val offset = toOriginalFile(element.startOffset) ?: return null
|
||||
return PsiTreeUtil.findElementOfClassAtOffset(originalFile, offset, element.javaClass, true)
|
||||
}
|
||||
|
||||
fun toSyntheticFile(declaration: KtDeclaration): KtDeclaration? {
|
||||
if (declaration.containingFile != originalFile) return declaration
|
||||
val offset = toSyntheticFile(declaration.startOffset) ?: return null
|
||||
return PsiTreeUtil.findElementOfClassAtOffset(syntheticFile, offset, KtDeclaration::class.java, true)
|
||||
fun <TElement : PsiElement> toSyntheticFile(element: TElement): TElement? {
|
||||
if (element.containingFile != originalFile) return element
|
||||
val offset = toSyntheticFile(element.startOffset) ?: return null
|
||||
return PsiTreeUtil.findElementOfClassAtOffset(syntheticFile, offset, element.javaClass, true)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -264,6 +264,8 @@ class TypeInstantiationItems(
|
||||
other.renderElement(presentation2)
|
||||
return presentation1.itemText == presentation2.itemText && presentation1.tailText == presentation2.tailText
|
||||
}
|
||||
|
||||
override fun hashCode() = lookupString.hashCode()
|
||||
}
|
||||
|
||||
return InstantiationLookupElement(lookupElement).addTail(tail)
|
||||
@@ -307,7 +309,7 @@ class TypeInstantiationItems(
|
||||
for (inheritor in ClassInheritorsSearch.search(parameters)) {
|
||||
val descriptor = inheritor.resolveToDescriptor(
|
||||
resolutionFacade,
|
||||
{ toFromOriginalFileMapper.toSyntheticFile(it) as KtClassOrObject? }
|
||||
{ toFromOriginalFileMapper.toSyntheticFile(it) }
|
||||
) ?: continue
|
||||
if (!visibilityFilter(descriptor)) continue
|
||||
|
||||
|
||||
+2
-1
@@ -5,4 +5,5 @@ class Outer {
|
||||
fun Outer.<caret>
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// NUMBER: 0
|
||||
// EXIST: Nested
|
||||
// NOTHING_ELSE
|
||||
+2
-1
@@ -5,4 +5,5 @@ class Outer {
|
||||
fun <T> Outer.<caret>
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// NUMBER: 0
|
||||
// EXIST: Nested
|
||||
// NOTHING_ELSE
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
class C {
|
||||
fun foo(p: Int) {
|
||||
unresolvedInFoo1()
|
||||
if (p > 0) {
|
||||
unresolvedInFoo2()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun <caret>
|
||||
|
||||
fun bar() {
|
||||
unresolvedInBar()
|
||||
}
|
||||
}
|
||||
|
||||
fun zoo() {
|
||||
unresolvedInZoo()
|
||||
}
|
||||
}
|
||||
|
||||
fun f() {
|
||||
unresolvedOutside()
|
||||
}
|
||||
|
||||
// EXIST: unresolvedInFoo1
|
||||
// EXIST: unresolvedInFoo2
|
||||
// EXIST: unresolvedInBar
|
||||
// EXIST: unresolvedInZoo
|
||||
// ABSENT: unresolvedOutside
|
||||
@@ -0,0 +1,32 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: Int) {
|
||||
print(unresolved0)
|
||||
|
||||
if (p > 0) {
|
||||
print(unresolved1)
|
||||
|
||||
val u<caret>
|
||||
|
||||
print(unresolved2)
|
||||
if (p > 0) {
|
||||
print(unresolved3)
|
||||
}
|
||||
|
||||
unresolvedCall()
|
||||
}
|
||||
|
||||
print(unresolved4)
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
print(unresolvedInBar)
|
||||
}
|
||||
|
||||
// ABSENT: unresolved0
|
||||
// ABSENT: unresolved1
|
||||
// EXIST: unresolved2
|
||||
// EXIST: unresolved3
|
||||
// ABSENT: unresolved4
|
||||
// ABSENT: unresolvedInBar
|
||||
// EXIST: unresolvedCall
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
class C {
|
||||
fun foo(p: Int) {
|
||||
unresolvedInFoo1()
|
||||
if (p > 0) {
|
||||
unresolvedInFoo2()
|
||||
}
|
||||
}
|
||||
|
||||
fun <caret>
|
||||
|
||||
fun bar(s: String) {
|
||||
unresolvedInBar()
|
||||
s.unresolvedWithReceiver()
|
||||
}
|
||||
}
|
||||
|
||||
fun f() {
|
||||
unresolvedOutside()
|
||||
}
|
||||
|
||||
// EXIST: unresolvedInFoo1
|
||||
// EXIST: unresolvedInFoo2
|
||||
// EXIST: unresolvedInBar
|
||||
// ABSENT: unresolvedWithReceiver
|
||||
// ABSENT: unresolvedOutside
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
class C {
|
||||
fun foo(p: Int) {
|
||||
print(unresolvedInFoo)
|
||||
}
|
||||
|
||||
val <caret>
|
||||
|
||||
fun bar(s: String, x: UnresolvedType) {
|
||||
print(unresolvedInBar)
|
||||
print(s.unresolvedWithReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
fun f() {
|
||||
print(unresolvedOutside)
|
||||
}
|
||||
|
||||
// EXIST: unresolvedInFoo
|
||||
// EXIST: unresolvedInBar
|
||||
// ABSENT: unresolvedWithReceiver
|
||||
// ABSENT: unresolvedOutside
|
||||
// ABSENT: UnresolvedType
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo() {
|
||||
unresolvedInFoo()
|
||||
}
|
||||
|
||||
fun String.<caret>
|
||||
|
||||
// ABSENT: unresolvedInFoo
|
||||
@@ -0,0 +1,16 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: Int, <caret>) {
|
||||
print(unresolvedInFoo1)
|
||||
if (p > 0) {
|
||||
print(unresolvedInFoo2)
|
||||
}
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
print(unresolvedInBar)
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "unresolvedInFoo1", itemText: "unresolvedInFoo1" }
|
||||
// EXIST: { lookupString: "unresolvedInFoo2", itemText: "unresolvedInFoo2" }
|
||||
// ABSENT: unresolvedInBar
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: UnresolvedClass1) {
|
||||
val foo = UnresolvedClass2()
|
||||
val bar = unresolvedValue
|
||||
}
|
||||
|
||||
class <caret>
|
||||
|
||||
// EXIST: TopLevelClass
|
||||
// EXIST: UnresolvedClass1
|
||||
// EXIST: UnresolvedClass2
|
||||
// ABSENT: unresolvedValue
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: Int, x: UnresolvedClassName) {
|
||||
unresolvedInFoo1()
|
||||
if (p > 0) {
|
||||
unresolvedInFoo2()
|
||||
}
|
||||
}
|
||||
|
||||
fun <caret>
|
||||
|
||||
fun bar() {
|
||||
unresolvedInBar()
|
||||
val v = unresolvedValue
|
||||
listOf(1).filter(::unresolvedFunctionRef)
|
||||
}
|
||||
|
||||
class C {
|
||||
fun f() {
|
||||
unresolvedInClass()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// EXIST: unresolvedInFoo1
|
||||
// EXIST: unresolvedInFoo2
|
||||
// EXIST: unresolvedInBar
|
||||
// EXIST: unresolvedInClass
|
||||
// ABSENT: UnresolvedClassName
|
||||
// ABSENT: unresolvedValue
|
||||
// EXIST: unresolvedFunctionRef
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: UnresolvedClass1) {
|
||||
val foo = UnresolvedClass2()
|
||||
val bar = unresolvedValue
|
||||
}
|
||||
|
||||
interface <caret>
|
||||
|
||||
// EXIST: TopLevelInterface
|
||||
// EXIST: UnresolvedClass1
|
||||
// ABSENT: UnresolvedClass2
|
||||
// ABSENT: unresolvedValue
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// RUN_HIGHLIGHTING_BEFORE
|
||||
|
||||
fun foo(p: UnresolvedClass1) {
|
||||
val foo = UnresolvedClass2()
|
||||
val bar = unresolvedValue
|
||||
}
|
||||
|
||||
object <caret>
|
||||
|
||||
// EXIST: TopLevelObject
|
||||
// EXIST: UnresolvedClass1
|
||||
// ABSENT: UnresolvedClass2
|
||||
// EXIST: unresolvedValue
|
||||
+7
-1
@@ -108,6 +108,7 @@ object ExpectedCompletionUtils {
|
||||
private val NUMBER_JAVA_LINE_PREFIX = "NUMBER_JAVA:"
|
||||
|
||||
private val NOTHING_ELSE_PREFIX = "NOTHING_ELSE"
|
||||
private val RUN_HIGHLIGHTING_BEFORE_PREFIX = "RUN_HIGHLIGHTING_BEFORE"
|
||||
|
||||
private val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:"
|
||||
private val WITH_ORDER_PREFIX = "WITH_ORDER"
|
||||
@@ -131,6 +132,7 @@ object ExpectedCompletionUtils {
|
||||
WITH_ORDER_PREFIX,
|
||||
AUTOCOMPLETE_SETTING_PREFIX,
|
||||
NOTHING_ELSE_PREFIX,
|
||||
RUN_HIGHLIGHTING_BEFORE_PREFIX,
|
||||
RUNTIME_TYPE,
|
||||
COMPLETION_TYPE_PREFIX,
|
||||
LightClassComputationControl.LIGHT_CLASS_DIRECTIVE,
|
||||
@@ -190,7 +192,11 @@ object ExpectedCompletionUtils {
|
||||
}
|
||||
|
||||
fun isNothingElseExpected(fileText: String): Boolean {
|
||||
return !InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, NOTHING_ELSE_PREFIX).isEmpty()
|
||||
return InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, NOTHING_ELSE_PREFIX).isNotEmpty()
|
||||
}
|
||||
|
||||
fun shouldRunHighlightingBeforeCompletion(fileText: String): Boolean {
|
||||
return InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, RUN_HIGHLIGHTING_BEFORE_PREFIX).isNotEmpty()
|
||||
}
|
||||
|
||||
fun getInvocationCount(fileText: String): Int? {
|
||||
|
||||
+81
-12
@@ -990,6 +990,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InExtFunName.kt")
|
||||
public void testInExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/InExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InGenericExtFunName.kt")
|
||||
public void testInGenericExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/InGenericExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutoPopupAfterNumberLiteral.kt")
|
||||
public void testNoAutoPopupAfterNumberLiteral() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutoPopupAfterNumberLiteral.kt");
|
||||
@@ -1002,24 +1014,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInExtFunName.kt")
|
||||
public void testNoAutopopupInExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInFunName.kt")
|
||||
public void testNoAutopopupInFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInGenericExtFunName.kt")
|
||||
public void testNoAutopopupInGenericExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInGenericExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInGenericFunName.kt")
|
||||
public void testNoAutopopupInGenericFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInGenericFunName.kt");
|
||||
@@ -1438,6 +1438,75 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FromUnresolvedNames extends AbstractJSBasicCompletionTest {
|
||||
public void testAllFilesPresentInFromUnresolvedNames() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/fromUnresolvedNames"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInCompanionObject.kt")
|
||||
public void testFunctionInCompanionObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/FunctionInCompanionObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LocalVal.kt")
|
||||
public void testLocalVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/LocalVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MemberFunction.kt")
|
||||
public void testMemberFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/MemberFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MemberProperty.kt")
|
||||
public void testMemberProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/MemberProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NotForExtensionFunction.kt")
|
||||
public void testNotForExtensionFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/NotForExtensionFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Parameter.kt")
|
||||
public void testParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/Parameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelClass.kt")
|
||||
public void testTopLevelClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunction.kt")
|
||||
public void testTopLevelFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelInterface.kt")
|
||||
public void testTopLevelInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelInterface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelObject.kt")
|
||||
public void testTopLevelObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+81
-12
@@ -990,6 +990,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InExtFunName.kt")
|
||||
public void testInExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/InExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InGenericExtFunName.kt")
|
||||
public void testInGenericExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/InGenericExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutoPopupAfterNumberLiteral.kt")
|
||||
public void testNoAutoPopupAfterNumberLiteral() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutoPopupAfterNumberLiteral.kt");
|
||||
@@ -1002,24 +1014,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInExtFunName.kt")
|
||||
public void testNoAutopopupInExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInFunName.kt")
|
||||
public void testNoAutopopupInFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInGenericExtFunName.kt")
|
||||
public void testNoAutopopupInGenericExtFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInGenericExtFunName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NoAutopopupInGenericFunName.kt")
|
||||
public void testNoAutopopupInGenericFunName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/autoPopup/NoAutopopupInGenericFunName.kt");
|
||||
@@ -1438,6 +1438,75 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FromUnresolvedNames extends AbstractJvmBasicCompletionTest {
|
||||
public void testAllFilesPresentInFromUnresolvedNames() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/fromUnresolvedNames"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionInCompanionObject.kt")
|
||||
public void testFunctionInCompanionObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/FunctionInCompanionObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LocalVal.kt")
|
||||
public void testLocalVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/LocalVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MemberFunction.kt")
|
||||
public void testMemberFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/MemberFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MemberProperty.kt")
|
||||
public void testMemberProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/MemberProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NotForExtensionFunction.kt")
|
||||
public void testNotForExtensionFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/NotForExtensionFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Parameter.kt")
|
||||
public void testParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/Parameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelClass.kt")
|
||||
public void testTopLevelClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelFunction.kt")
|
||||
public void testTopLevelFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelInterface.kt")
|
||||
public void testTopLevelInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelInterface.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelObject.kt")
|
||||
public void testTopLevelObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/fromUnresolvedNames/TopLevelObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+5
@@ -37,6 +37,11 @@ abstract class KotlinFixtureCompletionBaseTestCase : KotlinLightCodeInsightFixtu
|
||||
setUpFixture(testPath)
|
||||
|
||||
val fileText = FileUtil.loadFile(File(testPath), true)
|
||||
|
||||
if (ExpectedCompletionUtils.shouldRunHighlightingBeforeCompletion(fileText)) {
|
||||
myFixture.doHighlighting()
|
||||
}
|
||||
|
||||
testCompletion(fileText, getPlatform(), { completionType, count -> complete(completionType, count) }, defaultCompletionType(), defaultInvocationCount())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user