Lint: Update Uast implementation (the new version is without declaration level)

This commit is contained in:
Yan Zhulanow
2016-10-13 20:26:55 +03:00
committed by Yan Zhulanow
parent 6491d3fbac
commit d5d491e6b2
222 changed files with 4606 additions and 5405 deletions
@@ -1,215 +0,0 @@
/*
* Copyright 2010-2015 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 com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.lexer.KtTokens
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.expressions.KotlinUBreakExpression
import org.jetbrains.kotlin.uast.expressions.KotlinUContinueExpression
import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.kotlin.uast.extensions.PropertyAsCallAndroidUastVisitorExtension
import org.jetbrains.uast.*
object KotlinUastLanguagePlugin : UastLanguagePlugin {
override val converter: UastConverter = KotlinConverter
override val visitorExtensions = listOf(PropertyAsCallAndroidUastVisitorExtension())
}
internal object KotlinConverter : UastConverter {
override fun isFileSupported(name: String) = name.endsWith(".kt", false) || name.endsWith(".kts", false)
override fun convert(element: Any?, parent: UElement): UElement? {
if (element !is KtElement) return null
return convertKtElement(element, parent)
}
override fun convertWithParent(element: Any?): UElement? {
if (element !is KtElement) return null
if (element is KtFile) return KotlinUFile(element)
val parent = element.parent ?: return null
val parentUElement = convertWithParent(parent) ?: return null
return convertKtElement(element, parentUElement)
}
private fun convertKtElement(element: KtElement?, parent: UElement): UElement? = when (element) {
is KtFile -> KotlinUFile(element)
is KtAnnotationEntry -> KotlinUAnnotation(element, parent)
is KtAnnotation -> KotlinUAnnotationList(element, parent).apply {
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)
else -> {
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
asSimpleReference(element, parent)
} else {
null
}
}
}
internal fun convert(element: KtDeclaration, parent: UElement): UDeclaration? = when (element) {
is KtClassOrObject -> convert(element, parent)
is KtAnonymousInitializer -> KotlinAnonymousInitializerUFunction(element, parent)
is KtConstructor<*> -> KotlinConstructorUFunction(element, parent)
is KtFunction -> KotlinUFunction(element, parent)
is KtVariableDeclaration -> KotlinUVariable(element, parent)
is KtParameter -> convert(element, parent)
else -> null
}
private fun convertStringTemplateExpression(
expression: KtStringTemplateExpression,
parent: UElement,
i: Int
): UExpression {
return if (i == 1) KotlinStringTemplateUBinaryExpression(expression, parent).apply {
leftOperand = convert(expression.entries[0], this)
rightOperand = convert(expression.entries[1], this)
} else KotlinStringTemplateUBinaryExpression(expression, parent).apply {
leftOperand = convertStringTemplateExpression(expression, parent, i - 1)
rightOperand = convert(expression.entries[i], this)
}
}
internal fun convert(entry: KtStringTemplateEntry, parent: UElement): UExpression = when (entry) {
is KtStringTemplateEntryWithExpression -> convertOrEmpty(entry.expression, parent)
is KtEscapeStringTemplateEntry -> KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
else -> {
KotlinStringULiteralExpression(entry, parent)
}
}
internal fun convert(expression: KtExpression, parent: UElement): UExpression = when (expression) {
is KtFunction -> convertDeclaration(expression, parent)
is KtVariableDeclaration -> convertDeclaration(expression, parent)
is KtClass -> convertDeclaration(expression, parent)
is KtStringTemplateExpression -> {
if (expression.entries.isEmpty())
KotlinStringULiteralExpression(expression, parent, "")
else if (expression.entries.size == 1)
convert(expression.entries[0], parent)
else
convertStringTemplateExpression(expression, parent, expression.entries.size - 1)
}
is KtDestructuringDeclaration -> KotlinUDeclarationsExpression(parent).apply {
val tempAssignment = KotlinDestructuringUVariable(expression, this)
val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
KotlinDestructuredUVariable(entry, this).apply {
initializer = KotlinUComponentQualifiedExpression(entry, this).apply {
receiver = KotlinStringUSimpleReferenceExpression(tempAssignment.name, this)
selector = KotlinUComponentFunctionCallExpression(entry, i + 1, this)
}
}
}
declarations = listOf(tempAssignment) + destructuringAssignments
}
is KtLabeledExpression -> KotlinULabeledExpression(expression, parent)
is KtClassLiteralExpression -> KotlinUClassLiteralExpression(expression, parent)
is KtObjectLiteralExpression -> KotlinUObjectLiteralExpression(expression, parent)
is KtStringTemplateEntry -> convertOrEmpty(expression.expression, parent)
is KtDotQualifiedExpression -> KotlinUQualifiedExpression(expression, parent)
is KtSafeQualifiedExpression -> KotlinUSafeQualifiedExpression(expression, parent)
is KtSimpleNameExpression -> KotlinUSimpleReferenceExpression(expression, expression.getReferencedName(), parent)
is KtCallExpression -> KotlinUFunctionCallExpression(expression, parent)
is KtBinaryExpression -> KotlinUBinaryExpression(expression, parent)
is KtParenthesizedExpression -> KotlinUParenthesizedExpression(expression, parent)
is KtPrefixExpression -> KotlinUPrefixExpression(expression, parent)
is KtPostfixExpression -> KotlinUPostfixExpression(expression, parent)
is KtThisExpression -> KotlinUThisExpression(expression, parent)
is KtSuperExpression -> KotlinUSuperExpression(expression, parent)
is KtCallableReferenceExpression -> KotlinUCallableReferenceExpression(expression, parent)
is KtIsExpression -> KotlinUTypeCheckExpression(expression, parent)
is KtIfExpression -> KotlinUIfExpression(expression, parent)
is KtWhileExpression -> KotlinUWhileExpression(expression, parent)
is KtDoWhileExpression -> KotlinUDoWhileExpression(expression, parent)
is KtForExpression -> KotlinUForEachExpression(expression, parent)
is KtWhenExpression -> KotlinUSwitchExpression(expression, parent)
is KtBreakExpression -> KotlinUBreakExpression(expression, parent)
is KtContinueExpression -> KotlinUContinueExpression(expression, parent)
is KtReturnExpression -> KotlinUReturnExpression(expression, parent)
is KtThrowExpression -> KotlinUThrowExpression(expression, parent)
is KtBlockExpression -> KotlinUBlockExpression(expression, parent)
is KtConstantExpression -> KotlinULiteralExpression(expression, parent)
is KtTryExpression -> KotlinUTryExpression(expression, parent)
is KtArrayAccessExpression -> KotlinUArrayAccessExpression(expression, parent)
is KtLambdaExpression -> KotlinULambdaExpression(expression, parent)
is KtBinaryExpressionWithTypeRHS -> KotlinUBinaryExpressionWithType(expression, parent)
else -> UnknownKotlinExpression(expression, parent)
}
internal fun convert(element: KtParameter, parent: UElement) : UVariable {
return KotlinParameterUVariable(element, parent)
}
internal fun convert(element: KtClassOrObject, parent: UElement) : UClass {
return KotlinUClass(element, parent)
}
internal fun convert(element: KotlinType, project: Project, parent: UElement?): UType {
return KotlinUType(element, project, parent)
}
internal fun convert(typeReference: KtTypeReference?, parent: UElement): UType {
if (typeReference == null) return UastErrorType
val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL)
val type = bindingContext[BindingContext.TYPE, typeReference] ?: return UastErrorType
return KotlinUType(type, typeReference.project, parent, typeReference.typeElement)
}
internal fun convertTypeReference(typeReference: KtTypeReference, parent: UElement): UTypeReference {
return KotlinUTypeReference(typeReference, parent)
}
internal fun asSimpleReference(element: PsiElement?, parent: UElement): USimpleReferenceExpression? {
if (element == null) return null
return KotlinNameUSimpleReferenceExpression(element, KtPsiUtil.unquoteIdentifier(element.text), parent)
}
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement): UExpression {
return if (expression != null) convert(expression, parent) else EmptyUExpression(parent)
}
internal fun convertOrNull(expression: KtExpression?, parent: UElement): UExpression? {
return if (expression != null) convert(expression, parent) else null
}
private fun convertDeclaration(declaration: KtDeclaration, parent: UElement): UExpression {
val udeclarations = mutableListOf<UElement>()
return SimpleUDeclarationsExpression(parent, udeclarations).apply {
convert(declaration, this)?.let { udeclarations += it }
}
}
}
@@ -1,29 +0,0 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinDumbUElement(
override val psi: PsiElement?,
override val parent: UElement
) : KotlinAbstractUElement(), UElement, PsiElementBacked {
override fun logString() = "KotlinDumbUElement"
override fun renderString() = "<stub@$psi>"
}
@@ -1,42 +0,0 @@
/*
* 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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinParameterUTypeReference(
override val psi: KtTypeParameter,
override val parent: UElement
) : KotlinAbstractUElement(), UTypeReference, PsiElementBacked {
override fun resolve(context: UastContext): UClass? {
val descriptor = psi.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE_PARAMETER, psi]
?.typeConstructor?.declarationDescriptor as? ClassDescriptor ?: return null
return context.convert(descriptor.toSource()) as? UClass
}
override val nameElement: UElement?
get() = KotlinDumbUElement(psi, this)
override val name: String
get() = psi.name.orAnonymous()
}
@@ -1,61 +0,0 @@
/*
* 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.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUAnnotation(
override val psi: KtAnnotationEntry,
override val parent: UElement
) : KotlinAbstractUElement(), UAnnotation, PsiElementBacked {
override val fqName: String?
get() = resolveToDescriptor()?.fqNameSafe?.asString()
override val name: String
get() = (psi.typeReference?.typeElement as? KtUserType)?.referencedName.orAnonymous()
override val valueArguments by lz {
psi.valueArguments.map {
val name = it.getArgumentName()?.asName?.identifier.orAnonymous()
UNamedExpression(name, this).apply {
expression = KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this)
}
}
}
private fun resolveToDescriptor(): ClassDescriptor? {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = psi.calleeExpression?.getResolvedCall(bindingContext) ?: return null
return (resolvedCall.resultingDescriptor as? ClassConstructorDescriptor)?.containingDeclaration
}
override fun resolve(context: UastContext): UClass? {
val classDescriptor = resolveToDescriptor() ?: return null
val source = classDescriptor.toSource() ?: return null
return context.convert(source) as? UClass
}
}
@@ -1,40 +0,0 @@
/*
* 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.KtAnnotation
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UElement
import org.jetbrains.uast.acceptList
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.visitor.UastVisitor
class KotlinUAnnotationList(
override val psi: KtAnnotation,
override val parent: UElement
) : KotlinAbstractUElement(), UElement, PsiElementBacked {
lateinit var annotations: List<UAnnotation>
override fun logString() = "KotlinUAnnotationList"
override fun renderString() = annotations.joinToString(" ") { it.renderString() }
override fun accept(visitor: UastVisitor) {
if (visitor.visitElement(this)) return
annotations.acceptList(visitor)
visitor.afterVisitElement(this)
}
}
@@ -1,133 +0,0 @@
/*
* 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
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.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUClass(
override val psi: KtClassOrObject,
override val parent: UElement,
override val isAnonymous: Boolean = false
) : KotlinAbstractUElement(), UClass, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz {
val namePsiElement = psi.nameIdentifier
?: if (psi is KtObjectDeclaration && psi.isObjectLiteral()) psi.getObjectKeyword() else null
KotlinConverter.asSimpleReference(namePsiElement, this)
}
override val fqName: String?
get() = psi.fqName?.asString()
override val kind by lz {
when {
psi.isAnnotation() -> UastClassKind.ANNOTATION
(psi as? KtObjectDeclaration)?.isCompanion() ?: false -> KotlinClassKinds.COMPANION_OBJECT
psi is KtObjectDeclaration -> UastClassKind.OBJECT
(psi as? KtClass)?.isInterface() ?: false -> UastClassKind.INTERFACE
(psi as? KtClass)?.isEnum() ?: false -> UastClassKind.ENUM
else -> UastClassKind.CLASS
}
}
override val defaultType by lz {
val type = resolveToDescriptor()?.defaultType ?: return@lz UastErrorType
KotlinConverter.convert(type, psi.project, this)
}
override val companions by lz {
(psi as? KtClass)?.getCompanionObjects()?.map { KotlinConverter.convert(it, this) } ?: emptyList()
}
override val internalName by lz {
val descriptor = resolveToDescriptor() ?: return@lz null
val typeMapper = KotlinTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
typeMapper.mapClass(descriptor).internalName
}
override fun getSuperClass(context: UastContext): UClass? {
val descriptor = resolveToDescriptor() ?: return null
if (KotlinBuiltIns.isAny(descriptor)) return null
val source = descriptor.getSuperClassOrAny().toSource() ?: return null
return context.convert(source) as? UClass
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val declarations by lz {
val primaryConstructor = if (psi is KtObjectDeclaration && psi.isObjectLiteral()) {
KotlinObjectLiteralConstructorUFunction(psi, 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()
if (primaryConstructor != null)
listOf(primaryConstructor) + declarations + anonymousInitializers
else
declarations + anonymousInitializers
}
override val superTypes by lz {
val superTypes = resolveToDescriptor()?.typeConstructor?.supertypes ?: return@lz emptyList<UType>()
superTypes.map { KotlinConverter.convert(it, psi.project, this) }
}
override val annotations by lz { psi.getUastAnnotations(this) }
override val visibility by lz { psi.getVisibility() }
override fun isSubclassOf(fqName: String): Boolean {
val descriptor = psi.resolveToDescriptorIfAny() as? ClassDescriptor ?: return false
return descriptor.defaultType.supertypes().any {
it.constructor.declarationDescriptor?.fqNameSafe?.asString() == fqName
}
}
private fun resolveToDescriptor(): ClassDescriptor? {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
return bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? ClassDescriptor
}
}
@@ -1,29 +0,0 @@
/*
* 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.KtFile
import org.jetbrains.uast.UFile
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUFile(override val psi: KtFile): KotlinAbstractUElement(), UFile, PsiElementBacked {
override val packageFqName: String?
get() = psi.packageFqName.asString()
override val declarations by lz { psi.declarations.map { KotlinConverter.convert(it, this) }.filterNotNull() }
override val importStatements by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } }
}
@@ -1,36 +0,0 @@
/*
* 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.KtImportDirective
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.UastContext
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUImportStatement(
override val psi: KtImportDirective,
override val parent: UElement
) : KotlinAbstractUElement(), UImportStatement, PsiElementBacked {
override val fqNameToImport = psi.importedFqName?.asString()
override val isStarImport: Boolean
get() = psi.isAllUnder
//TODO support
override fun resolve(context: UastContext) = null
}
@@ -1,81 +0,0 @@
/*
* 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 com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUType(
val type: KotlinType,
val project: Project,
override val parent: UElement?,
override val psi: PsiElement? = null
) : KotlinAbstractUElement(), UType, PsiElementBacked {
override val name: String
get() = type.toString()
override val fqName: String?
get() = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
override fun resolve(context: UastContext): UClass? {
val descriptor = type.constructor.declarationDescriptor ?: return null
val sourceElement = descriptor.toSource() ?: return null
return context.convert(sourceElement) as? UClass
}
override val isBoolean: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._boolean)
override val isInt: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._int)
override val isShort: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._short)
override val isLong: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._long)
override val isFloat: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._float)
override val isDouble: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._double)
override val isChar: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._char)
override val isByte: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._byte)
private fun checkType(fqNameUnsafe: FqNameUnsafe): Boolean {
val descriptor = type.constructor.declarationDescriptor
return descriptor is ClassDescriptor
&& descriptor.getName() == fqNameUnsafe.shortName()
&& fqNameUnsafe == DescriptorUtils.getFqName(descriptor)
}
//TODO support descriptor annotations
override val annotations = emptyList<UAnnotation>()
}
@@ -1,42 +0,0 @@
/*
* 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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUTypeReference(
override val psi: KtTypeReference,
override val parent: UElement
) : KotlinAbstractUElement(), UTypeReference, PsiElementBacked {
override fun resolve(context: UastContext): UClass? {
val descriptor = psi.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, psi]
?.constructor?.declarationDescriptor as? ClassDescriptor ?: return null
return context.convert(descriptor.toSource()) as? UClass
}
override val nameElement: UElement?
get() = KotlinDumbUElement(psi, this)
override val name: String
get() = psi.name.orAnonymous()
}
@@ -1,199 +0,0 @@
/*
* 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.descriptors.CallableDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.uast.kinds.KotlinVariableInitializerKinds
import org.jetbrains.uast.*
import org.jetbrains.uast.kinds.UastVariableInitialierKind
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUVariable(
override val psi: KtVariableDeclaration,
override val parent: UElement
) : KotlinAbstractUElement(), UVariable, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz { KotlinDumbUElement(psi.nameIdentifier, this) }
override val initializer by lz {
val expression = (psi as? KtProperty)?.delegateExpression ?: psi.initializer
KotlinConverter.convertOrEmpty(expression, this)
}
override val initializerKind by lz {
if ((psi as? KtProperty)?.delegateExpression != null)
KotlinVariableInitializerKinds.DELEGATION
else if (psi.initializer != null)
UastVariableInitialierKind.EXPRESSION
else
UastVariableInitialierKind.NO_INITIALIZER
}
override val type by lz {
val descriptor = psi.resolveToDescriptorIfAny() as? CallableDescriptor ?: return@lz UastErrorType
val type = descriptor.returnType ?: return@lz UastErrorType
KotlinConverter.convert(type, psi.project, this)
}
override val accessors: List<UFunction>? by lz {
(psi as? KtProperty)?.accessors?.map { VariableAccessorFunction(it, this) }
}
override val kind: UastVariableKind
get() = when (psi.parent) {
is KtClassBody -> UastVariableKind.MEMBER
is KtClassOrObject -> UastVariableKind.MEMBER
else -> UastVariableKind.LOCAL_VARIABLE
}
override val visibility: UastVisibility
get() = psi.getVisibility()
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations by lz { psi.getUastAnnotations(this) }
private class VariableAccessorFunction(
override val psi: KtPropertyAccessor,
override val parent: UVariable
) : KotlinAbstractUElement(), UFunction, PsiElementBacked {
override val kind: UastFunctionKind
get() = if (psi.isGetter)
UastFunctionKind.GETTER
else if (psi.isSetter)
UastFunctionKind.SETTER
else
UastFunctionKind.FUNCTION
override val valueParameters by lz { psi.valueParameters.map { KotlinConverter.convert(it, this) } }
override val valueParameterCount: Int
get() = psi.valueParameters.size
override val typeParameters: List<UTypeReference>
get() = emptyList()
override val typeParameterCount: Int
get() = 0
override val returnType: UType?
get() = if (psi.isSetter) null else parent.type
override val body by lz { KotlinConverter.convertOrNull(psi.bodyExpression, this) }
override val visibility: UastVisibility
get() = psi.getVisibility()
override fun getSuperFunctions(context: UastContext) = emptyList<UFunction>()
override val nameElement by lz { KotlinDumbUElement(psi.namePlaceholder, this) }
override val name: String
get() = when {
psi.isSetter -> "<set>"
psi.isGetter -> "<get>"
else -> "<accessor>"
}
override fun hasModifier(modifier: UastModifier) = false
override val annotations: List<UAnnotation>
get() = emptyList()
}
}
class KotlinDestructuredUVariable(
val entry: KtDestructuringDeclarationEntry,
parent: UElement
) : KotlinUVariable(entry, parent) {
override lateinit var initializer: UExpression
internal set
override val type by lz {
val bindingContext = entry.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = bindingContext[BindingContext.COMPONENT_RESOLVED_CALL, entry] ?: return@lz UastErrorType
val returnType = resolvedCall.resultingDescriptor.returnType ?: return@lz UastErrorType
KotlinConverter.convert(returnType, entry.project, this)
}
override val visibility: UastVisibility
get() = UastVisibility.LOCAL
}
class KotlinDestructuringUVariable(
override val psi: KtDestructuringDeclaration,
override val parent: UElement
) : KotlinAbstractUElement(), UVariable, PsiElementBacked {
override val name = "var" + psi.text.hashCode()
override val initializer by lz { KotlinConverter.convertOrEmpty(psi.initializer, this) }
override val initializerKind: UastVariableInitialierKind
get() = if (initializer != null)
UastVariableInitialierKind.EXPRESSION
else
UastVariableInitialierKind.NO_INITIALIZER
override val kind = UastVariableKind.LOCAL_VARIABLE
override val type: UType
get() = initializer.getExpressionType() ?: UastErrorType
override val nameElement = null
override fun hasModifier(modifier: UastModifier) = false
override val annotations = emptyList<UAnnotation>()
override val visibility: UastVisibility
get() = UastVisibility.LOCAL
}
class KotlinParameterUVariable(
override val psi: KtParameter,
override val parent: UElement
) : KotlinAbstractUElement(), UVariable, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz { KotlinDumbUElement(psi.nameIdentifier, this) }
override val initializer by lz { KotlinConverter.convert(psi.defaultValue, this) as? UExpression }
override val initializerKind: UastVariableInitialierKind
get() = if (initializer != null)
UastVariableInitialierKind.EXPRESSION
else
UastVariableInitialierKind.NO_INITIALIZER
override val kind = UastVariableKind.VALUE_PARAMETER
override val type by lz {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val param = bindingContext[BindingContext.VALUE_PARAMETER, psi] ?: return@lz UastErrorType
KotlinConverter.convert(param.type, psi.project, this)
}
override val visibility: UastVisibility
get() = UastVisibility.LOCAL
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations = psi.getUastAnnotations(this)
}
@@ -1,263 +0,0 @@
/*
* 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.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
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.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JvmAbi
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.uast.*
import org.jetbrains.uast.kinds.UastVariableInitialierKind
import org.jetbrains.uast.psi.PsiElementBacked
abstract class KotlinAbstractUFunction : KotlinAbstractUElement(), UFunction, PsiElementBacked {
override abstract val psi: KtFunction
override val name by lz { psi.name.orAnonymous() }
override val valueParameterCount: Int
get() = psi.valueParameters.size
override val valueParameters by lz { psi.valueParameters.map { KotlinConverter.convert(it, this) } }
override fun getSuperFunctions(context: UastContext): List<UFunction> {
if (this.isTopLevel()) return emptyList()
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val clazz = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? FunctionDescriptor ?: return emptyList()
return clazz.overriddenDescriptors.map {
context.convert(it.toSource()) as? UFunction
}.filterNotNull()
}
override val bytecodeDescriptor by lz {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? FunctionDescriptor ?: return@lz null
fun KotlinType?.isAnonymous(): Boolean {
if (this == null) return true
return false
}
if (descriptor.valueParameters.any { it.type.isAnonymous() } || descriptor.returnType.isAnonymous()) {
return@lz null
}
val typeMapper = KotlinTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
typeMapper.mapAsmMethod(descriptor).descriptor
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations by lz { psi.getUastAnnotations(this) }
override val body by lz { KotlinConverter.convertOrNull(psi.bodyExpression, this) }
override val visibility by lz { psi.getVisibility() }
}
class KotlinConstructorUFunction(
override val psi: KtConstructor<*>,
override val parent: UElement
) : KotlinAbstractUFunction(), PsiElementBacked {
override val name: String
get() = "<init>"
override val nameElement by lz {
val constructorKeyword = psi.getConstructorKeyword()?.let { KotlinDumbUElement(it, this) }
constructorKeyword ?: this.getContainingFunction()?.nameElement
}
override val kind = UastFunctionKind.CONSTRUCTOR
override val typeParameterCount = 0
override val typeParameters = emptyList<UTypeReference>()
override val returnType = null
}
class KotlinUFunction(
override val psi: KtFunction,
override val parent: UElement
) : KotlinAbstractUFunction(), PsiElementBacked {
override val nameElement by lz { psi.nameIdentifier?.let { KotlinDumbUElement(it, this) } }
override val kind = UastFunctionKind.FUNCTION
override val returnType by lz {
val descriptor = psi.resolveToDescriptorIfAny() as? FunctionDescriptor ?: return@lz null
val type = descriptor.returnType ?: return@lz null
KotlinConverter.convert(type, psi.project, this)
}
override val typeParameterCount: Int
get() = psi.typeParameters.size
override val typeParameters by lz { psi.typeParameters.map { KotlinParameterUTypeReference(it, this) } }
}
class KotlinAnonymousInitializerUFunction(
override val psi: KtAnonymousInitializer,
override val parent: UElement
) : KotlinAbstractUElement(), UFunction, PsiElementBacked {
override val kind = KotlinFunctionKinds.INIT_BLOCK
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 by lz { KotlinConverter.convertOrNull(psi.body, this) }
override val visibility: UastVisibility
get() = UastVisibility.PRIVATE
override fun getSuperFunctions(context: UastContext) = emptyList<UFunction>()
override val nameElement by lz { KotlinDumbUElement(psi.node.findChildByType(KtTokens.INIT_KEYWORD)?.psi ?: psi, this) }
override val name: String
get() = "<init>"
override fun hasModifier(modifier: UastModifier) = false
override val annotations: List<UAnnotation>
get() = emptyList()
}
open class KotlinDefaultPrimaryConstructorUFunction(
override val psi: KtClassOrObject,
override val parent: UClass
) : KotlinAbstractUElement(), UFunction, PsiElementBacked, NoModifiers, NoAnnotations {
override val kind: UastFunctionKind
get() = UastFunctionKind.CONSTRUCTOR
override val nameElement by lz { KotlinDumbUElement(psi.nameIdentifier, 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?
get() = null
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
) : KotlinAbstractUElement(), 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 { KotlinDumbUElement(psi.nameIdentifier, 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 initializerKind: UastVariableInitialierKind
get() = UastVariableInitialierKind.NO_INITIALIZER
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 val visibility: UastVisibility
get() = UastVisibility.LOCAL
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?
get() = null
override val visibility: UastVisibility
get() = parent.visibility
override fun getSuperFunctions(context: UastContext) = emptyList<UFunction>()
}
@@ -1,35 +0,0 @@
/*
* 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.KtCallableReferenceExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUCallableReferenceExpression(
override val psi: KtCallableReferenceExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UCallableReferenceExpression, PsiElementBacked, KotlinUElementWithType {
override val qualifierExpression by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) }
override val qualifierType: UType? get() = null // TODO
override val callableName: String
get() = psi.callableReference.getReferencedName()
override fun resolve(context: UastContext): UDeclaration? {
throw UnsupportedOperationException()
}
}
@@ -1,30 +0,0 @@
/*
* 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.KtClassLiteralExpression
import org.jetbrains.uast.UClassLiteralExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UType
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUClassLiteralExpression(
override val psi: KtClassLiteralExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UClassLiteralExpression, PsiElementBacked, KotlinUElementWithType {
override val type: UType? get() = null // TODO
}
@@ -1,123 +0,0 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUFunctionCallExpression(
override val psi: KtCallExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UCallExpression, PsiElementBacked, KotlinUElementWithType {
private val resolvedCall by lz { psi.getResolvedCall(psi.analyze(BodyResolveMode.PARTIAL)) }
override val receiverType by lz {
val resolvedCall = this.resolvedCall ?: return@lz null
val receiver = resolvedCall.extensionReceiver ?: resolvedCall.dispatchReceiver ?: return@lz null
KotlinConverter.convert(receiver.type, psi.project, null)
}
override val functionName: String? by lz { resolvedCall?.resultingDescriptor?.name?.asString().orAnonymous() }
override fun matchesFunctionName(name: String) = functionName == name
override val functionNameElement by lz { psi.calleeExpression?.let { KotlinConverter.convert(it, this) } }
override val classReference by lz {
KotlinClassViaConstructorUSimpleReferenceExpression(psi, functionName.orAnonymous("class"), this)
}
override val functionReference by lz {
val calleeExpression = psi.calleeExpression ?: return@lz null
val name = (calleeExpression as? KtSimpleNameExpression)?.getReferencedName() ?: return@lz null
KotlinNameUSimpleReferenceExpression(calleeExpression, name, this)
}
override val valueArgumentCount: Int
get() = psi.valueArguments.size
override val valueArguments by lz { psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } }
override val typeArgumentCount: Int
get() = psi.typeArguments.size
override val typeArguments by lz { psi.typeArguments.map { KotlinConverter.convert(it.typeReference, this) } }
override val kind by lz {
when (resolvedCall?.resultingDescriptor) {
is ConstructorDescriptor -> UastCallKind.CONSTRUCTOR_CALL
else -> UastCallKind.FUNCTION_CALL
}
}
override fun resolve(context: UastContext): UFunction? {
val descriptor = resolvedCall?.resultingDescriptor ?: return null
val source = descriptor.toSource() ?: return null
if (descriptor is ConstructorDescriptor && descriptor.isPrimary
&& source is KtClassOrObject && source.getPrimaryConstructor() == null
&& source.getSecondaryConstructors().isEmpty()) {
return (context.convert(source) as? UClass)?.constructors?.firstOrNull()
}
return context.convert(source) as? UFunction
}
}
class KotlinUComponentFunctionCallExpression(
override val psi: PsiElement,
n: Int,
override val parent: UElement
) : UCallExpression, PsiElementBacked {
override val receiverType: UType?
get() = null
override val valueArgumentCount: Int
get() = 0
override val valueArguments: List<UExpression>
get() = emptyList()
override val typeArgumentCount: Int
get() = 0
override val typeArguments: List<UType>
get() = emptyList()
override val classReference: USimpleReferenceExpression?
get() = null
override val functionName = "component$n"
override val functionReference by lz { KotlinStringUSimpleReferenceExpression(functionName, this) }
override val functionNameElement: UElement?
get() = null
override val kind: UastCallKind
get() = UastCallKind.FUNCTION_CALL
override fun resolve(context: UastContext): UFunction? {
return null
}
}
@@ -1,41 +0,0 @@
/*
* 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.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UObjectLiteralExpression
import org.jetbrains.uast.UType
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUObjectLiteralExpression(
override val psi: KtObjectLiteralExpression,
override val parent: UElement
) : UObjectLiteralExpression, PsiElementBacked, KotlinUElementWithType {
override val declaration by lz { KotlinUClass(psi.objectDeclaration, this, true) }
override fun getExpressionType(): UType? {
val obj = psi.objectDeclaration
val bindingContext = obj.analyze(BodyResolveMode.PARTIAL)
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, obj] as? ClassDescriptor ?: return null
return KotlinConverter.convert(descriptor.getSuperClassOrAny().defaultType, psi.project, null)
}
}
@@ -1,75 +0,0 @@
/*
* 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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUSimpleReferenceExpression(
override val psi: PsiElement,
override val identifier: String,
override val parent: UElement,
private val descriptor: DeclarationDescriptor? = null
) : KotlinAbstractUElement(), USimpleReferenceExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override fun resolve(context: UastContext): UDeclaration? {
val resultingDescriptor = descriptor ?: run {
val ktElement = psi as? KtElement ?: return null
val bindingContext = ktElement.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = ktElement.getResolvedCall(bindingContext) ?: return null
resolvedCall.resultingDescriptor
}
val source = resultingDescriptor.toSource() ?: return null
return context.convert(source) as? UDeclaration
}
}
class KotlinNameUSimpleReferenceExpression(
psi: PsiElement,
identifier: String,
parent: UElement,
descriptor: DeclarationDescriptor? = null
) : KotlinUSimpleReferenceExpression(psi, identifier, parent, descriptor)
class KotlinClassViaConstructorUSimpleReferenceExpression(
override val psi: KtCallExpression,
override val identifier: String,
override val parent: UElement
) : KotlinAbstractUElement(), USimpleReferenceExpression, PsiElementBacked, KotlinUElementWithType {
override fun resolve(context: UastContext): UDeclaration? {
val resolvedCall = psi.getResolvedCall(psi.analyze(BodyResolveMode.PARTIAL))
val resultingDescriptor = resolvedCall?.resultingDescriptor as? ConstructorDescriptor ?: return null
val clazz = resultingDescriptor.containingDeclaration
val source = clazz.toSource() ?: return null
return context.convert(source) as? UClass
}
}
class KotlinStringUSimpleReferenceExpression(
override val identifier: String,
override val parent: UElement
) : KotlinAbstractUElement(), USimpleReferenceExpression {
override fun resolve(context: UastContext) = null
}
@@ -1,103 +0,0 @@
/*
* 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.extensions
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.uast.*
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.visitor.UastVisitor
class PropertyAsCallAndroidUastVisitorExtension : UastVisitorExtension {
override fun invoke(element: UElement, visitor: UastVisitor, context: UastContext) {
val expr = element as? KotlinUSimpleReferenceExpression ?: return
if (expr is KotlinNameUSimpleReferenceExpression) return
val ktElement = expr.psi as? KtElement ?: return
val bindingContext = ktElement.analyze(BodyResolveMode.PARTIAL)
val referenceToAccessor = ktElement.references.firstOrNull { it is SyntheticPropertyAccessorReference } ?: return
val accessorDescriptor = (referenceToAccessor as SyntheticPropertyAccessorReference)
.resolveToDescriptors(bindingContext).firstOrNull() ?: return
val resolvedCall = ktElement.getResolvedCall(bindingContext) ?: return
val setterValue = if (referenceToAccessor is SyntheticPropertyAccessorReference.Setter)
findAssignment(ktElement, ktElement.parent)?.right ?: return
else
null
val callExpression: UCallExpression = object : UCallExpression, PsiElementBacked, SynthesizedUElement {
override val parent = element.parent
override val psi = ktElement
override val receiverType by lz {
val type = (resolvedCall.extensionReceiver ?: resolvedCall.dispatchReceiver)?.type ?: return@lz null
KotlinConverter.convert(type, psi.project, null)
}
override val functionReference = KotlinNameUSimpleReferenceExpression(
expr.psi, expr.identifier, expr.parent, accessorDescriptor)
override val classReference = null
override val functionName = accessorDescriptor.name.asString()
override val functionNameElement by lz { KotlinDumbUElement(ktElement, this) }
override val valueArgumentCount: Int
get() = if (setterValue != null) 1 else 0
override val valueArguments by lz {
if (setterValue != null)
listOf(KotlinConverter.convert(setterValue, this))
else
emptyList()
}
override val typeArgumentCount: Int
get() = resolvedCall.typeArguments.size
override val typeArguments by lz {
resolvedCall.typeArguments.map { KotlinUType(it.value, ktElement.project, this) }
}
override val kind = UastCallKind.FUNCTION_CALL
override fun resolve(context: UastContext): UFunction? {
val source = accessorDescriptor.toSource()
if (source != null) {
(context.convert(source) as? UFunction)?.let { return it }
}
return element.resolveIfCan(context) as? UFunction
}
}
visitor.visitCallExpression(callExpression)
}
private tailrec fun findAssignment(prev: PsiElement?, element: PsiElement?): KtBinaryExpression? = when (element) {
is KtBinaryExpression -> if (element.left == prev && element.operationToken == KtTokens.EQ) element else null
is KtQualifiedExpression -> findAssignment(element, element.parent)
is KtSimpleNameExpression -> findAssignment(element, element.parent)
else -> null
}
}
@@ -1,128 +0,0 @@
/*
* 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 com.intellij.openapi.application.ApplicationManager
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
import org.jetbrains.kotlin.idea.util.findAnnotation
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.uast.kinds.KotlinUastVisibilities
import org.jetbrains.uast.*
private val JVM_STATIC_FQNAME = "kotlin.jvm.JvmStatic"
private val JVM_FIELD_FQNAME = "kotlin.jvm.JvmField"
private val MODIFIER_MAP = mapOf(
UastModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD,
UastModifier.OVERRIDE to KtTokens.OVERRIDE_KEYWORD
)
internal fun KtDeclaration.getVisibility() = when (visibilityModifierType()) {
KtTokens.PRIVATE_KEYWORD -> UastVisibility.PRIVATE
KtTokens.PROTECTED_KEYWORD -> UastVisibility.PROTECTED
KtTokens.INTERNAL_KEYWORD -> KotlinUastVisibilities.INTERNAL
else -> UastVisibility.PUBLIC
}
internal fun KtModifierListOwner.hasModifier(modifier: UastModifier): Boolean {
if (modifier == UastModifier.STATIC) {
// Object literals can't be static
if (this is KtObjectDeclaration && this.isObjectLiteral()) {
return false
}
if (this is KtClassOrObject && !hasModifier(KtTokens.INNER_KEYWORD)) {
return true
}
if (this is KtDeclaration && (parent is KtObjectDeclaration ||
parent is KtClassBody && parent?.parent is KtObjectDeclaration)) {
return hasAnyAnnotation(JVM_STATIC_FQNAME, JVM_FIELD_FQNAME)
}
return false
}
if (modifier == UastModifier.JVM_FIELD) {
var bindingContext: BindingContext? = null
fun getOrCreateBindingContext(): BindingContext {
if (bindingContext == null) {
bindingContext = analyze(BodyResolveMode.PARTIAL)
}
return bindingContext!!
}
if (this is KtProperty) {
val context = getOrCreateBindingContext()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? PropertyDescriptor ?: return false
return context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] ?: false
}
}
if (modifier == UastModifier.FINAL) return hasModifier(KtTokens.FINAL_KEYWORD)
if (modifier == UastModifier.IMMUTABLE && this is KtVariableDeclaration && !this.isVar) return true
val javaModifier = MODIFIER_MAP[modifier] ?: return false
return hasModifier(javaModifier)
}
private fun KtElement.hasAnyAnnotation(vararg annotationFqNames: String): Boolean {
if (this !is KtAnnotated) return false
val bindingContext = analyze(BodyResolveMode.PARTIAL)
for (annotationFqName in annotationFqNames) {
val annotationEntry = findAnnotation(FqName(annotationFqName)) ?: continue
val annotationDescriptor = bindingContext[BindingContext.ANNOTATION, annotationEntry] ?: continue
val classifierDescriptor = annotationDescriptor.type.constructor.declarationDescriptor ?: continue
val fqName = DescriptorUtils.getFqName(classifierDescriptor).asString()
return fqName == annotationFqName
}
return false
}
internal fun KtElement?.resolveCallToUDeclaration(context: UastContext): UDeclaration? {
if (this == null) return null
val resolvedCall = this.getResolvedCall(analyze(BodyResolveMode.PARTIAL)) ?: return null
val source = (resolvedCall.resultingDescriptor).toSource() ?: return null
return context.convert(source) as? UDeclaration
}
@Suppress("NOTHING_TO_INLINE")
internal inline fun String?.orAnonymous(kind: String = ""): String {
return this ?: "<anonymous" + (if (kind.isNotBlank()) " $kind" else "") + ">"
}
internal fun KtAnnotated.getUastAnnotations(parent: UElement) = annotationEntries.map { KotlinUAnnotation(it, parent) }
internal fun DeclarationDescriptor.toSource() = try {
DescriptorToSourceUtils.descriptorToDeclaration(this)
} catch (e: Exception) {
null
}
internal fun <T> lz(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE, initializer)
@@ -1,25 +0,0 @@
/*
* 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.uast.UastClassKind
object KotlinClassKinds {
@JvmField
val COMPANION_OBJECT = UastClassKind("companion object")
}
@@ -1,23 +0,0 @@
/*
* 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.uast.UastFunctionKind
object KotlinFunctionKinds {
val INIT_BLOCK = UastFunctionKind.UastInitializerKind("<init>")
}
@@ -1,24 +0,0 @@
/*
* 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.kinds
import org.jetbrains.uast.UastVisibility
object KotlinUastVisibilities {
@JvmField
val INTERNAL = UastVisibility("internal")
}
@@ -1,24 +0,0 @@
/*
* 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.kinds
import org.jetbrains.uast.kinds.UastVariableInitialierKind
object KotlinVariableInitializerKinds {
@JvmField
val DELEGATION = UastVariableInitialierKind("delegation")
}
@@ -14,9 +14,12 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.psi.PsiElementBacked
abstract class KotlinAbstractUElement : UElement {
@@ -27,4 +30,6 @@ abstract class KotlinAbstractUElement : UElement {
return this.psi == other.psi
}
}
}
abstract class KotlinAbstractUExpression : KotlinAbstractUElement(), UExpression
@@ -0,0 +1,297 @@
/*
* Copyright 2010-2015 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.uast.kotlin
import com.intellij.lang.Language
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtLightParameter
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.java.JavaUastLanguagePlugin
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
import org.jetbrains.uast.kotlin.expressions.KotlinUBreakExpression
import org.jetbrains.uast.kotlin.expressions.KotlinUContinueExpression
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
import org.jetbrains.uast.psi.PsiElementBacked
interface KotlinUastBindingContextProviderService {
fun getBindingContext(element: KtElement): BindingContext
fun getTypeMapper(element: KtElement): KotlinTypeMapper?
}
class KotlinUastLanguagePlugin(override val project: Project) : UastLanguagePlugin {
override val priority = 10
private val javaPlugin by lz { UastLanguagePlugin.getInstances(project).first { it is JavaUastLanguagePlugin } }
override val language: Language
get() = KotlinLanguage.INSTANCE
override fun isFileSupported(fileName: String): Boolean {
return fileName.endsWith(".kt", false) || fileName.endsWith(".kts", false)
}
override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element !is PsiElement) return null
return convertDeclaration(element, parent, requiredType) ?: KotlinConverter.convertPsiElement(element, parent, requiredType)
}
override fun convertElementWithParent(element: PsiElement, requiredType: Class<out UElement>?): UElement? {
if (element !is PsiElement) return null
if (element is PsiFile) return convertDeclaration(element, null, requiredType)
val parent = element.parent ?: return null
val parentUElement = convertElementWithParent(parent, null) ?: return null
return convertElement(element, parentUElement, requiredType)
}
override fun getMethodCallExpression(
element: PsiElement,
containingClassFqName: String?,
methodName: String
): UastLanguagePlugin.ResolvedMethod? {
if (element !is KtCallExpression) return null
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null
val resultingDescriptor = resolvedCall.resultingDescriptor
if (resultingDescriptor !is FunctionDescriptor || resultingDescriptor.name.asString() != methodName) return null
val parent = element.parent ?: return null
val parentUElement = convertElementWithParent(parent, null) ?: return null
val uExpression = KotlinUFunctionCallExpression(element, parentUElement, resolvedCall)
val method = uExpression.resolve() ?: return null
if (method.name != methodName) return null
return UastLanguagePlugin.ResolvedMethod(uExpression, method)
}
override fun getConstructorCallExpression(
element: PsiElement,
fqName: String
): UastLanguagePlugin.ResolvedConstructor? {
if (element !is KtCallExpression) return null
val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null
val resultingDescriptor = resolvedCall.resultingDescriptor
if (resultingDescriptor !is ConstructorDescriptor
|| resultingDescriptor.returnType.constructor.declarationDescriptor?.name?.asString() != fqName) {
return null
}
val parent = element.parent ?: return null
val parentUElement = convertElementWithParent(parent, null) ?: return null
val uExpression = KotlinUFunctionCallExpression(element, parentUElement, resolvedCall)
val method = uExpression.resolve() ?: return null
val containingClass = method.containingClass ?: return null
return UastLanguagePlugin.ResolvedConstructor(uExpression, method, containingClass)
}
private fun convertDeclaration(element: PsiElement, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
if (element is UElement) return element
if (element.isValid) element.getUserData(KOTLIN_CACHED_UELEMENT_KEY)?.let { ref ->
ref.get()?.let { return it }
}
val original = element.originalElement
return when (original) {
is KtLightMethod -> KotlinUMethod.create(original, parent)
is KtLightClass -> KotlinUClass.create(original, parent)
is KtLightField, is KtLightParameter, is UastKotlinPsiParameter, is UastKotlinPsiVariable -> {
KotlinUVariable.create(original as PsiVariable, parent)
}
is KtClassOrObject -> original.toLightClass()?.let { lightClass -> KotlinUClass.create(lightClass, parent) }
is KtFunction -> {
val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null
convertDeclaration(lightMethod, parent, requiredType)
}
is KtPropertyAccessor -> javaPlugin.convertOpt<UMethod>(
LightClassUtil.getLightClassAccessorMethod(original), parent)
is KtProperty -> javaPlugin.convertOpt<UField>(
LightClassUtil.getLightClassBackingField(original), parent)
?: convertDeclaration(element.parent, parent, requiredType)
is KtFile -> KotlinUFile(original, this)
is FakeFileForLightClass -> KotlinUFile(original.navigationElement, this)
else -> null
}
}
override fun isExpressionValueUsed(element: UExpression): Boolean {
return when (element) {
is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null
is KotlinAbstractUExpression -> {
val ktElement = ((element as? PsiElementBacked)?.psi as? KtElement) ?: return false
ktElement.analyze()[BindingContext.USED_AS_EXPRESSION, ktElement] ?: false
}
else -> false
}
}
}
internal inline fun <reified T : UElement> Class<out UElement>?.el(f: () -> UElement?): UElement? {
return if (this == null || T::class.java == this) f() else null
}
internal inline fun <reified T : UElement> Class<out UElement>?.expr(f: () -> UExpression): UExpression {
return if (this == null || T::class.java == this) f() else UastEmptyExpression
}
internal object KotlinConverter {
internal fun convertPsiElement(element: PsiElement?, parent: UElement?, requiredType: Class<out UElement>?): UElement? {
return with (requiredType) { when (element) {
is KtParameterList -> el<UVariableDeclarationsExpression> {
KotlinUVariableDeclarationsExpression(parent).apply {
variables = element.parameters.mapIndexed { i, p ->
KotlinUVariable.create(UastKotlinPsiParameter.create(p, element, parent!!, i), this)
}
}
}
is KtClassBody -> KotlinUExpressionList(element, KotlinSpecialExpressionKinds.CLASS_BODY, parent).apply {
expressions = emptyList()
}
is KtCatchClause -> el<UCatchClause> { KotlinUCatchClause(element, parent) }
is KtExpression -> KotlinConverter.convertExpression(element, parent, requiredType)
else -> {
if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) {
el<UIdentifier> { UIdentifier(element, parent) }
} else {
null
}
}
}}
}
private fun convertVariablesDeclaration(
psi: KtVariableDeclaration,
parent: UElement?
): UVariableDeclarationsExpression {
val parentPsiElement = (parent as? PsiElementBacked)?.psi
val variable = KotlinUVariable.create(UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent)
return KotlinUVariableDeclarationsExpression(parent).apply { variables = listOf(variable) }
}
private fun convertStringTemplateExpression(
expression: KtStringTemplateExpression,
parent: UElement?,
i: Int
): UExpression {
return if (i == 1) KotlinStringTemplateUBinaryExpression(expression, parent).apply {
leftOperand = convert(expression.entries[0], this)
rightOperand = convert(expression.entries[1], this)
} else KotlinStringTemplateUBinaryExpression(expression, parent).apply {
leftOperand = convertStringTemplateExpression(expression, parent, i - 1)
rightOperand = convert(expression.entries[i], this)
}
}
internal fun convert(entry: KtStringTemplateEntry, parent: UElement?): UExpression = when (entry) {
is KtStringTemplateEntryWithExpression -> convertOrEmpty(entry.expression, parent)
is KtEscapeStringTemplateEntry -> KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
else -> {
KotlinStringULiteralExpression(entry, parent)
}
}
internal fun convertExpression(expression: KtExpression, parent: UElement?, requiredType: Class<out UElement>? = null): UExpression {
return with (requiredType) { when (expression) {
is KtVariableDeclaration -> expr<UVariableDeclarationsExpression> { convertVariablesDeclaration(expression, parent) }
is KtStringTemplateExpression -> expr<ULiteralExpression> {
if (expression.entries.isEmpty())
KotlinStringULiteralExpression(expression, parent, "")
else if (expression.entries.size == 1)
convert(expression.entries[0], parent)
else
convertStringTemplateExpression(expression, parent, expression.entries.size - 1)
}
is KtDestructuringDeclaration -> expr<UVariableDeclarationsExpression> {
KotlinUVariableDeclarationsExpression(parent).apply {
val tempAssignment = KotlinUVariable.create(UastKotlinPsiVariable.create(expression, parent!!), parent)
val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
val psiFactory = KtPsiFactory(expression.project)
val initializer = psiFactory.createExpression("${tempAssignment.name}.component${i + 1}()")
KotlinUVariable.create(UastKotlinPsiVariable.create(
entry, tempAssignment.psi, parent, initializer), parent)
}
variables = listOf(tempAssignment) + destructuringAssignments
}
}
is KtLabeledExpression -> expr<ULabeledExpression> { KotlinULabeledExpression(expression, parent) }
is KtClassLiteralExpression -> expr<UClassLiteralExpression> { KotlinUClassLiteralExpression(expression, parent) }
is KtObjectLiteralExpression -> expr<UObjectLiteralExpression> { KotlinUObjectLiteralExpression(expression, parent) }
is KtStringTemplateEntry -> expression.expression?.let { convertExpression(it, parent, requiredType) } ?: UastEmptyExpression
is KtDotQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUQualifiedReferenceExpression(expression, parent) }
is KtSafeQualifiedExpression -> expr<UQualifiedReferenceExpression> { KotlinUSafeQualifiedExpression(expression, parent) }
is KtSimpleNameExpression -> expr<USimpleNameReferenceExpression> {
KotlinUSimpleReferenceExpression(expression, expression.getReferencedName(), parent)
}
is KtCallExpression -> expr<UCallExpression> { KotlinUFunctionCallExpression(expression, parent) }
is KtBinaryExpression -> expr<UBinaryExpression> { KotlinUBinaryExpression(expression, parent) }
is KtParenthesizedExpression -> expr<UParenthesizedExpression> { KotlinUParenthesizedExpression(expression, parent) }
is KtPrefixExpression -> expr<UPrefixExpression> { KotlinUPrefixExpression(expression, parent) }
is KtPostfixExpression -> expr<UPostfixExpression> { KotlinUPostfixExpression(expression, parent) }
is KtThisExpression -> expr<UThisExpression> { KotlinUThisExpression(expression, parent) }
is KtSuperExpression -> expr<USuperExpression> { KotlinUSuperExpression(expression, parent) }
is KtCallableReferenceExpression -> expr<UCallableReferenceExpression> { KotlinUCallableReferenceExpression(expression, parent) }
is KtIsExpression -> expr<UBinaryExpressionWithType> { KotlinUTypeCheckExpression(expression, parent) }
is KtIfExpression -> expr<UIfExpression> { KotlinUIfExpression(expression, parent) }
is KtWhileExpression -> expr<UWhileExpression> { KotlinUWhileExpression(expression, parent) }
is KtDoWhileExpression -> expr<UDoWhileExpression> { KotlinUDoWhileExpression(expression, parent) }
is KtForExpression -> expr<UForEachExpression> { KotlinUForEachExpression(expression, parent) }
is KtWhenExpression -> expr<USwitchExpression> { KotlinUSwitchExpression(expression, parent) }
is KtBreakExpression -> expr<UBreakExpression> { KotlinUBreakExpression(expression, parent) }
is KtContinueExpression -> expr<UContinueExpression> { KotlinUContinueExpression(expression, parent) }
is KtReturnExpression -> expr<UReturnExpression> { KotlinUReturnExpression(expression, parent) }
is KtThrowExpression -> expr<UThrowExpression> { KotlinUThrowExpression(expression, parent) }
is KtBlockExpression -> expr<UBlockExpression> { KotlinUBlockExpression(expression, parent) }
is KtConstantExpression -> expr<ULiteralExpression> { KotlinULiteralExpression(expression, parent) }
is KtTryExpression -> expr<UTryExpression> { KotlinUTryExpression(expression, parent) }
is KtArrayAccessExpression -> expr<UArrayAccessExpression> { KotlinUArrayAccessExpression(expression, parent) }
is KtLambdaExpression -> expr<ULambdaExpression> { KotlinULambdaExpression(expression, parent) }
is KtBinaryExpressionWithTypeRHS -> expr<UBinaryExpressionWithType> { KotlinUBinaryExpressionWithType(expression, parent) }
else -> UnknownKotlinExpression(expression, parent)
}}
}
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression {
return if (expression != null) convertExpression(expression, parent, null) else UastEmptyExpression
}
internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? {
return if (expression != null) convertExpression(expression, parent, null) else null
}
}
@@ -0,0 +1,91 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiAnonymousClass
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.uast.*
import org.jetbrains.uast.java.AbstractJavaUClass
import org.jetbrains.uast.kotlin.declarations.KotlinUMethod
class KotlinUClass private constructor(
psi: KtLightClass,
override val containingElement: UElement?
) : AbstractJavaUClass(), PsiClass by psi {
val ktClass = psi.kotlinOrigin
override val psi = unwrap<UClass, PsiClass>(psi)
override val uastAnchor: UElement
get() = UIdentifier(psi.nameIdentifier, this)
override val uastMethods: List<UMethod> by lz {
val primaryConstructor = ktClass?.getPrimaryConstructor()?.toLightMethods()?.firstOrNull()
val initBlocks = ktClass?.getAnonymousInitializers() ?: emptyList()
psi.methods.map {
if (it is KtLightMethod && it.isConstructor && initBlocks.isNotEmpty()
&& (primaryConstructor == null || it == primaryConstructor)) {
object : KotlinUMethod(it, this@KotlinUClass) {
override val uastBody by lz {
val initializers = ktClass?.getAnonymousInitializers() ?: return@lz UastEmptyExpression
val containingMethod = this
object : UBlockExpression {
override val containingElement: UElement?
get() = containingMethod
override val expressions by lz {
initializers.map {
getLanguagePlugin().convertOpt<UExpression>(it.body, this) ?: UastEmptyExpression
}
}
}
}
}
}
else {
getLanguagePlugin().convert<UMethod>(it, this)
}
}
}
companion object {
fun create(psi: KtLightClass, containingElement: UElement?): UClass {
return if (psi is PsiAnonymousClass)
KotlinUAnonymousClass(psi, containingElement)
else
KotlinUClass(psi, containingElement)
}
}
}
class KotlinUAnonymousClass(
psi: PsiAnonymousClass,
override val containingElement: UElement?
) : AbstractJavaUClass(), UAnonymousClass, PsiAnonymousClass by psi {
override val psi: PsiAnonymousClass = unwrap<UAnonymousClass, PsiAnonymousClass>(psi)
override val uastAnchor: UElement?
get() {
val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null
return UIdentifier(ktClassOrObject.getObjectKeyword(), this)
}
}
@@ -0,0 +1,41 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.uast.*
import java.util.*
class KotlinUFile(override val psi: KtFile, override val languagePlugin: UastLanguagePlugin) : UFile {
override val packageName: String
get() = psi.packageFqName.asString()
override val allCommentsInFile by lz {
val comments = ArrayList<UComment>(0)
psi.accept(object : PsiRecursiveElementWalkingVisitor() {
override fun visitComment(comment: PsiComment) {
comments += UComment(comment, this@KotlinUFile)
}
})
comments
}
override val imports by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } }
override val classes by lz { psi.classes.map { languagePlugin.convert<UClass>(it, this) } }
}
@@ -0,0 +1,53 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.USimpleNameReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUImportStatement(
override val psi: KtImportDirective,
override val containingElement: UElement?
) : UImportStatement {
override val isOnDemand: Boolean
get() = psi.isAllUnder
private val importRef by lz { psi.importedReference?.let { ImportReference(it, psi.name ?: psi.text, this) } }
override val importReference: UElement?
get() = importRef
override fun resolve() = importRef?.resolve()
private class ImportReference(
override val psi: KtExpression,
override val identifier: String,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, PsiElementBacked {
override val resolvedName: String?
get() = identifier
override fun resolve() = psi.getQualifiedElementSelector()?.mainReference?.resolve()?.getMaybeLightElement(this)
}
}
@@ -0,0 +1,58 @@
/*
* 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.uast.kotlin.declarations
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.uast.*
import org.jetbrains.uast.java.JavaUMethod
import org.jetbrains.uast.kotlin.lz
import org.jetbrains.uast.kotlin.unwrap
open class KotlinUMethod(
psi: KtLightMethod,
containingElement: UElement?
) : JavaUMethod(psi, containingElement) {
override val psi: KtLightMethod = unwrap<UMethod, KtLightMethod>(psi)
private val kotlinOrigin = (psi.originalElement as KtLightElement<*, *>).kotlinOrigin
override val uastBody by lz {
val bodyExpression = (kotlinOrigin as? KtFunction)?.bodyExpression ?: return@lz null
getLanguagePlugin().convertElement(bodyExpression, this) as? UExpression
}
companion object {
fun create(psi: KtLightMethod, containingElement: UElement?) = when (psi) {
is KtLightMethodImpl.KtLightAnnotationMethod -> KotlinUAnnotationMethod(psi, containingElement)
else -> KotlinUMethod(psi, containingElement)
}
}
}
class KotlinUAnnotationMethod(
override val psi: KtLightMethodImpl.KtLightAnnotationMethod,
containingElement: UElement?
) : KotlinUMethod(psi, containingElement), UAnnotationMethod {
override val uastDefaultValue by lz {
val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null
val defaultValue = annotationParameter.defaultValue ?: return@lz null
getLanguagePlugin().convertElement(defaultValue, this) as? UExpression
}
}
@@ -0,0 +1,136 @@
/*
* 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.uast.kotlin
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UReferenceExpression
import org.jetbrains.uast.expressions.UTypeReferenceExpression
import org.jetbrains.uast.java.AbstractJavaUVariable
import org.jetbrains.uast.java.JavaAbstractUExpression
import org.jetbrains.uast.java.annotations
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
import org.jetbrains.uast.psi.PsiElementBacked
abstract class AbstractKotlinUVariable : AbstractJavaUVariable() {
override val uastInitializer: UExpression?
get() {
val psi = psi
val initializerExpression = when (psi) {
is UastKotlinPsiVariable -> psi.ktInitializer
is UastKotlinPsiParameter -> psi.ktDefaultValue
is KtLightElement<*, *> -> (psi.kotlinOrigin as? KtVariableDeclaration)?.initializer
else -> null
} ?: return null
return getLanguagePlugin().convertElement(initializerExpression, this) as? UExpression ?: UastEmptyExpression
}
}
class KotlinUVariable(
psi: PsiVariable,
override val containingElement: UElement?
) : AbstractKotlinUVariable(), UVariable, PsiVariable by psi {
override val psi = unwrap<UVariable, PsiVariable>(psi)
override val uastAnnotations by lz { psi.annotations.map { SimpleUAnnotation(it, this) } }
override val typeReference by lz { getLanguagePlugin().convertOpt<UTypeReferenceExpression>(psi.typeElement, this) }
companion object {
fun create(psi: PsiVariable, containingElement: UElement?): UVariable {
return when (psi) {
is PsiEnumConstant -> KotlinUEnumConstant(psi, containingElement)
is PsiLocalVariable -> KotlinULocalVariable(psi, containingElement)
is PsiParameter -> KotlinUParameter(psi, containingElement)
is PsiField -> KotlinUField(psi, containingElement)
else -> KotlinUVariable(psi, containingElement)
}
}
}
}
open class KotlinUParameter(
psi: PsiParameter,
override val containingElement: UElement?
) : AbstractKotlinUVariable(), UParameter, PsiParameter by psi {
override val psi = unwrap<UParameter, PsiParameter>(psi)
}
open class KotlinUField(
psi: PsiField,
override val containingElement: UElement?
) : AbstractKotlinUVariable(), UField, PsiField by psi {
override val psi = unwrap<UField, PsiField>(psi)
}
open class KotlinULocalVariable(
psi: PsiLocalVariable,
override val containingElement: UElement?
) : AbstractKotlinUVariable(), ULocalVariable, PsiLocalVariable by psi {
override val psi = unwrap<ULocalVariable, PsiLocalVariable>(psi)
}
open class KotlinUEnumConstant(
psi: PsiEnumConstant,
override val containingElement: UElement?
) : AbstractKotlinUVariable(), UEnumConstant, PsiEnumConstant by psi {
override val psi = unwrap<UEnumConstant, PsiEnumConstant>(psi)
override val kind: UastCallKind
get() = UastCallKind.CONSTRUCTOR_CALL
override val receiver: UExpression?
get() = null
override val receiverType: PsiType?
get() = null
override val methodIdentifier: UIdentifier?
get() = null
override val classReference: UReferenceExpression?
get() = KotlinEnumConstantClassReference(psi, this)
override val typeArgumentCount: Int
get() = 0
override val typeArguments: List<PsiType>
get() = emptyList()
override val valueArgumentCount: Int
get() = psi.argumentList?.expressions?.size ?: 0
override val valueArguments by lz {
psi.argumentList?.expressions?.map {
getLanguagePlugin().convertElement(it, this) as? UExpression ?: UastEmptyExpression
} ?: emptyList()
}
override val returnType: PsiType?
get() = psi.type
override fun resolve() = psi.resolveMethod()
override val methodName: String?
get() = null
private class KotlinEnumConstantClassReference(
override val psi: PsiEnumConstant,
override val containingElement: UElement?
) : JavaAbstractUExpression(), USimpleNameReferenceExpression, PsiElementBacked {
override fun resolve() = psi.containingClass
override val resolvedName: String?
get() = psi.containingClass?.name
override val identifier: String
get() = psi.containingClass?.name ?: "<error>"
}
}
@@ -14,19 +14,16 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.uast.UBinaryExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UastBinaryOperator
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinStringTemplateUBinaryExpression(
override val psi: KtStringTemplateExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override lateinit var leftOperand: UExpression
internal set
@@ -34,4 +31,9 @@ class KotlinStringTemplateUBinaryExpression(
internal set
override val operator = UastBinaryOperator.PLUS
override val operatorIdentifier: UIdentifier?
get() = null
override fun resolveOperator() = null
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.uast.UArrayAccessExpression
@@ -23,8 +23,8 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUArrayAccessExpression(
override val psi: KtArrayAccessExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UArrayAccessExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UArrayAccessExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) }
override val indices by lz { psi.indexExpressions.map { KotlinConverter.convert(it, this) } }
override val indices by lz { psi.indexExpressions.map { KotlinConverter.convertExpression(it, this) } }
}
@@ -14,26 +14,44 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBinaryExpression(
override val psi: KtBinaryExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
private companion object {
val BITWISE_OPERATORS = mapOf(
"or" to UastBinaryOperator.BITWISE_OR,
"and" to UastBinaryOperator.BITWISE_AND,
"xor" to UastBinaryOperator.BITWISE_XOR
)
}
override val leftOperand by lz { KotlinConverter.convertOrEmpty(psi.left, this) }
override val rightOperand by lz { KotlinConverter.convertOrEmpty(psi.right, this) }
override val operatorIdentifier: UIdentifier?
get() = UIdentifier(psi.operationReference, this)
override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod
override val operator = when (psi.operationToken) {
KtTokens.EQ -> UastBinaryOperator.ASSIGN
KtTokens.PLUS -> UastBinaryOperator.PLUS
KtTokens.MINUS -> UastBinaryOperator.MINUS
KtTokens.MUL -> UastBinaryOperator.MULT
KtTokens.MUL -> UastBinaryOperator.MULTIPLY
KtTokens.DIV -> UastBinaryOperator.DIV
KtTokens.PERC -> UastBinaryOperator.MOD
KtTokens.OROR -> UastBinaryOperator.LOGICAL_OR
@@ -54,14 +72,25 @@ class KotlinUBinaryExpression(
KtTokens.IN_KEYWORD -> KotlinBinaryOperators.IN
KtTokens.NOT_IN -> KotlinBinaryOperators.NOT_IN
KtTokens.RANGE -> KotlinBinaryOperators.RANGE_TO
else -> UastBinaryOperator.UNKNOWN
else -> run { // Handle bitwise operators
val other = UastBinaryOperator.OTHER
val ref = psi.operationReference
val resolvedCall = psi.operationReference.getResolvedCall(ref.analyze()) ?: return@run other
val resultingDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return@run other
val applicableOperator = BITWISE_OPERATORS[resultingDescriptor.name.asString()] ?: return@run other
val containingClass = resultingDescriptor.containingDeclaration as? ClassDescriptor ?: return@run other
if (containingClass.typeConstructor.supertypes.any {
it.constructor.declarationDescriptor?.fqNameSafe?.asString() == "kotlin.Number"
}) applicableOperator else other
}
}
}
class KotlinCustomUBinaryExpression(
override val psi: PsiElement,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpression, PsiElementBacked {
lateinit override var leftOperand: UExpression
internal set
@@ -70,4 +99,9 @@ class KotlinCustomUBinaryExpression(
lateinit override var rightOperand: UExpression
internal set
override val operatorIdentifier: UIdentifier?
get() = null
override fun resolveOperator() = null
}
@@ -14,21 +14,32 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
import org.jetbrains.uast.*
import org.jetbrains.uast.UBinaryExpressionWithType
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UastBinaryExpressionWithTypeKind
import org.jetbrains.uast.expressions.UTypeReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBinaryExpressionWithType(
override val psi: KtBinaryExpressionWithTypeRHS,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpressionWithType, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convert(psi.left, this) }
override val type by lz { KotlinConverter.convert(psi.right, this) }
override val typeReference by lz { psi.right?.let { KotlinConverter.convertTypeReference(it, this) } }
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType, PsiElementBacked,
KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertExpression(psi.left, this) }
override val type by lz { psi.right.toPsiType(this) }
override val typeReference by lz {
psi.right?.let { KotlinUTypeReferenceExpression(it.toPsiType(this), it, this) }
}
override val operationKind = when (psi.operationReference.getReferencedNameElementType()) {
KtTokens.AS_KEYWORD -> UastBinaryExpressionWithTypeKind.TYPE_CAST
KtTokens.AS_SAFE -> KotlinBinaryExpressionWithTypeKinds.SAFE_TYPE_CAST
@@ -38,17 +49,17 @@ class KotlinUBinaryExpressionWithType(
class KotlinCustomUBinaryExpressionWithType(
override val psi: PsiElement,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpressionWithType, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType, PsiElementBacked {
lateinit override var operand: UExpression
internal set
lateinit override var operationKind: UastBinaryExpressionWithTypeKind
internal set
lateinit override var type: UType
lateinit override var type: PsiType
internal set
override var typeReference: UTypeReference? = null
override var typeReference: UTypeReferenceExpression? = null
internal set
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.uast.UBlockExpression
@@ -23,7 +23,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBlockExpression(
override val psi: KtBlockExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UBlockExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBlockExpression, PsiElementBacked, KotlinUElementWithType {
override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, this) } }
}
@@ -14,18 +14,18 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast.expressions
package org.jetbrains.uast.kotlin.expressions
import org.jetbrains.kotlin.psi.KtBreakExpression
import org.jetbrains.kotlin.uast.KotlinAbstractUElement
import org.jetbrains.uast.UBreakExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBreakExpression(
override val psi: KtBreakExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UBreakExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBreakExpression, PsiElementBacked {
override val label: String?
get() = psi.getLabelName()
}
@@ -0,0 +1,46 @@
/*
* 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.uast.kotlin
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.UCallableReferenceExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUCallableReferenceExpression(
override val psi: KtCallableReferenceExpression,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UCallableReferenceExpression, PsiElementBacked, KotlinUElementWithType {
override val qualifierExpression: UExpression?
get() {
if (qualifierType != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this)
}
override val qualifierType by lz {
val ktType = psi.analyze(BodyResolveMode.PARTIAL)[DOUBLE_COLON_LHS, psi.receiverExpression]?.type ?: return@lz null
ktType.toPsiType(this, psi, boxed = true)
}
override val callableName: String
get() = psi.callableReference.getReferencedName()
}
@@ -14,28 +14,31 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtCatchClause
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.UCatchClause
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UType
import org.jetbrains.uast.UVariable
import org.jetbrains.uast.UParameter
import org.jetbrains.uast.expressions.UTypeReferenceExpression
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUCatchClause(
override val psi: KtCatchClause,
override val parent: UElement
override val containingElement: UElement?
) : KotlinAbstractUElement(), UCatchClause, PsiElementBacked {
override val body by lz { KotlinConverter.convertOrEmpty(psi.catchBody, this) }
override val parameters by lz { psi.catchParameter?.let { listOf(KotlinConverter.convert(it, this)) } ?: emptyList<UVariable>() }
override val types by lz {
val catchParameter = psi.catchParameter ?: return@lz emptyList<UType>()
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val parameter = bindingContext[BindingContext.VALUE_PARAMETER, catchParameter] ?: return@lz emptyList<UType>()
listOf(KotlinConverter.convert(parameter.type, psi.project, this))
override val parameters by lz {
val parameter = psi.catchParameter ?: return@lz emptyList<UParameter>()
listOf(KotlinUParameter(UastKotlinPsiParameter.create(parameter, psi, this, 0), this))
}
override val typeReferences by lz {
val parameter = psi.catchParameter ?: return@lz emptyList<UTypeReferenceExpression>()
val typeReference = parameter.typeReference
val type = typeReference.toPsiType(this, boxed = true)
listOf(KotlinUTypeReferenceExpression(type, typeReference, this))
}
}
@@ -0,0 +1,43 @@
/*
* 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.uast.kotlin
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtClassLiteralExpression
import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.UClassLiteralExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUClassLiteralExpression(
override val psi: KtClassLiteralExpression,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UClassLiteralExpression, PsiElementBacked, KotlinUElementWithType {
override val type by lz {
val ktType = psi.analyze(BodyResolveMode.PARTIAL)[DOUBLE_COLON_LHS, psi.receiverExpression]?.type ?: return@lz null
ktType.toPsiType(this, psi, boxed = true)
}
override val expression: UExpression?
get() {
if (type != null) return null
val receiverExpression = psi.receiverExpression ?: return null
return KotlinConverter.convertExpression(receiverExpression, this)
}
}
@@ -14,18 +14,18 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast.expressions
package org.jetbrains.uast.kotlin.expressions
import org.jetbrains.kotlin.psi.KtContinueExpression
import org.jetbrains.kotlin.uast.KotlinAbstractUElement
import org.jetbrains.uast.UContinueExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUContinueExpression(
override val psi: KtContinueExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UContinueExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UContinueExpression, PsiElementBacked {
override val label: String?
get() = psi.getLabelName()
}
@@ -14,17 +14,24 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtDoWhileExpression
import org.jetbrains.uast.UDoWhileExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUDoWhileExpression(
override val psi: KtDoWhileExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UDoWhileExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UDoWhileExpression, PsiElementBacked {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
override val doIdentifier: UIdentifier
get() = UIdentifier(null, this)
override val whileIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
@@ -14,29 +14,28 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UType
import org.jetbrains.uast.psi.PsiElementBacked
interface KotlinUElementWithType : UExpression, PsiElementBacked {
override fun getExpressionType(): UType? {
override fun getExpressionType(): PsiType? {
val ktElement = psi as? KtExpression ?: return null
val ktType = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.EXPRESSION_TYPE_INFO, ktElement]?.type ?: return null
return KotlinConverter.convert(ktType, ktElement.project, null)
val ktType = ktElement.analyze()[BindingContext.EXPRESSION_TYPE_INFO, ktElement]?.type ?: return null
return ktType.toPsiType(this, ktElement, boxed = false)
}
}
interface KotlinEvaluatableUElement : UExpression, PsiElementBacked {
override fun evaluate(): Any? {
val ktElement = psi as? KtExpression ?: return null
val compileTimeConst = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.COMPILE_TIME_VALUE, ktElement]
val compileTimeConst = ktElement.analyze()[BindingContext.COMPILE_TIME_VALUE, ktElement]
return compileTimeConst?.getValue(TypeUtils.NO_EXPECTED_TYPE)
}
}
@@ -14,36 +14,29 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.USpecialExpressionList
import org.jetbrains.uast.UExpressionList
import org.jetbrains.uast.UastSpecialExpressionKind
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUSpecialExpressionList(
open class KotlinUExpressionList(
override val psi: PsiElement?,
override val kind: UastSpecialExpressionKind, // original element
override val parent: UElement
) : KotlinAbstractUElement(), USpecialExpressionList, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
class Empty(psi: PsiElement, expressionType: UastSpecialExpressionKind, parent: UElement) :
KotlinUSpecialExpressionList(psi, expressionType, parent) {
init { expressions = emptyList() }
}
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UExpressionList, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override lateinit var expressions: List<UExpression>
internal set
override fun evaluate(): Any? {
val ktElement = psi as? KtExpression ?: return null
val compileTimeConst = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.COMPILE_TIME_VALUE, ktElement]
val compileTimeConst = ktElement.analyze()[BindingContext.COMPILE_TIME_VALUE, ktElement]
return compileTimeConst?.getValue(TypeUtils.NO_EXPECTED_TYPE)
}
}
@@ -14,17 +14,30 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtForExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UForEachExpression
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.psi.UastPsiParameterNotResolved
class KotlinUForEachExpression(
override val psi: KtForExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UForEachExpression, PsiElementBacked {
override val variable by lz { psi.loopParameter?.let { KotlinConverter.convert(it, this) } ?: UVariableNotResolved }
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UForEachExpression, PsiElementBacked {
override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
override val variable by lz {
val parameter = psi.loopParameter?.let { UastKotlinPsiParameter.create(it, psi, this, 0) }
?: UastPsiParameterNotResolved(psi, KotlinLanguage.INSTANCE)
KotlinUParameter(parameter, this)
}
override val forIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
@@ -0,0 +1,120 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.visitor.UastVisitor
class KotlinUFunctionCallExpression(
override val psi: KtCallExpression,
override val containingElement: UElement?,
private val _resolvedCall: ResolvedCall<*>? = null
) : KotlinAbstractUExpression(), UCallExpression, PsiElementBacked, KotlinUElementWithType {
companion object {
fun resolveSource(descriptor: DeclarationDescriptor, source: PsiElement?): PsiMethod? {
if (descriptor is ConstructorDescriptor && descriptor.isPrimary
&& source is KtClassOrObject && source.getPrimaryConstructor() == null
&& source.getSecondaryConstructors().isEmpty()) {
return source.toLightClass()?.constructors?.firstOrNull()
}
return when (source) {
is KtFunction -> LightClassUtil.getLightClassMethod(source)
is PsiMethod -> source
else -> null
}
}
}
private val resolvedCall by lz {
_resolvedCall ?: psi.getResolvedCall(psi.analyze())
}
override val receiverType by lz {
val resolvedCall = this.resolvedCall ?: return@lz null
val receiver = resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver ?: return@lz null
receiver.type.toPsiType(this, psi, boxed = true)
}
override val methodName by lz { resolvedCall?.resultingDescriptor?.name?.asString() }
override val classReference by lz {
KotlinClassViaConstructorUSimpleReferenceExpression(psi, methodName.orAnonymous("class"), this)
}
override val methodIdentifier by lz {
val calleeExpression = psi.calleeExpression ?: return@lz null
UIdentifier(calleeExpression, this)
}
override val valueArgumentCount: Int
get() = psi.valueArguments.size
override val valueArguments by lz { psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } }
override val typeArgumentCount: Int
get() = psi.typeArguments.size
override val typeArguments by lz { psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) } }
override val returnType: PsiType?
get() = getExpressionType()
override val kind by lz {
when (resolvedCall?.resultingDescriptor) {
is ConstructorDescriptor -> UastCallKind.CONSTRUCTOR_CALL
else -> UastCallKind.METHOD_CALL
}
}
override val receiver: UExpression?
get() {
return if (containingElement is UQualifiedReferenceExpression && containingElement.selector == this)
containingElement.receiver
else
null
}
override fun resolve(): PsiMethod? {
val descriptor = resolvedCall?.resultingDescriptor ?: return null
val source = descriptor.toSource() ?: return null
return resolveSource(descriptor, source)
}
override fun accept(visitor: UastVisitor) {
if (visitor.visitCallExpression(this)) return
methodIdentifier?.accept(visitor)
classReference.accept(visitor)
valueArguments.acceptList(visitor)
visitor.afterVisitCallExpression(this)
}
}
@@ -14,19 +14,26 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtIfExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UIfExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUIfExpression(
override val psi: KtIfExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UIfExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UIfExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val thenBranch by lz { KotlinConverter.convertOrNull(psi.then, this) }
override val elseBranch by lz { KotlinConverter.convertOrNull(psi.`else`, this) }
override val thenExpression by lz { KotlinConverter.convertOrNull(psi.then, this) }
override val elseExpression by lz { KotlinConverter.convertOrNull(psi.`else`, this) }
override val isTernary = false
override val ifIdentifier: UIdentifier
get() = UIdentifier(null, this)
override val elseIdentifier: UIdentifier?
get() = null
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtLabeledExpression
import org.jetbrains.uast.UElement
@@ -23,8 +23,8 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinULabeledExpression(
override val psi: KtLabeledExpression,
override val parent: UElement
) : KotlinAbstractUElement(), ULabeledExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), ULabeledExpression, PsiElementBacked {
override val label: String
get() = psi.getLabelName().orAnonymous("label")
@@ -14,25 +14,35 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.*
import org.jetbrains.uast.*
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.withMargin
class KotlinULambdaExpression(
override val psi: KtLambdaExpression,
override val parent: UElement
) : KotlinAbstractUElement(), ULambdaExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), ULambdaExpression, PsiElementBacked, KotlinUElementWithType {
override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
override val valueParameters by lz { psi.valueParameters.map { KotlinConverter.convert(it, this) } }
override fun renderString(): String {
override val valueParameters by lz {
psi.valueParameters.mapIndexed { i, p ->
KotlinUParameter(UastKotlinPsiParameter.create(p, psi, this, i), this)
}
}
override fun asRenderString(): String {
val renderedValueParameters = if (valueParameters.isEmpty())
""
else
valueParameters.joinToString { it.renderString() } + " ->\n"
valueParameters.joinToString { it.asRenderString() } + " ->\n"
val expressions = (body as? UBlockExpression)?.expressions
?.joinToString("\n") { it.renderString().withMargin } ?: body.renderString()
?.joinToString("\n") { it.asRenderString().withMargin } ?: body.asRenderString()
return "{ " + renderedValueParameters + "\n" + expressions + "\n}"
}
@@ -14,11 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULiteralExpression
@@ -26,19 +26,19 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinULiteralExpression(
override val psi: KtConstantExpression,
override val parent: UElement
) : KotlinAbstractUElement(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val isNull: Boolean
get() = psi.isNullExpression()
get() = psi.unwrapBlockOrParenthesis().node?.elementType == KtNodeTypes.NULL
override val value by lz { evaluate() }
}
class KotlinStringULiteralExpression(
override val psi: PsiElement,
override val parent: UElement,
override val containingElement: UElement?,
val text: String? = null
) : KotlinAbstractUElement(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType{
) : KotlinAbstractUExpression(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType{
override val value: String
get() = text ?: StringUtil.unescapeStringCharacters(psi.text)
@@ -0,0 +1,72 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUObjectLiteralExpression(
override val psi: KtObjectLiteralExpression,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UObjectLiteralExpression, PsiElementBacked, KotlinUElementWithType {
override val declaration by lz { getLanguagePlugin().convert<UClass>(psi.objectDeclaration.toLightClass()!!, this) }
override fun getExpressionType() = psi.objectDeclaration.toPsiType()
private val superClassConstructorCall by lz {
psi.objectDeclaration.getSuperTypeListEntries().firstOrNull { it is KtSuperTypeCallEntry } as? KtSuperTypeCallEntry
}
override val classReference: UReferenceExpression? by lz { superClassConstructorCall?.let { ObjectLiteralClassReference(it, this) } }
override val valueArgumentCount: Int
get() = superClassConstructorCall?.valueArguments?.size ?: 0
override val valueArguments by lz {
val psi = superClassConstructorCall ?: return@lz emptyList<UExpression>()
psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) }
}
override val typeArgumentCount: Int
get() = superClassConstructorCall?.typeArguments?.size ?: 0
override val typeArguments by lz {
val psi = superClassConstructorCall ?: return@lz emptyList<PsiType>()
psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) }
}
override fun resolve() = superClassConstructorCall?.resolveCallToDeclaration(this) as? PsiMethod
private class ObjectLiteralClassReference(
override val psi: KtSuperTypeCallEntry,
override val containingElement: UElement?
) : KotlinAbstractUElement(), USimpleNameReferenceExpression, PsiElementBacked {
override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass
override val resolvedName: String?
get() = identifier
override val identifier: String
get() = psi.name ?: "<error>"
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
import org.jetbrains.uast.UElement
@@ -23,7 +23,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUParenthesizedExpression(
override val psi: KtParenthesizedExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UParenthesizedExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UParenthesizedExpression, PsiElementBacked, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrEmpty(psi.expression, this) }
}
@@ -14,19 +14,18 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtPostfixExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UPostfixExpression
import org.jetbrains.uast.UastPostfixOperator
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUPostfixExpression(
override val psi: KtPostfixExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UPostfixExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UPostfixExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement, UResolvable {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operator = when (psi.operationToken) {
@@ -35,4 +34,14 @@ class KotlinUPostfixExpression(
KtTokens.EXCLEXCL -> KotlinPostfixOperators.EXCLEXCL
else -> UastPostfixOperator.UNKNOWN
}
override val operatorIdentifier: UIdentifier?
get() = UIdentifier(psi.operationReference, this)
override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod
override fun resolve(): PsiMethod? = when (psi.operationToken) {
KtTokens.EXCLEXCL -> operand.tryResolve() as? PsiMethod
else -> null
}
}
@@ -14,21 +14,28 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtPrefixExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UPrefixExpression
import org.jetbrains.uast.UastPrefixOperator
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUPrefixExpression(
override val psi: KtPrefixExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UPrefixExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UPrefixExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operatorIdentifier: UIdentifier?
get() = UIdentifier(psi.operationReference, this)
override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod
override val operator = when (psi.operationToken) {
KtTokens.EXCL -> UastPrefixOperator.LOGICAL_NOT
KtTokens.PLUS -> UastPrefixOperator.UNARY_PLUS
@@ -14,42 +14,53 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.UastQualifiedExpressionAccessType
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUQualifiedExpression(
class KotlinUQualifiedReferenceExpression(
override val psi: KtDotQualifiedExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UQualifiedExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression,
PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) }
override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) }
override val accessType = UastQualifiedExpressionAccessType.SIMPLE
override fun resolve() = psi.selectorExpression?.resolveCallToDeclaration(this)
override fun resolve(context: UastContext) = psi.selectorExpression.resolveCallToUDeclaration(context)
override val resolvedName: String?
get() = (resolve() as? PsiNamedElement)?.name
}
class KotlinUComponentQualifiedExpression(
class KotlinUComponentQualifiedReferenceExpression(
override val psi: KtDestructuringDeclarationEntry,
override val parent: UElement
) : KotlinAbstractUElement(), UQualifiedExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression,
PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val accessType = UastQualifiedExpressionAccessType.SIMPLE
override lateinit var receiver: UExpression
internal set
override lateinit var selector: UExpression
internal set
override val accessType = UastQualifiedExpressionAccessType.SIMPLE
override fun resolve(context: UastContext): UDeclaration? {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
override val resolvedName: String?
get() = psi.analyze()[BindingContext.COMPONENT_RESOLVED_CALL, psi]?.resultingDescriptor?.name?.asString()
override fun resolve(): PsiElement? {
val bindingContext = psi.analyze()
val descriptor = bindingContext[BindingContext.COMPONENT_RESOLVED_CALL, psi]?.resultingDescriptor ?: return null
val source = descriptor.toSource() ?: return null
return context.convert(source) as? UDeclaration
return descriptor.toSource()?.getMaybeLightElement(this)
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtReturnExpression
import org.jetbrains.uast.UElement
@@ -23,7 +23,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUReturnExpression(
override val psi: KtReturnExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UReturnExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UReturnExpression, PsiElementBacked, KotlinUElementWithType {
override val returnExpression by lz { KotlinConverter.convertOrNull(psi.returnedExpression, this) }
}
@@ -14,21 +14,25 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.psi.KtSafeQualifiedExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UQualifiedExpression
import org.jetbrains.uast.UastContext
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUSafeQualifiedExpression(
override val psi: KtSafeQualifiedExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UQualifiedExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UQualifiedReferenceExpression,
PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.receiverExpression, this) }
override val selector by lz { KotlinConverter.convertOrEmpty(psi.selectorExpression, this) }
override val accessType = KotlinQualifiedExpressionAccessTypes.SAFE
override fun resolve(context: UastContext) = psi.selectorExpression.resolveCallToUDeclaration(context)
override val resolvedName: String?
get() = (resolve() as? PsiNamedElement)?.name
override fun resolve() = psi.selectorExpression?.resolveCallToDeclaration(this)
}
@@ -0,0 +1,207 @@
/*
* 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.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.utils.addToStdlib.constant
import org.jetbrains.uast.*
import org.jetbrains.uast.expressions.UReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.visitor.UastVisitor
open class KotlinUSimpleReferenceExpression(
override val psi: KtSimpleNameExpression,
override val identifier: String,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
private val resolvedDeclaration by lz { psi.resolveCallToDeclaration(this) }
override fun resolve() = resolvedDeclaration
override val resolvedName: String?
get() = (resolvedDeclaration as? PsiNamedElement)?.name
override fun accept(visitor: UastVisitor) {
visitor.visitSimpleNameReferenceExpression(this)
// Visit Kotlin get-set synthetic Java property calls as function calls
val bindingContext = psi.analyze()
val access = psi.readWriteAccess()
val resolvedCall = psi.getResolvedCall(bindingContext)
val resultingDescriptor = resolvedCall?.resultingDescriptor as? SyntheticJavaPropertyDescriptor
if (resultingDescriptor != null) {
val setterValue = if (access.isWrite) {
findAssignment(psi, psi.parent)?.right ?: run {
visitor.afterVisitSimpleNameReferenceExpression(this)
return
}
} else {
null
}
if (resolvedCall != null) {
if (access.isRead) {
val getDescriptor = resultingDescriptor.getMethod
KotlinAccessorCallExpression(psi, this, resolvedCall, getDescriptor, null).accept(visitor)
}
if (access.isWrite && setterValue != null) {
val setDescriptor = resultingDescriptor.setMethod
if (setDescriptor != null) {
KotlinAccessorCallExpression(psi, this, resolvedCall, setDescriptor, setterValue).accept(visitor)
}
}
}
}
visitor.afterVisitSimpleNameReferenceExpression(this)
}
private tailrec fun findAssignment(prev: PsiElement?, element: PsiElement?): KtBinaryExpression? = when (element) {
is KtBinaryExpression -> if (element.left == prev && element.operationToken == KtTokens.EQ) element else null
is KtQualifiedExpression -> findAssignment(element, element.parent)
is KtSimpleNameExpression -> findAssignment(element, element.parent)
else -> null
}
class KotlinAccessorCallExpression(
override val psi: KtElement,
override val containingElement: KotlinUSimpleReferenceExpression,
private val resolvedCall: ResolvedCall<*>,
private val accessorDescriptor: DeclarationDescriptor,
val setterValue: KtExpression?
) : UCallExpression, PsiElementBacked {
override val methodName: String?
get() = accessorDescriptor.name.asString()
override val receiver: UExpression?
get() {
val containingElement = containingElement.containingElement
return if (containingElement is UQualifiedReferenceExpression && containingElement.selector == this)
containingElement.receiver
else
null
}
override val receiverType by lz {
val type = (resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver)?.type ?: return@lz null
type.toPsiType(this, psi, boxed = true)
}
override val methodIdentifier: UIdentifier?
get() = UIdentifier(containingElement.psi, this)
override val classReference: UReferenceExpression?
get() = null
override val valueArgumentCount: Int
get() = if (setterValue != null) 1 else 0
override val valueArguments by lz {
if (setterValue != null)
listOf(KotlinConverter.convertOrEmpty(setterValue, this))
else
emptyList()
}
override val typeArgumentCount: Int
get() = resolvedCall.typeArguments.size
override val typeArguments by lz {
resolvedCall.typeArguments.values.map { it.toPsiType(this, psi, true) }
}
override val returnType by lz {
(accessorDescriptor as? CallableDescriptor)?.returnType?.toPsiType(this, psi, boxed = false)
}
override val kind: UastCallKind
get() = UastCallKind.METHOD_CALL
override fun resolve(): PsiMethod? {
val source = accessorDescriptor.toSource()
return KotlinUFunctionCallExpression.resolveSource(accessorDescriptor, source)
}
}
enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) {
READ(true, false), WRITE(false, true), READ_WRITE(true, true)
}
private fun KtExpression.readWriteAccess(): ReferenceAccess {
var expression = getQualifiedExpressionForSelectorOrThis()
loop@ while (true) {
val parent = expression.parent
when (parent) {
is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
else -> break@loop
}
}
val assignment = expression.getAssignmentByLHS()
if (assignment != null) {
when (assignment.operationToken) {
KtTokens.EQ -> return ReferenceAccess.WRITE
else -> return ReferenceAccess.READ_WRITE
}
}
return if ((expression.parent as? KtUnaryExpression)?.operationToken
in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) })
ReferenceAccess.READ_WRITE
else
ReferenceAccess.READ
}
}
class KotlinClassViaConstructorUSimpleReferenceExpression(
override val psi: KtCallExpression,
override val identifier: String,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression, PsiElementBacked, KotlinUElementWithType {
override val resolvedName: String?
get() = (psi.getResolvedCall(psi.analyze())?.resultingDescriptor as? ConstructorDescriptor)
?.containingDeclaration?.name?.asString()
override fun resolve(): PsiElement? {
val resolvedCall = psi.getResolvedCall(psi.analyze())
val resultingDescriptor = resolvedCall?.resultingDescriptor as? ConstructorDescriptor ?: return null
val clazz = resultingDescriptor.containingDeclaration
return clazz.toSource()?.getMaybeLightElement(this)
}
}
class KotlinStringUSimpleReferenceExpression(
override val identifier: String,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USimpleNameReferenceExpression {
override fun resolve() = null
override val resolvedName: String?
get() = identifier
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtSuperExpression
import org.jetbrains.uast.UElement
@@ -23,5 +23,5 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUSuperExpression(
override val psi: KtSuperExpression,
override val parent: UElement
) : KotlinAbstractUElement(), USuperExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USuperExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement
@@ -14,40 +14,42 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.*
import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.psi.PsiElementBacked
import org.jetbrains.uast.visitor.UastVisitor
class KotlinUSwitchExpression(
override val psi: KtWhenExpression,
override val parent: UElement
) : KotlinAbstractUElement(), USwitchExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), USwitchExpression, PsiElementBacked, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
override val body: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this) {
override fun renderString() = expressions.joinToString("\n") { it.renderString().withMargin }
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this) {
override fun asRenderString() = expressions.joinToString("\n") { it.asRenderString().withMargin }
}.apply {
expressions = this@KotlinUSwitchExpression.psi.entries.map { KotlinUSwitchEntry(it, this) }
}
}
override fun renderString() = buildString {
val expr = expression?.let { "(" + it.renderString() + ") " } ?: ""
override fun asRenderString() = buildString {
val expr = expression?.let { "(" + it.asRenderString() + ") " } ?: ""
appendln("switch $expr {")
appendln(body.renderString())
appendln(body.asRenderString())
appendln("}")
}
override val switchIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
class KotlinUSwitchEntry(
override val psi: KtWhenEntry,
override val parent: UExpression
) : KotlinAbstractUElement(), USwitchClauseExpressionWithBody, PsiElementBacked {
override val containingElement: UExpression
) : KotlinAbstractUExpression(), USwitchClauseExpressionWithBody, PsiElementBacked {
override val caseValues by lz {
psi.conditions.map { when (it) {
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply {
@@ -65,32 +67,33 @@ class KotlinUSwitchEntry(
else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK
}
val typeRef = it.typeReference
type = KotlinConverter.convert(typeRef, this)
typeReference = typeRef?.let { KotlinConverter.convertTypeReference(it, this) }
val type = typeRef.toPsiType(this, boxed = true)
this.type = type
typeReference = typeRef?.let { KotlinUTypeReferenceExpression(type, it, this) }
}
is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(it.expression, this)
else -> EmptyUExpression(this)
else -> UastEmptyExpression
}}
}
override val body: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this) {
override fun renderString() = buildString {
object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this) {
override fun asRenderString() = buildString {
appendln("{")
expressions.forEach { appendln(it.renderString().withMargin) }
expressions.forEach { appendln(it.asRenderString().withMargin) }
appendln("}")
}
}.apply {
val exprPsi = this@KotlinUSwitchEntry.psi.expression
val userExpressions = when (exprPsi) {
is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convert(it, this) }
is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convertExpression(it, this) }
else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this))
}
parent
containingElement
expressions = userExpressions + object : UBreakExpression {
override val label: String?
get() = null
override val parent: UElement?
override val containingElement: UElement?
get() = this@KotlinUSwitchEntry
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtThisExpression
import org.jetbrains.uast.UElement
@@ -23,5 +23,5 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUThisExpression(
override val psi: KtThisExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UThisExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UThisExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtThrowExpression
import org.jetbrains.uast.UElement
@@ -23,7 +23,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUThrowExpression(
override val psi: KtThrowExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UThrowExpression, PsiElementBacked, KotlinUElementWithType {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UThrowExpression, PsiElementBacked, KotlinUElementWithType {
override val thrownExpression by lz { KotlinConverter.convertOrEmpty(psi.thrownExpression, this) }
}
@@ -14,20 +14,32 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiResourceListElement
import org.jetbrains.kotlin.psi.KtTryExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UTryExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUTryExpression(
override val psi: KtTryExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UTryExpression, PsiElementBacked, KotlinUElementWithType {
override val tryClause by lz { KotlinConverter.convert(psi.tryBlock, this) }
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UTryExpression, PsiElementBacked, KotlinUElementWithType {
override val tryClause by lz { KotlinConverter.convertExpression(psi.tryBlock, this) }
override val catchClauses by lz { psi.catchClauses.map { KotlinUCatchClause(it, this) } }
override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convert(it, this) } }
override val resources: List<UElement>?
override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, this) } }
override val resources: List<PsiResourceListElement>?
get() = null
override val isResources: Boolean
get() = false
override val tryIdentifier: UIdentifier
get() = UIdentifier(null, this)
override val finallyIdentifier: UIdentifier?
get() = null
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtIsExpression
import org.jetbrains.uast.UBinaryExpressionWithType
@@ -23,10 +23,15 @@ import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUTypeCheckExpression(
override val psi: KtIsExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UBinaryExpressionWithType, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convert(psi.leftHandSide, this) }
override val type by lz { KotlinConverter.convert(psi.typeReference, this) }
override val typeReference by lz { psi.typeReference?.let { KotlinConverter.convertTypeReference(it, this) } }
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UBinaryExpressionWithType, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
override val operand by lz { KotlinConverter.convertExpression(psi.leftHandSide, this) }
override val type by lz { psi.typeReference.toPsiType(this) }
override val typeReference by lz {
psi.typeReference?.let { KotlinUTypeReferenceExpression(it.toPsiType(this), it, this) }
}
override val operationKind = KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK
}
@@ -0,0 +1,13 @@
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import org.jetbrains.uast.UElement
import org.jetbrains.uast.expressions.UTypeReferenceExpression
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUTypeReferenceExpression(
override val type: PsiType,
override val psi: PsiElement?,
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UTypeReferenceExpression, PsiElementBacked, KotlinUElementWithType
@@ -15,9 +15,11 @@
*/
package org.jetbrains.uast
import org.jetbrains.kotlin.uast.KotlinAbstractUElement
import org.jetbrains.uast.kotlin.KotlinAbstractUExpression
class KotlinUDeclarationsExpression(override val parent: UElement) : KotlinAbstractUElement(), UDeclarationsExpression {
override lateinit var declarations: List<UElement>
class KotlinUVariableDeclarationsExpression(
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UVariableDeclarationsExpression {
override lateinit var variables: List<UVariable>
internal set
}
@@ -14,17 +14,21 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtWhileExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIdentifier
import org.jetbrains.uast.UWhileExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUWhileExpression(
override val psi: KtWhileExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UWhileExpression, PsiElementBacked {
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UWhileExpression, PsiElementBacked {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
override val whileIdentifier: UIdentifier
get() = UIdentifier(null, this)
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.uast.UElement
@@ -23,7 +23,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class UnknownKotlinExpression(
override val psi: KtExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UExpression, PsiElementBacked {
override fun logString() = "[!] UnknownKotlinExpression ($psi)"
override val containingElement: UElement?
) : KotlinAbstractUExpression(), UExpression, PsiElementBacked {
override fun asLogString() = "[!] UnknownKotlinExpression ($psi)"
}
@@ -0,0 +1,58 @@
package org.jetbrains.uast.kotlin.internal
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension
import org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService
class CliKotlinUastBindingContextProviderService : KotlinUastBindingContextProviderService {
val Project.analysisCompletedHandler: UastAnalysisCompletedHandlerExtension?
get() = getExtensions(AnalysisCompletedHandlerExtension.extensionPointName)
.filterIsInstance<UastAnalysisCompletedHandlerExtension>()
.firstOrNull()
override fun getBindingContext(element: KtElement): BindingContext {
return element.project.analysisCompletedHandler?.getBindingContext() ?: BindingContext.EMPTY
}
override fun getTypeMapper(element: KtElement): KotlinTypeMapper? {
return element.project.analysisCompletedHandler?.getTypeMapper()
}
}
class UastAnalysisCompletedHandlerExtension : AnalysisCompletedHandlerExtension {
private var context: BindingContext? = null
private var typeMapper: KotlinTypeMapper? = null
fun getBindingContext() = context
fun getTypeMapper(): KotlinTypeMapper? {
if (typeMapper != null) return typeMapper
val bindingContext = context ?: return null
val typeMapper = KotlinTypeMapper(bindingContext, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
this.typeMapper = typeMapper
return typeMapper
}
override fun analysisCompleted(
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
context = bindingTrace.bindingContext
return null
}
}
@@ -0,0 +1,37 @@
/*
* 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.uast.kotlin.internal
import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.kotlin.KotlinUastBindingContextProviderService
class IdeaKotlinUastBindingContextProviderService : KotlinUastBindingContextProviderService {
override fun getBindingContext(element: KtElement) = element.analyze(BodyResolveMode.PARTIAL)
override fun getTypeMapper(element: KtElement): KotlinTypeMapper? {
return KotlinTypeMapper(getBindingContext(element),
ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME, false)
}
}
@@ -0,0 +1,158 @@
/*
* 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.uast.kotlin
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiPrimitiveType
import com.intellij.psi.PsiType
import com.intellij.psi.impl.cache.TypeInfo
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.compiled.SignatureParsing
import com.intellij.psi.impl.compiled.StubBuildingVisitor
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.uast.*
import java.lang.ref.WeakReference
import java.text.StringCharacterIterator
internal val KOTLIN_CACHED_UELEMENT_KEY = Key.create<WeakReference<UElement>>("cached-kotlin-uelement")
@Suppress("NOTHING_TO_INLINE")
internal inline fun String?.orAnonymous(kind: String = ""): String {
return this ?: "<anonymous" + (if (kind.isNotBlank()) " $kind" else "") + ">"
}
internal fun DeclarationDescriptor.toSource() = try {
DescriptorToSourceUtils.descriptorToDeclaration(this)
} catch (e: Exception) {
null
}
internal fun <T> lz(initializer: () -> T) = lazy(LazyThreadSafetyMode.NONE, initializer)
internal fun KotlinType.toPsiType(source: UElement, element: KtElement, boxed: Boolean): PsiType {
if (this.isError) return UastErrorType
if (arguments.isEmpty()) {
val typeFqName = this.constructor.declarationDescriptor?.fqNameSafe?.asString()
fun PsiPrimitiveType.orBoxed() = if (boxed) getBoxedType(element) else this
val psiType = when (typeFqName) {
"kotlin.Int" -> PsiType.INT.orBoxed()
"kotlin.Long" -> PsiType.LONG.orBoxed()
"kotlin.Short" -> PsiType.SHORT.orBoxed()
"kotlin.Boolean" -> PsiType.BOOLEAN.orBoxed()
"kotlin.Byte" -> PsiType.BYTE.orBoxed()
"kotlin.Char" -> PsiType.CHAR.orBoxed()
"kotlin.Double" -> PsiType.DOUBLE.orBoxed()
"kotlin.Float" -> PsiType.FLOAT.orBoxed()
"kotlin.String" -> PsiType.getJavaLangString(element.manager, GlobalSearchScope.projectScope(element.project))
else -> null
}
if (psiType != null) return psiType
}
val project = element.project
val typeMapper = ServiceManager.getService(project, KotlinUastBindingContextProviderService::class.java)
.getTypeMapper(element) ?: return UastErrorType
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT
typeMapper.mapType(this, signatureWriter, typeMappingMode)
val signature = StringCharacterIterator(signatureWriter.toString())
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
val typeInfo = TypeInfo.fromString(javaType, false)
val typeText = TypeInfo.createTypeText(typeInfo) ?: return UastErrorType
return ClsTypeElementImpl(source.getParentOfType<UDeclaration>(false)?.psi ?: element, typeText, '\u0000').type
}
internal fun KtTypeReference?.toPsiType(source: UElement, boxed: Boolean = false): PsiType {
if (this == null) return UastErrorType
return (analyze()[BindingContext.TYPE, this] ?: return UastErrorType).toPsiType(source, this, boxed)
}
internal fun KtClassOrObject.toPsiType(): PsiType {
val lightClass = toLightClass() ?: return UastErrorType
return PsiTypesUtil.getClassType(lightClass)
}
internal fun PsiElement.getMaybeLightElement(context: UElement): PsiElement? {
return when (this) {
is KtVariableDeclaration -> {
val lightElement = toLightElements().firstOrNull()
if (lightElement != null) return lightElement
val languagePlugin = context.getLanguagePlugin()
val uElement = languagePlugin.convertElementWithParent(this, null)
when (uElement) {
is UDeclaration -> uElement.psi
is UVariableDeclarationsExpression -> uElement.variables.firstOrNull()?.psi
else -> null
}
}
is KtDeclaration -> toLightElements().firstOrNull()
is KtElement -> null
else -> this
}
}
internal fun KtElement.resolveCallToDeclaration(
context: KotlinAbstractUElement,
resultingDescriptor: DeclarationDescriptor? = null
): PsiElement? {
val descriptor = resultingDescriptor ?: run {
val resolvedCall = getResolvedCall(analyze()) ?: return null
resolvedCall.resultingDescriptor
}
return descriptor.toSource()?.getMaybeLightElement(context)
}
internal fun KtExpression.unwrapBlockOrParenthesis(): KtExpression {
val innerExpression = KtPsiUtil.safeDeparenthesize(this)
if (innerExpression is KtBlockExpression) {
val statement = innerExpression.statements.singleOrNull() ?: return this
return KtPsiUtil.safeDeparenthesize(statement)
}
return innerExpression
}
internal fun KtElement.analyze(): BindingContext {
return ServiceManager.getService(project, KotlinUastBindingContextProviderService::class.java)
?.getBindingContext(this) ?: BindingContext.EMPTY
}
internal inline fun <reified T : UDeclaration, reified P : PsiElement> unwrap(element: P): P {
val unwrapped = if (element is T) element.psi else element
assert(unwrapped !is UElement)
return unwrapped as P
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.uast.UastBinaryExpressionWithTypeKind
@@ -14,13 +14,14 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.uast.UastBinaryOperator
object KotlinBinaryOperators {
@JvmField
val IN = UastBinaryOperator("in")
@JvmField
val NOT_IN = UastBinaryOperator("!in")
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.uast.UastPostfixOperator
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
package org.jetbrains.uast.kotlin
import org.jetbrains.uast.UastQualifiedExpressionAccessType
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.uast.kinds
package org.jetbrains.uast.kotlin.kinds
import org.jetbrains.uast.UastSpecialExpressionKind
@@ -27,7 +27,4 @@ object KotlinSpecialExpressionKinds {
@JvmField
val CLASS_BODY = UastSpecialExpressionKind("class_body")
@JvmField
val VARARG = UastSpecialExpressionKind("vararg")
}
@@ -0,0 +1,54 @@
package org.jetbrains.uast.kotlin.psi
import com.intellij.lang.Language
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiParameter
import com.intellij.psi.PsiType
import com.intellij.psi.impl.light.LightParameter
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastErrorType
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.kotlin.analyze
import org.jetbrains.uast.kotlin.toPsiType
class UastKotlinPsiParameter(
name: String,
type: PsiType,
parent: PsiElement,
language: Language,
isVarArgs: Boolean,
val ktDefaultValue: KtExpression?,
val ktParameter: KtParameter
) : LightParameter(name, type, parent, language, isVarArgs) {
companion object {
fun create(parameter: KtParameter, parent: PsiElement, containingElement: UElement, index: Int): PsiParameter {
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
return UastKotlinPsiParameter(
parameter.name ?: "p$index",
(parameter.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, parameter] as? VariableDescriptor)
?.type?.toPsiType(containingElement, parameter, boxed = false) ?: UastErrorType,
psiParent,
KotlinLanguage.INSTANCE,
parameter.isVarArg,
parameter.defaultValue,
parameter)
}
}
override fun getContainingFile(): PsiFile? = ktParameter.containingFile
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return ktParameter == (other as? UastKotlinPsiParameter)?.ktParameter
}
override fun hashCode() = ktParameter.hashCode()
}
@@ -0,0 +1,87 @@
package org.jetbrains.uast.kotlin.psi
import com.intellij.lang.Language
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.elements.LightVariableBuilder
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastErrorType
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.kotlin.analyze
import org.jetbrains.uast.kotlin.orAnonymous
import org.jetbrains.uast.kotlin.toPsiType
class UastKotlinPsiVariable(
manager: PsiManager,
name: String,
type: PsiType,
language: Language,
val ktInitializer: KtExpression?,
val psiParent: PsiElement?,
val containingElement: UElement,
val ktElement: KtElement
) : LightVariableBuilder(manager, name, type, language), PsiLocalVariable {
override fun getParent() = psiParent
override fun hasInitializer() = ktInitializer != null
override fun getInitializer(): PsiExpression? = ktInitializer?.let { KotlinUastPsiExpression(it, containingElement) }
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
return ktElement == (other as? UastKotlinPsiVariable)?.ktElement
}
override fun getTypeElement() = throw NotImplementedError()
override fun setInitializer(initializer: PsiExpression?) = throw NotImplementedError()
override fun getContainingFile(): PsiFile? = ktElement.containingFile
override fun hashCode() = ktElement.hashCode()
companion object {
fun create(
declaration: KtVariableDeclaration,
parent: PsiElement?,
containingElement: UElement,
initializer: KtExpression? = null
): PsiVariable {
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: parent
return UastKotlinPsiVariable(
declaration.manager,
declaration.name.orAnonymous("unnamed"),
declaration.typeReference.toPsiType(containingElement),
KotlinLanguage.INSTANCE,
initializer ?: declaration.initializer,
psiParent,
containingElement,
declaration)
}
fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiVariable {
val psiParent = containingElement.getParentOfType<UDeclaration>()?.psi ?: declaration.parent
return UastKotlinPsiVariable(
declaration.manager,
"var" + Integer.toHexString(declaration.hashCode()),
UastErrorType, //TODO,
KotlinLanguage.INSTANCE,
declaration.initializer,
psiParent,
containingElement,
declaration)
}
}
}
private class KotlinUastPsiExpression(val ktExpression: KtExpression, val parent: UElement) : PsiElement by ktExpression, PsiExpression {
override fun getType(): PsiType? {
val ktType = ktExpression.analyze()[BindingContext.EXPRESSION_TYPE_INFO, ktExpression]?.type ?: return null
return ktType.toPsiType(parent, ktExpression, boxed = false)
}
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.uast
import org.jetbrains.android.inspections.klint.AndroidLintInspectionBase
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
@@ -28,7 +27,7 @@ abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() {
override fun setUp() {
super.setUp()
ConfigLibraryUtil.configureKotlinRuntime(myModule)
AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap()
// AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap()
}
override fun tearDown() {
@@ -46,28 +45,29 @@ abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() {
inspectionClassNames += className
}
myFixture.enableInspections(*inspectionClassNames.map { className ->
val inspectionClass = Class.forName(className)
inspectionClass.newInstance() as AndroidLintInspectionBase
}.toTypedArray())
//TODO
// myFixture.enableInspections(*inspectionClassNames.map { className ->
// val inspectionClass = Class.forName(className)
// inspectionClass.newInstance() as AndroidLintInspectionBase
// }.toTypedArray())
val additionalResourcesDir = File(ktFile.parentFile, getTestName(true))
if (additionalResourcesDir.exists()) {
for (file in additionalResourcesDir.listFiles()) {
if (file.isFile) {
myFixture.copyFileToProject(file.absolutePath, file.name)
}
else if (file.isDirectory) {
myFixture.copyDirectoryToProject(file.absolutePath, file.name)
}
}
}
val virtualFile = myFixture.copyFileToProject(ktFile.absolutePath, "src/" + getTestName(true) + ".kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
myFixture.doHighlighting()
myFixture.checkHighlighting(true, false, false)
// val additionalResourcesDir = File(ktFile.parentFile, getTestName(true))
// if (additionalResourcesDir.exists()) {
// for (file in additionalResourcesDir.listFiles()) {
// if (file.isFile) {
// myFixture.copyFileToProject(file.absolutePath, file.name)
// }
// else if (file.isDirectory) {
// myFixture.copyDirectoryToProject(file.absolutePath, file.name)
// }
// }
// }
//
// val virtualFile = myFixture.copyFileToProject(ktFile.absolutePath, "src/" + getTestName(true) + ".kt");
// myFixture.configureFromExistingVirtualFile(virtualFile)
//
// myFixture.doHighlighting()
// myFixture.checkHighlighting(true, false, false)
}
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory() + "/plugins/uast-kotlin/testData/lint/"
@@ -18,57 +18,53 @@ package org.jetbrains.kotlin.uast
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.uast.UElement
import org.jetbrains.uast.visitor.AbstractUastVisitor
import java.io.File
abstract class AbstractKotlinUastStructureTest : KotlinLightCodeInsightFixtureTestCase() {
fun doTest() {
val testName = getTestName(false)
myFixture.configureByFile("$testName.kt")
val logFile = File(File(testDataPath, "log"), "$testName.txt")
val renderFile = File(File(testDataPath, "render"), "$testName.txt")
val treeFile = File(File(testDataPath, "tree"), "$testName.txt")
val psiFile = myFixture.file
val uElement = KotlinUastLanguagePlugin.converter.convertWithParent(psiFile) ?: error("UFile was not created")
val logActual = uElement.logString()
val renderActual = trimEmptyLines(uElement.renderString())
try {
KotlinTestUtils.assertEqualsToFile(logFile, logActual)
} catch (e: Throwable) {
KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
throw e
}
KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
KotlinTestUtils.assertEqualsToFile(treeFile, genTree(uElement))
// val testName = getTestName(false)
// myFixture.configureByFile("$testName.kt")
//
// val logFile = File(File(testDataPath, "log"), "$testName.txt")
// val renderFile = File(File(testDataPath, "render"), "$testName.txt")
// val treeFile = File(File(testDataPath, "tree"), "$testName.txt")
//
// val psiFile = myFixture.file
// val uElement = KotlinUastLanguagePlugin.converter.convertWithParent(psiFile) ?: error("UFile was not created")
//
// val logActual = uElement.logString()
// val renderActual = trimEmptyLines(uElement.renderString())
//
// try {
// KotlinTestUtils.assertEqualsToFile(logFile, logActual)
// } catch (e: Throwable) {
// KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
// throw e
// }
// KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
// KotlinTestUtils.assertEqualsToFile(treeFile, genTree(uElement))
}
private fun trimEmptyLines(s: String): String {
val lineSeparator = System.getProperty("line.separator")
return s.lines().map { if (it.trim().isEmpty()) "" else it.trimEnd() }.joinToString(lineSeparator)
}
// private fun trimEmptyLines(s: String): String {
// val lineSeparator = System.getProperty("line.separator")
// return s.lines().map { if (it.trim().isEmpty()) "" else it.trimEnd() }.joinToString(lineSeparator)
// }
private fun genTree(node: UElement): String {
val builder = StringBuilder()
val visitor = object : AbstractUastVisitor() {
private tailrec fun height(node: UElement, current: Int): Int {
val parent = node.parent ?: return current
return height(parent, current + 1)
}
override fun visitElement(node: UElement): Boolean {
builder.appendln(" ".repeat(height(node, 0)) + node.javaClass.simpleName)
return super.visitElement(node)
}
}
node.accept(visitor)
return builder.toString()
}
// private fun genTree(node: UElement): String {
// val builder = StringBuilder()
// val visitor = object : AbstractUastVisitor() {
// private tailrec fun height(node: UElement, current: Int): Int {
// val parent = node.parent ?: return current
// return height(parent, current + 1)
// }
//
// override fun visitElement(node: UElement): Boolean {
// builder.appendln(" ".repeat(height(node, 0)) + node.javaClass.simpleName)
// return super.visitElement(node)
// }
// }
// node.accept(visitor)
// return builder.toString()
// }
override fun getTestDataPath() = "plugins/uast-kotlin/testData"
+2 -4
View File
@@ -19,10 +19,8 @@
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="idea-test-framework" scope="TEST" />
<orderEntry type="module" module-name="tests-common" scope="TEST" />
<orderEntry type="module" module-name="uast-android" />
<orderEntry type="module" module-name="lint-api" scope="TEST" />
<orderEntry type="module" module-name="lint-checks" scope="TEST" />
<orderEntry type="module" module-name="lint-idea" scope="TEST" />
<orderEntry type="module" module-name="android-extensions-idea" scope="TEST" />
<orderEntry type="module" module-name="light-classes" />
<orderEntry type="module" module-name="util.runtime" />
</component>
</module>