From a8c72b7e844ed35798bd2551dfae546590931d95 Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Tue, 24 Sep 2019 16:47:49 +0200 Subject: [PATCH] Do not resolve services in static initializers in IDEKotlinBinaryClassCache, KT-33973 --- .../core/formatter/KotlinCodeStyleSettings.java | 13 +++++++++++-- .../jetbrains/kotlin/idea/util/FormatterUtil.kt | 2 +- .../idea/caches/IDEKotlinBinaryClassCache.kt | 9 ++++++++- .../classFile/ClassFileDecompilerUtil.kt | 11 +++++++---- .../DeserializerForClassfileDecompiler.kt | 7 ++++--- .../classFile/KotlinClassFileDecompiler.kt | 7 ++++--- .../decompiler/classFile/KotlinClsStubBuilder.kt | 3 ++- .../kotlin/idea/vfilefinder/fileIndexes.kt | 2 +- .../kotlin/idea/formatter/ImportSettingsPanel.kt | 4 ++-- .../formatter/KotlinFormatterUsageCollector.kt | 16 ++++++++++------ .../AbstractInternalCompiledClassesTest.kt | 2 +- .../BuiltInDecompilerConsistencyTest.kt | 2 +- 12 files changed, 52 insertions(+), 26 deletions(-) diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java index 941917ff0ff..97e1e1c4bb9 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/KotlinCodeStyleSettings.java @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.idea.core.formatter; import com.intellij.application.options.CodeStyle; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; @@ -33,8 +35,6 @@ import org.jetbrains.kotlin.idea.util.ReflectionUtil; import static com.intellij.util.ReflectionUtil.copyFields; public class KotlinCodeStyleSettings extends CustomCodeStyleSettings { - public static final KotlinCodeStyleSettings DEFAULT = new KotlinCodeStyleSettings(new CodeStyleSettings()); - public final PackageEntryTable PACKAGES_TO_USE_STAR_IMPORTS = new PackageEntryTable(); public boolean SPACE_AROUND_RANGE = false; public boolean SPACE_BEFORE_TYPE_COLON = false; @@ -180,4 +180,13 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings { copyFrom(settingsAgainstPreviousDefaults); } } + + public static KotlinCodeStyleSettings defaultSettings() { + return ServiceManager.getService(KotlinCodeStyleSettingsHolder.class).defaultSettings; + } + + @Service + private static final class KotlinCodeStyleSettingsHolder { + private final KotlinCodeStyleSettings defaultSettings = new KotlinCodeStyleSettings(new CodeStyleSettings()); + } } diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt index ef27c908b1c..d736a949be7 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt @@ -16,4 +16,4 @@ fun ASTBlock.requireNode() = node ?: error("ASTBlock.getNode() returned null") /** * Can be removed with all usages after moving master to 1.3 with new default code style settings. */ -val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.DEFAULT.CONTINUATION_INDENT_FOR_CHAINED_CALLS } \ No newline at end of file +val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.defaultSettings().CONTINUATION_INDENT_FOR_CHAINED_CALLS } \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/IDEKotlinBinaryClassCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/IDEKotlinBinaryClassCache.kt index d10598075ab..33691e25626 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/IDEKotlinBinaryClassCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/IDEKotlinBinaryClassCache.kt @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.idea.caches import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.openapi.components.Service import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.components.service import com.intellij.openapi.util.Key import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileWithId @@ -28,7 +30,8 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId -object IDEKotlinBinaryClassCache { +@Service +class IDEKotlinBinaryClassCache { class KotlinBinaryClassHeaderData( val classId: ClassId, val kind: KotlinClassHeader.Kind, @@ -132,4 +135,8 @@ object IDEKotlinBinaryClassCache { return null } + + companion object { + fun getInstance(): IDEKotlinBinaryClassCache = service() + } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt index d561db9970e..3f935554fc3 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/ClassFileDecompilerUtil.kt @@ -41,9 +41,10 @@ val KEY = Key.create(KOTLIN_COMPILED_FILE_ATTRIBUTE) * Checks if this file is a compiled Kotlin class file ABI-compatible with the current plugin */ fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean { - if (!IDEKotlinBinaryClassCache.isKotlinJvmCompiledFile(file)) return false + val ideKotlinBinaryClassCache = IDEKotlinBinaryClassCache.getInstance() + if (!ideKotlinBinaryClassCache.isKotlinJvmCompiledFile(file)) return false - val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) + val kotlinClass = ideKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file) return kotlinClass != null && kotlinClass.metadataVersion.isCompatible() } @@ -57,7 +58,9 @@ fun isKotlinInternalCompiledFile(file: VirtualFile, fileContent: ByteArray? = nu return false } - if (!IDEKotlinBinaryClassCache.isKotlinJvmCompiledFile(file, fileContent)) { + val ideKotlinBinaryClassCache = IDEKotlinBinaryClassCache.getInstance() + + if (!ideKotlinBinaryClassCache.isKotlinJvmCompiledFile(file, fileContent)) { return false } @@ -80,7 +83,7 @@ fun isKotlinInternalCompiledFile(file: VirtualFile, fileContent: ByteArray? = nu return true } - val header = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file, fileContent) ?: return false + val header = ideKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(file, fileContent) ?: return false if (header.classId.isLocal) return true return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS || diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt index d9730716947..3275bfa8a2e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/DeserializerForClassfileDecompiler.kt @@ -43,8 +43,9 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import java.io.InputStream fun DeserializerForClassfileDecompiler(classFile: VirtualFile): DeserializerForClassfileDecompiler { - val kotlinClassHeaderInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(classFile) - ?: error("Decompiled data factory shouldn't be called on an unsupported file: " + classFile) + val kotlinClassHeaderInfo = + IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(classFile) + ?: error("Decompiled data factory shouldn't be called on an unsupported file: $classFile") val packageFqName = kotlinClassHeaderInfo.classId.packageFqName return DeserializerForClassfileDecompiler(classFile.parent!!, packageFqName) } @@ -119,7 +120,7 @@ class DirectoryBasedClassFinder( val targetName = classId.relativeClassName.pathSegments().joinToString("$", postfix = ".class") val virtualFile = packageDirectory.findChild(targetName) if (virtualFile != null && isKotlinWithCompatibleAbiVersion(virtualFile)) { - return IDEKotlinBinaryClassCache.getKotlinBinaryClass(virtualFile)?.let(::KotlinClass) + return IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClass(virtualFile)?.let(::KotlinClass) } return null } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt index 3d8ecebb418..8301227cb5e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClassFileDecompiler.kt @@ -40,7 +40,7 @@ import org.jetbrains.kotlin.types.isFlexible class KotlinClassFileDecompiler : ClassFileDecompilers.Full() { private val stubBuilder = KotlinClsStubBuilder() - override fun accepts(file: VirtualFile) = IDEKotlinBinaryClassCache.isKotlinJvmCompiledFile(file) + override fun accepts(file: VirtualFile) = IDEKotlinBinaryClassCache.getInstance().isKotlinJvmCompiledFile(file) override fun getStubBuilder() = stubBuilder @@ -67,8 +67,9 @@ fun buildDecompiledTextForClassFile( classFile: VirtualFile, resolver: ResolverForDecompiler = DeserializerForClassfileDecompiler(classFile) ): DecompiledText { - val classHeader = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(classFile) - ?: error("Decompiled data factory shouldn't be called on an unsupported file: " + classFile) + val classHeader = + IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(classFile) + ?: error("Decompiled data factory shouldn't be called on an unsupported file: $classFile") val classId = classHeader.classId diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt index e16912a7373..9200a5c0325 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/classFile/KotlinClsStubBuilder.kt @@ -59,7 +59,8 @@ open class KotlinClsStubBuilder : ClsStubBuilder() { } private fun doBuildFileStub(file: VirtualFile, fileContent: ByteArray): PsiFileStub? { - val kotlinClass = IDEKotlinBinaryClassCache.getKotlinBinaryClass(file, fileContent) ?: error("Can't find binary class for Kotlin file: $file") + val kotlinClass = IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClass(file, fileContent) + ?: error("Can't find binary class for Kotlin file: $file") val header = kotlinClass.classHeader val classId = kotlinClass.classId val packageFqName = header.packageName?.let { FqName(it) } ?: classId.packageFqName diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt index 8cde604956a..f2e0bbc5930 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt @@ -92,7 +92,7 @@ object KotlinClassFileIndex : KotlinFileIndexBase(KotlinCl private val VERSION = 3 private val INDEXER = indexer { fileContent -> - val headerInfo = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(fileContent.file, fileContent.content) + val headerInfo = IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(fileContent.file, fileContent.content) if (headerInfo != null && headerInfo.metadataVersion.isCompatible()) headerInfo.classId.asSingleFqName() else null } } diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt index 1b38dd4ef93..2ee055ec03a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/ImportSettingsPanel.kt @@ -70,9 +70,9 @@ class ImportSettingsPanel(private val commonSettings: CodeStyleSettings) : JPane private val starImportPackageTable = ImportLayoutPanel.createTableForPackageEntries(starImportPackageEntryTable, dummyImportLayoutPanel) private val nameCountToUseStarImportSelector = NameCountToUseStarImportSelector( - "Top-level Symbols", KotlinCodeStyleSettings.DEFAULT.NAME_COUNT_TO_USE_STAR_IMPORT) + "Top-level Symbols", KotlinCodeStyleSettings.defaultSettings().NAME_COUNT_TO_USE_STAR_IMPORT) private val nameCountToUseStarImportForMembersSelector = NameCountToUseStarImportSelector( - "Java Statics and Enum Members", KotlinCodeStyleSettings.DEFAULT.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS) + "Java Statics and Enum Members", KotlinCodeStyleSettings.defaultSettings().NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS) init { layout = BorderLayout() diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt index 577d008d1a5..1692083fcff 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/KotlinFormatterUsageCollector.kt @@ -42,14 +42,18 @@ class KotlinFormatterUsageCollector { private val KOTLIN_DEFAULT_COMMON = KotlinLanguageCodeStyleSettingsProvider().defaultCommonSettings .also { KotlinStyleGuideCodeStyle.applyToCommonSettings(it) } - private val KOTLIN_DEFAULT_CUSTOM = KotlinCodeStyleSettings.DEFAULT.cloneSettings() - .also { KotlinStyleGuideCodeStyle.applyToKotlinCustomSettings(it) } + private val KOTLIN_DEFAULT_CUSTOM by lazy { + KotlinCodeStyleSettings.defaultSettings().cloneSettings() + .also { KotlinStyleGuideCodeStyle.applyToKotlinCustomSettings(it) } + } private val KOTLIN_OBSOLETE_DEFAULT_COMMON = KotlinLanguageCodeStyleSettingsProvider().defaultCommonSettings .also { KotlinObsoleteCodeStyle.applyToCommonSettings(it) } - private val KOTLIN_OBSOLETE_DEFAULT_CUSTOM = KotlinCodeStyleSettings.DEFAULT.cloneSettings() - .also { KotlinObsoleteCodeStyle.applyToKotlinCustomSettings(it) } + private val KOTLIN_OBSOLETE_DEFAULT_CUSTOM by lazy { + KotlinCodeStyleSettings.defaultSettings().cloneSettings() + .also { KotlinObsoleteCodeStyle.applyToKotlinCustomSettings(it) } + } fun getKotlinFormatterKind(project: Project): KotlinFormatterKind { val isProject = CodeStyleSettingsManager.getInstance(project).USE_PER_PROJECT_SETTINGS @@ -60,11 +64,11 @@ class KotlinFormatterUsageCollector { val kotlinCustomSettings = settings.kotlinCustomSettings val isDefaultKotlinCommonSettings = kotlinCommonSettings == KotlinLanguageCodeStyleSettingsProvider().defaultCommonSettings - val isDefaultKotlinCustomSettings = kotlinCustomSettings == KotlinCodeStyleSettings.DEFAULT + val isDefaultKotlinCustomSettings = kotlinCustomSettings == KotlinCodeStyleSettings.defaultSettings() if (isDefaultKotlinCommonSettings && isDefaultKotlinCustomSettings) { return if (isDefaultOfficialCodeStyle) { - paired(IDEA_OFFICIAL_DEFAULT, isProject) + paired(KotlinFormatterKind.IDEA_OFFICIAL_DEFAULT, isProject) } else { paired(IDEA_DEFAULT, isProject) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt index 619dd517212..3beea24a228 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/AbstractInternalCompiledClassesTest.kt @@ -16,7 +16,7 @@ import org.junit.Assert abstract class AbstractInternalCompiledClassesTest : KotlinLightCodeInsightFixtureTestCase() { private fun isFileWithHeader(predicate: (IDEKotlinBinaryClassCache.KotlinBinaryClassHeaderData, ClassId) -> Boolean) : VirtualFile.() -> Boolean = { - val info = IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(this) + val info = IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(this) info != null && predicate(info, info.classId) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/BuiltInDecompilerConsistencyTest.kt b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/BuiltInDecompilerConsistencyTest.kt index 1dcd00faa31..4e7e1744a2e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/BuiltInDecompilerConsistencyTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/decompiler/stubBuilder/BuiltInDecompilerConsistencyTest.kt @@ -63,7 +63,7 @@ class BuiltInDecompilerConsistencyTest : KotlinLightCodeInsightFixtureTestCase() for (className in classFiles) { val classFile = dir.findChild(className + "." + JavaClassFileType.INSTANCE.defaultExtension)!! val fileContent = FileContentImpl.createByFile(classFile) - if (IDEKotlinBinaryClassCache.getKotlinBinaryClassHeaderData(fileContent.file) == null) continue + if (IDEKotlinBinaryClassCache.getInstance().getKotlinBinaryClassHeaderData(fileContent.file) == null) continue val fileStub = classFileDecompiler.stubBuilder.buildFileStub(fileContent) ?: continue val classStub = fileStub.findChildStubByType(KtClassElementType.getStubType(false)) ?: continue val classFqName = classStub.getFqName()!!