[FIR IDE] Extract common components of the Analysis API to separate modules
This commit is contained in:
committed by
teamcityserver
parent
44a1fe668e
commit
e2c9be0932
@@ -16,6 +16,7 @@ dependencies {
|
||||
api(project(":compiler:fir:checkers:checkers.jvm"))
|
||||
api(project(":compiler:fir:java"))
|
||||
api(project(":compiler:backend.common.jvm"))
|
||||
api(project(":analysis:analysis-api-impl-barebone"))
|
||||
testApi(project(":analysis:analysis-api-fir"))
|
||||
implementation(project(":compiler:ir.psi2ir"))
|
||||
implementation(project(":compiler:fir:entrypoint"))
|
||||
@@ -32,6 +33,7 @@ dependencies {
|
||||
testApi(toolsJar())
|
||||
testApi(projectTests(":compiler:tests-common"))
|
||||
testApi(projectTests(":compiler:fir:analysis-tests:legacy-fir-tests"))
|
||||
testApi(projectTests(":analysis:analysis-api-impl-barebone"))
|
||||
testApi(project(":kotlin-test:kotlin-test-junit"))
|
||||
testApiJUnit5()
|
||||
testApi(project(":kotlin-reflect"))
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
|
||||
+10
-10
@@ -6,7 +6,16 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.DiagnosticsCollector
|
||||
@@ -28,15 +37,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousFunctionExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.analysis.low.level.api.fir.annotations
|
||||
|
||||
@RequiresOptIn
|
||||
annotation class PrivateForInline
|
||||
|
||||
@RequiresOptIn
|
||||
annotation class InternalForInline
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.analysis.low.level.api.fir.annotations
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class ThreadSafe
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class NotThreadSafe
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class Immutable
|
||||
+1
-1
@@ -6,10 +6,10 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveType
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
|
||||
+1
-2
@@ -6,13 +6,12 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirIdeResolveStateService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveType
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.analyzer.ModuleSourceInfoBase
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
+12
-12
@@ -6,7 +6,19 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirModuleResolveStateDepended
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirModuleResolveStateImpl
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FileTowerProvider
|
||||
@@ -20,19 +32,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentsOfType
|
||||
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
|
||||
+1
-1
@@ -7,11 +7,11 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.FirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
|
||||
+1
-1
@@ -5,13 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.builder.BodyBuildingMode
|
||||
import org.jetbrains.kotlin.fir.builder.PsiHandlingMode
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirPhaseRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -5,8 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.PrivateForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.ResolveTreeBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.lockWithPCECheck
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
+1
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
|
||||
|
||||
import com.intellij.concurrency.ConcurrentCollectionFactory
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
@@ -13,7 +14,6 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.ThreadSafe
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
+1
-1
@@ -5,11 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentOfType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.Immutable
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.annotations.Immutable
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
|
||||
+3
-14
@@ -12,6 +12,8 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import com.intellij.psi.util.*
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
@@ -20,8 +22,6 @@ import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.Lock
|
||||
import kotlin.reflect.KProperty
|
||||
@@ -135,15 +135,4 @@ fun KtElement.getElementTextInContext(): String {
|
||||
return builder.toString().trimIndent().trim()
|
||||
}
|
||||
|
||||
private const val ELEMENT_TAG = "ELEMENT"
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.parentOfType(withSelf: Boolean = false): T? {
|
||||
return PsiTreeUtil.getParentOfType(this, T::class.java, !withSelf)
|
||||
}
|
||||
|
||||
fun <T : PsiElement> PsiElement.parentsOfType(clazz: Class<out T>, withSelf: Boolean = true): Sequence<T> {
|
||||
return (if (withSelf) parentsWithSelf else parents).filterIsInstance(clazz)
|
||||
}
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.parentsOfType(withSelf: Boolean = true): Sequence<T> =
|
||||
parentsOfType(T::class.java, withSelf)
|
||||
private const val ELEMENT_TAG = "ELEMENT"
|
||||
+1
-1
@@ -7,13 +7,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.expressionMarkerProvider
|
||||
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.analysis.low.level.api.fir.api.getOrBuildFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.AbstractLowLevelApiSingleFileTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.expressionMarkerProvider
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
|
||||
+11
-36
@@ -5,14 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.AbstractCompilerBasedTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.TestKtModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.createResolveStateForNoCaching
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.FirLazyTransformerForIDE
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.test.TestConfiguration
|
||||
import org.jetbrains.kotlin.test.bind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.builders.firHandlersStep
|
||||
@@ -20,28 +20,14 @@ import org.jetbrains.kotlin.test.builders.testConfiguration
|
||||
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
|
||||
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||
import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.TestInfo
|
||||
|
||||
abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() {
|
||||
private var _disposable: Disposable? = null
|
||||
protected val disposable: Disposable get() = _disposable!!
|
||||
|
||||
@BeforeEach
|
||||
private fun intiDisposable(testInfo: TestInfo) {
|
||||
_disposable = Disposer.newDisposable("disposable for ${testInfo.displayName}")
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
private fun disposeDisposable() {
|
||||
_disposable?.let { Disposer.dispose(it) }
|
||||
_disposable = null
|
||||
}
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendFacade
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
||||
|
||||
abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
|
||||
final override fun TestConfigurationBuilder.configuration() {
|
||||
globalDefaults {
|
||||
frontend = FrontendKinds.FIR
|
||||
@@ -62,7 +48,6 @@ abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() {
|
||||
|
||||
open fun TestConfigurationBuilder.configureTest() {}
|
||||
|
||||
|
||||
inner class LowLevelFirFrontendFacade(
|
||||
testServices: TestServices
|
||||
) : FrontendFacade<FirOutputArtifact>(testServices, FrontendKinds.FIR) {
|
||||
@@ -103,14 +88,4 @@ abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() {
|
||||
FirLazyTransformerForIDE.enableDeepEnsure = oldEnableDeepEnsure
|
||||
}
|
||||
}
|
||||
|
||||
private fun ignoreTest(filePath: String, configuration: TestConfiguration): Boolean {
|
||||
val modules = configuration.moduleStructureExtractor.splitTestDataByModules(filePath, configuration.directives)
|
||||
|
||||
if (modules.modules.none { it.files.any { it.isKtFile } }) {
|
||||
return true // nothing to highlight
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
|
||||
class ModuleRegistrarPreAnalysisHandler(
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestService
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
class TestKtModuleProvider(
|
||||
private val testServices: TestServices
|
||||
) : TestService {
|
||||
private val cache = mutableMapOf<String, TestKtSourceModule>()
|
||||
|
||||
fun registerModuleInfo(project: Project, testModule: TestModule, ktFiles: Map<TestFile, KtFile>) {
|
||||
cache[testModule.name] = TestKtSourceModule(project, testModule, ktFiles, testServices)
|
||||
}
|
||||
|
||||
internal fun getModuleInfoByKtFile(ktFile: KtFile): TestKtSourceModule =
|
||||
cache.values.first { moduleSourceInfo ->
|
||||
(if (ktFile.isPhysical) ktFile else ktFile.originalFile) in moduleSourceInfo.ktFiles
|
||||
}
|
||||
|
||||
internal fun getModule(moduleName: String): TestKtSourceModule =
|
||||
cache.getValue(moduleName)
|
||||
}
|
||||
|
||||
val TestServices.projectModuleProvider: TestKtModuleProvider by TestServices.testServiceAccessor()
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.compiler.based
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||
import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
internal class TestKtSourceModule(
|
||||
override val project: Project,
|
||||
val testModule: TestModule,
|
||||
val testFilesToKtFiles: Map<TestFile, KtFile>,
|
||||
testServices: TestServices,
|
||||
) : KtSourceModule {
|
||||
private val moduleProvider = testServices.projectModuleProvider
|
||||
private val compilerConfigurationProvider = testServices.compilerConfigurationProvider
|
||||
private val configuration = compilerConfigurationProvider.getCompilerConfiguration(testModule)
|
||||
|
||||
val ktFiles = testFilesToKtFiles.values.toSet()
|
||||
|
||||
override val moduleName: String
|
||||
get() = testModule.name
|
||||
|
||||
override val directRegularDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
buildList {
|
||||
testModule.allDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
||||
addIfNotNull(
|
||||
libraryByRoots(
|
||||
(configuration.jvmModularRoots + configuration.jvmClasspathRoots).map(File::toPath)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
override val directRefinementDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
testModule.dependsOnDependencies
|
||||
.map { moduleProvider.getModule(it.moduleName) }
|
||||
}
|
||||
override val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
buildList {
|
||||
testModule.friendDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
||||
addIfNotNull(
|
||||
libraryByRoots(configuration[JVMConfigurationKeys.FRIEND_PATHS].orEmpty().map(Paths::get))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun libraryByRoots(roots: List<Path>): LibraryByRoots? {
|
||||
if (roots.isEmpty()) return null
|
||||
return LibraryByRoots(
|
||||
roots,
|
||||
this@TestKtSourceModule,
|
||||
project,
|
||||
)
|
||||
}
|
||||
|
||||
override val contentScope: GlobalSearchScope =
|
||||
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, testFilesToKtFiles.values)
|
||||
|
||||
override val languageVersionSettings: LanguageVersionSettings
|
||||
get() = testModule.languageVersionSettings
|
||||
|
||||
override val platform: TargetPlatform
|
||||
get() = testModule.targetPlatform
|
||||
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices
|
||||
get() = testModule.targetPlatform.getAnalyzerServices()
|
||||
}
|
||||
|
||||
private class LibraryByRoots(
|
||||
private val roots: List<Path>,
|
||||
private val sourceModule: KtSourceModule,
|
||||
override val project: Project,
|
||||
) : KtLibraryModule {
|
||||
override val libraryName: String get() = "Test Library"
|
||||
override val directRegularDependencies: List<KtModule> get() = emptyList()
|
||||
override val directRefinementDependencies: List<KtModule> get() = emptyList()
|
||||
override val directFriendDependencies: List<KtModule> get() = emptyList()
|
||||
override val contentScope: GlobalSearchScope get() = ProjectScope.getLibrariesScope(project)
|
||||
override val platform: TargetPlatform get() = sourceModule.platform
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices get() = sourceModule.analyzerServices
|
||||
override fun getBinaryRoots(): Collection<Path> = roots
|
||||
override val librarySources: KtLibrarySourceModule? get() = null
|
||||
}
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.FirIdeResolveStateService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartProviderFactory
|
||||
|
||||
+2
-2
@@ -5,13 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.addIdeTestIgnoreHandler
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
|
||||
import org.jetbrains.kotlin.test.runners.baseFirSpecDiagnosticTestConfiguration
|
||||
|
||||
abstract class AbstractDiagnosisCompilerTestDataSpecTest : AbstractCompilerBasedTest() {
|
||||
abstract class AbstractDiagnosisCompilerTestDataSpecTest : AbstractCompilerBasedTestForFir() {
|
||||
override fun TestConfigurationBuilder.configureTest() {
|
||||
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade)
|
||||
baseFirSpecDiagnosticTestConfiguration()
|
||||
|
||||
+2
-2
@@ -5,12 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTest
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.addIdeTestIgnoreHandler
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
|
||||
|
||||
abstract class AbstractDiagnosisCompilerTestDataTest : AbstractCompilerBasedTest() {
|
||||
abstract class AbstractDiagnosisCompilerTestDataTest : AbstractCompilerBasedTestForFir() {
|
||||
override fun TestConfigurationBuilder.configureTest() {
|
||||
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade)
|
||||
addIdeTestIgnoreHandler()
|
||||
|
||||
+7
-1
@@ -5,4 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.test.base
|
||||
|
||||
abstract class AbstractLowLevelApiSingleModuleTest : AbstractLowLevelApiTest()
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.AbstractFrontendApiTest
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
|
||||
abstract class AbstractLowLevelApiSingleModuleTest : AbstractFrontendApiTest() {
|
||||
override val configurator: FrontendApiTestConfiguratorService
|
||||
get() = FirLowLevelFrontendApiTestConfiguratorService
|
||||
}
|
||||
-193
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.test.base
|
||||
|
||||
import com.intellij.mock.MockApplication
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.testFramework.TestDataFile
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.analyse
|
||||
import org.jetbrains.kotlin.analysis.api.analyseInDependedAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.ModuleRegistrarPreAnalysisHandler
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.TestKtModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.projectModuleProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.TestInfrastructureInternals
|
||||
import org.jetbrains.kotlin.test.bind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
import org.jetbrains.kotlin.test.builders.testConfiguration
|
||||
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
|
||||
import org.jetbrains.kotlin.test.model.DependencyKind
|
||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||
import org.jetbrains.kotlin.test.model.ResultingArtifact
|
||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.TestInfo
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.ExecutionException
|
||||
import kotlin.io.path.nameWithoutExtension
|
||||
|
||||
abstract class AbstractLowLevelApiTest : TestWithDisposable() {
|
||||
private lateinit var testInfo: KotlinTestInfo
|
||||
private var useDependedAnalysisSession: Boolean = false
|
||||
open protected val enableTestInDependedMode: Boolean = true
|
||||
|
||||
@OptIn(TestInfrastructureInternals::class)
|
||||
private val configure: TestConfigurationBuilder.() -> Unit = {
|
||||
globalDefaults {
|
||||
frontend = FrontendKinds.FIR
|
||||
targetPlatform = JvmPlatforms.defaultJvmPlatform
|
||||
dependencyKind = DependencyKind.Source
|
||||
}
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::JvmEnvironmentConfigurator,
|
||||
)
|
||||
assertions = JUnit5Assertions
|
||||
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
|
||||
|
||||
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
|
||||
useDirectives(JvmEnvironmentConfigurationDirectives)
|
||||
|
||||
useSourcePreprocessor(::ExpressionMarkersSourceFilePreprocessor)
|
||||
useAdditionalService { ExpressionMarkerProvider() }
|
||||
useAdditionalService(::TestKtModuleProvider)
|
||||
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable))
|
||||
configureTest(this)
|
||||
|
||||
startingArtifactFactory = { ResultingArtifact.Source() }
|
||||
this.testInfo = this@AbstractLowLevelApiTest.testInfo
|
||||
}
|
||||
|
||||
protected lateinit var testDataPath: Path
|
||||
|
||||
protected fun testDataFileSibling(extension: String): Path {
|
||||
val extensionWithDot = "." + extension.removePrefix(".")
|
||||
return testDataPath.resolveSibling(testDataPath.nameWithoutExtension + extensionWithDot)
|
||||
}
|
||||
|
||||
open fun configureTest(builder: TestConfigurationBuilder) {}
|
||||
|
||||
protected fun runTest(@TestDataFile path: String) {
|
||||
testDataPath = Paths.get(path)
|
||||
val testConfiguration = testConfiguration(path, configure)
|
||||
Disposer.register(disposable, testConfiguration.rootDisposable)
|
||||
val testServices = testConfiguration.testServices
|
||||
val moduleStructure = testConfiguration.moduleStructureExtractor.splitTestDataByModules(
|
||||
path,
|
||||
testConfiguration.directives,
|
||||
).also { testModuleStructure ->
|
||||
testConfiguration.testServices.register(TestModuleStructure::class, testModuleStructure)
|
||||
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
|
||||
preprocessor.preprocessModuleStructure(testModuleStructure)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val singleModule = moduleStructure.modules.single()
|
||||
val project = testServices.compilerConfigurationProvider.getProject(singleModule)
|
||||
val moduleInfoProvider = testServices.projectModuleProvider
|
||||
|
||||
val moduleInfo = moduleInfoProvider.getModule(singleModule.name)
|
||||
|
||||
with(project as MockProject) {
|
||||
registerServicesForProject(this)
|
||||
}
|
||||
|
||||
registerApplicationServices()
|
||||
|
||||
val ktFiles = moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
|
||||
|
||||
doTestByFileStructure(ktFiles, moduleStructure, testServices)
|
||||
if (!enableTestInDependedMode || ktFiles.any {
|
||||
InTextDirectivesUtils.isDirectiveDefined(it.text, DISABLE_DEPENDED_MODE_DIRECTIVE)
|
||||
}) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
useDependedAnalysisSession = true
|
||||
doTestByFileStructure(ktFiles.map {
|
||||
val fakeFile = it.copy() as KtFile
|
||||
fakeFile.originalKtFile = it
|
||||
fakeFile
|
||||
}, moduleStructure, testServices)
|
||||
} catch (e: SkipDependedModeException) {
|
||||
// Skip the test if needed
|
||||
} catch (e: ExecutionException) {
|
||||
if (e.cause !is SkipDependedModeException)
|
||||
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
|
||||
} catch (e: Exception) {
|
||||
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerApplicationServices() {
|
||||
val application = ApplicationManager.getApplication() as MockApplication
|
||||
KotlinCoreEnvironment.underApplicationLock {
|
||||
registerApplicationServices(application)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun registerServicesForProject(project: MockProject) {}
|
||||
|
||||
protected open fun registerApplicationServices(application: MockApplication) {}
|
||||
|
||||
protected abstract fun doTestByFileStructure(ktFiles: List<KtFile>, moduleStructure: TestModuleStructure, testServices: TestServices)
|
||||
|
||||
@BeforeEach
|
||||
fun initTestInfo(testInfo: TestInfo) {
|
||||
this.testInfo = KotlinTestInfo(
|
||||
className = testInfo.testClass.orElseGet(null)?.name ?: "_undefined_",
|
||||
methodName = testInfo.testMethod.orElseGet(null)?.name ?: "_testUndefined_",
|
||||
tags = testInfo.tags
|
||||
)
|
||||
}
|
||||
|
||||
protected inline fun <R> analyseOnPooledThreadInReadAction(context: KtElement, crossinline action: KtAnalysisSession.() -> R): R =
|
||||
executeOnPooledThreadInReadAction {
|
||||
analyseForTest(context) { action() }
|
||||
}
|
||||
|
||||
protected inline fun <T> runReadAction(crossinline runnable: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction(Computable { runnable() })
|
||||
}
|
||||
|
||||
protected inline fun <R> executeOnPooledThreadInReadAction(crossinline action: () -> R): R =
|
||||
ApplicationManager.getApplication().executeOnPooledThread<R> { runReadAction(action) }.get()
|
||||
|
||||
|
||||
protected fun <R> analyseForTest(contextElement: KtElement, action: KtAnalysisSession.() -> R): R {
|
||||
return if (useDependedAnalysisSession) {
|
||||
// Depended mode does not support analysing a KtFile. See org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir#getResolveStateForDependentCopy
|
||||
if (contextElement is KtFile) throw SkipDependedModeException()
|
||||
|
||||
require(!contextElement.isPhysical)
|
||||
analyseInDependedAnalysisSession(contextElement.containingKtFile.originalKtFile!!, contextElement, action)
|
||||
} else {
|
||||
analyse(contextElement, action)
|
||||
}
|
||||
}
|
||||
|
||||
private class SkipDependedModeException : Exception()
|
||||
|
||||
companion object {
|
||||
val DISABLE_DEPENDED_MODE_DIRECTIVE = "DISABLE_DEPENDED_MODE"
|
||||
}
|
||||
}
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.test.base
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.annotations.PrivateForInline
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.parentOfType
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.services.SourceFilePreprocessor
|
||||
import org.jetbrains.kotlin.test.services.TestService
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
|
||||
internal class ExpressionMarkersSourceFilePreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
|
||||
override fun process(file: TestFile, content: String): String {
|
||||
val withSelectedProcessed = processSelectedExpression(file, content)
|
||||
return processCaretExpression(file, withSelectedProcessed)
|
||||
}
|
||||
|
||||
private fun processSelectedExpression(file: TestFile, content: String): String {
|
||||
val startCaretPosition = content.indexOfOrNull(TAGS.OPENING_EXPRESSION_TAG) ?: return content
|
||||
|
||||
val endCaretPosition = content.indexOfOrNull(TAGS.CLOSING_EXPRESSION_TAG)
|
||||
?: error("${TAGS.CLOSING_EXPRESSION_TAG} was not found in the file")
|
||||
|
||||
check(startCaretPosition < endCaretPosition)
|
||||
testServices.expressionMarkerProvider.addSelectedExpression(
|
||||
file,
|
||||
TextRange.create(startCaretPosition, endCaretPosition - TAGS.OPENING_EXPRESSION_TAG.length)
|
||||
)
|
||||
return content
|
||||
.replace(TAGS.OPENING_EXPRESSION_TAG, "")
|
||||
.replace(TAGS.CLOSING_EXPRESSION_TAG, "")
|
||||
}
|
||||
|
||||
private fun processCaretExpression(file: TestFile, content: String): String {
|
||||
val startCaretPosition = content.indexOfOrNull(TAGS.CARET) ?: return content
|
||||
|
||||
testServices.expressionMarkerProvider.addCaret(file, startCaretPosition)
|
||||
return content
|
||||
.replace(TAGS.CARET, "")
|
||||
}
|
||||
|
||||
object TAGS {
|
||||
const val OPENING_EXPRESSION_TAG = "<expr>"
|
||||
const val CLOSING_EXPRESSION_TAG = "</expr>"
|
||||
const val CARET = "<caret>"
|
||||
}
|
||||
}
|
||||
|
||||
class ExpressionMarkerProvider : TestService {
|
||||
private val selected = mutableMapOf<String, TextRange>()
|
||||
|
||||
@PrivateForInline
|
||||
val atCaret = mutableMapOf<String, Int>()
|
||||
|
||||
fun addSelectedExpression(file: TestFile, range: TextRange) {
|
||||
selected[file.relativePath] = range
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun addCaret(file: TestFile, caret: Int) {
|
||||
atCaret[file.relativePath] = caret
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun getCaretPosition(file: KtFile): Int {
|
||||
return atCaret[file.name]
|
||||
?: error("No caret found in file")
|
||||
}
|
||||
|
||||
inline fun <reified P : KtElement> getElementOfTypAtCaret(file: KtFile): P {
|
||||
val offset = getCaretPosition(file)
|
||||
return file.findElementAt(offset)
|
||||
?.parentOfType<P>()
|
||||
?: error("No expression found at caret")
|
||||
}
|
||||
|
||||
|
||||
fun getSelectedElement(file: KtFile): KtElement {
|
||||
val range = selected[file.name]
|
||||
?: error("No selected expression found in file")
|
||||
val elements = file.elementsInRange(range).trimWhitespaces()
|
||||
if (elements.size != 1) {
|
||||
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 }
|
||||
}
|
||||
|
||||
private fun String.indexOfOrNull(substring: String) =
|
||||
indexOf(substring).takeIf { it >= 0 }
|
||||
|
||||
val TestServices.expressionMarkerProvider: ExpressionMarkerProvider by TestServices.testServiceAccessor()
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.test.base
|
||||
|
||||
import com.intellij.mock.MockApplication
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.ModuleRegistrarPreAnalysisHandler
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.originalKtFile
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.bind
|
||||
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
|
||||
|
||||
object FirLowLevelFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
|
||||
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
|
||||
usePreAnalysisHandlers(::ModuleRegistrarPreAnalysisHandler.bind(disposable))
|
||||
}
|
||||
|
||||
override fun processTestFiles(files: List<KtFile>): List<KtFile> {
|
||||
return files.map {
|
||||
val fakeFile = it.copy() as KtFile
|
||||
fakeFile.originalKtFile = it
|
||||
fakeFile
|
||||
}
|
||||
}
|
||||
|
||||
override fun getOriginalFile(file: KtFile): KtFile {
|
||||
return file.originalKtFile!!
|
||||
}
|
||||
|
||||
override fun registerProjectServices(project: MockProject) {}
|
||||
override fun registerApplicationServices(application: MockApplication) {}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.analysis.low.level.api.fir.test.base
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.TestInfo
|
||||
|
||||
abstract class TestWithDisposable {
|
||||
private var _disposable: Disposable? = null
|
||||
protected val disposable: Disposable get() = _disposable!!
|
||||
|
||||
@BeforeEach
|
||||
private fun intiDisposable(testInfo: TestInfo) {
|
||||
_disposable = Disposer.newDisposable("disposable for ${testInfo.displayName}")
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
private fun disposeDisposable() {
|
||||
_disposable?.let { Disposer.dispose(it) }
|
||||
_disposable = null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user