Skip to content

Commit fee5821

Browse files
Refactor KotlinPsiFileFactory to KotlinCompiler
Remove workaround for Kotlin Compiler version 1.6 on Java 1.8 (see #1271) which requires KtlintRuleEngine to be injected. The problem of #1271, can still be reproduced with Ktlint 0.43.0 on java 1.8.0_432. With Ktlint 0.44.0 until 1.5.0 which included the workaround, the problem can not be reproduced on that same java version. Without the workaround on that same java version, the problem is also resolved. So, the workaround is no longer needed as it has been resolved in a Kotlin version after 1.6.0. By removing this workaround, the code is simplified.
1 parent 6a553b0 commit fee5821

File tree

2 files changed

+28
-66
lines changed

2 files changed

+28
-66
lines changed

ktlint-rule-engine/src/main/kotlin/com/pinterest/ktlint/rule/engine/internal/KotlinPsiFileFactory.kt ktlint-rule-engine/src/main/kotlin/com/pinterest/ktlint/rule/engine/internal/KotlinCompiler.kt

+16-47
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.pinterest.ktlint.rule.engine.internal
22

3-
import com.pinterest.ktlint.rule.engine.api.KtLintRuleEngine
4-
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
3+
import com.pinterest.ktlint.rule.engine.core.util.cast
54
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
65
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
76
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
@@ -14,43 +13,32 @@ import org.jetbrains.kotlin.com.intellij.pom.PomModelAspect
1413
import org.jetbrains.kotlin.com.intellij.pom.PomTransaction
1514
import org.jetbrains.kotlin.com.intellij.pom.impl.PomTransactionBase
1615
import org.jetbrains.kotlin.com.intellij.pom.tree.TreeAspect
16+
import org.jetbrains.kotlin.com.intellij.psi.PsiFile
1717
import org.jetbrains.kotlin.com.intellij.psi.PsiFileFactory
1818
import org.jetbrains.kotlin.config.CommonConfigurationKeys
1919
import org.jetbrains.kotlin.config.CompilerConfiguration
20+
import org.jetbrains.kotlin.idea.KotlinLanguage
2021
import sun.reflect.ReflectionFactory
21-
import java.nio.file.Files
22-
import java.nio.file.Path
2322
import org.jetbrains.kotlin.com.intellij.openapi.diagnostic.Logger as DiagnosticLogger
2423

25-
internal class KotlinPsiFileFactoryProvider {
26-
private lateinit var psiFileFactory: PsiFileFactory
24+
internal object KotlinCompiler {
25+
private val psiFileFactory = initPsiFileFactory()
2726

28-
@Synchronized
29-
fun getKotlinPsiFileFactory(ktLintRuleEngine: KtLintRuleEngine): PsiFileFactory =
30-
if (::psiFileFactory.isInitialized) {
31-
psiFileFactory
32-
} else {
33-
initPsiFileFactory(ktLintRuleEngine).also { psiFileFactory = it }
34-
}
27+
fun createFileFromText(
28+
psiFileName: String,
29+
normalizedText: String,
30+
): PsiFile = psiFileFactory.createFileFromText(psiFileName, KotlinLanguage.INSTANCE, normalizedText)
3531
}
3632

3733
/**
3834
* Initialize Kotlin Lexer.
3935
*/
40-
internal fun initPsiFileFactory(ktLintRuleEngine: KtLintRuleEngine): PsiFileFactory {
36+
private fun initPsiFileFactory(): PsiFileFactory {
4137
DiagnosticLogger.setFactory(LoggerFactory::class.java)
4238

43-
val compilerConfiguration = CompilerConfiguration()
44-
compilerConfiguration.put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
45-
// Special workaround on JDK 1.8 when KtLint is used from shipped CLI
46-
// to prevent Kotlin compiler initialization error
47-
if (ktLintRuleEngine.isInvokedFromCli && System.getProperty("java.specification.version") == "1.8") {
48-
val extensionPath = extractCompilerExtension()
49-
compilerConfiguration.put(
50-
CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT,
51-
extensionPath.toAbsolutePath().toString(),
52-
)
53-
}
39+
val compilerConfiguration =
40+
CompilerConfiguration()
41+
.apply { put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) }
5442

5543
val disposable = Disposer.newDisposable()
5644
try {
@@ -60,8 +48,9 @@ internal fun initPsiFileFactory(ktLintRuleEngine: KtLintRuleEngine): PsiFileFact
6048
disposable,
6149
compilerConfiguration,
6250
EnvironmentConfigFiles.JVM_CONFIG_FILES,
63-
).project as MockProject
64-
project.registerFormatPomModel()
51+
).project
52+
.cast<MockProject>()
53+
.apply { registerFormatPomModel() }
6554

6655
return PsiFileFactory.getInstance(project)
6756
} finally {
@@ -72,26 +61,6 @@ internal fun initPsiFileFactory(ktLintRuleEngine: KtLintRuleEngine): PsiFileFact
7261
}
7362
}
7463

