Provide incremental analysis of a file when it is applicable
#KT32868 Fixed
This commit is contained in:
+1
-1
@@ -107,7 +107,7 @@ class CompletionBindingContextProvider(project: Project) {
|
||||
val inStatement = position.findStatementInBlock()
|
||||
val block = inStatement?.parent as KtBlockExpression?
|
||||
val prevStatement = inStatement?.siblings(forward = false, withItself = false)?.firstIsInstanceOrNull<KtExpression>()
|
||||
val modificationScope = inStatement?.let { KotlinCodeBlockModificationListener.getInsideCodeBlockModificationScope(it) }
|
||||
val modificationScope = inStatement?.let { KotlinCodeBlockModificationListener.getInsideCodeBlockModificationScope(it)?.element }
|
||||
|
||||
val psiElementsBeforeAndAfter = modificationScope?.let { collectPsiElementsBeforeAndAfter(modificationScope, inStatement) }
|
||||
|
||||
|
||||
+13
-14
@@ -19,13 +19,16 @@ import org.jetbrains.kotlin.utils.addToStdlib.indexOfOrNull
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractCompletionHandlerTest(private val defaultCompletionType: CompletionType) : CompletionHandlerTestBase() {
|
||||
private val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:"
|
||||
private val LOOKUP_STRING_PREFIX = "ELEMENT:"
|
||||
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
|
||||
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
|
||||
private val COMPLETION_CHAR_PREFIX = "CHAR:"
|
||||
private val COMPLETION_CHARS_PREFIX = "CHARS:"
|
||||
private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
|
||||
|
||||
companion object {
|
||||
val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:"
|
||||
val LOOKUP_STRING_PREFIX = "ELEMENT:"
|
||||
val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
|
||||
val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
|
||||
val COMPLETION_CHAR_PREFIX = "CHAR:"
|
||||
val COMPLETION_CHARS_PREFIX = "CHARS:"
|
||||
val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:"
|
||||
}
|
||||
|
||||
protected open fun doTest(testPath: String) {
|
||||
setUpFixture(fileName())
|
||||
@@ -42,11 +45,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
|
||||
val lookupString = InTextDirectivesUtils.findStringWithPrefixes(fileText, LOOKUP_STRING_PREFIX)
|
||||
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
|
||||
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
|
||||
|
||||
val completionChars = completionChars(
|
||||
char = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX),
|
||||
chars = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHARS_PREFIX)
|
||||
)
|
||||
val completionChars = completionChars(fileText)
|
||||
|
||||
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
|
||||
|
||||
@@ -58,8 +57,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
|
||||
val settingValue = line.substring(index + 1).trim()
|
||||
val (field, settings) = try {
|
||||
kotlinStyleSettings::class.java.getField(settingName) to kotlinStyleSettings
|
||||
}
|
||||
catch (e: NoSuchFieldException) {
|
||||
} catch (e: NoSuchFieldException) {
|
||||
commonStyleSettings::class.java.getField(settingName) to commonStyleSettings
|
||||
}
|
||||
when (field.type.name) {
|
||||
@@ -70,6 +68,7 @@ abstract class AbstractCompletionHandlerTest(private val defaultCompletionType:
|
||||
}
|
||||
|
||||
doTestWithTextLoaded(
|
||||
myFixture,
|
||||
completionType,
|
||||
invocationCount,
|
||||
lookupString,
|
||||
|
||||
+10
-1
@@ -31,7 +31,16 @@ class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
||||
|
||||
private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
|
||||
fixture.configureByFile(fileName())
|
||||
doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar.toString(), fileName() + ".after")
|
||||
doTestWithTextLoaded(
|
||||
myFixture,
|
||||
CompletionType.BASIC,
|
||||
time,
|
||||
lookupString,
|
||||
itemText,
|
||||
tailText,
|
||||
completionChar.toString(),
|
||||
fileName() + ".after"
|
||||
)
|
||||
}
|
||||
|
||||
fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n')
|
||||
|
||||
+98
-79
@@ -11,114 +11,133 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
import com.intellij.codeInsight.lookup.LookupEvent
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import org.jetbrains.kotlin.idea.completion.test.ExpectedCompletionUtils
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
|
||||
abstract class CompletionHandlerTestBase : KotlinLightCodeInsightFixtureTestCase() {
|
||||
protected val fixture: JavaCodeInsightTestFixture
|
||||
get() = myFixture
|
||||
|
||||
protected fun doTestWithTextLoaded(
|
||||
completionType: CompletionType,
|
||||
time: Int,
|
||||
lookupString: String?,
|
||||
itemText: String?,
|
||||
tailText: String?,
|
||||
completionChars: String,
|
||||
afterFilePath: String
|
||||
) {
|
||||
for (idx in 0 until completionChars.length - 1) {
|
||||
fixture.type(completionChars[idx])
|
||||
companion object {
|
||||
fun doTestWithTextLoaded(
|
||||
fixture: JavaCodeInsightTestFixture,
|
||||
completionType: CompletionType,
|
||||
time: Int,
|
||||
lookupString: String?,
|
||||
itemText: String?,
|
||||
tailText: String?,
|
||||
completionChars: String,
|
||||
afterFilePath: String,
|
||||
actions: List<String>? = emptyList(),
|
||||
afterTypingBlock: () -> Unit = {}
|
||||
) {
|
||||
for (idx in 0 until completionChars.length - 1) {
|
||||
fixture.type(completionChars[idx])
|
||||
afterTypingBlock()
|
||||
}
|
||||
|
||||
if (actions != null && actions.isNotEmpty()) {
|
||||
for (action in actions) {
|
||||
fixture.performEditorAction(action)
|
||||
}
|
||||
}
|
||||
|
||||
fixture.complete(completionType, time)
|
||||
|
||||
if (lookupString != null || itemText != null || tailText != null) {
|
||||
val item = getExistentLookupElement(fixture.project, lookupString, itemText, tailText)
|
||||
if (item != null) {
|
||||
selectItem(fixture, item, completionChars.last())
|
||||
}
|
||||
}
|
||||
afterTypingBlock()
|
||||
|
||||
fixture.checkResultByFile(afterFilePath)
|
||||
}
|
||||
|
||||
fixture.complete(completionType, time)
|
||||
|
||||
if (lookupString != null || itemText != null || tailText != null) {
|
||||
val item = getExistentLookupElement(lookupString, itemText, tailText)
|
||||
if (item != null) {
|
||||
selectItem(item, completionChars.last())
|
||||
fun completionChars(text: String): String {
|
||||
val char: String? = InTextDirectivesUtils.findStringWithPrefixes(text, AbstractCompletionHandlerTest.COMPLETION_CHAR_PREFIX)
|
||||
val chars: String? = InTextDirectivesUtils.findStringWithPrefixes(text, AbstractCompletionHandlerTest.COMPLETION_CHARS_PREFIX)
|
||||
return when (char) {
|
||||
null -> when (chars) {
|
||||
null -> "\n"
|
||||
else -> chars.replace("\\n", "\n").replace("\\t", "\t")
|
||||
}
|
||||
"\\n" -> "\n"
|
||||
"\\t" -> "\t"
|
||||
else -> char.single().toString() ?: error("Incorrect completion char: \"$char\"")
|
||||
}
|
||||
}
|
||||
fixture.checkResultByFile(afterFilePath)
|
||||
}
|
||||
|
||||
protected fun completionChars(char: String?, chars: String?): String =
|
||||
when (char) {
|
||||
null -> when (chars) {
|
||||
null -> "\n"
|
||||
else -> chars.replace("\\n", "\n").replace("\\t", "\t")
|
||||
fun getExistentLookupElement(project: Project, lookupString: String?, itemText: String?, tailText: String?): LookupElement? {
|
||||
val lookup = LookupManager.getInstance(project)?.activeLookup as LookupImpl? ?: return null
|
||||
val items = lookup.items
|
||||
|
||||
if (lookupString == "*") {
|
||||
assert(itemText == null)
|
||||
assert(tailText == null)
|
||||
return items.firstOrNull()
|
||||
}
|
||||
"\\n" -> "\n"
|
||||
"\\t" -> "\t"
|
||||
else -> char.single().toString() ?: error("Incorrect completion char: \"$char\"")
|
||||
}
|
||||
|
||||
protected fun getExistentLookupElement(lookupString: String?, itemText: String?, tailText: String?): LookupElement? {
|
||||
val lookup = LookupManager.getInstance(project)?.activeLookup as LookupImpl? ?: return null
|
||||
val items = lookup.items
|
||||
var foundElement : LookupElement? = null
|
||||
val presentation = LookupElementPresentation()
|
||||
for (lookupElement in items) {
|
||||
val lookupOk = if (lookupString != null) lookupElement.lookupString == lookupString else true
|
||||
|
||||
if (lookupString == "*") {
|
||||
assert(itemText == null)
|
||||
assert(tailText == null)
|
||||
return items.firstOrNull()
|
||||
}
|
||||
if (lookupOk) {
|
||||
lookupElement.renderElement(presentation)
|
||||
|
||||
var foundElement : LookupElement? = null
|
||||
val presentation = LookupElementPresentation()
|
||||
for (lookupElement in items) {
|
||||
val lookupOk = if (lookupString != null) lookupElement.lookupString == lookupString else true
|
||||
|
||||
if (lookupOk) {
|
||||
lookupElement.renderElement(presentation)
|
||||
|
||||
val textOk = if (itemText != null) {
|
||||
val itemItemText = presentation.itemText
|
||||
itemItemText != null && itemItemText == itemText
|
||||
}
|
||||
else {
|
||||
true
|
||||
}
|
||||
|
||||
if (textOk) {
|
||||
val tailOk = if (tailText != null) {
|
||||
val itemTailText = presentation.tailText
|
||||
itemTailText != null && itemTailText == tailText
|
||||
val textOk = if (itemText != null) {
|
||||
val itemItemText = presentation.itemText
|
||||
itemItemText != null && itemItemText == itemText
|
||||
}
|
||||
else {
|
||||
true
|
||||
}
|
||||
|
||||
if (tailOk) {
|
||||
if (foundElement != null) {
|
||||
val dump = ExpectedCompletionUtils.listToString(ExpectedCompletionUtils.getItemsInformation(arrayOf(foundElement, lookupElement)))
|
||||
fail("Several elements satisfy to completion restrictions:\n$dump")
|
||||
if (textOk) {
|
||||
val tailOk = if (tailText != null) {
|
||||
val itemTailText = presentation.tailText
|
||||
itemTailText != null && itemTailText == tailText
|
||||
}
|
||||
else {
|
||||
true
|
||||
}
|
||||
|
||||
foundElement = lookupElement
|
||||
if (tailOk) {
|
||||
if (foundElement != null) {
|
||||
val dump = ExpectedCompletionUtils.listToString(ExpectedCompletionUtils.getItemsInformation(arrayOf(foundElement, lookupElement)))
|
||||
fail("Several elements satisfy to completion restrictions:\n$dump")
|
||||
}
|
||||
|
||||
foundElement = lookupElement
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (foundElement == null) {
|
||||
val dump = ExpectedCompletionUtils.listToString(ExpectedCompletionUtils.getItemsInformation(items.toTypedArray()))
|
||||
error("No element satisfy completion restrictions in:\n$dump")
|
||||
}
|
||||
return foundElement
|
||||
}
|
||||
|
||||
if (foundElement == null) {
|
||||
val dump = ExpectedCompletionUtils.listToString(ExpectedCompletionUtils.getItemsInformation(items.toTypedArray()))
|
||||
error("No element satisfy completion restrictions in:\n$dump")
|
||||
}
|
||||
return foundElement
|
||||
}
|
||||
|
||||
protected fun selectItem(item: LookupElement?, completionChar: Char) {
|
||||
val lookup = (fixture.lookup as LookupImpl)
|
||||
if (lookup.currentItem != item) { // do not touch selection if not changed - important for char filter tests
|
||||
lookup.currentItem = item
|
||||
}
|
||||
lookup.focusDegree = LookupImpl.FocusDegree.FOCUSED
|
||||
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
|
||||
lookup.finishLookup(completionChar)
|
||||
}
|
||||
else {
|
||||
fixture.type(completionChar)
|
||||
fun selectItem(fixture: JavaCodeInsightTestFixture, item: LookupElement?, completionChar: Char) {
|
||||
val lookup = (fixture.lookup as LookupImpl)
|
||||
if (lookup.currentItem != item) { // do not touch selection if not changed - important for char filter tests
|
||||
lookup.currentItem = item
|
||||
}
|
||||
lookup.focusDegree = LookupImpl.FocusDegree.FOCUSED
|
||||
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
|
||||
lookup.finishLookup(completionChar)
|
||||
}
|
||||
else {
|
||||
fixture.type(completionChar)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user