Kotlin Uast: Initial implementation

This commit is contained in:
Yan Zhulanow
2016-03-03 17:46:54 +03:00
parent a13a1e1e4a
commit 92d2e7a0a9
60 changed files with 2485 additions and 0 deletions
@@ -0,0 +1,24 @@
/*
* 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.lint
import com.android.tools.lint.client.api.LintLanguageExtension
import org.jetbrains.kotlin.uast.KotlinConverter
class KotlinLintLanguageExtension : LintLanguageExtension() {
override fun getConverter() = KotlinConverter
}
@@ -0,0 +1,186 @@
/*
* 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.uast.*
object KotlinConverter : UastConverter {
override fun isFileSupported(path: String) = path.endsWith(".kt", false) || path.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 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 -> KotlinUClass(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)
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.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 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 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 -> KotlinUSpecialExpressionList.Empty(expression, UastSpecialExpressionKind.BREAK, parent)
is KtContinueExpression -> KotlinUSpecialExpressionList.Empty(expression, UastSpecialExpressionKind.CONTINUE, parent)
is KtReturnExpression -> KotlinUSpecialExpressionList(expression, UastSpecialExpressionKind.RETURN, parent).apply {
expressions = listOf(convertOrEmpty(expression.returnedExpression, this))
}
is KtThrowExpression -> KotlinUSpecialExpressionList(expression, UastSpecialExpressionKind.THROW, parent).apply {
expressions = singletonListOrEmpty(convertOrNull(expression.thrownExpression, this))
}
is KtBlockExpression -> KotlinUBlockExpression(expression, parent)
is KtConstantExpression -> KotlinULiteralExpression(expression, parent)
is KtTryExpression -> KotlinUTryExpression(expression, parent)
is KtArrayAccessExpression -> KotlinUArrayAccess(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: KotlinType, project: Project, parent: UElement?): UType {
return KotlinUType(element, project, parent)
}
internal fun convert(typeReference: KtTypeReference?, parent: UElement): UType {
if (typeReference == null) return KotlinUErrorType
val bindingContext = typeReference.analyze(BodyResolveMode.PARTIAL)
val type = bindingContext[BindingContext.TYPE, typeReference] ?: return KotlinUErrorType
return convert(type, typeReference.project, parent)
}
internal fun asSimpleReference(element: PsiElement?, parent: UElement): USimpleReferenceExpression? {
if (element == null) return null
return KotlinUSimpleReferenceExpression(element, KtPsiUtil.unquoteIdentifier(element.text), parent)
}
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement): UExpression {
return if (expression != null) convert(expression, parent) else EmptyExpression(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 }
}
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
import com.intellij.psi.PsiElement
import org.jetbrains.uast.NoTraverse
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinPsiElementStub(
override val psi: PsiElement,
override val parent: UElement
) : UElement, PsiElementBacked, NoTraverse {
override fun logString() = "KotlinPsiElementStub"
override fun renderString() = "<stub@$psi>"
}
@@ -0,0 +1,61 @@
/*
* 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.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
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
) : 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? ConstructorDescriptor)?.containingDeclaration
}
override fun resolve(context: UastContext): UClass? {
val classDescriptor = resolveToDescriptor() ?: return null
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, classDescriptor) ?: return null
return context.convert(source) as? UClass
}
}
@@ -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.kotlin.uast
import org.jetbrains.kotlin.psi.KtAnnotation
import org.jetbrains.uast.UAnnotation
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastHandler
import org.jetbrains.uast.handleTraverseList
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUAnnotationList(
override val psi: KtAnnotation,
override val parent: UElement
) : UElement, PsiElementBacked {
lateinit var annotations: List<UAnnotation>
override fun logString() = "KotlinUAnnotationList"
override fun renderString() = annotations.joinToString(" ") { it.renderString() }
override fun traverse(handler: UastHandler) {
annotations.handleTraverseList(handler)
}
}
@@ -0,0 +1,106 @@
/*
* 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.JetTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.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
) : UClass, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz { KotlinConverter.asSimpleReference(psi.nameIdentifier, this) }
override val fqName: String?
get() = psi.fqName?.asString()
override val isEnum: Boolean
get() = (psi as? KtClass)?.isEnum() ?: false
override val isInterface: Boolean
get() = (psi as? KtClass)?.isInterface() ?: false
override val isObject: Boolean
get() = psi is KtObjectDeclaration
override val isAnnotation: Boolean
get() = psi.isAnnotation()
override val isAnonymous = false
override val internalName by lz {
val descriptor = resolveToDescriptor() ?: return@lz null
val typeMapper = JetTypeMapper(BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES, NoResolveFileClassesProvider, null,
IncompatibleClassTracker.DoNothing, JvmAbi.DEFAULT_MODULE_NAME)
typeMapper.mapClass(descriptor).internalName
}
override fun getSuperClass(context: UastContext): UClass? {
val superClass = resolveToDescriptor()?.getSuperClassOrAny() ?: return null
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, superClass) ?: return null
return context.convert(source) as? UClass
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val declarations by lz {
val primaryConstructor = psi.getPrimaryConstructor()?.let { KotlinConverter.convert(it, this) }
val declarations = psi.declarations.map { KotlinConverter.convert(it, this) }.filterNotNull()
if (primaryConstructor != null) listOf(primaryConstructor) + declarations else declarations
}
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(name: String): Boolean {
val descriptor = psi.resolveToDescriptorIfAny() as? ClassDescriptor ?: return false
return descriptor.defaultType.supertypes().any {
it.constructor.declarationDescriptor?.fqNameSafe?.asString() == name
}
}
private fun resolveToDescriptor(): ClassDescriptor? {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
return bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? ClassDescriptor
}
}
@@ -0,0 +1,31 @@
/*
* 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): UFile, PsiElementBacked {
override val packageFqName by lz {
val packageName = psi.packageFqName.asString()
if (packageName.isNotBlank()) packageName else null
}
override val declarations by lz { psi.declarations.map { KotlinConverter.convert(it, this) }.filterNotNull() }
override val importStatements by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } }
}
@@ -0,0 +1,32 @@
/*
* 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.psi.PsiElementBacked
class KotlinUImportStatement(
override val psi: KtImportDirective,
override val parent: UElement
) : UImportStatement, PsiElementBacked {
override val nameToImport = psi.importedFqName?.asString()
override val isStarImport: Boolean
get() = psi.isAllUnder
}
@@ -0,0 +1,59 @@
/*
* 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 org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
import org.jetbrains.uast.*
class KotlinUType(
val type: KotlinType,
val project: Project,
override val parent: UElement?
) : UType {
override val name: String
get() = type.toString()
override val fqName: String?
get() = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
override val isInt = name == "Int"
override fun resolve(context: UastContext): UClass? {
val descriptor = type.constructor.declarationDescriptor ?: return null
val sourceElement = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: return null
return context.convert(sourceElement) as? UClass
}
override val isBoolean: Boolean
get() = type.isBooleanOrNullableBoolean()
//TODO
override val annotations = emptyList<UAnnotation>()
}
object KotlinUErrorType : UType, NoAnnotations {
override val isInt = false
override val parent = null
override val name = "<error>"
override val fqName = null
override val isBoolean = false
override fun resolve(context: UastContext) = null
}
@@ -0,0 +1,106 @@
/*
* 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.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUVariable(
override val psi: KtVariableDeclaration,
override val parent: UElement
) : UVariable, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz { KotlinConverter.asSimpleReference(psi.nameIdentifier, this) }
override val initializer by lz { KotlinConverter.convertOrEmpty(psi.initializer, this) }
override val type by lz {
val descriptor = psi.resolveToDescriptorIfAny() as? CallableDescriptor ?: return@lz KotlinUErrorType
val type = descriptor.returnType ?: return@lz KotlinUErrorType
KotlinConverter.convert(type, psi.project, this)
}
override val kind: UastVariableKind
get() = when (psi.parent) {
is KtClassBody -> UastVariableKind.MEMBER
is KtClassOrObject -> UastVariableKind.MEMBER
else -> UastVariableKind.LOCAL_VARIABLE
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations by lz { psi.getUastAnnotations(this) }
}
class KotlinDestructuredUVariable(
val entry: KtDestructuringDeclarationEntry,
parent: UElement
) : KotlinUVariable(entry, parent) {
override lateinit var initializer: UExpression
override val type by lz {
val bindingContext = entry.analyze(BodyResolveMode.PARTIAL)
val resolvedCall = bindingContext[BindingContext.COMPONENT_RESOLVED_CALL, entry] ?: return@lz KotlinUErrorType
val returnType = resolvedCall.resultingDescriptor.returnType ?: return@lz KotlinUErrorType
KotlinConverter.convert(returnType, entry.project, this)
}
}
class KotlinDestructuringUVariable(
override val psi: KtDestructuringDeclaration,
override val parent: UElement
) : UVariable, PsiElementBacked {
override val name = "var" + psi.text.hashCode()
override val initializer by lz { KotlinConverter.convertOrEmpty(psi.initializer, this) }
override val kind = UastVariableKind.LOCAL_VARIABLE
override val type: UType
get() = initializer.getExpressionType() ?: KotlinUErrorType
override val nameElement = null
override fun hasModifier(modifier: UastModifier) = false
override val annotations = emptyList<UAnnotation>()
}
class KotlinParameterUVariable(
override val psi: KtParameter,
override val parent: UElement
) : UVariable, PsiElementBacked {
override val name: String
get() = psi.name.orAnonymous()
override val nameElement by lz { KotlinConverter.asSimpleReference(psi.nameIdentifier, this) }
override val initializer by lz { KotlinConverter.convertOrEmpty(psi.defaultValue, this) }
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 KotlinUErrorType
KotlinConverter.convert(param.type, psi.project, this)
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations = psi.getUastAnnotations(this)
}
@@ -0,0 +1,89 @@
/*
* 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.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
abstract class KotlinAbstractUFunction : 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> {
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val clazz = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? FunctionDescriptor ?: return emptyList()
return clazz.overriddenDescriptors.map {
context.convert(DescriptorToSourceUtilsIde.getAnyDeclaration(psi.getProject(), it)) as? UFunction
}.filterNotNull()
}
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations by lz { psi.getUastAnnotations(this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
override val visibility by lz { psi.getVisibility() }
}
class KotlinConstructorUFunction(
override val psi: KtConstructor<*>,
override val parent: UElement
) : KotlinAbstractUFunction(), PsiElementBacked {
override val nameElement by lz {
val constructorKeyword = psi.getConstructorKeyword()?.let { KotlinPsiElementStub(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 { KotlinConverter.convert(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)
}
//TODO
override val typeParameterCount = 0
override val typeParameters = emptyList<UTypeReference>()
}
@@ -0,0 +1,34 @@
/*
* 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.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.psi.PsiElementBacked
class KotlinStringTemplateUBinaryExpression(
override val psi: KtStringTemplateExpression,
override val parent: UElement
) : UBinaryExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override lateinit var leftOperand: UExpression
override lateinit var rightOperand: UExpression
override val operator = UastBinaryOperator.PLUS
}
@@ -0,0 +1,31 @@
/*
* 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.KtArrayAccessExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UArrayAccessExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUArrayAccess(
override val psi: KtArrayAccessExpression,
override val parent: UElement
) : UArrayAccessExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) }
override val indices by lz { psi.indexExpressions.map { KotlinConverter.convert(it, this) } }
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.uast.UArrayAccessExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUArrayAccessExpression(
override val psi: KtArrayAccessExpression,
override val parent: UElement
) : UArrayAccessExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val receiver by lz { KotlinConverter.convertOrEmpty(psi.arrayExpression, this) }
override val indices by lz { psi.indexExpressions.map { KotlinConverter.convert(it, this) } }
}
@@ -0,0 +1,59 @@
/*
* 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.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBinaryExpression(
override val psi: KtBinaryExpression,
override val parent: UElement
) : UBinaryExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val leftOperand by lz { KotlinConverter.convertOrEmpty(psi.left, this) }
override val rightOperand by lz { KotlinConverter.convertOrEmpty(psi.right, this) }
override val operator = when (psi.operationToken) {
KtTokens.PLUS -> UastBinaryOperator.PLUS
KtTokens.MINUS -> UastBinaryOperator.MINUS
KtTokens.MUL -> UastBinaryOperator.MULT
KtTokens.DIV -> UastBinaryOperator.DIV
KtTokens.PERC -> UastBinaryOperator.MOD
KtTokens.EQEQ -> UastBinaryOperator.EQUALS
KtTokens.EXCLEQ -> UastBinaryOperator.NOT_EQUALS
KtTokens.EQEQEQ -> UastBinaryOperator.IDENTITY_EQUALS
KtTokens.EXCLEQEQEQ -> UastBinaryOperator.IDENTITY_NOT_EQUALS
KtTokens.GT -> UastBinaryOperator.GREATER
KtTokens.GTEQ -> UastBinaryOperator.GREATER_OR_EQUAL
KtTokens.LT -> UastBinaryOperator.LESS
KtTokens.LTEQ -> UastBinaryOperator.LESS_OR_EQUAL
KtTokens.IN_KEYWORD -> KotlinBinaryOperators.IN
KtTokens.NOT_IN -> KotlinBinaryOperators.NOT_IN
else -> UastBinaryOperator.UNKNOWN
}
}
class KotlinCustomUBinaryExpression(
override val psi: PsiElement,
override val parent: UElement
) : UBinaryExpression, PsiElementBacked, NoEvaluate {
lateinit override var leftOperand: UExpression
lateinit override var operator: UastBinaryOperator
lateinit override var rightOperand: UExpression
}
@@ -0,0 +1,45 @@
/*
* 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.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBinaryExpressionWithType(
override val psi: KtBinaryExpressionWithTypeRHS,
override val parent: UElement
) : UBinaryExpressionWithType, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val operand by lz { KotlinConverter.convert(psi.left, this) }
override val type by lz { KotlinConverter.convert(psi.right, this) }
override val operationKind = when (psi.operationReference.getReferencedNameElementType()) {
KtTokens.AS_KEYWORD -> UastBinaryExpressionWithTypeKind.TYPE_CAST
KtTokens.AS_SAFE -> KotlinBinaryExpressionWithTypeKinds.SAFE_TYPE_CAST
else -> UastBinaryExpressionWithTypeKind.UNKNOWN
}
}
class KotlinCustomUBinaryExpressionWithType(
override val psi: PsiElement,
override val parent: UElement
) : UBinaryExpressionWithType, PsiElementBacked, NoEvaluate {
lateinit override var operand: UExpression
lateinit override var operationKind: UastBinaryExpressionWithTypeKind
lateinit override var type: UType
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.uast
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UBlockExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUBlockExpression(
override val psi: KtBlockExpression,
override val parent: UElement
) : UBlockExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override val expressions by lz { psi.statements.map { KotlinConverter.convertOrEmpty(it, 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.kotlin.uast
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.psi.PsiElementBacked
class KotlinUCatchClause(
override val psi: KtCatchClause,
override val parent: UElement
) : 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))
}
}
@@ -0,0 +1,21 @@
/*
* 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
class KotlinUDeclarationsExpression(override val parent: UElement) : UDeclarationsExpression {
override lateinit var declarations: List<UElement>
override fun evaluate() = null
}
@@ -0,0 +1,31 @@
/*
* 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.KtDoWhileExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UDoWhileExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUDoWhileExpression(
override val psi: KtDoWhileExpression,
override val parent: UElement
) : UDoWhileExpression, PsiElementBacked, NoEvaluate {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
}
@@ -0,0 +1,42 @@
/*
* 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.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.UExpression
import org.jetbrains.uast.UType
import org.jetbrains.uast.psi.PsiElementBacked
interface KotlinTypeHelper : UExpression, PsiElementBacked {
override fun getExpressionType(): UType? {
val ktElement = psi as? KtExpression ?: return null
val ktType = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.EXPECTED_EXPRESSION_TYPE, ktElement] ?: return null
return KotlinConverter.convert(ktType, ktElement.project, null)
}
}
interface KotlinEvaluateHelper : UExpression, PsiElementBacked {
override fun evaluate(): Any? {
val ktElement = psi as? KtExpression ?: return null
val compileTimeConst = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.COMPILE_TIME_VALUE, ktElement]
return compileTimeConst?.getValue(TypeUtils.NO_EXPECTED_TYPE)
}
}
@@ -0,0 +1,32 @@
/*
* 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.KtForExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UForEachExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUForEachExpression(
override val psi: KtForExpression,
override val parent: UElement
) : UForEachExpression, PsiElementBacked, NoEvaluate {
override val variableName by lz { psi.loopParameter?.name }
override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
}
@@ -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.kotlin.uast
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
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
class KotlinUFunctionCallExpression(
override val psi: KtCallExpression,
override val parent: UElement
) : UCallExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override val functionName: String?
get() = (psi.calleeExpression as? KtSimpleNameExpression)?.getReferencedName()
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
KotlinUSimpleReferenceExpression(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 (resolveCall()?.resultingDescriptor) {
is ConstructorDescriptor -> UastCallKind.CONSTRUCTOR_CALL
else -> UastCallKind.FUNCTION_CALL
}
}
override fun resolve(context: UastContext): UFunction? {
val resultingDescriptor = resolveCall()?.resultingDescriptor ?: return null
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, resultingDescriptor) ?: return null
return context.convert(source) as? UFunction
}
private fun resolveCall() = psi.getResolvedCall(psi.analyze(BodyResolveMode.PARTIAL))
}
class KotlinUComponentFunctionCallExpression(
override val psi: PsiElement,
val n: Int,
override val parent: UElement
) : UCallExpression, PsiElementBacked, NoEvaluate {
override val valueArgumentCount = 0
override val valueArguments = emptyList<UExpression>()
override val typeArgumentCount = 0
override val typeArguments = emptyList<UType>()
override val classReference = null
override val functionName = "component$n"
override val functionReference by lz { KotlinStringUSimpleReferenceExpression(functionName, this) }
override val functionNameElement = null
override val kind = UastCallKind.FUNCTION_CALL
override fun resolve(context: UastContext) = null
}
@@ -0,0 +1,32 @@
/*
* 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.KtIfExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UIfExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUIfExpression(
override val psi: KtIfExpression,
override val parent: UElement
) : UIfExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
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 isTernary = false
}
@@ -0,0 +1,39 @@
/*
* 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.*
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinULambdaExpression(
override val psi: KtLambdaExpression,
override val parent: UElement
) : ULambdaExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
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 {
val renderedValueParameters = if (valueParameters.isEmpty())
""
else
valueParameters.joinToString { it.renderString() } + " ->\n"
val expressions = (body as? UBlockExpression)?.expressions
?.joinToString("\n") { it.renderString().withMargin } ?: body.renderString()
return "{ " + renderedValueParameters + "\n" + expressions + "\n}"
}
}
@@ -0,0 +1,51 @@
/*
* 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.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULiteralExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinULiteralExpression(
override val psi: KtConstantExpression,
override val parent: UElement
) : ULiteralExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val isNull: Boolean
get() = psi.isNullExpression()
override val text: String
get() = psi.text
override val value by lz { evaluate() }
}
class KotlinStringULiteralExpression(
override val psi: PsiElement,
override val parent: UElement
) : ULiteralExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val isNull = false
override val text: String
get() = '"' + psi.text + '"'
override val value: String
get() = psi.text
override fun evaluate() = psi.text
}
@@ -0,0 +1,29 @@
/*
* 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.KtParenthesizedExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UParenthesizedExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUParenthesizedExpression(
override val psi: KtParenthesizedExpression,
override val parent: UElement
) : UParenthesizedExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val expression by lz { KotlinConverter.convertOrEmpty(psi.expression, this) }
}
@@ -0,0 +1,39 @@
/*
* 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.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtPostfixExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UPostfixExpression
import org.jetbrains.uast.UastPostfixOperator
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUPostfixExpression(
override val psi: KtPostfixExpression,
override val parent: UElement
) : UPostfixExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operator = when (psi.operationToken) {
KtTokens.PLUSPLUS -> UastPostfixOperator.INC
KtTokens.MINUSMINUS -> UastPostfixOperator.DEC
KtTokens.EXCLEXCL -> KotlinPostfixOperators.EXCLEXCL
else -> UastPostfixOperator.UNKNOWN
}
}
@@ -0,0 +1,40 @@
/*
* 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.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtPrefixExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
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
) : UPrefixExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operator = when (psi.operationToken) {
KtTokens.PLUS -> UastPrefixOperator.UNARY_PLUS
KtTokens.MINUS -> UastPrefixOperator.UNARY_MINUS
KtTokens.PLUSPLUS -> UastPrefixOperator.INC
KtTokens.MINUSMINUS -> UastPrefixOperator.DEC
else -> UastPrefixOperator.UNKNOWN
}
}
@@ -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.kotlin.uast
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUQualifiedExpression(
override val psi: KtDotQualifiedExpression,
override val parent: UElement
) : UQualifiedExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
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(context: UastContext) = psi.selectorExpression.resolveCallToUDeclaration(context)
}
class KotlinUComponentQualifiedExpression(
override val psi: KtDestructuringDeclarationEntry,
override val parent: UElement
) : UQualifiedExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override lateinit var receiver: UExpression
override lateinit var selector: UExpression
override val accessType = UastQualifiedExpressionAccessType.SIMPLE
override fun resolve(context: UastContext) = null
}
@@ -0,0 +1,35 @@
/*
* 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.KtSafeQualifiedExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UQualifiedExpression
import org.jetbrains.uast.UastContext
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUSafeQualifiedExpression(
override val psi: KtSafeQualifiedExpression,
override val parent: UElement
) : UQualifiedExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
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)
}
@@ -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.kotlin.uast
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.KtCallExpression
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
class KotlinUSimpleReferenceExpression(
override val psi: PsiElement,
override val identifier: String,
override val parent: UElement
) : USimpleReferenceExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override fun resolve(context: UastContext) = context.convert(
psi.references.firstOrNull()?.resolve()) as? UDeclaration
}
class KotlinClassViaConstructorUSimpleReferenceExpression(
override val psi: KtCallExpression,
override val identifier: String,
override val parent: UElement
) : USimpleReferenceExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
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 = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, clazz) ?: return null
return context.convert(source) as? UClass
}
}
class KotlinStringUSimpleReferenceExpression(
override val identifier: String,
override val parent: UElement
) : USimpleReferenceExpression, NoEvaluate {
override fun resolve(context: UastContext) = null
}
@@ -0,0 +1,48 @@
/*
* 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.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.UastSpecialExpressionKind
import org.jetbrains.uast.psi.PsiElementBacked
open class KotlinUSpecialExpressionList(
override val psi: PsiElement,
override val kind: UastSpecialExpressionKind, // original element
override val parent: UElement
) : USpecialExpressionList, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
class Empty(psi: PsiElement, expressionType: UastSpecialExpressionKind, parent: UElement) :
KotlinUSpecialExpressionList(psi, expressionType, parent) {
init { expressions = emptyList() }
}
override lateinit var expressions: List<UExpression>
override fun evaluate(): Any? {
val ktElement = psi as? KtExpression ?: return null
val compileTimeConst = ktElement.analyze(BodyResolveMode.PARTIAL)[BindingContext.COMPILE_TIME_VALUE, ktElement]
return compileTimeConst?.getValue(TypeUtils.NO_EXPECTED_TYPE)
}
}
@@ -0,0 +1,27 @@
/*
* 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.KtSuperExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.USuperExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUSuperExpression(
override val psi: KtSuperExpression,
override val parent: UElement
) : USuperExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper
@@ -0,0 +1,107 @@
/*
* 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.*
import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUSwitchExpression(
override val psi: KtWhenExpression,
override val parent: UElement
) : USwitchExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
//TODO to entries
override val body: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this) {
override fun renderString() = expressions.joinToString("\n") { it.renderString().withMargin }
}.apply {
expressions = this@KotlinUSwitchExpression.psi.entries.map { KotlinUSwitchEntry(it, this) }
}
}
override fun renderString() = buildString {
val expr = expression?.let { "(" + it.renderString() + ") " } ?: ""
appendln("switch $expr {")
appendln(body.renderString())
appendln("}")
}
}
class KotlinUSwitchEntry(
override val psi: KtWhenEntry,
override val parent: UExpression
) : UExpression, PsiElementBacked, NoEvaluate {
val conditions by lz {
psi.conditions.map { when (it) {
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply {
leftOperand = KotlinStringUSimpleReferenceExpression("it", this)
operator = when {
it.isNegated -> KotlinBinaryOperators.NOT_IN
else -> KotlinBinaryOperators.IN
}
rightOperand = KotlinConverter.convertOrEmpty(it.rangeExpression, this)
}
is KtWhenConditionIsPattern -> KotlinCustomUBinaryExpressionWithType(it, this).apply {
operand = KotlinStringUSimpleReferenceExpression("it", this)
operationKind = when {
it.isNegated -> KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK
else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK
}
type = KotlinConverter.convert(it.typeReference, this)
}
is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(it.expression, this)
else -> EmptyExpression(this)
}}
}
val expression: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this) {
override fun renderString() = buildString {
appendln("{")
expressions.forEach { appendln(it.renderString().withMargin) }
appendln("}")
}
}.apply {
val exprPsi = this@KotlinUSwitchEntry.psi.expression
val userExpressions = when (exprPsi) {
is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convert(it, this) }
else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this))
}
expressions = userExpressions + KotlinUSpecialExpressionList.Empty(
exprPsi ?: this@KotlinUSwitchEntry.psi, UastSpecialExpressionKind.BREAK, parent)
}
}
override fun renderString() = buildString {
if (conditions.isEmpty()) {
append("else")
} else {
append(conditions.joinToString { it.renderString() })
}
append(" -> ")
append(expression.renderString())
}
override fun logString() = log("KotlinUSwitchEntry", expression)
override fun traverse(handler: UastHandler) {
expression.handleTraverse(handler)
}
}
@@ -0,0 +1,28 @@
/*
* 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.KtThisExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UThisExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUThisExpression(
override val psi: KtThisExpression,
override val parent: UElement
) : UThisExpression, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper
@@ -0,0 +1,32 @@
/*
* 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.KtTryExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UTryExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUTryExpression(
override val psi: KtTryExpression,
override val parent: UElement
) : UTryExpression, PsiElementBacked, KotlinTypeHelper, NoEvaluate {
override val tryClause by lz { KotlinConverter.convert(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) } }
}
@@ -0,0 +1,31 @@
/*
* 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.KtIsExpression
import org.jetbrains.uast.UBinaryExpressionWithType
import org.jetbrains.uast.UElement
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUTypeCheckExpression(
override val psi: KtIsExpression,
override val parent: UElement
) : UBinaryExpressionWithType, PsiElementBacked, KotlinTypeHelper, KotlinEvaluateHelper {
override val operand by lz { KotlinConverter.convert(psi.leftHandSide, this) }
override val type by lz { KotlinConverter.convert(psi.typeReference, this) }
override val operationKind = KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK
}
@@ -0,0 +1,31 @@
/*
* 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.KtWhileExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UWhileExpression
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUWhileExpression(
override val psi: KtWhileExpression,
override val parent: UElement
) : UWhileExpression, PsiElementBacked, NoEvaluate {
override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) }
override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
}
@@ -0,0 +1,32 @@
/*
* 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.KtExpression
import org.jetbrains.uast.NoEvaluate
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.UastHandler
import org.jetbrains.uast.psi.PsiElementBacked
class UnknownKotlinExpression(
override val psi: KtExpression,
override val parent: UElement
) : UExpression, PsiElementBacked, NoEvaluate {
override fun traverse(handler: UastHandler) {}
override fun logString() = "[!] UnknownKotlinExpression ($psi)"
}
@@ -0,0 +1,77 @@
/*
* 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.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.resolve.BindingContext
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 MODIFIER_MAP = mapOf(
UastModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD,
UastModifier.INNER to KtTokens.INNER_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 {
val javaModifier = MODIFIER_MAP[modifier] ?: return false
return hasModifier(javaModifier)
}
internal fun <T> runReadAction(action: () -> T): T {
return ApplicationManager.getApplication().runReadAction<T>(action)
}
internal fun KtElement?.resolveCallToUDeclaration(context: UastContext): UDeclaration? {
if (this == null) return null
val resolvedCall = this.getResolvedCall(analyze(BodyResolveMode.PARTIAL)) ?: return null
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(project, resolvedCall.resultingDescriptor) ?: return null
return context.convert(source) as? UDeclaration
}
internal fun KtElement?.resolveElementToUDeclaration(context: UastContext): UDeclaration? {
if (this == null) return null
val bindingContext = analyze(BodyResolveMode.PARTIAL)
val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return null
val source = DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) ?: 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 <T> singletonListOrEmpty(element: T?) = if (element != null) listOf(element) else emptyList<T>()
@@ -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.kotlin.uast
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
internal fun <T> lz(initializer: () -> T): ReadOnlyProperty<Any, T> = UnsafeLazyInsideReadAction(initializer, false)
private class UnsafeLazyInsideReadAction<out T>(initializer: () -> T, private val readAction: Boolean) : ReadOnlyProperty<Any, T> {
private var initializer: (() -> T)? = initializer
private var _value: Any? = UNINITIALIZED_VALUE
override fun getValue(thisRef: Any, property: KProperty<*>): T {
if (_value === UNINITIALIZED_VALUE) {
if (readAction) {
_value = runReadAction { initializer!!() }
}
else {
_value = initializer!!()
}
initializer = null
}
return _value as T
}
}
private object UNINITIALIZED_VALUE
@@ -0,0 +1,27 @@
/*
* 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.UastBinaryExpressionWithTypeKind
object KotlinBinaryExpressionWithTypeKinds {
@JvmField
val NEGATED_INSTANCE_CHECK = UastBinaryExpressionWithTypeKind("!is")
@JvmField
val SAFE_TYPE_CAST = UastBinaryExpressionWithTypeKind("!is")
}
@@ -0,0 +1,26 @@
/*
* 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.UastBinaryOperator
object KotlinBinaryOperators {
@JvmField
val IN = UastBinaryOperator("in")
@JvmField
val NOT_IN = UastBinaryOperator("!in")
}
@@ -0,0 +1,24 @@
/*
* 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.UastPostfixOperator
object KotlinPostfixOperators {
@JvmField
val EXCLEXCL = UastPostfixOperator("!!")
}
@@ -0,0 +1,24 @@
/*
* 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.UastQualifiedExpressionAccessType
object KotlinQualifiedExpressionAccessTypes {
@JvmField
val SAFE = UastQualifiedExpressionAccessType("?.")
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.uast.kinds
import org.jetbrains.uast.UastSpecialExpressionKind
object KotlinSpecialExpressionKinds {
@JvmField
val WHEN = UastSpecialExpressionKind("when")
@JvmField
val WHEN_ENTRY = UastSpecialExpressionKind("when_entry")
@JvmField
val DESTRUCTURING = UastSpecialExpressionKind("destructuring")
}
@@ -0,0 +1,24 @@
/*
* 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")
}
@@ -0,0 +1,50 @@
/*
* 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.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.test.KotlinTestUtils
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 psiFile = myFixture.file
val uElement = KotlinConverter.convertWithParent(psiFile) ?: error("UFile was not created")
val logActual = uElement.logString()
val renderActual = uElement.renderString()
try {
KotlinTestUtils.assertEqualsToFile(logFile, logActual)
} catch (e: Throwable) {
KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
throw e
}
KotlinTestUtils.assertEqualsToFile(renderFile, renderActual)
}
override fun getTestDataPath() = "plugins/uast-kotlin/testData"
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
}
@@ -0,0 +1,25 @@
/*
* 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.test.TestMetadata
class KotlinUastStructureTest : AbstractKotlinUastStructureTest() {
@TestMetadata("Simple.kt") fun testSimple() = doTest()
@TestMetadata("Declarations.kt") fun testDeclarations() = doTest()
@TestMetadata("ControlStructures.kt") fun testControlStructures() = doTest()
}
+59
View File
@@ -0,0 +1,59 @@
class ControlStructures {
fun test(): Boolean {
if (5 > 3) {
println("5 > 3")
}
for (c in "ABC") {
println(c)
}
for (c: Char in "DEF") {
println(c.toByte())
}
var i = 5
while (i > 0) {
i--
if (i == 3) break
if (i == 2) {
continue
}
}
i = 5
do {
i -= 1
} while (i > 0)
"ABC".forEach { println(it.toString()[0]) }
"ABC".zip("DEF").forEach { println(it.first + " " + it.second) }
val (a, b) = "ABC".zip("DEF")
val value = if (5 > 3) "a" else "b"
val list = listOf("A")
val list2 = listOf("A")
val type = when (value) {
in list -> "inlist"
!in list2 -> "notinlist2"
is String -> "string"
is CharSequence -> "cs"
else -> "unknown"
}
val x = when {
value == "b" -> "B"
5 % 2 == 0 -> {
println("A")
"Q"
}
false -> "!"
else -> "A"
}
return false
}
}
+13
View File
@@ -0,0 +1,13 @@
class Declarations {
val a: String = "a"
class NestedClass {
val b: String = "b"
}
inner class InnerClass {
val c: CharSequence = a
}
fun func(a: Int, b: String): Int {
return (a + 1) * b.length
}
}
+8
View File
@@ -0,0 +1,8 @@
class Simple {
val a: String = "text" + "other" + "text"
val b = listOf("A")
fun test() {
System.out.println(5.0f / 2)
}
}
+11
View File
@@ -0,0 +1,11 @@
UFile (package = null)
UClass (ControlStructures, enum = false, interface = false, object = false)
UFunction (test, kind = function, paramCount = 0)
UBlockExpression
UDeclarationsExpression
UVariable (x, kind = local)
UFunctionCallExpression (FUNCTION_CALL, argCount = 1)
USimpleReferenceExpression (listOf)
ULiteralExpression ("ABC")
USpecialExpressionList (return)
ULiteralExpression (false)
+21
View File
@@ -0,0 +1,21 @@
UFile (package = null)
UClass (Declarations, enum = false, interface = false, object = false)
UVariable (a, kind = member)
ULiteralExpression ("a")
UClass (NestedClass, enum = false, interface = false, object = false)
UVariable (b, kind = member)
ULiteralExpression ("b")
UClass (InnerClass, enum = false, interface = false, object = false)
UVariable (c, kind = member)
USimpleReferenceExpression (a)
UFunction (func, kind = function, paramCount = 2)
UBlockExpression
USpecialExpressionList (return)
UBinaryExpression (*)
UParenthesizedExpression
UBinaryExpression (+)
USimpleReferenceExpression (a)
ULiteralExpression (1)
UQualifiedExpression
USimpleReferenceExpression (b)
USimpleReferenceExpression (length)
+19
View File
@@ -0,0 +1,19 @@
UFile (package = null)
UClass (Simple, enum = false, interface = false, object = false)
UVariable (a, kind = member)
UBinaryExpression (+)
UBinaryExpression (+)
ULiteralExpression ("text")
ULiteralExpression ("other")
ULiteralExpression ("text")
UFunction (test, kind = function, paramCount = 0)
UBlockExpression
UQualifiedExpression
UQualifiedExpression
USimpleReferenceExpression (System)
USimpleReferenceExpression (out)
UFunctionCallExpression (FUNCTION_CALL, argCount = 1)
USimpleReferenceExpression (println)
UBinaryExpression (/)
ULiteralExpression (5.0f)
ULiteralExpression (2)
@@ -0,0 +1,7 @@
public class ControlStructures {
public fun test(): Boolean {
var x: List = listOf("ABC")
return false
}
}
+16
View File
@@ -0,0 +1,16 @@
public class Declarations {
var a: String = "a"
public class NestedClass {
var b: String = "b"
}
public inner class InnerClass {
var c: CharSequence = a
}
public fun func(a: Int, b: String): Int {
return (a + 1) * b.length
}
}
+9
View File
@@ -0,0 +1,9 @@
public class Simple {
var a: String = "text" + "other" + "text"
val b = listOf("A")
public fun test(): Unit {
System.out.println(5.0f / 2)
}
}
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
<orderEntry type="library" name="idea-full" level="project" />
<orderEntry type="module" module-name="uast-common" exported="" />
<orderEntry type="module" module-name="uast-java" exported="" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="module" module-name="idea" />
<orderEntry type="module" module-name="idea-analysis" />
<orderEntry type="module" module-name="backend" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="idea-test-framework" scope="TEST" />
<orderEntry type="module" module-name="compiler-tests" scope="TEST" />
<orderEntry type="module" module-name="uast-android" />
</component>
</module>