LL API: add basic tests for kt -> fir mapping
This commit is contained in:
committed by
teamcityserver
parent
609296a46b
commit
c0eb669191
@@ -62,6 +62,7 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
|
||||
val renderPropertyAccessors: Boolean = true,
|
||||
val renderDeclarationAttributes: Boolean = false,
|
||||
val renderDeclarationOrigin: Boolean = false,
|
||||
val renderPackageDirective: Boolean = false,
|
||||
) {
|
||||
companion object {
|
||||
val Normal = RenderMode(
|
||||
@@ -1368,4 +1369,10 @@ class FirRenderer(builder: StringBuilder, private val mode: RenderMode = RenderM
|
||||
override fun visitContractDescription(contractDescription: FirContractDescription) {
|
||||
require(contractDescription is FirEmptyContractDescription)
|
||||
}
|
||||
|
||||
override fun visitPackageDirective(packageDirective: FirPackageDirective) {
|
||||
if (mode.renderPackageDirective) {
|
||||
println("package ${packageDirective.packageFqName.asString()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.idea.fir.frontend.api.scopes.AbstractMemberScopeByFq
|
||||
import org.jetbrains.kotlin.idea.fir.frontend.api.symbols.AbstractSymbolByFqNameTest
|
||||
import org.jetbrains.kotlin.idea.fir.frontend.api.symbols.AbstractSymbolByPsiTest
|
||||
import org.jetbrains.kotlin.idea.fir.frontend.api.symbols.AbstractSymbolByReferenceTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyBodiesCalculatorTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyDeclarationResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirOnAirResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractPartialRawFirBuilderTestCase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostic.AbstractDiagnosticTraversalCounterTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostic.AbstractFirContextCollectionTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.diagnostic.compiler.based.AbstractDiagnosisCompilerTestDataSpecTest
|
||||
@@ -115,6 +112,10 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractPartialRawFirBuilderTestCase> {
|
||||
model("partialRawBuilder", testMethod = "doRawFirTest")
|
||||
}
|
||||
|
||||
testClass<AbstractGetOrBuildFirTest> {
|
||||
model("getOrBuildFir")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup(
|
||||
|
||||
idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/firstImportNamePart.kt
Vendored
+1
@@ -0,0 +1 @@
|
||||
import <expr>a</expr>.b.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirImportImpl
|
||||
|
||||
FIR element rendered:
|
||||
import a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
import a.<expr>b</expr>.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirImportImpl
|
||||
|
||||
FIR element rendered:
|
||||
import a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
import <expr>a.b</expr>.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtDotQualifiedExpression
|
||||
FIR element: FirImportImpl
|
||||
|
||||
FIR element rendered:
|
||||
import a.b.c
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtImportDirective
|
||||
|
||||
<expr>import a.b.c</expr>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtImportDirective
|
||||
FIR element: FirImportImpl
|
||||
|
||||
FIR element rendered:
|
||||
import a.b.c
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
import <expr>a.b.c</expr>
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtDotQualifiedExpression
|
||||
FIR element: FirImportImpl
|
||||
|
||||
FIR element rendered:
|
||||
import a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
package <expr>a</expr>.b.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirPackageDirectiveImpl
|
||||
|
||||
FIR element rendered:
|
||||
package a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
package a.<expr>b</expr>.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirPackageDirectiveImpl
|
||||
|
||||
FIR element rendered:
|
||||
package a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
package <expr>a.b</expr>.c
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtDotQualifiedExpression
|
||||
FIR element: FirPackageDirectiveImpl
|
||||
|
||||
FIR element rendered:
|
||||
package a.b.c
|
||||
+1
@@ -0,0 +1 @@
|
||||
<expr>package a.b.c</expr>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtPackageDirective
|
||||
FIR element: FirPackageDirectiveImpl
|
||||
|
||||
FIR element rendered:
|
||||
package a.b.c
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
package <expr>a.b.c</expr>
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtDotQualifiedExpression
|
||||
FIR element: FirPackageDirectiveImpl
|
||||
|
||||
FIR element rendered:
|
||||
package a.b.c
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
class B {
|
||||
class C {
|
||||
val x = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun x() {
|
||||
<expr>A</expr>.B.C().x
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirFunctionCallImpl
|
||||
|
||||
FIR element rendered:
|
||||
Q|A.B|.R|/A.B.C.C|()
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
class B {
|
||||
class C {
|
||||
val x = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun x() {
|
||||
A.B.<expr>C()</expr>.x
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtCallExpression
|
||||
FIR element: FirFunctionCallImpl
|
||||
|
||||
FIR element rendered:
|
||||
Q|A.B|.R|/A.B.C.C|()
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
class B {
|
||||
class C {
|
||||
val x = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun x() {
|
||||
A.<expr>B</expr>.C().x
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtNameReferenceExpression
|
||||
FIR element: FirResolvedQualifierImpl
|
||||
|
||||
FIR element rendered:
|
||||
Q|A.B|
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
class B {
|
||||
class C {
|
||||
val x = 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun x() {
|
||||
<expr>A.B</expr>.C().x
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtDotQualifiedExpression
|
||||
FIR element: FirFunctionCallImpl
|
||||
|
||||
FIR element rendered:
|
||||
Q|A.B|.R|/A.B.C.C|()
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): <expr>List<Int, String></expr> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeReference
|
||||
FIR element: FirErrorTypeRefImpl
|
||||
|
||||
FIR element rendered:
|
||||
<ERROR TYPE REF: Wrong number of type arguments>
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): List<Int, <expr>String</expr>> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/String|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): List< <expr>String</expr>, Int > = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/String|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): List<Int, <expr>String</expr>> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/String|
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
fun x(): Map<String, List< <expr> Int </expr> >> = TODO()
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/Int|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): Map<String, <expr> List<Int> </expr> > = TODO()
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/collections/List<kotlin/Int>|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): <expr>List<UNRESOVLED></expr> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeReference
|
||||
FIR element: FirResolvedTypeRefImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/collections/List<ERROR CLASS: Symbol not found for UNRESOVLED>|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): UNRESOLVED<String, List< <expr> Int </expr> >> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/Int|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): UNRESOLVED<String, <expr> List<Int> </expr> > = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeProjection
|
||||
FIR element: FirTypeProjectionWithVarianceImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/collections/List<kotlin/Int>|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x(): <expr> Map<String, List<Int>> </expr> = TODO()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeReference
|
||||
FIR element: FirResolvedTypeRefImpl
|
||||
|
||||
FIR element rendered:
|
||||
R|kotlin/collections/Map<kotlin/String, kotlin/collections/List<kotlin/Int>>|
|
||||
+1
@@ -0,0 +1 @@
|
||||
class X< <expr>T</expr> >()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeParameter
|
||||
FIR element: FirTypeParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
T
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
enum class X {
|
||||
<expr>ENTRY</expr>
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtEnumEntry
|
||||
FIR element: FirEnumEntryImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final static enum entry ENTRY: R|X|
|
||||
+1
@@ -0,0 +1 @@
|
||||
fun x< <expr>T</expr> > foo(){}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeParameter
|
||||
FIR element: FirTypeParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
T
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun foo(<expr>x: Int</expr>) {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtParameter
|
||||
FIR element: FirValueParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
x: R|kotlin/Int|
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
val x: String
|
||||
<expr>get() = ""</expr>
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
KT element: KtPropertyAccessor
|
||||
FIR element: FirPropertyAccessorImpl
|
||||
|
||||
FIR element rendered:
|
||||
public get(): R|kotlin/String| {
|
||||
^ String()
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fun y() {
|
||||
<expr>
|
||||
class X {
|
||||
fun y(): String
|
||||
}
|
||||
</expr>
|
||||
}
|
||||
idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/localClass.txt
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
KT element: KtClass
|
||||
FIR element: FirRegularClassImpl
|
||||
|
||||
FIR element rendered:
|
||||
local final class X : R|kotlin/Any| {
|
||||
public constructor(): R|X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun y(): R|kotlin/String|
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun y() {
|
||||
<expr>
|
||||
fun x(): String = ""
|
||||
</expr>
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
KT element: KtNamedFunction
|
||||
FIR element: FirSimpleFunctionImpl
|
||||
|
||||
FIR element rendered:
|
||||
local final fun x(): R|kotlin/String| {
|
||||
^x String()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun y() {
|
||||
<expr>
|
||||
val x: String = ""
|
||||
</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtProperty
|
||||
FIR element: FirPropertyImpl
|
||||
|
||||
FIR element rendered:
|
||||
lval x: R|kotlin/String| = String()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Y {
|
||||
<expr>
|
||||
fun x(): String = ""
|
||||
</expr>
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
KT element: KtNamedFunction
|
||||
FIR element: FirSimpleFunctionImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final fun x(): R|kotlin/String| {
|
||||
^x String()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Y {
|
||||
<expr>
|
||||
val x: String = ""
|
||||
</expr>
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
KT element: KtProperty
|
||||
FIR element: FirPropertyImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final val x: R|kotlin/String| = String()
|
||||
public get(): R|kotlin/String|
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Y {
|
||||
<expr>
|
||||
typealias Str = String
|
||||
</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeAlias
|
||||
FIR element: FirTypeAliasImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final typealias Str = R|kotlin/String|
|
||||
idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/nestedClass.kt
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
class Y {
|
||||
<expr>
|
||||
class X {
|
||||
fun y(): String
|
||||
}
|
||||
</expr>
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
KT element: KtClass
|
||||
FIR element: FirRegularClassImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final class X : R|kotlin/Any| {
|
||||
public constructor(): R|Y.X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun y(): R|kotlin/String|
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
class X(<expr>val x: Int</expr>)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtParameter
|
||||
FIR element: FirValueParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
x: R|kotlin/Int|
|
||||
+1
@@ -0,0 +1 @@
|
||||
class X(<expr>x: Int</expr>)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtParameter
|
||||
FIR element: FirValueParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
x: R|kotlin/Int|
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class X(x: Int) {
|
||||
constructor(<expr>y: String</expr>): this(1)
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtParameter
|
||||
FIR element: FirValueParameterImpl
|
||||
|
||||
FIR element rendered:
|
||||
y: R|kotlin/String|
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
var x: String
|
||||
<expr>set(value) {}</expr>
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
KT element: KtPropertyAccessor
|
||||
FIR element: FirPropertyAccessorImpl
|
||||
|
||||
FIR element rendered:
|
||||
public set(value: R|kotlin/String|): R|kotlin/Unit| {
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<expr>
|
||||
class X {
|
||||
fun y(): String
|
||||
}
|
||||
</expr>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
KT element: KtClass
|
||||
FIR element: FirRegularClassImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final class X : R|kotlin/Any| {
|
||||
public constructor(): R|X| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun y(): R|kotlin/String|
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<expr>
|
||||
fun x() {
|
||||
fun y(): String
|
||||
}
|
||||
</expr>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
KT element: KtNamedFunction
|
||||
FIR element: FirSimpleFunctionImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final fun x(): R|kotlin/Unit| {
|
||||
local final fun y(): R|kotlin/String|
|
||||
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<expr>
|
||||
val x = 1
|
||||
</expr>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
KT element: KtProperty
|
||||
FIR element: FirPropertyImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final val x: R|kotlin/Int| = Int(1)
|
||||
public get(): R|kotlin/Int|
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<expr>
|
||||
typealias Str = String
|
||||
</expr>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KT element: KtTypeAlias
|
||||
FIR element: FirTypeAliasImpl
|
||||
|
||||
FIR element rendered:
|
||||
public final typealias Str = R|kotlin/String|
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.kotlin.idea.fir.low.level.api
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.FirImport
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.AbstractLowLevelApiSingleFileTest
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
|
||||
import org.jetbrains.kotlin.test.services.TestModuleStructure
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.assertions
|
||||
|
||||
abstract class AbstractGetOrBuildFirTest : AbstractLowLevelApiSingleFileTest() {
|
||||
override fun configureTest(builder: TestConfigurationBuilder) {
|
||||
super.configureTest(builder)
|
||||
with(builder) {
|
||||
useDirectives(Directives)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doTestByFileStructure(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices) {
|
||||
val selectedElement = getElementOfType(ktFile, moduleStructure, testServices) as KtElement
|
||||
|
||||
val actual = resolveWithClearCaches(ktFile) { state ->
|
||||
val fir = selectedElement.getOrBuildFir(state)
|
||||
"""|KT element: ${selectedElement::class.simpleName}
|
||||
|FIR element: ${fir::class.simpleName}
|
||||
|
|
||||
|FIR element rendered:
|
||||
|${render(fir)}""".trimMargin()
|
||||
}
|
||||
testServices.assertions.assertEqualsToFile(testDataFileSibling(".txt"), actual)
|
||||
}
|
||||
|
||||
private fun getElementOfType(ktFile: KtFile, moduleStructure: TestModuleStructure, testServices: TestServices): PsiElement {
|
||||
val selectedElement = testServices.expressionMarkerProvider.getSelectedElement(ktFile)
|
||||
val expectedType = moduleStructure.allDirectives[Directives.LOOK_UP_FOR_ELEMENT_OF_TYPE].firstOrNull() ?: return selectedElement
|
||||
@Suppress("UNCHECKED_CAST") val expectedClass = Class.forName(expectedType) as Class<PsiElement>
|
||||
if (expectedClass.isInstance(selectedElement)) return selectedElement
|
||||
|
||||
return listOfNotNull(
|
||||
PsiTreeUtil.getChildOfType(selectedElement, expectedClass),
|
||||
).single { it.textRange == selectedElement.textRange }
|
||||
}
|
||||
|
||||
private fun render(firElement: FirElement): String = when (firElement) {
|
||||
is FirImport -> "import ${firElement.importedFqName}"
|
||||
else -> firElement.render(renderingMode)
|
||||
}
|
||||
|
||||
private val renderingMode = FirRenderer.RenderMode.Normal.copy(
|
||||
renderPackageDirective = true,
|
||||
)
|
||||
|
||||
private object Directives : SimpleDirectivesContainer() {
|
||||
val LOOK_UP_FOR_ELEMENT_OF_TYPE by stringDirective("LOOK_UP_FOR_ELEMENT_OF_TYPE")
|
||||
}
|
||||
}
|
||||
+340
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* 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.kotlin.idea.fir.low.level.api;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInGetOrBuildFir() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class InImport {
|
||||
@Test
|
||||
public void testAllFilesPresentInInImport() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("firstImportNamePart.kt")
|
||||
public void testFirstImportNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/firstImportNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("middleImportNamePart.kt")
|
||||
public void testMiddleImportNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/middleImportNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("qualifiedImportNamePart.kt")
|
||||
public void testQualifiedImportNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/qualifiedImportNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("wholeImportDirective.kt")
|
||||
public void testWholeImportDirective() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/wholeImportDirective.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("wholeImportName.kt")
|
||||
public void testWholeImportName() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inImport/wholeImportName.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class InPackage {
|
||||
@Test
|
||||
public void testAllFilesPresentInInPackage() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("firstPackageNamePart.kt")
|
||||
public void testFirstPackageNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage/firstPackageNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("middlePackageNamePart.kt")
|
||||
public void testMiddlePackageNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage/middlePackageNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("qualifiedPackageNamePart.kt")
|
||||
public void testQualifiedPackageNamePart() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage/qualifiedPackageNamePart.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("wholePackageDirective.kt")
|
||||
public void testWholePackageDirective() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage/wholePackageDirective.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("wholePackageName.kt")
|
||||
public void testWholePackageName() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/inPackage/wholePackageName.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class QualifiedExpressions {
|
||||
@Test
|
||||
public void testAllFilesPresentInQualifiedExpressions() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("firstPartOfQualifiedCallWithNestedClasses.kt")
|
||||
public void testFirstPartOfQualifiedCallWithNestedClasses() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions/firstPartOfQualifiedCallWithNestedClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lastPartOfQualifiedCallWithNestedClasses.kt")
|
||||
public void testLastPartOfQualifiedCallWithNestedClasses() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions/lastPartOfQualifiedCallWithNestedClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("middlePartOfQualifiedCallWithNestedClasses.kt")
|
||||
public void testMiddlePartOfQualifiedCallWithNestedClasses() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions/middlePartOfQualifiedCallWithNestedClasses.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("qualifiedPartOfQualifiedCallWithNestedClasses.kt")
|
||||
public void testQualifiedPartOfQualifiedCallWithNestedClasses() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/qualifiedExpressions/qualifiedPartOfQualifiedCallWithNestedClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Types {
|
||||
@Test
|
||||
public void testAllFilesPresentInTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidTypeArgumentsCount.kt")
|
||||
public void testInvalidTypeArgumentsCount() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/invalidTypeArgumentsCount.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidTypeArgumentsCountArgument.kt")
|
||||
public void testInvalidTypeArgumentsCountArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/invalidTypeArgumentsCountArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidTypeArgumentsCountFirstArgument.kt")
|
||||
public void testInvalidTypeArgumentsCountFirstArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/invalidTypeArgumentsCountFirstArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("invalidTypeArgumentsCountLastArgument.kt")
|
||||
public void testInvalidTypeArgumentsCountLastArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/invalidTypeArgumentsCountLastArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedTypeArgument.kt")
|
||||
public void testNestedTypeArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/nestedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeArgument.kt")
|
||||
public void testTypeArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/typeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedTypeArgumentResolvedTypeConsturctor.kt")
|
||||
public void testUnresolvedTypeArgumentResolvedTypeConsturctor() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/unresolvedTypeArgumentResolvedTypeConsturctor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedTypeConsturctorResolvedNestedTypeArgument.kt")
|
||||
public void testUnresolvedTypeConsturctorResolvedNestedTypeArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/unresolvedTypeConsturctorResolvedNestedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("unresolvedTypeConsturctorResolvedTypeArgument.kt")
|
||||
public void testUnresolvedTypeConsturctorResolvedTypeArgument() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/unresolvedTypeConsturctorResolvedTypeArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("wholeType.kt")
|
||||
public void testWholeType() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/types/wholeType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class WholeDeclaration {
|
||||
@Test
|
||||
public void testAllFilesPresentInWholeDeclaration() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classTypeParemeter.kt")
|
||||
public void testClassTypeParemeter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/classTypeParemeter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumEntry.kt")
|
||||
public void testEnumEntry() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/enumEntry.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeParemeter.kt")
|
||||
public void testFunctionTypeParemeter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/functionTypeParemeter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionValueParameter.kt")
|
||||
public void testFunctionValueParameter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/functionValueParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("getter.kt")
|
||||
public void testGetter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/getter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localClass.kt")
|
||||
public void testLocalClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/localClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localFunction.kt")
|
||||
public void testLocalFunction() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/localFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("localProperty.kt")
|
||||
public void testLocalProperty() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/localProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberFunction.kt")
|
||||
public void testMemberFunction() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/memberFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberProperty.kt")
|
||||
public void testMemberProperty() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/memberProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberTypeAlias.kt")
|
||||
public void testMemberTypeAlias() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/memberTypeAlias.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/nestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primaryConstructorValValueParameter.kt")
|
||||
public void testPrimaryConstructorValValueParameter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/primaryConstructorValValueParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primaryConstructorValueParameter.kt")
|
||||
public void testPrimaryConstructorValueParameter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/primaryConstructorValueParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("secondaryConstructorValueParameter.kt")
|
||||
public void testSecondaryConstructorValueParameter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/secondaryConstructorValueParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("setter.kt")
|
||||
public void testSetter() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/setter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelClass.kt")
|
||||
public void testTopLevelClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/topLevelClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelFunction.kt")
|
||||
public void testTopLevelFunction() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/topLevelFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelProperty.kt")
|
||||
public void testTopLevelProperty() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/topLevelProperty.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("topLevelTypelTypeAlias.kt")
|
||||
public void testTopLevelTypelTypeAlias() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/getOrBuildFir/wholeDeclaration/topLevelTypelTypeAlias.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-3
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.idea.fir.low.level.api.test.base
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.PrivateForInline
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.parentOfType
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -55,7 +57,9 @@ internal class ExpressionMarkersSourceFilePreprocessor(testServices: TestService
|
||||
|
||||
class ExpressionMarkerProvider(testServices: TestServices) : TestService {
|
||||
private val selected = mutableMapOf<String, TextRange>()
|
||||
@PrivateForInline val atCaret = mutableMapOf<String, Int>()
|
||||
|
||||
@PrivateForInline
|
||||
val atCaret = mutableMapOf<String, Int>()
|
||||
|
||||
fun addSelectedExpression(file: TestFile, range: TextRange) {
|
||||
selected[file.relativePath] = range
|
||||
@@ -79,12 +83,16 @@ class ExpressionMarkerProvider(testServices: TestServices) : TestService {
|
||||
fun getSelectedElement(file: KtFile): KtElement {
|
||||
val range = selected[file.name]
|
||||
?: error("No selected expression found in file")
|
||||
val elements = file.elementsInRange(range)
|
||||
val elements = file.elementsInRange(range).trimWhitespaces()
|
||||
if (elements.size != 1) {
|
||||
error("Expected one element at rage but found ${elements.size} [${elements.joinToString { it.text }}]")
|
||||
error("Expected one element at rage but found ${elements.size} [${elements.joinToString { it::class.simpleName + ": " + it.text }}]")
|
||||
}
|
||||
return elements.single() as KtElement
|
||||
}
|
||||
|
||||
private fun List<PsiElement>.trimWhitespaces(): List<PsiElement> =
|
||||
dropWhile { it is PsiWhiteSpace }
|
||||
.dropLastWhile { it is PsiWhiteSpace }
|
||||
}
|
||||
|
||||
val TestServices.expressionMarkerProvider: ExpressionMarkerProvider by TestServices.testServiceAccessor()
|
||||
|
||||
Reference in New Issue
Block a user