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() return this.toString()
} }
fun LighterASTNode.getAsStringUnescapedValue(): String {
return this.toString().replaceFirst("\\", "")
}
fun LighterASTNode.isExpression(): Boolean { fun LighterASTNode.isExpression(): Boolean {
return when (this.tokenType) { return when (this.tokenType) {
is KtNodeType, is KtNodeType,
@@ -157,9 +153,15 @@ object ConverterUtil {
return this return this
} }
fun FirValueParameter.toFirExpression(stubMode: Boolean): FirExpression { inline fun isClassLocal(classNode: LighterASTNode, getParent: LighterASTNode.() -> LighterASTNode?): Boolean {
return if (stubMode) FirExpressionStub(this.session, null) var currentNode: LighterASTNode? = classNode
else TODO("not implemeted") 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 com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.* 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.nameAsSafeName
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.toDelegatedSelfType 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.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.generateComponentFunctions
import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateCopyFunction import org.jetbrains.kotlin.fir.lightTree.converter.DataClassUtil.generateCopyFunction
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast 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.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.SpecialNames
class DeclarationsConverter( class DeclarationsConverter(
private val session: FirSession, private val session: FirSession,
@@ -59,8 +63,7 @@ class DeclarationsConverter(
* [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble] * [org.jetbrains.kotlin.parsing.KotlinParsing.parsePreamble]
*/ */
fun convertFile(file: LighterASTNode, fileName: String = ""): FirFile { fun convertFile(file: LighterASTNode, fileName: String = ""): FirFile {
val tokenType = file.tokenType if (file.tokenType != KT_FILE) {
if (tokenType !is IFileElementType) {
//TODO throw error //TODO throw error
throw Exception() throw Exception()
} }
@@ -327,7 +330,7 @@ class DeclarationsConverter(
/** /**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassOrObject * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseClassOrObject
*/ */
fun convertClass(classNode: LighterASTNode): FirDeclaration { private fun convertClass(classNode: LighterASTNode): FirDeclaration {
var modifiers = Modifier(session) var modifiers = Modifier(session)
lateinit var classKind: ClassKind lateinit var classKind: ClassKind
var identifier: String? = null var identifier: String? = null
@@ -370,6 +373,7 @@ class DeclarationsConverter(
val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "") val className = identifier.nameAsSafeName(if (modifiers.isCompanion()) "Companion" else "")
superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef } superTypeRefs.ifEmpty { superTypeRefs += defaultDelegatedSuperTypeRef }
val isLocal = isClassLocal(classNode) { getParent() }
return ClassNameUtil.withChildClassName(className) { return ClassNameUtil.withChildClassName(className) {
val firClass = FirClassImpl( val firClass = FirClassImpl(
@@ -377,7 +381,7 @@ class DeclarationsConverter(
null, null,
FirClassSymbol(ClassNameUtil.currentClassId), FirClassSymbol(ClassNameUtil.currentClassId),
className, className,
if (classNode.getParent()?.tokenType == BLOCK) Visibilities.LOCAL else modifiers.getVisibility(), if (isLocal) Visibilities.LOCAL else modifiers.getVisibility(),
modifiers.getModality(), modifiers.getModality(),
modifiers.hasExpect(), modifiers.hasExpect(),
modifiers.hasActual(), 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 * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumEntry
*/ */
@@ -709,8 +764,9 @@ class DeclarationsConverter(
val propertyName = identifier.nameAsSafeName() val propertyName = identifier.nameAsSafeName()
val parentType = property.getParent()?.tokenType val parentNode = property.getParent()
return if (parentType == BLOCK || parentType == WHEN) { val isLocal = !(parentNode?.tokenType == KT_FILE || parentNode?.tokenType == CLASS_BODY)
return if (isLocal) {
FirVariableImpl( FirVariableImpl(
session, session,
null, null,
@@ -799,7 +855,7 @@ class DeclarationsConverter(
var returnType: FirTypeRef? = null var returnType: FirTypeRef? = null
var firValueParameters: FirValueParameter = FirDefaultSetterValueParameter(session, null, propertyTypeRef) var firValueParameters: FirValueParameter = FirDefaultSetterValueParameter(session, null, propertyTypeRef)
var block: LighterASTNode? = null var block: LighterASTNode? = null
var firExpression: FirExpression? = null var expression: LighterASTNode? = null
getterOrSetter.forEachChildren { getterOrSetter.forEachChildren {
if (it.getAsString() == "set") isGetter = false if (it.getAsString() == "set") isGetter = false
when (it.tokenType) { when (it.tokenType) {
@@ -808,7 +864,7 @@ class DeclarationsConverter(
TYPE_REFERENCE -> returnType = convertType(it) TYPE_REFERENCE -> returnType = convertType(it)
VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef) VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRef)
BLOCK -> block = it 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.valueParameters += firValueParameters
} }
firAccessor.body = convertFunctionBody(block, firExpression) firAccessor.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
FunctionUtil.firFunctions.removeLast() FunctionUtil.firFunctions.removeLast()
return firAccessor return firAccessor
} }
@@ -874,7 +930,7 @@ class DeclarationsConverter(
var returnType: FirTypeRef? = null var returnType: FirTypeRef? = null
val typeConstraints = mutableListOf<TypeConstraint>() val typeConstraints = mutableListOf<TypeConstraint>()
var block: LighterASTNode? = null var block: LighterASTNode? = null
var firExpression: FirExpression? = null var expression: LighterASTNode? = null
functionDeclaration.forEachChildren { functionDeclaration.forEachChildren {
when (it.tokenType) { when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it) MODIFIER_LIST -> modifiers = convertModifierList(it)
@@ -885,17 +941,18 @@ class DeclarationsConverter(
TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it) TYPE_REFERENCE -> if (isReturnType) returnType = convertType(it) else receiverType = convertType(it)
TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it) TYPE_CONSTRAINT_LIST -> typeConstraints += convertTypeConstraints(it)
BLOCK -> block = it BLOCK -> block = it
else -> if (it.isExpression()) firExpression = expressionConverter.getAsFirExpression(it) else -> if (it.isExpression()) expression = it
} }
} }
if (returnType == null) { if (returnType == null) {
returnType = returnType =
if (block != null || (block == null && firExpression == null)) implicitUnitType if (block != null || (block == null && expression == null)) implicitUnitType
else implicitType 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) { val firFunction = if (identifier == null) {
FirAnonymousFunctionImpl(session, null, returnType!!, receiverType) FirAnonymousFunctionImpl(session, null, returnType!!, receiverType)
} else { } else {
@@ -930,7 +987,7 @@ class DeclarationsConverter(
} }
firFunction.valueParameters += valueParametersList.map { it.firValueParameter } firFunction.valueParameters += valueParametersList.map { it.firValueParameter }
firFunction.body = convertFunctionBody(block, firExpression) firFunction.body = convertFunctionBody(block, expression?.let { expressionConverter.getAsFirExpression(it) })
FunctionUtil.firFunctions.removeLast() FunctionUtil.firFunctions.removeLast()
return firFunction return firFunction
} }
@@ -6,28 +6,33 @@
package org.jetbrains.kotlin.fir.lightTree.converter package org.jetbrains.kotlin.fir.lightTree.converter
import com.intellij.lang.LighterASTNode 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 com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.* import org.jetbrains.kotlin.fir.builder.*
import org.jetbrains.kotlin.fir.declarations.FirClass 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.*
import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.labels.FirLabelImpl import org.jetbrains.kotlin.fir.labels.FirLabelImpl
import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir 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.getAsString
import org.jetbrains.kotlin.fir.lightTree.converter.ConverterUtil.isExpression 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.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.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.pop
import org.jetbrains.kotlin.fir.lightTree.converter.FunctionUtil.removeLast
import org.jetbrains.kotlin.fir.lightTree.converter.utils.* 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.ValueParameter
import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry 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.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference import org.jetbrains.kotlin.fir.references.FirExplicitSuperReference
import org.jetbrains.kotlin.fir.references.FirExplicitThisReference 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.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType import org.jetbrains.kotlin.psi.stubs.elements.KtConstantExpressionElementType
import org.jetbrains.kotlin.resolve.constants.evaluate.* import org.jetbrains.kotlin.resolve.constants.evaluate.*
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
@@ -90,12 +96,11 @@ class ExpressionsConverter(
PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses()) PARENTHESIZED, PROPERTY_DELEGATE, INDICES -> convertExpression(expression.getExpressionInParentheses())
THIS_EXPRESSION -> convertThisExpression(expression) THIS_EXPRESSION -> convertThisExpression(expression)
SUPER_EXPRESSION -> convertSuperExpression(expression) SUPER_EXPRESSION -> convertSuperExpression(expression)
OBJECT_LITERAL -> convertObjectLiteral(expression)
OBJECT_LITERAL -> declarationsConverter.convertObjectLiteral(expression)
FUN -> declarationsConverter.convertFunctionDeclaration(expression) FUN -> declarationsConverter.convertFunctionDeclaration(expression)
else -> FirExpressionStub(session, null) else -> FirExpressionStub(session, null)
} }
//TODO("not fully implemented")
} }
return FirExpressionStub(session, null) return FirExpressionStub(session, null)
@@ -467,8 +472,8 @@ class ExpressionsConverter(
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString()) FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsString())
} }
ESCAPE_STRING_TEMPLATE_ENTRY -> { ESCAPE_STRING_TEMPLATE_ENTRY -> {
sb.append(it.getAsStringUnescapedValue()) sb.append(escapedStringToCharacter(it.getAsString()))
FirConstExpressionImpl(session, null, IrConstKind.String, it.getAsStringUnescapedValue()) FirConstExpressionImpl(session, null, IrConstKind.String, escapedStringToCharacter(it.getAsString())?.toString() ?: "")
} }
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> { SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true 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 = val rangeVal =
generateTemporaryVariable(this@ExpressionsConverter.session, null, Name.special("<range>"), rangeExpression) generateTemporaryVariable(this@ExpressionsConverter.session, null, Name.special("<range>"), rangeExpression)
statements += rangeVal 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 * @see org.jetbrains.kotlin.fir.builder.ConversionUtilsKt.initializeLValue
*/ */
@@ -26,16 +26,10 @@ class ClassWrapper(
private val classKind: ClassKind, private val classKind: ClassKind,
val hasPrimaryConstructor: Boolean, val hasPrimaryConstructor: Boolean,
val hasSecondaryConstructor: Boolean, val hasSecondaryConstructor: Boolean,
var delegatedSelfTypeRef: FirTypeRef, val delegatedSelfTypeRef: FirTypeRef,
val delegatedSuperTypeRef: FirTypeRef, val delegatedSuperTypeRef: FirTypeRef,
val superTypeCallEntry: MutableList<FirExpression> val superTypeCallEntry: MutableList<FirExpression>
) { ) {
init {
if (className == SpecialNames.NO_NAME_PROVIDED) {
delegatedSelfTypeRef = delegatedSuperTypeRef
}
}
private fun isObject(): Boolean { private fun isObject(): Boolean {
return classKind == ClassKind.OBJECT 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] == '\\') { assert(text.isNotEmpty() && text[0] == '\\') {
"Only escaped sequences must be passed to this routine: $text" "Only escaped sequences must be passed to this routine: $text"
} }