Kotlin Uast: Support object literals
This commit is contained in:
@@ -859,9 +859,6 @@ public class ApiDetector extends ResourceXmlDetector
|
||||
owner = null;
|
||||
}
|
||||
} else if (owner.startsWith("java/")) { //$NON-NLS-1$
|
||||
if (owner.equals(LocaleDetector.DATE_FORMAT_OWNER)) {
|
||||
checkSimpleDateFormat(context, method, node, minSdk);
|
||||
}
|
||||
// Already inlined; see comment above
|
||||
owner = null;
|
||||
} else if (node.getOpcode() == Opcodes.INVOKEVIRTUAL) {
|
||||
|
||||
@@ -23,5 +23,7 @@ class UastModifier(val name: String) {
|
||||
val STATIC = UastModifier("static")
|
||||
@JvmField
|
||||
val FINAL = UastModifier("final")
|
||||
@JvmField
|
||||
val VARARG = UastModifier("vararg")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds
|
||||
import org.jetbrains.kotlin.uast.lint.PropertyAsCallAndroidUastAdditionalChecker
|
||||
import org.jetbrains.uast.*
|
||||
|
||||
@@ -57,6 +58,12 @@ internal object KotlinConverter : UastConverter {
|
||||
annotations = element.entries.map { KotlinUAnnotation(it, this) }
|
||||
}
|
||||
is KtDeclaration -> convert(element, parent)
|
||||
is KtParameterList -> KotlinUDeclarationsExpression(parent).apply {
|
||||
declarations = element.parameters.map { convert(it, this) }
|
||||
}
|
||||
is KtClassBody -> KotlinUSpecialExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply {
|
||||
expressions = emptyList()
|
||||
}
|
||||
is KtImportDirective -> KotlinUImportStatement(element, parent)
|
||||
is KtCatchClause -> KotlinUCatchClause(element, parent)
|
||||
is KtExpression -> KotlinConverter.convert(element, parent)
|
||||
@@ -121,6 +128,7 @@ internal object KotlinConverter : UastConverter {
|
||||
}
|
||||
declarations = listOf(tempAssignment) + destructuringAssignments
|
||||
}
|
||||
is KtObjectLiteralExpression -> KotlinUObjectLiteralExpression(expression, parent)
|
||||
is KtStringTemplateEntry -> convertOrEmpty(expression.expression, parent)
|
||||
is KtDotQualifiedExpression -> KotlinUQualifiedExpression(expression, parent)
|
||||
is KtSafeQualifiedExpression -> KotlinUSafeQualifiedExpression(expression, parent)
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.uast
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
@@ -40,12 +40,22 @@ import org.jetbrains.uast.psi.PsiElementBacked
|
||||
|
||||
class KotlinUClass(
|
||||
override val psi: KtClassOrObject,
|
||||
override val parent: UElement
|
||||
override val parent: UElement,
|
||||
override val isAnonymous: Boolean = false
|
||||
) : UClass, PsiElementBacked {
|
||||
override val name: String
|
||||
get() = psi.name.orAnonymous()
|
||||
|
||||
override val nameElement by lz { KotlinConverter.asSimpleReference(psi.nameIdentifier, this) }
|
||||
override val nameElement by lz {
|
||||
fun objectKeyword() = try { // !! in getObjectKeyword()
|
||||
if (psi is KtObjectDeclaration && psi.isObjectLiteral()) psi.getObjectKeyword() else null
|
||||
} catch (e: NullPointerException) {
|
||||
null
|
||||
}
|
||||
|
||||
val namePsiElement = psi.nameIdentifier ?: objectKeyword()
|
||||
KotlinConverter.asSimpleReference(namePsiElement, this)
|
||||
}
|
||||
|
||||
override val fqName: String?
|
||||
get() = psi.fqName?.asString()
|
||||
@@ -75,25 +85,37 @@ class KotlinUClass(
|
||||
(psi as? KtClass)?.getCompanionObjects()?.map { KotlinConverter.convert(it, this) } ?: emptyList()
|
||||
}
|
||||
|
||||
override val isAnonymous = false
|
||||
|
||||
override val internalName by lz {
|
||||
val descriptor = resolveToDescriptor() ?: return@lz null
|
||||
val typeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null,
|
||||
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME)
|
||||
val typeMapper = KotlinTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null,
|
||||
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME)
|
||||
typeMapper.mapClass(descriptor).internalName
|
||||
}
|
||||
|
||||
override fun getSuperClass(context: UastContext): UClass? {
|
||||
val superClass = resolveToDescriptor()?.getSuperClassOrAny() ?: return null
|
||||
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, superClass) ?: return null
|
||||
val descriptor = resolveToDescriptor() ?: return null
|
||||
if (KotlinBuiltIns.isAny(descriptor)) return null
|
||||
val source = descriptor.getSuperClassOrAny().toSource(psi.project) ?: return null
|
||||
return context.convert(source) as? UClass
|
||||
}
|
||||
|
||||
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
|
||||
|
||||
override val declarations by lz {
|
||||
val primaryConstructor = psi.getPrimaryConstructor()?.let { KotlinConverter.convert(it, this) }
|
||||
val primaryConstructor = if (psi is KtObjectDeclaration && psi.isObjectLiteral()) {
|
||||
val obj = psi
|
||||
object : KotlinObjectLiteralConstructorUFunction(obj, this) {
|
||||
|
||||
}
|
||||
} else {
|
||||
psi.getPrimaryConstructor()?.let { KotlinConverter.convert(it, this) } ?: run {
|
||||
if (psi.getSecondaryConstructors().isEmpty())
|
||||
KotlinDefaultPrimaryConstructorUFunction(psi, this)
|
||||
else
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val anonymousInitializers = psi.getAnonymousInitializers().map { KotlinConverter.convert(it, this) }.filterNotNull()
|
||||
val declarations = psi.declarations.map { KotlinConverter.convert(it, this) }.filterNotNull()
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.uast
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
@@ -125,4 +126,103 @@ class KotlinAnonymousInitializerUFunction(
|
||||
|
||||
override val annotations: List<UAnnotation>
|
||||
get() = emptyList()
|
||||
}
|
||||
|
||||
open class KotlinDefaultPrimaryConstructorUFunction(
|
||||
override val psi: KtClassOrObject,
|
||||
override val parent: UClass
|
||||
) : UFunction, PsiElementBacked, NoModifiers, NoAnnotations {
|
||||
override val kind: UastFunctionKind
|
||||
get() = UastFunctionKind.CONSTRUCTOR
|
||||
|
||||
override val nameElement by lz { psi.nameIdentifier?.let { KotlinPsiElementStub(it, this) } }
|
||||
override val name: String
|
||||
get() = "<init>"
|
||||
|
||||
override val valueParameters: List<UVariable>
|
||||
get() = emptyList()
|
||||
override val valueParameterCount: Int
|
||||
get() = 0
|
||||
|
||||
override val typeParameters: List<UTypeReference>
|
||||
get() = emptyList()
|
||||
override val typeParameterCount: Int
|
||||
get() = 0
|
||||
|
||||
override val returnType: UType?
|
||||
get() = null
|
||||
|
||||
override val body: UExpression = EmptyExpression(this)
|
||||
|
||||
override val visibility: UastVisibility
|
||||
get() = parent.visibility
|
||||
|
||||
override fun getSuperFunctions(context: UastContext) = emptyList<UFunction>()
|
||||
}
|
||||
|
||||
open class KotlinObjectLiteralConstructorUFunction(
|
||||
override val psi: KtObjectDeclaration,
|
||||
override val parent: UClass
|
||||
) : UFunction, PsiElementBacked, NoModifiers, NoAnnotations {
|
||||
private val resolvedCall by lz {
|
||||
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
|
||||
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? ClassDescriptor
|
||||
val primaryConstructor = descriptor?.unsubstitutedPrimaryConstructor ?: return@lz null
|
||||
bindingContext[BindingContext.CONSTRUCTOR_RESOLVED_DELEGATION_CALL, primaryConstructor]
|
||||
}
|
||||
|
||||
override val kind: UastFunctionKind
|
||||
get() = UastFunctionKind.CONSTRUCTOR
|
||||
|
||||
override val nameElement by lz { psi.nameIdentifier?.let { KotlinPsiElementStub(it, this) } }
|
||||
override val name: String
|
||||
get() = "<init>"
|
||||
|
||||
|
||||
override val valueParameters by lz {
|
||||
val params = resolvedCall?.valueArguments?.keys ?: return@lz emptyList<UVariable>()
|
||||
params.map { param ->
|
||||
object : UVariable {
|
||||
override val initializer: UExpression?
|
||||
get() = null
|
||||
override val kind: UastVariableKind
|
||||
get() = UastVariableKind.VALUE_PARAMETER
|
||||
override val type: UType
|
||||
get() = KotlinConverter.convert(param.type, psi.project, this)
|
||||
override val nameElement: UElement?
|
||||
get() = null
|
||||
override val parent: UElement?
|
||||
get() = this@KotlinObjectLiteralConstructorUFunction
|
||||
override val name: String
|
||||
get() = param.name.asString()
|
||||
|
||||
override fun hasModifier(modifier: UastModifier) = when(modifier) {
|
||||
UastModifier.VARARG -> param.varargElementType != null
|
||||
else -> false
|
||||
}
|
||||
|
||||
override val annotations: List<UAnnotation>
|
||||
get() = emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val valueParameterCount: Int
|
||||
get() = resolvedCall?.valueArgumentsByIndex?.size ?: 0
|
||||
|
||||
override val typeParameters: List<UTypeReference>
|
||||
get() = emptyList()
|
||||
|
||||
override val typeParameterCount: Int
|
||||
get() = 0
|
||||
|
||||
override val returnType: UType?
|
||||
get() = null
|
||||
|
||||
override val body: UExpression = EmptyExpression(this)
|
||||
|
||||
override val visibility: UastVisibility
|
||||
get() = parent.visibility
|
||||
|
||||
override fun getSuperFunctions(context: UastContext) = emptyList<UFunction>()
|
||||
}
|
||||
+61
@@ -95,4 +95,65 @@ class KotlinUComponentFunctionCallExpression(
|
||||
override val functionNameElement = null
|
||||
override val kind = UastCallKind.FUNCTION_CALL
|
||||
override fun resolve(context: UastContext) = null
|
||||
}
|
||||
|
||||
class KotlinUSuperConstructorCallExpression(
|
||||
override val psi: KtObjectDeclaration,
|
||||
override val parent: UElement,
|
||||
val resolvedCall: () -> ResolvedCall<*>?
|
||||
) : UCallExpression, PsiElementBacked, NoEvaluate {
|
||||
override val functionReference: USimpleReferenceExpression?
|
||||
get() = null
|
||||
|
||||
override val classReference: USimpleReferenceExpression by lz {
|
||||
val referenceParent = this
|
||||
object : USimpleReferenceExpression, PsiElementBacked, NoEvaluate {
|
||||
override val parent: UElement?
|
||||
get() = referenceParent
|
||||
|
||||
override val identifier: String
|
||||
get() = resolvedCall()?.resultingDescriptor?.name?.asString().orAnonymous()
|
||||
|
||||
override fun resolve(context: UastContext): UDeclaration? {
|
||||
val descriptor = resolvedCall()?.resultingDescriptor ?: return null
|
||||
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, descriptor) ?: return null
|
||||
return context.convert(source) as? UDeclaration
|
||||
}
|
||||
|
||||
override val psi: PsiElement
|
||||
get() = this@KotlinUSuperConstructorCallExpression.psi
|
||||
}
|
||||
}
|
||||
|
||||
override val functionName: String?
|
||||
get() = "<init>"
|
||||
|
||||
override val functionNameElement by lz {
|
||||
try {
|
||||
KotlinPsiElementStub(psi.getObjectKeyword(), this)
|
||||
} catch (e: NullPointerException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override val valueArgumentCount: Int
|
||||
get() = resolvedCall()?.valueArguments?.size ?: 0
|
||||
|
||||
override val valueArguments by lz {
|
||||
resolvedCall()?.call?.valueArguments?.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } ?: emptyList()
|
||||
}
|
||||
|
||||
override val typeArgumentCount: Int
|
||||
get() = 0
|
||||
override val typeArguments: List<UType>
|
||||
get() = emptyList()
|
||||
|
||||
override val kind: UastCallKind
|
||||
get() = UastCallKind.CONSTRUCTOR_CALL
|
||||
|
||||
override fun resolve(context: UastContext): UFunction? {
|
||||
val descriptor = resolvedCall()?.resultingDescriptor ?: return null
|
||||
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, descriptor) ?: return null
|
||||
return context.convert(source) as? UFunction
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.uast
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
|
||||
import org.jetbrains.uast.NoEvaluate
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UObjectLiteralExpression
|
||||
import org.jetbrains.uast.psi.PsiElementBacked
|
||||
|
||||
class KotlinUObjectLiteralExpression(
|
||||
override val psi: KtObjectLiteralExpression,
|
||||
override val parent: UElement
|
||||
) : UObjectLiteralExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
|
||||
override val declaration by lz { KotlinUClass(psi.objectDeclaration, this, true) }
|
||||
}
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.jetbrains.uast.UastSpecialExpressionKind
|
||||
import org.jetbrains.uast.psi.PsiElementBacked
|
||||
|
||||
open class KotlinUSpecialExpressionList(
|
||||
override val psi: PsiElement,
|
||||
override val psi: PsiElement?,
|
||||
override val kind: UastSpecialExpressionKind, // original element
|
||||
override val parent: UElement
|
||||
) : USpecialExpressionList, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
|
||||
|
||||
+4
-1
@@ -26,5 +26,8 @@ object KotlinSpecialExpressionKinds {
|
||||
val WHEN_ENTRY = UastSpecialExpressionKind("when_entry")
|
||||
|
||||
@JvmField
|
||||
val DESTRUCTURING = UastSpecialExpressionKind("destructuring")
|
||||
val CLASS_BODY = UastSpecialExpressionKind("class_body")
|
||||
|
||||
@JvmField
|
||||
val VARARG = UastSpecialExpressionKind("vararg")
|
||||
}
|
||||
Reference in New Issue
Block a user