75-
/**
76-
* Note: this only works in CLI shadowed jar! 'extensions/compiler.xml' is absent in non-shadowed jar.
77-
*/
78-
private fun extractCompilerExtension(): Path {
79-
KtLintRuleEngine::class.java.getResourceAsStream("/META-INF/extensions/compiler.xml").use { input ->
80-
val tempDir = Files.createTempDirectory("ktlint")
81-
tempDir.toFile().deleteOnExit()
82-
83-
val extensionsDir =
84-
tempDir.resolve("META-INF/extensions").also {
85-
Files.createDirectories(it)
86-
}
87-
extensionsDir.resolve("compiler.xml").toFile().outputStream().buffered().use {
88-
input!!.copyTo(it)
89-
}
90-
91-
return tempDir
92-
}
93-
}
94-
9564
/**
9665
* Do not print anything to the stderr when lexer is unable to match input.
9766
*/

ktlint-rule-engine/src/main/kotlin/com/pinterest/ktlint/rule/engine/internal/RuleExecutionContext.kt

+12-19
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@ import org.jetbrains.kotlin.com.intellij.lang.ASTNode
2424
import org.jetbrains.kotlin.com.intellij.lang.FileASTNode
2525
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
2626
import org.jetbrains.kotlin.com.intellij.psi.PsiErrorElement
27-
import org.jetbrains.kotlin.idea.KotlinLanguage
28-
import org.jetbrains.kotlin.psi.KtFile
2927
import kotlin.io.path.pathString
3028

31-
private val KOTLIN_PSI_FILE_FACTORY_PROVIDER = KotlinPsiFileFactoryProvider()
32-
3329
private val LOGGER = KotlinLogging.logger {}.initKtLintKLogger()
3430

3531
internal class RuleExecutionContext private constructor(
@@ -209,7 +205,6 @@ internal class RuleExecutionContext private constructor(
209205
ktLintRuleEngine: KtLintRuleEngine,
210206
code: Code,
211207
): RuleExecutionContext {
212-
val psiFileFactory = KOTLIN_PSI_FILE_FACTORY_PROVIDER.getKotlinPsiFileFactory(ktLintRuleEngine)
213208
val normalizedText = normalizeText(code.content)
214209
val positionInTextLocator = buildPositionInTextLocator(normalizedText)
215210

@@ -222,20 +217,18 @@ internal class RuleExecutionContext private constructor(
222217
} else {
223218
"File.kt"
224219
}
225-
val psiFile =
226-
psiFileFactory.createFileFromText(
227-
psiFileName,
228-
KotlinLanguage.INSTANCE,
229-
normalizedText,
230-
) as KtFile
231-
psiFile
232-
.findErrorElement()
233-
?.let { errorElement ->
234-
val (line, col) = positionInTextLocator(errorElement.textOffset)
235-
throw KtLintParseException(line, col, errorElement.errorDescription)
236-
}
237-
238-
val rootNode = psiFile.node
220+
val rootNode =
221+
KotlinCompiler
222+
.createFileFromText(psiFileName, normalizedText)
223+
.also {
224+
// Throw exception when PSI contains an error element
225+
it
226+
.findErrorElement()
227+
?.let { errorElement ->
228+
val (line, col) = positionInTextLocator(errorElement.textOffset)
229+
throw KtLintParseException(line, col, errorElement.errorDescription)
230+
}
231+
}.node
239232

240233
val editorConfig =
241234
ktLintRuleEngine

0 commit comments

Comments
 (0)