FIR LC: populate no-arg constructor if needed
This commit is contained in:
committed by
Ilya Kirillov
parent
d253f9ba0e
commit
edc17a9d5f
+4
-4
@@ -19,16 +19,16 @@ import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.KtSecondaryConstructor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
|
||||
open class FirLightIdentifier(
|
||||
internal class FirLightIdentifier(
|
||||
private val lightOwner: PsiElement,
|
||||
private val firSymbol: KtSymbol
|
||||
private val firSymbol: KtSymbol?
|
||||
) : LightIdentifier(
|
||||
lightOwner.manager,
|
||||
(firSymbol as? KtNamedSymbol)?.name?.identifierOrNullIfSpecial
|
||||
), PsiCompiledElement, PsiElementWithOrigin<PsiElement> {
|
||||
|
||||
override val origin: PsiElement?
|
||||
get() = when (val ktDeclaration = firSymbol.psi) {
|
||||
get() = when (val ktDeclaration = firSymbol?.psi) {
|
||||
is KtSecondaryConstructor -> ktDeclaration.getConstructorKeyword()
|
||||
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
|
||||
?: ktDeclaration.valueParameterList
|
||||
@@ -44,4 +44,4 @@ open class FirLightIdentifier(
|
||||
override fun getContainingFile(): PsiFile = lightOwner.containingFile
|
||||
override fun getTextRange(): TextRange = origin?.textRange ?: TextRange.EMPTY_RANGE
|
||||
override fun getTextOffset(): Int = origin?.textOffset ?: -1
|
||||
}
|
||||
}
|
||||
|
||||
+62
-13
@@ -6,19 +6,11 @@
|
||||
package org.jetbrains.kotlin.light.classes.symbol.classes
|
||||
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiReferenceList
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.analysis.providers.createProjectWideOutOfBlockModificationTracker
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.KotlinSuperTypeListBuilder
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_BASE
|
||||
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.isPrivateOrPrivateToThis
|
||||
@@ -26,10 +18,16 @@ import org.jetbrains.kotlin.analysis.api.tokens.HackToForceAllowRunningAnalyzeOn
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.hackyAllowRunningOnEdt
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.light.classes.symbol.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
@@ -114,17 +112,68 @@ internal fun FirLightClassBase.createConstructors(
|
||||
declarations: Sequence<KtConstructorSymbol>,
|
||||
result: MutableList<KtLightMethod>
|
||||
) {
|
||||
for (declaration in declarations) {
|
||||
if (declaration.isHiddenOrSynthetic(project)) continue
|
||||
val constructors = declarations.toList()
|
||||
if (constructors.isEmpty()) {
|
||||
result.add(defaultConstructor())
|
||||
return
|
||||
}
|
||||
for (constructor in constructors) {
|
||||
if (constructor.isHiddenOrSynthetic(project)) continue
|
||||
result.add(
|
||||
FirLightConstructorForSymbol(
|
||||
constructorSymbol = declaration,
|
||||
constructorSymbol = constructor,
|
||||
lightMemberOrigin = null,
|
||||
containingClass = this@createConstructors,
|
||||
methodIndex = METHOD_INDEX_BASE
|
||||
)
|
||||
)
|
||||
}
|
||||
val primaryConstructor = constructors.singleOrNull { it.isPrimary }
|
||||
if (primaryConstructor != null && shouldGenerateNoArgOverload(primaryConstructor, constructors)) {
|
||||
result.add(
|
||||
noArgConstructor(primaryConstructor.visibility.externalDisplayName, METHOD_INDEX_FOR_NO_ARG_OVERLOAD_CTOR)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirLightClassBase.shouldGenerateNoArgOverload(
|
||||
primaryConstructor: KtConstructorSymbol,
|
||||
constructors: Iterable<KtConstructorSymbol>,
|
||||
): Boolean {
|
||||
val classOrObject = kotlinOrigin ?: return false
|
||||
return !primaryConstructor.visibility.isPrivateOrPrivateToThis() &&
|
||||
!classOrObject.hasModifier(INNER_KEYWORD) && !isEnum &&
|
||||
!classOrObject.hasModifier(SEALED_KEYWORD) &&
|
||||
primaryConstructor.valueParameters.isNotEmpty() &&
|
||||
primaryConstructor.valueParameters.all { it.hasDefaultValue } &&
|
||||
constructors.none { it.valueParameters.isEmpty() } &&
|
||||
!primaryConstructor.hasJvmOverloadsAnnotation()
|
||||
}
|
||||
|
||||
private fun FirLightClassBase.defaultConstructor(): KtLightMethod {
|
||||
val classOrObject = kotlinOrigin
|
||||
val visibility = when {
|
||||
classOrObject is KtObjectDeclaration || classOrObject?.hasModifier(SEALED_KEYWORD) == true || isEnum -> PsiModifier.PRIVATE
|
||||
classOrObject is KtEnumEntry -> PsiModifier.PACKAGE_LOCAL
|
||||
else -> PsiModifier.PUBLIC
|
||||
}
|
||||
return noArgConstructor(visibility, METHOD_INDEX_FOR_DEFAULT_CTOR)
|
||||
}
|
||||
|
||||
private fun FirLightClassBase.noArgConstructor(
|
||||
visibility: String,
|
||||
methodIndex: Int,
|
||||
): KtLightMethod {
|
||||
return FirLightNoArgConstructor(
|
||||
LightMemberOriginForDeclaration(
|
||||
originalElement = kotlinOrigin!!,
|
||||
originKind = JvmDeclarationOriginKind.OTHER,
|
||||
auxiliaryOriginalElement = kotlinOrigin as? KtDeclaration
|
||||
),
|
||||
this,
|
||||
visibility,
|
||||
methodIndex
|
||||
)
|
||||
}
|
||||
|
||||
internal fun FirLightClassBase.createMethods(
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.light.classes.symbol
|
||||
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
|
||||
internal class FirLightNoArgConstructor(
|
||||
lightMemberOrigin: LightMemberOrigin?,
|
||||
containingClass: FirLightClassBase,
|
||||
visibility: String,
|
||||
methodIndex: Int,
|
||||
): FirLightMethod(lightMemberOrigin, containingClass, methodIndex) {
|
||||
private val _name: String? = containingClass.name
|
||||
|
||||
override fun getName(): String = _name ?: ""
|
||||
|
||||
override fun isConstructor(): Boolean = true
|
||||
|
||||
override fun hasTypeParameters(): Boolean = false
|
||||
override fun getTypeParameterList(): PsiTypeParameterList? = null
|
||||
override fun getTypeParameters(): Array<PsiTypeParameter> = PsiTypeParameter.EMPTY_ARRAY
|
||||
|
||||
private val _identifier: PsiIdentifier by lazyPub {
|
||||
FirLightIdentifier(this, firSymbol = null)
|
||||
}
|
||||
|
||||
override fun getNameIdentifier(): PsiIdentifier = _identifier
|
||||
|
||||
override fun isDeprecated(): Boolean = false
|
||||
|
||||
private val _modifiers: Set<String> by lazyPub {
|
||||
setOf(visibility)
|
||||
}
|
||||
|
||||
private val _modifierList: PsiModifierList by lazyPub {
|
||||
FirLightMemberModifierList(this, _modifiers, emptyList())
|
||||
}
|
||||
|
||||
override fun getModifierList(): PsiModifierList = _modifierList
|
||||
|
||||
private val _parameterList: PsiParameterList by lazyPub {
|
||||
FirLightParameterList(this, callableSymbol = null) {}
|
||||
}
|
||||
|
||||
override fun getParameterList(): PsiParameterList = _parameterList
|
||||
|
||||
override fun getReturnType(): PsiType? = null
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
this === other ||
|
||||
(other is FirLightNoArgConstructor &&
|
||||
kotlinOrigin == other.kotlinOrigin &&
|
||||
containingClass == other.containingClass)
|
||||
|
||||
override fun hashCode(): Int = containingClass.hashCode()
|
||||
|
||||
override fun isValid(): Boolean = super.isValid() && containingClass.isValid
|
||||
}
|
||||
+5
-3
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.psi.KtParameterList
|
||||
|
||||
internal class FirLightParameterList(
|
||||
private val parent: FirLightMethod,
|
||||
private val callableSymbol: KtCallableSymbol,
|
||||
private val callableSymbol: KtCallableSymbol?,
|
||||
parameterPopulator: (LightParameterListBuilder) -> Unit,
|
||||
) : KtLightElement<KtParameterList, PsiParameterList>,
|
||||
// With this, a parent chain is properly built: from FirLightParameter through FirLightParameterList to FirLightMethod
|
||||
@@ -31,8 +31,10 @@ internal class FirLightParameterList(
|
||||
override val clsDelegate: PsiParameterList by lazyPub {
|
||||
val builder = LightParameterListBuilder(manager, language)
|
||||
|
||||
FirLightParameterForReceiver.tryGet(callableSymbol, parent)?.let {
|
||||
builder.addParameter(it)
|
||||
callableSymbol?.let {
|
||||
FirLightParameterForReceiver.tryGet(it, parent)?.let { receiver ->
|
||||
builder.addParameter(receiver)
|
||||
}
|
||||
}
|
||||
|
||||
parameterPopulator.invoke(builder)
|
||||
|
||||
@@ -3,3 +3,5 @@ data class User(val name: String = "", val age: Int = 0)
|
||||
data class Person(val name: String) {
|
||||
var age: Int = 0
|
||||
}
|
||||
|
||||
// FIR_COMPARISON
|
||||
|
||||
Reference in New Issue
Block a user