FIR UAST: commonize utils from UAST Kotlin

This commit is contained in:
Jinseong Jeon
2021-04-27 00:07:00 -07:00
committed by Ilya Kirillov
parent f37c722c76
commit eac875b5d6
16 changed files with 99 additions and 158 deletions
+18
View File
@@ -0,0 +1,18 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
implementation(kotlinStdlib())
implementation(project(":compiler:psi"))
implementation(project(":compiler:light-classes"))
// BEWARE: Uast should not depend on IDEA.
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "asm-all", rootProject = rootProject) }
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
}
sourceSets {
"main" { projectDefault() }
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2017 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 com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.KtValueArgument
import org.jetbrains.uast.UComment
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
interface KotlinUElementWithComments : UElement {
override val comments: List<UComment>
get() {
val psi = sourcePsi ?: return emptyList()
val childrenComments = psi.children.filterIsInstance<PsiComment>().map { UComment(it, this) }
if (this !is UExpression) return childrenComments
val childrenAndSiblingComments = childrenComments +
psi.nearestCommentSibling(forward = true)?.let { listOf(UComment(it, this)) }.orEmpty() +
psi.nearestCommentSibling(forward = false)?.let { listOf(UComment(it, this)) }.orEmpty()
val parent = psi.parent as? KtValueArgument ?: return childrenAndSiblingComments
return childrenAndSiblingComments +
parent.nearestCommentSibling(forward = true)?.let { listOf(UComment(it, this)) }.orEmpty() +
parent.nearestCommentSibling(forward = false)?.let { listOf(UComment(it, this)) }.orEmpty()
}
private fun PsiElement.nearestCommentSibling(forward: Boolean): PsiComment? {
var sibling = if (forward) nextSibling else prevSibling
while (sibling is PsiWhiteSpace && !sibling.text.contains('\n')) {
sibling = if (forward) sibling.nextSibling else sibling.prevSibling
}
return sibling as? PsiComment
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.uast.kotlin
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.asJava.elements.KtLightMember
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
fun <T> lz(initializer: () -> T) =
lazy(LazyThreadSafetyMode.SYNCHRONIZED, initializer)
inline fun <reified T : UDeclaration, reified P : PsiElement> unwrap(element: P): P {
val unwrapped = if (element is T) element.javaPsi else element
assert(unwrapped !is UElement)
return unwrapped as P
}
fun unwrapFakeFileForLightClass(file: PsiFile): PsiFile = (file as? FakeFileForLightClass)?.ktFile ?: file
fun getKotlinMemberOrigin(element: PsiElement?): KtDeclaration? {
(element as? KtLightMember<*>)?.lightMemberOrigin?.auxiliaryOriginalElement?.let { return it }
(element as? KtLightElement<*, *>)?.kotlinOrigin?.let { return it as? KtDeclaration }
return null
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.uast.kotlin
import org.jetbrains.uast.DEFAULT_EXPRESSION_TYPES_LIST
import org.jetbrains.uast.DEFAULT_TYPES_LIST
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UExpression
fun expressionTypes(requiredType: Class<out UElement>?) =
requiredType?.let { arrayOf(it) } ?: DEFAULT_EXPRESSION_TYPES_LIST
fun elementTypes(requiredType: Class<out UElement>?) =
requiredType?.let { arrayOf(it) } ?: DEFAULT_TYPES_LIST
fun <T : UElement> Array<out Class<out T>>.nonEmptyOr(default: Array<out Class<out UElement>>) =
takeIf { it.isNotEmpty() } ?: default
inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.el(f: () -> UElement?): UElement? {
return if (isAssignableFrom(ActualT::class.java)) f() else null
}
inline fun <reified ActualT : UElement> Array<out Class<out UElement>>.expr(f: () -> UExpression?): UExpression? {
return if (isAssignableFrom(ActualT::class.java)) f() else null
}
fun Array<out Class<out UElement>>.isAssignableFrom(cls: Class<*>) = any { it.isAssignableFrom(cls) }
fun <U : UElement> Array<out Class<out UElement>>.accommodate(vararg makers: UElementAlternative<out U>): Sequence<UElement> {
val makersSeq = makers.asSequence()
return this.asSequence()
.flatMap { requiredType -> makersSeq.filter { requiredType.isAssignableFrom(it.uType) } }
.distinct()
.mapNotNull { it.make.invoke() }
}
inline fun <reified U : UElement> alternative(noinline make: () -> U?) = UElementAlternative(U::class.java, make)
class UElementAlternative<U : UElement>(val uType: Class<U>, val make: () -> U?)