Move object literal parsing, rewrite the determination that member is local

This commit is contained in:
Ivan Cilcic
2019-07-22 13:42:23 +03:00
committed by Mikhail Glukhikh
parent 531ee03a92
commit c8c37fd86e
5 changed files with 98 additions and 53 deletions
@@ -64,10 +64,6 @@ object ConverterUtil {
return this.toString()
}
fun LighterASTNode.getAsStringUnescapedValue(): String {
return this.toString().replaceFirst("\\", "")
}
fun LighterASTNode.isExpression(): Boolean {
return when (this.tokenType) {
is KtNodeType,
@@ -157,9 +153,15 @@ object ConverterUtil {
return this
}
fun FirValueParameter.toFirExpression(stubMode: Boolean): FirExpression {
return if (stubMode) FirExpressionStub(this.session, null)
else TODO("not implemeted")
inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.() -> LighterASTNode?): Boolean {
var currentNode: LighterASTNode? = classNode
while (currentNode != null) {
if (currentNode.tokenType == KtNodeTypes.BLOCK) {
return true
}
currentNode = currentNode.getParent()
}
return false
}
}
@@ -10,8 +10,10 @@ import com.intellij.psi.tree.IFileElementType
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.*
@@ -26,6 +28,7 @@ import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.joinTypeParame
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toDelegatedSelfType
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isClassLocal
import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateComponentFunctions
import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateCopyFunction
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
@@ -46,6 +49,7 @@ import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.SpecialNames
class DeclarationsConverter(
private val session: FirSession,
@@ -59,8 +63,7 @@ class DeclarationsConverter(
* [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble]
*/
fun convertFile(file: LighterASTNode, fileName: String = ""): FirFile {
val tokenType = file.tokenType
if (tokenType !is IFileElementType) {
if (file.tokenType != KT_FILE) {
//TODO throw error
throw Exception()
}
@@ -327,7 +330,7 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassOrObject
*/
fun convertClass(classNode: LighterASTNode): FirDeclaration {
private fun convertClass(classNode: LighterASTNode): FirDeclaration {
var modifiers = Modifier(session)
lateinit var classKind: ClassKind
var identifier: String? = null
@@ -370,6 +373,7 @@ class DeclarationsConverter(
val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "")
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
val isLocal = isClassLocal(classNode) { getParent() }
return ClassNameUtil.withChildClassName(className) {
val firClass = FirClassImpl(
@@ -377,7 +381,7 @@ class DeclarationsConverter(
null,
FirClassSymbol(ClassNameUtil.currentClassId),
className,
if (classNode.getParent()?.tokenType == BLOCK) Visibilities.LOCAL else modifiers.getVisibility(),
if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality(),
modifiers.hasExpect(),
modifiers.hasActual(),
@@ -426,6 +430,57 @@ class DeclarationsConverter(
}
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseObjectLiteral
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression
*/
fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement {
var modifiers = Modifier(session)
var primaryConstructor: LighterASTNode? = null
val superTypeRefs = mutableListOf<FirTypeRef>()
val superTypeCallEntry = mutableListOf<FirExpression>()
var delegatedSuperTypeRef: FirTypeRef? = null
var classBody: LighterASTNode? = null
objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first().forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
PRIMARY_CONSTRUCTOR -> primaryConstructor = it
SUPER_TYPE_LIST -> convertDelegationSpecifiers(it).apply {
delegatedSuperTypeRef = first
superTypeRefs += second
superTypeCallEntry += third
}
CLASS_BODY -> classBody = it
}
}
superTypeRefs.ifEmpty { superTypeRefs += implicitAnyType }
val delegatedType = delegatedSuperTypeRef ?: implicitAnyType
return FirAnonymousObjectImpl(session, null).apply {
annotations += modifiers.annotations
this.superTypeRefs += superTypeRefs
this.typeRef = superTypeRefs.first()
val classWrapper = ClassWrapper(
this@DeclarationsConverter.session, SpecialNames.NO_NAME_PROVIDED, modifiers, ClassKind.OBJECT,
hasPrimaryConstructor = false,
hasSecondaryConstructor = false,
delegatedSelfTypeRef = delegatedType,
delegatedSuperTypeRef = delegatedType,
superTypeCallEntry = superTypeCallEntry
)
//parse primary constructor
val firPrimaryConstructor = convertPrimaryConstructor(primaryConstructor, classWrapper)
firPrimaryConstructor?.let { this.declarations += it }
//parse declarations
classBody?.let {
this.declarations += convertClassBody(it, classWrapper)
}
}
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumEntry
*/
@@ -709,8 +764,9 @@ class DeclarationsConverter(
val propertyName = identifier.nameAsSafeName()
val parentType = property.getParent()?.tokenType
return if (parentType == BLOCK || parentType == WHEN) {
val parentNode = property.getParent()
val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY)
return if (isLocal) {
FirVariableImpl(
session,
null,
@@ -799,7 +855,7 @@ class DeclarationsConverter(
var returnType: FirTypeRef? = null
var firValueParameters: FirValueParameter = FirDefaultSetterValueParameter(session, null, propertyTypeRef)
var block: LighterASTNode? = null
var firExpression: FirExpression? = null
var expression: LighterASTNode? = null
getterOrSetter.forEachChildren {
if (it.getAsString() == "set") isGetter = false
when (it.tokenType) {
@@ -808,7 +864,7 @@ class DeclarationsConverter(
TYPE_REFERENCE -> returnType = convertType(it)
VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef)
BLOCK -> block = it
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
else -> if (it.isExpression()) expression = it
}
}
@@ -826,7 +882,7 @@ class DeclarationsConverter(
firAccessor.valueParameters += firValueParameters
}
firAccessor.body = convertFunctionBody(block, firExpression)
firAccessor.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
FunctionUtil.firFunctions.removeLast()
return firAccessor
}
@@ -874,7 +930,7 @@ class DeclarationsConverter(
var returnType: FirTypeRef? = null
val typeConstraints = mutableListOf<TypeConstraint>()
var block: LighterASTNode? = null
var firExpression: FirExpression? = null
var expression: LighterASTNode? = null
functionDeclaration.forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
@@ -885,17 +941,18 @@ class DeclarationsConverter(
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
BLOCK -> block = it
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it)
else -> if (it.isExpression()) expression = it
}
}
if (returnType == null) {
returnType =
if (block != null || (block == null && firExpression == null)) implicitUnitType
if (block != null || (block == null && expression == null)) implicitUnitType
else implicitType
}
val isLocal = functionDeclaration.getParent()?.tokenType == BLOCK
val parentNode = functionDeclaration.getParent()
val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY)
val firFunction = if (identifier == null) {
FirAnonymousFunctionImpl(session, null, returnType!!, receiverType)
} else {
@@ -930,7 +987,7 @@ class DeclarationsConverter(
}
firFunction.valueParameters += valueParametersList.map { it.firValueParameter }
firFunction.body = convertFunctionBody(block, firExpression)
firFunction.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
FunctionUtil.firFunctions.removeLast()
return firFunction
}
@@ -6,28 +6,33 @@
package org.jetbrains.kotlin.fir.lightTree.converter
import com.intellij.lang.LighterASTNode
import com.intellij.psi.tree.IElementType
import com.intellij.psi.impl.source.tree.java.PsiForStatementImpl
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.*
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirAnonymousObjectImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirErrorLoop
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.labels.FirLabelImpl
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsString
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.nameAsSafeName
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.getAsStringUnescapedValue
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.extractArgumentsFrom
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toReturn
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.pop
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
import org.jetbrains.kotlin.fir.lightTree.converter.utils.*
import org.jetbrains.kotlin.fir.lightTree.fir.ClassWrapper
import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry
import org.jetbrains.kotlin.fir.lightTree.fir.modifier.Modifier
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference
@@ -39,6 +44,7 @@ import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -90,12 +96,11 @@ class ExpressionsConverter(
PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses())
THIS_EXPRESSION -> convertThisExpression(expression)
SUPER_EXPRESSION -> convertSuperExpression(expression)
OBJECT_LITERAL -> convertObjectLiteral(expression)
OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression)
FUN -> declarationsConverter.convertFunctionDeclaration(expression)
else -> FirExpressionStub(session, null)
}
//TODO("not fully implemented")
}
return FirExpressionStub(session, null)
@@ -467,8 +472,8 @@ class ExpressionsConverter(
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString())
}
ESCAPE_STRING_TEMPLATE_ENTRY -> {
sb.append(it.getAsStringUnescapedValue())
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsStringUnescapedValue())
sb.append(escapedStringToCharacter(it.getAsString()))
FirConstExpressionImpl(session, null, IrConstKind.String, escapedStringToCharacter(it.getAsString())?.toString() ?: "")
}
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true
@@ -781,7 +786,8 @@ class ExpressionsConverter(
}
}
return FirBlockImpl(session, null).apply {
//TODO psi must be null
return FirBlockImpl(session, KtForExpression(PsiForStatementImpl())).apply {
val rangeVal =
generateTemporaryVariable(this@ExpressionsConverter.session, null, Name.special("<range>"), rangeExpression)
statements += rangeVal
@@ -1088,20 +1094,6 @@ class ExpressionsConverter(
}
}
/**
* @see org.jetbrains.kotlin.parsing.KotlinExpressionParsing.parseObjectLiteral
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.visitObjectLiteralExpression
*/
private fun convertObjectLiteral(objectLiteral: LighterASTNode): FirElement {
val firObject = declarationsConverter.convertClass(objectLiteral.getChildNodesByType(OBJECT_DECLARATION).first()) as FirClass
return FirAnonymousObjectImpl(session, null).apply {
annotations += firObject.annotations
superTypeRefs += firObject.superTypeRefs
this.typeRef = superTypeRefs.first()
declarations += firObject.declarations
}
}
/**
* @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue
*/
@@ -26,16 +26,10 @@ class ClassWrapper(
private val classKind: ClassKind,
val hasPrimaryConstructor: Boolean,
val hasSecondaryConstructor: Boolean,
var delegatedSelfTypeRef: FirTypeRef,
val delegatedSelfTypeRef: FirTypeRef,
val delegatedSuperTypeRef: FirTypeRef,
val superTypeCallEntry: MutableList<FirExpression>
) {
init {
if (className == SpecialNames.NO_NAME_PROVIDED) {
delegatedSelfTypeRef = delegatedSuperTypeRef
}
}
private fun isObject(): Boolean {
return classKind == ClassKind.OBJECT
}
@@ -58,7 +58,7 @@ fun String.parseCharacter(): Char? {
}
}
internal fun escapedStringToCharacter(text: String): Char? {
fun escapedStringToCharacter(text: String): Char? {
assert(text.isNotEmpty() && text[0] == '\\') {
"Only escaped sequences must be passed to this routine: $text"
}