From c853ae49a27ba1f0f6d8108d1a3f26c8dda3d21e Mon Sep 17 00:00:00 2001 From: Alexander Podkhalyuzin Date: Wed, 29 May 2019 09:35:12 +0200 Subject: [PATCH] Faster startup avoiding unnecessary class loading --- .../kotlin/parsing/KotlinParserDefinition.kt | 4 +- .../psi/stubs/elements/KtFileElementType.java | 2 + .../stubs/elements/KtStubElementTypes.java | 2 +- .../kotlin/utils/KotlinPathsFromHomeDir.kt | 2 +- .../builtIns/KotlinBuiltInDecompiler.kt | 15 ++-- .../common/KotlinMetadataDecompiler.kt | 38 ++++---- .../common/KotlinMetadataStubBuilder.kt | 4 +- .../js/KotlinJavaScriptMetaFileDecompiler.kt | 4 +- .../KotlinNativeMetadataDecompiler.kt | 6 +- .../KotlinNativeMetadataDecompilerBase.kt | 20 +++-- .../KotlinNativeMetadataStubBuilder.kt | 4 +- .../JavaStandardLibrarySupportProvider.kt | 14 +-- .../idea/editor/KotlinTypedHandler.java | 12 +-- .../intentions/AddForLoopIndicesIntention.kt | 4 +- .../ConvertForEachToForLoopIntention.kt | 4 +- .../LambdaToAnonymousFunctionIntention.kt | 3 +- .../RemoveForLoopIndicesIntention.kt | 4 +- ...undantCallsOfConversionMethodsIntention.kt | 22 ++--- .../ReplaceAddWithPlusAssignIntention.kt | 2 +- .../SwapBinaryExpressionIntention.kt | 8 +- .../idea/reporter/KotlinReportSubmitter.kt | 4 +- .../versions/KotlinJvmMetadataVersionIndex.kt | 88 ++++++++++--------- 22 files changed, 147 insertions(+), 119 deletions(-) diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParserDefinition.kt b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParserDefinition.kt index 8ffadd5d8be..0503320d6e1 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParserDefinition.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParserDefinition.kt @@ -41,8 +41,8 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtWhenEntry import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.stubs.elements.KtFileElementType import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementType -import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes class KotlinParserDefinition : ParserDefinition { @@ -50,7 +50,7 @@ class KotlinParserDefinition : ParserDefinition { override fun createParser(project: Project): PsiParser = KotlinParser(project) - override fun getFileNodeType(): IFileElementType = KtStubElementTypes.FILE + override fun getFileNodeType(): IFileElementType = KtFileElementType.INSTANCE override fun getWhitespaceTokens(): TokenSet = KtTokens.WHITESPACES diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFileElementType.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFileElementType.java index 82ddccb21c3..03443efef6a 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFileElementType.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFileElementType.java @@ -37,6 +37,8 @@ import java.io.IOException; public class KtFileElementType extends IStubFileElementType { private static final String NAME = "kotlin.FILE"; + public static KtFileElementType INSTANCE = new KtFileElementType(); + public KtFileElementType() { super(NAME, KotlinLanguage.INSTANCE); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java index 4f0199e4997..3aae198cdf0 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtStubElementTypes.java @@ -20,7 +20,7 @@ import com.intellij.psi.tree.TokenSet; import org.jetbrains.kotlin.psi.*; public interface KtStubElementTypes { - KtFileElementType FILE = new KtFileElementType(); + KtFileElementType FILE = KtFileElementType.INSTANCE; KtClassElementType CLASS = new KtClassElementType("CLASS"); KtFunctionElementType FUNCTION = new KtFunctionElementType("FUN"); diff --git a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.kt b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.kt index 29c4c7da03e..7354ddd9497 100644 --- a/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.kt +++ b/compiler/util/src/org/jetbrains/kotlin/utils/KotlinPathsFromHomeDir.kt @@ -25,7 +25,7 @@ class KotlinPathsFromHomeDir( ) : KotlinPathsFromBaseDirectory(File(homePath, "lib")) { // TODO: extend when needed - val libsWithSources = setOf(KotlinPaths.Jar.StdLib, KotlinPaths.Jar.JsStdLib) + val libsWithSources: Set by lazy { setOf(KotlinPaths.Jar.StdLib, KotlinPaths.Jar.JsStdLib) } override fun sourcesJar(jar: KotlinPaths.Jar): File? = if (jar in libsWithSources) super.sourcesJar(jar) else null } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt index 12f82d4f088..9d20f69a943 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt @@ -32,8 +32,8 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId import java.io.ByteArrayInputStream class KotlinBuiltInDecompiler : KotlinMetadataDecompiler( - KotlinBuiltInFileType, BuiltInSerializerProtocol, - FlexibleTypeDeserializer.ThrowException, BuiltInsBinaryVersion.INSTANCE, BuiltInsBinaryVersion.INVALID_VERSION, + KotlinBuiltInFileType, { BuiltInSerializerProtocol }, + FlexibleTypeDeserializer.ThrowException, { BuiltInsBinaryVersion.INSTANCE }, { BuiltInsBinaryVersion.INVALID_VERSION }, KotlinStubVersions.BUILTIN_STUB_VERSION ) { override fun readFile(bytes: ByteArray, file: VirtualFile): FileWithMetadata? { @@ -42,10 +42,10 @@ class KotlinBuiltInDecompiler : KotlinMetadataDecompiler( } class BuiltInDefinitionFile( - proto: ProtoBuf.PackageFragment, - version: BuiltInsBinaryVersion, - val packageDirectory: VirtualFile, - val isMetadata: Boolean + proto: ProtoBuf.PackageFragment, + version: BuiltInsBinaryVersion, + val packageDirectory: VirtualFile, + val isMetadata: Boolean ) : FileWithMetadata.Compatible(proto, version, BuiltInSerializerProtocol) { override val classesToDecompile: List get() = super.classesToDecompile.let { classes -> @@ -77,7 +77,8 @@ class BuiltInDefinitionFile( BuiltInDefinitionFile(proto, version, file.parent, file.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION) val packageProto = result.proto.`package` if (result.classesToDecompile.isEmpty() && - packageProto.typeAliasCount == 0 && packageProto.functionCount == 0 && packageProto.propertyCount == 0) { + packageProto.typeAliasCount == 0 && packageProto.functionCount == 0 && packageProto.propertyCount == 0 + ) { // No declarations to decompile: should skip this file return null } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt index b0093e31b82..fdda5d8eaf0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataDecompiler.kt @@ -40,29 +40,31 @@ import org.jetbrains.kotlin.utils.addIfNotNull import java.io.IOException abstract class KotlinMetadataDecompiler( - private val fileType: FileType, - private val serializerProtocol: SerializerExtensionProtocol, - private val flexibleTypeDeserializer: FlexibleTypeDeserializer, - private val expectedBinaryVersion: V, - private val invalidBinaryVersion: V, - stubVersion: Int + private val fileType: FileType, + private val serializerProtocol: () -> SerializerExtensionProtocol, + private val flexibleTypeDeserializer: FlexibleTypeDeserializer, + private val expectedBinaryVersion: () -> V, + private val invalidBinaryVersion: () -> V, + stubVersion: Int ) : ClassFileDecompilers.Full() { - private val stubBuilder = KotlinMetadataStubBuilder(stubVersion, fileType, serializerProtocol, ::readFileSafely) + private val metadataStubBuilder: KotlinMetadataStubBuilder = + KotlinMetadataStubBuilder(stubVersion, fileType, serializerProtocol, ::readFileSafely) - private val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } + private val renderer: DescriptorRenderer by lazy { + DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } + } abstract fun readFile(bytes: ByteArray, file: VirtualFile): FileWithMetadata? override fun accepts(file: VirtualFile) = file.fileType == fileType - override fun getStubBuilder() = stubBuilder + override fun getStubBuilder() = metadataStubBuilder override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider { return KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> if (readFileSafely(provider.virtualFile) == null) { null - } - else { + } else { KtDecompiledFile(provider, this::buildDecompiledText) } } @@ -91,16 +93,16 @@ abstract class KotlinMetadataDecompiler( return when (file) { null -> { - createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, invalidBinaryVersion) + createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion(), invalidBinaryVersion()) } is FileWithMetadata.Incompatible -> { - createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, file.version) + createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion(), file.version) } is FileWithMetadata.Compatible -> { val packageFqName = file.packageFqName val resolver = KotlinMetadataDeserializerForDecompiler( packageFqName, file.proto, file.nameResolver, file.version, - serializerProtocol, flexibleTypeDeserializer + serializerProtocol(), flexibleTypeDeserializer ) val declarations = arrayListOf() declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName)) @@ -126,9 +128,9 @@ sealed class FileWithMetadata { val packageFqName = FqName(nameResolver.getPackageFqName(proto.`package`.getExtension(serializerProtocol.packageFqName))) open val classesToDecompile: List = - proto.class_List.filter { proto -> - val classId = nameResolver.getClassId(proto.fqName) - !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST - } + proto.class_List.filter { proto -> + val classId = nameResolver.getClassId(proto.fqName) + !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST + } } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt index 33d739b3a53..cdd0f1e5eba 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/common/KotlinMetadataStubBuilder.kt @@ -32,7 +32,7 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId open class KotlinMetadataStubBuilder( private val version: Int, private val fileType: FileType, - private val serializerProtocol: SerializerExtensionProtocol, + private val serializerProtocol: () -> SerializerExtensionProtocol, private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata? ) : ClsStubBuilder() { override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version @@ -52,7 +52,7 @@ open class KotlinMetadataStubBuilder( val nameResolver = file.nameResolver val components = ClsStubBuilderComponents( ProtoBasedClassDataFinder(file.proto, nameResolver, file.version), - AnnotationLoaderForStubBuilderImpl(serializerProtocol), + AnnotationLoaderForStubBuilderImpl(serializerProtocol()), virtualFile ) val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptMetaFileDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptMetaFileDecompiler.kt index af97f18216b..ce7ea2e6d41 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptMetaFileDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/js/KotlinJavaScriptMetaFileDecompiler.kt @@ -28,8 +28,8 @@ import org.jetbrains.kotlin.utils.JsMetadataVersion import java.io.ByteArrayInputStream class KotlinJavaScriptMetaFileDecompiler : KotlinMetadataDecompiler( - KotlinJavaScriptMetaFileType, JsSerializerProtocol, DynamicTypeDeserializer, - JsMetadataVersion.INSTANCE, JsMetadataVersion.INVALID_VERSION, KotlinStubVersions.JS_STUB_VERSION + KotlinJavaScriptMetaFileType, { JsSerializerProtocol }, DynamicTypeDeserializer, + { JsMetadataVersion.INSTANCE }, { JsMetadataVersion.INVALID_VERSION }, KotlinStubVersions.JS_STUB_VERSION ) { override fun readFile(bytes: ByteArray, file: VirtualFile): FileWithMetadata? { val stream = ByteArrayInputStream(bytes) diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompiler.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompiler.kt index d9f1d42900d..4ad8f09f4ad 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompiler.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompiler.kt @@ -15,9 +15,9 @@ import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer class KotlinNativeMetadataDecompiler : KotlinNativeMetadataDecompilerBase( - KotlinNativeMetaFileType, KonanSerializerProtocol, NullFlexibleTypeDeserializer, - KotlinNativeMetadataVersion.DEFAULT_INSTANCE, - KotlinNativeMetadataVersion.INVALID_VERSION, + KotlinNativeMetaFileType, { KonanSerializerProtocol }, NullFlexibleTypeDeserializer, + { KotlinNativeMetadataVersion.DEFAULT_INSTANCE }, + { KotlinNativeMetadataVersion.INVALID_VERSION }, KotlinNativeMetaFileType.STUB_VERSION ) { diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompilerBase.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompilerBase.kt index 23535c03c3a..0799694151f 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompilerBase.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataDecompilerBase.kt @@ -30,14 +30,14 @@ import java.io.IOException abstract class KotlinNativeMetadataDecompilerBase( private val fileType: FileType, - private val serializerProtocol: SerializerExtensionProtocol, + private val serializerProtocol: () -> SerializerExtensionProtocol, private val flexibleTypeDeserializer: FlexibleTypeDeserializer, - private val expectedBinaryVersion: V, - private val invalidBinaryVersion: V, + private val expectedBinaryVersion: () -> V, + private val invalidBinaryVersion: () -> V, stubVersion: Int ) : ClassFileDecompilers.Full() { - private val stubBuilder = + private val metadataStubBuilder: KotlinNativeMetadataStubBuilder = KotlinNativeMetadataStubBuilder( stubVersion, fileType, @@ -45,13 +45,15 @@ abstract class KotlinNativeMetadataDecompilerBase( ::readFileSafely ) - private val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } + private val renderer: DescriptorRenderer by lazy { + DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } + } protected abstract fun doReadFile(file: VirtualFile): FileWithMetadata? override fun accepts(file: VirtualFile) = file.fileType == fileType - override fun getStubBuilder() = stubBuilder + override fun getStubBuilder() = metadataStubBuilder override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean) = KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> @@ -81,14 +83,14 @@ abstract class KotlinNativeMetadataDecompilerBase( val file = readFileSafely(virtualFile) return when (file) { - is FileWithMetadata.Incompatible -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, file.version) + is FileWithMetadata.Incompatible -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion(), file.version) is FileWithMetadata.Compatible -> decompiledText( file, - serializerProtocol, + serializerProtocol(), flexibleTypeDeserializer, renderer ) - null -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, invalidBinaryVersion) + null -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion(), invalidBinaryVersion()) } } } diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataStubBuilder.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataStubBuilder.kt index ea539ce288c..08a46209ff0 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataStubBuilder.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/decompiler/KotlinNativeMetadataStubBuilder.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer open class KotlinNativeMetadataStubBuilder( private val version: Int, private val fileType: FileType, - private val serializerProtocol: SerializerExtensionProtocol, + private val serializerProtocol: () -> SerializerExtensionProtocol, private val readFile: (VirtualFile) -> FileWithMetadata? ) : ClsStubBuilder() { @@ -39,7 +39,7 @@ open class KotlinNativeMetadataStubBuilder( val renderer = DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } val ktFileText = decompiledText( file, - serializerProtocol, + serializerProtocol(), NullFlexibleTypeDeserializer, renderer ) diff --git a/idea/jvm-debugger/jvm-debugger-sequence/src/org/jetbrains/kotlin/idea/debugger/sequence/lib/java/JavaStandardLibrarySupportProvider.kt b/idea/jvm-debugger/jvm-debugger-sequence/src/org/jetbrains/kotlin/idea/debugger/sequence/lib/java/JavaStandardLibrarySupportProvider.kt index 2b8e374eaca..92a3b563668 100644 --- a/idea/jvm-debugger/jvm-debugger-sequence/src/org/jetbrains/kotlin/idea/debugger/sequence/lib/java/JavaStandardLibrarySupportProvider.kt +++ b/idea/jvm-debugger/jvm-debugger-sequence/src/org/jetbrains/kotlin/idea/debugger/sequence/lib/java/JavaStandardLibrarySupportProvider.kt @@ -24,12 +24,14 @@ import org.jetbrains.kotlin.idea.debugger.sequence.trace.impl.KotlinTraceExpress class JavaStandardLibrarySupportProvider : LibrarySupportProvider { private companion object { - val builder = TerminatedChainBuilder( - KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()), - StandardLibraryCallChecker(PackageBasedCallChecker("java.util.stream")) - ) - val support = StandardLibrarySupport() - val dsl = DslImpl(KotlinStatementFactory(JavaPeekCallFactory())) + val builder: TerminatedChainBuilder by lazy { + TerminatedChainBuilder( + KotlinChainTransformerImpl(JavaStreamChainTypeExtractor()), + StandardLibraryCallChecker(PackageBasedCallChecker("java.util.stream")) + ) + } + val support: StandardLibrarySupport by lazy { StandardLibrarySupport() } + val dsl: DslImpl by lazy { DslImpl(KotlinStatementFactory(JavaPeekCallFactory())) } } override fun getLanguageId(): String = KotlinLanguage.INSTANCE.id diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinTypedHandler.java b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinTypedHandler.java index 18968d7483b..22be5953bcd 100644 --- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinTypedHandler.java +++ b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinTypedHandler.java @@ -47,20 +47,22 @@ import org.jetbrains.kotlin.kdoc.lexer.KDocTokens; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.*; -public class KotlinTypedHandler extends TypedHandlerDelegate { - private final static TokenSet CONTROL_FLOW_EXPRESSIONS = TokenSet.create( +class KotlinTypedHandlerInner { + final static TokenSet CONTROL_FLOW_EXPRESSIONS = TokenSet.create( KtNodeTypes.IF, KtNodeTypes.ELSE, KtNodeTypes.FOR, KtNodeTypes.WHILE, KtNodeTypes.TRY); - private final static TokenSet SUPPRESS_AUTO_INSERT_CLOSE_BRACE_AFTER = TokenSet.create( + final static TokenSet SUPPRESS_AUTO_INSERT_CLOSE_BRACE_AFTER = TokenSet.create( KtTokens.RPAR, KtTokens.ELSE_KEYWORD, KtTokens.TRY_KEYWORD ); +} +public class KotlinTypedHandler extends TypedHandlerDelegate { private boolean kotlinLTTyped; private boolean isGlobalPreviousDollarInString; // Global flag for all editors @@ -107,7 +109,7 @@ public class KotlinTypedHandler extends TypedHandlerDelegate { iterator.retreat(); } - if (iterator.atEnd() || !(SUPPRESS_AUTO_INSERT_CLOSE_BRACE_AFTER.contains(iterator.getTokenType()))) { + if (iterator.atEnd() || !(KotlinTypedHandlerInner.SUPPRESS_AUTO_INSERT_CLOSE_BRACE_AFTER.contains(iterator.getTokenType()))) { AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null); return Result.CONTINUE; } @@ -119,7 +121,7 @@ public class KotlinTypedHandler extends TypedHandlerDelegate { PsiElement leaf = file.findElementAt(offset); if (leaf != null) { PsiElement parent = leaf.getParent(); - if (parent != null && CONTROL_FLOW_EXPRESSIONS.contains(parent.getNode().getElementType())) { + if (parent != null && KotlinTypedHandlerInner.CONTROL_FLOW_EXPRESSIONS.contains(parent.getNode().getElementType())) { ASTNode nonWhitespaceSibling = FormatterUtil.getPreviousNonWhitespaceSibling(leaf.getNode()); if (nonWhitespaceSibling != null && nonWhitespaceSibling.getStartOffset() == tokenBeforeBraceOffset) { EditorModificationUtil.insertStringAtCaret(editor, "{", false, true); diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt index 8c2dbcd01a9..4b3d7e44cda 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddForLoopIndicesIntention.kt @@ -34,7 +34,9 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode class AddForLoopIndicesIntention : SelfTargetingRangeIntention(KtForExpression::class.java, "Add indices to 'for' loop"), LowPriorityAction { private val WITH_INDEX_NAME = "withIndex" - private val WITH_INDEX_FQ_NAMES = sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet() + private val WITH_INDEX_FQ_NAMES: Set by lazy { + sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet() + } override fun applicabilityRange(element: KtForExpression): TextRange? { if (element.loopParameter == null) return null diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt index 8252da89933..580414e562f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertForEachToForLoopIntention.kt @@ -33,7 +33,9 @@ class ConvertForEachToForLoopIntention : SelfTargetingOffsetIndependentIntention ) { companion object { private const val FOR_EACH_NAME = "forEach" - private val FOR_EACH_FQ_NAMES = sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$FOR_EACH_NAME" }.toSet() + private val FOR_EACH_FQ_NAMES: Set by lazy { + sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$FOR_EACH_NAME" }.toSet() + } } override fun isApplicableTo(element: KtSimpleNameExpression): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/LambdaToAnonymousFunctionIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/LambdaToAnonymousFunctionIntention.kt index febb752b4a3..9839aa66faa 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/LambdaToAnonymousFunctionIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/LambdaToAnonymousFunctionIntention.kt @@ -49,8 +49,6 @@ class LambdaToAnonymousFunctionIntention : SelfTargetingIntention = emptyMap(), replaceElement: (KtNamedFunction) -> KtExpression = { lambda.replaced(it) } ): KtExpression? { + val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE_TYPES val functionLiteral = lambda.functionLiteral val bodyExpression = functionLiteral.bodyExpression ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveForLoopIndicesIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveForLoopIndicesIntention.kt index f833d1de1fd..a32f43f28f8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveForLoopIndicesIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveForLoopIndicesIntention.kt @@ -39,7 +39,9 @@ class RemoveForLoopIndicesInspection : IntentionBasedInspection class RemoveForLoopIndicesIntention : SelfTargetingRangeIntention(KtForExpression::class.java, "Remove indices in 'for' loop") { private val WITH_INDEX_NAME = "withIndex" - private val WITH_INDEX_FQ_NAMES = sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet() + private val WITH_INDEX_FQ_NAMES: Set by lazy { + sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$WITH_INDEX_NAME" }.toSet() + } override fun applicabilityRange(element: KtForExpression): TextRange? { val loopRange = element.loopRange as? KtDotQualifiedExpression ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveRedundantCallsOfConversionMethodsIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveRedundantCallsOfConversionMethodsIntention.kt index d7d033c106f..6ee153025f2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveRedundantCallsOfConversionMethodsIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/RemoveRedundantCallsOfConversionMethodsIntention.kt @@ -42,16 +42,18 @@ class RemoveRedundantCallsOfConversionMethodsIntention : SelfTargetingRangeInten "Remove redundant calls of the conversion method" ) { - private val targetClassMap = mapOf( - "toString()" to String::class.qualifiedName, - "toDouble()" to Double::class.qualifiedName, - "toFloat()" to Float::class.qualifiedName, - "toLong()" to Long::class.qualifiedName, - "toInt()" to Int::class.qualifiedName, - "toChar()" to Char::class.qualifiedName, - "toShort()" to Short::class.qualifiedName, - "toByte()" to Byte::class.qualifiedName - ) + private val targetClassMap: Map by lazy { + mapOf( + "toString()" to String::class.qualifiedName, + "toDouble()" to Double::class.qualifiedName, + "toFloat()" to Float::class.qualifiedName, + "toLong()" to Long::class.qualifiedName, + "toInt()" to Int::class.qualifiedName, + "toChar()" to Char::class.qualifiedName, + "toShort()" to Short::class.qualifiedName, + "toByte()" to Byte::class.qualifiedName + ) + } override fun applyTo(element: KtQualifiedExpression, editor: Editor?) { diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceAddWithPlusAssignIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceAddWithPlusAssignIntention.kt index 8013e420542..f5ff72922c4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceAddWithPlusAssignIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ReplaceAddWithPlusAssignIntention.kt @@ -33,7 +33,7 @@ class ReplaceAddWithPlusAssignIntention : SelfTargetingOffsetIndependentIntentio KtDotQualifiedExpression::class.java, "Replace with '+='" ) { - private val compatibleNames = setOf("add", "addAll") + private val compatibleNames: Set by lazy { setOf("add", "addAll") } override fun isApplicableTo(element: KtDotQualifiedExpression): Boolean { if (element.callExpression?.valueArguments?.size != 1) return false diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SwapBinaryExpressionIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SwapBinaryExpressionIntention.kt index d9941540c33..b323c61c9f1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SwapBinaryExpressionIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SwapBinaryExpressionIntention.kt @@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.LowPriorityAction import com.intellij.openapi.editor.Editor import org.jetbrains.kotlin.idea.core.copied import org.jetbrains.kotlin.idea.util.PsiPrecedences +import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtExpression @@ -29,11 +30,14 @@ import org.jetbrains.kotlin.types.expressions.OperatorConventions class SwapBinaryExpressionIntention : SelfTargetingIntention(KtBinaryExpression::class.java, "Flip binary expression"), LowPriorityAction { companion object { - private val SUPPORTED_OPERATIONS = setOf(PLUS, MUL, OROR, ANDAND, EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ, GT, LT, GTEQ, LTEQ) + private val SUPPORTED_OPERATIONS: Set by lazy { + setOf(PLUS, MUL, OROR, ANDAND, EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ, GT, LT, GTEQ, LTEQ) + } - private val SUPPORTED_OPERATION_NAMES = + private val SUPPORTED_OPERATION_NAMES: Set by lazy { SUPPORTED_OPERATIONS.asSequence().mapNotNull { OperatorConventions.BINARY_OPERATION_NAMES[it]?.asString() }.toSet() + setOf("xor", "or", "and", "equals") + } } override fun isApplicableTo(element: KtBinaryExpression, caretOffset: Int): Boolean { diff --git a/idea/src/org/jetbrains/kotlin/idea/reporter/KotlinReportSubmitter.kt b/idea/src/org/jetbrains/kotlin/idea/reporter/KotlinReportSubmitter.kt index c5ca27316b5..69bdaaefd61 100644 --- a/idea/src/org/jetbrains/kotlin/idea/reporter/KotlinReportSubmitter.kt +++ b/idea/src/org/jetbrains/kotlin/idea/reporter/KotlinReportSubmitter.kt @@ -136,7 +136,9 @@ class KotlinReportSubmitter : ITNReporterCompat() { return ChronoUnit.DAYS.between(releaseDate, LocalDate.now()) > NUMBER_OF_REPORTING_DAYS_FROM_RELEASE } - private val RELEASE_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd") + private val RELEASE_DATE_FORMATTER: DateTimeFormatter by lazy { + DateTimeFormatter.ofPattern("yyyy-MM-dd") + } private fun readStoredPluginReleaseDate(): LocalDate? { val pluginVersionToReleaseDate = PropertiesComponent.getInstance().getValue(KOTLIN_PLUGIN_RELEASE_DATE) ?: return null diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJvmMetadataVersionIndex.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJvmMetadataVersionIndex.kt index 65e39ca6684..0926e4eca0d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJvmMetadataVersionIndex.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinJvmMetadataVersionIndex.kt @@ -46,55 +46,59 @@ object KotlinJvmMetadataVersionIndex : KotlinMetadataVersionIndexBase by lazy { + setOf( + KotlinClassHeader.Kind.CLASS, + KotlinClassHeader.Kind.FILE_FACADE, + KotlinClassHeader.Kind.MULTIFILE_CLASS + ) + } - private val INDEXER = DataIndexer { inputData: FileContent -> - var versionArray: IntArray? = null - var isStrictSemantics = false - var annotationPresent = false - var kind: KotlinClassHeader.Kind? = null + private val INDEXER: DataIndexer by lazy { + DataIndexer { inputData: FileContent -> + var versionArray: IntArray? = null + var isStrictSemantics = false + var annotationPresent = false + var kind: KotlinClassHeader.Kind? = null - tryBlock(inputData) { - val classReader = ClassReader(inputData.content) - classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) { - override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { - if (desc != METADATA_DESC) return null + tryBlock(inputData) { + val classReader = ClassReader(inputData.content) + classReader.accept(object : ClassVisitor(Opcodes.API_VERSION) { + override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? { + if (desc != METADATA_DESC) return null - annotationPresent = true - return object : AnnotationVisitor(Opcodes.API_VERSION) { - override fun visit(name: String, value: Any) { - when (name) { - METADATA_VERSION_FIELD_NAME -> if (value is IntArray) { - versionArray = value - } - KIND_FIELD_NAME -> if (value is Int) { - kind = KotlinClassHeader.Kind.getById(value) - } - METADATA_EXTRA_INT_FIELD_NAME -> if (value is Int) { - isStrictSemantics = (value and METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0 + annotationPresent = true + return object : AnnotationVisitor(Opcodes.API_VERSION) { + override fun visit(name: String, value: Any) { + when (name) { + METADATA_VERSION_FIELD_NAME -> if (value is IntArray) { + versionArray = value + } + KIND_FIELD_NAME -> if (value is Int) { + kind = KotlinClassHeader.Kind.getById(value) + } + METADATA_EXTRA_INT_FIELD_NAME -> if (value is Int) { + isStrictSemantics = (value and METADATA_STRICT_VERSION_SEMANTICS_FLAG) != 0 + } } } } } - } - }, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES) + }, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES) + } + + var version = + if (versionArray != null) createBinaryVersion(versionArray!!, isStrictSemantics) else null + + if (kind !in kindsToIndex) { + // Do not index metadata version for synthetic classes + version = null + } else if (annotationPresent && version == null) { + // No version at all because the class is too old, or version is set to something weird + version = JvmMetadataVersion.INVALID_VERSION + } + + if (version != null) mapOf(version to null) else emptyMap() } - - var version = - if (versionArray != null) createBinaryVersion(versionArray!!, isStrictSemantics) else null - - if (kind !in kindsToIndex) { - // Do not index metadata version for synthetic classes - version = null - } else if (annotationPresent && version == null) { - // No version at all because the class is too old, or version is set to something weird - version = JvmMetadataVersion.INVALID_VERSION - } - - if (version != null) mapOf(version to null) else emptyMap() } }