FIR IDE: add Java synthetic properties support for completion

This commit is contained in:
Ilya Kirillov
2020-12-10 19:40:38 +01:00
parent 48b7150566
commit a0651cdba7
7 changed files with 49 additions and 6 deletions
@@ -0,0 +1,8 @@
// FIR_COMPARISON
fun foo(a: java.lang.Thread) {
a.na<caret>
}
// EXIST: {"lookupString":"name","tailText":" (from getName()/setName())","allLookupStrings":"getName, name, setName","itemText":"name"}
@@ -1,3 +1,5 @@
// FIR_COMPARISON
import java.io.File
fun foo(file: File) {
@@ -1,3 +1,5 @@
// FIR_COMPARISON
import java.io.File
fun foo(file: File) {
@@ -2950,6 +2950,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
runTest("idea/idea-completion/testData/basic/java/JavaPackage.kt");
}
@TestMetadata("JavaSyntheticProperty.kt")
public void testJavaSyntheticProperty() throws Exception {
runTest("idea/idea-completion/testData/basic/java/JavaSyntheticProperty.kt");
}
@TestMetadata("KProperty.kt")
public void testKProperty() throws Exception {
runTest("idea/idea-completion/testData/basic/java/KProperty.kt");
@@ -34,7 +34,7 @@ internal class KotlinFirLookupElementFactory {
fun KtAnalysisSession.createLookupElement(symbol: KtNamedSymbol): LookupElement? {
val elementBuilder = when (symbol) {
is KtFunctionSymbol -> with(functionLookupElementFactory) { createLookup(symbol) }
is KtVariableLikeSymbol -> with(variableLookupElementFactory) { createLookup(symbol) }
is KtVariableLikeSymbol -> with(variableLookupElementFactory) { createLookup(symbol) }
is KtClassLikeSymbol -> classLookupElementFactory.createLookup(symbol)
is KtTypeParameterSymbol -> typeParameterLookupElementFactory.createLookup(symbol)
else -> throw IllegalArgumentException("Cannot create a lookup element for $symbol")
@@ -67,9 +67,23 @@ private class VariableLookupElementFactory {
fun KtAnalysisSession.createLookup(symbol: KtVariableLikeSymbol): LookupElementBuilder {
return LookupElementBuilder.create(UniqueLookupObject(), symbol.name.asString())
.withTypeText(symbol.type.render())
.markIfSyntheticJavaProperty(symbol)
.withInsertHandler(createInsertHandler(symbol))
}
private fun LookupElementBuilder.markIfSyntheticJavaProperty(symbol: KtVariableLikeSymbol): LookupElementBuilder = when (symbol) {
is KtSyntheticJavaPropertySymbol -> {
val getterName = symbol.javaGetterName.asString()
val setterName = symbol.javaSetterName?.asString()
this.withTailText((" (from ${buildSyntheticPropertyTailText(getterName, setterName)})"))
.withLookupStrings(listOfNotNull(getterName, setterName))
}
else -> this
}
private fun buildSyntheticPropertyTailText(getterName: String, setterName: String?): String =
if (setterName != null) "$getterName()/$setterName()" else "$getterName()"
private fun createInsertHandler(symbol: KtVariableLikeSymbol): InsertHandler<LookupElement> {
return QuotedNamesAwareInsertionHandler(symbol.name)
}
@@ -2950,6 +2950,11 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
runTest("idea/idea-completion/testData/basic/java/JavaPackage.kt");
}
@TestMetadata("JavaSyntheticProperty.kt")
public void testJavaSyntheticProperty() throws Exception {
runTest("idea/idea-completion/testData/basic/java/JavaSyntheticProperty.kt");
}
@TestMetadata("KProperty.kt")
public void testKProperty() throws Exception {
runTest("idea/idea-completion/testData/basic/java/KProperty.kt");
@@ -6,15 +6,14 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticPropertiesScope
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacadeForCompletion
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getFirFile
@@ -122,9 +121,17 @@ internal class KtFirScopeProvider(
firResolveState.firTransformerProvider.getScopeSession(firSession),
FakeOverrideTypeCalculator.Forced
) ?: return null
return convertToKtScope(firTypeScope)
return getCompositeScope(
listOf(
convertToKtScope(firTypeScope),
firTypeScope.getSyntheticPropertiesScope(firSession)
)
)
}
private fun FirTypeScope.getSyntheticPropertiesScope(firSession: FirSession): KtScope =
convertToKtScope(FirSyntheticPropertiesScope(firSession, this))
override fun getScopeContextForPosition(
originalFile: KtFile,
positionInFakeFile: KtElement