Faster startup avoiding unnecessary class loading
This commit is contained in:
committed by
Vladimir Dolzhenko
parent
f7d0be980b
commit
c853ae49a2
@@ -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
|
||||
|
||||
|
||||
@@ -37,6 +37,8 @@ import java.io.IOException;
|
||||
public class KtFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||
private static final String NAME = "kotlin.FILE";
|
||||
|
||||
public static KtFileElementType INSTANCE = new KtFileElementType();
|
||||
|
||||
public KtFileElementType() {
|
||||
super(NAME, KotlinLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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<KotlinPaths.Jar> 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
|
||||
}
|
||||
|
||||
+8
-7
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
class KotlinBuiltInDecompiler : KotlinMetadataDecompiler<BuiltInsBinaryVersion>(
|
||||
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<BuiltInsBinaryVersion>(
|
||||
}
|
||||
|
||||
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<ProtoBuf.Class>
|
||||
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
|
||||
}
|
||||
|
||||
+20
-18
@@ -40,29 +40,31 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.io.IOException
|
||||
|
||||
abstract class KotlinMetadataDecompiler<out V : BinaryVersion>(
|
||||
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<out V : BinaryVersion>(
|
||||
|
||||
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<DeclarationDescriptor>()
|
||||
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<ProtoBuf.Class> =
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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))
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ import org.jetbrains.kotlin.utils.JsMetadataVersion
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
class KotlinJavaScriptMetaFileDecompiler : KotlinMetadataDecompiler<JsMetadataVersion>(
|
||||
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)
|
||||
|
||||
+3
-3
@@ -15,9 +15,9 @@ import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol
|
||||
import org.jetbrains.kotlin.serialization.konan.NullFlexibleTypeDeserializer
|
||||
|
||||
class KotlinNativeMetadataDecompiler : KotlinNativeMetadataDecompilerBase<KotlinNativeMetadataVersion>(
|
||||
KotlinNativeMetaFileType, KonanSerializerProtocol, NullFlexibleTypeDeserializer,
|
||||
KotlinNativeMetadataVersion.DEFAULT_INSTANCE,
|
||||
KotlinNativeMetadataVersion.INVALID_VERSION,
|
||||
KotlinNativeMetaFileType, { KonanSerializerProtocol }, NullFlexibleTypeDeserializer,
|
||||
{ KotlinNativeMetadataVersion.DEFAULT_INSTANCE },
|
||||
{ KotlinNativeMetadataVersion.INVALID_VERSION },
|
||||
KotlinNativeMetaFileType.STUB_VERSION
|
||||
) {
|
||||
|
||||
|
||||
+11
-9
@@ -30,14 +30,14 @@ import java.io.IOException
|
||||
|
||||
abstract class KotlinNativeMetadataDecompilerBase<out V : BinaryVersion>(
|
||||
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<out V : BinaryVersion>(
|
||||
::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<out V : BinaryVersion>(
|
||||
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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
)
|
||||
|
||||
+8
-6
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -34,7 +34,9 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
class AddForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(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<String> 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
|
||||
|
||||
@@ -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<String> by lazy {
|
||||
sequenceOf("collections", "sequences", "text", "ranges").map { "kotlin.$it.$FOR_EACH_NAME" }.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun isApplicableTo(element: KtSimpleNameExpression): Boolean {
|
||||
|
||||
@@ -49,8 +49,6 @@ class LambdaToAnonymousFunctionIntention : SelfTargetingIntention<KtLambdaExpres
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE_TYPES
|
||||
|
||||
fun convertLambdaToFunction(
|
||||
lambda: KtLambdaExpression,
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
@@ -58,6 +56,7 @@ class LambdaToAnonymousFunctionIntention : SelfTargetingIntention<KtLambdaExpres
|
||||
typeParameters: Map<String, KtTypeReference> = emptyMap(),
|
||||
replaceElement: (KtNamedFunction) -> KtExpression = { lambda.replaced(it) }
|
||||
): KtExpression? {
|
||||
val typeSourceCode = IdeDescriptorRenderers.SOURCE_CODE_TYPES
|
||||
val functionLiteral = lambda.functionLiteral
|
||||
val bodyExpression = functionLiteral.bodyExpression ?: return null
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ class RemoveForLoopIndicesInspection : IntentionBasedInspection<KtForExpression>
|
||||
|
||||
class RemoveForLoopIndicesIntention : SelfTargetingRangeIntention<KtForExpression>(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<String> 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
|
||||
|
||||
+12
-10
@@ -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<String, String?> 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?) {
|
||||
|
||||
@@ -33,7 +33,7 @@ class ReplaceAddWithPlusAssignIntention : SelfTargetingOffsetIndependentIntentio
|
||||
KtDotQualifiedExpression::class.java,
|
||||
"Replace with '+='"
|
||||
) {
|
||||
private val compatibleNames = setOf("add", "addAll")
|
||||
private val compatibleNames: Set<String> by lazy { setOf("add", "addAll") }
|
||||
|
||||
override fun isApplicableTo(element: KtDotQualifiedExpression): Boolean {
|
||||
if (element.callExpression?.valueArguments?.size != 1) return false
|
||||
|
||||
@@ -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>(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<KtSingleValueToken> 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<String> 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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -46,55 +46,59 @@ object KotlinJvmMetadataVersionIndex : KotlinMetadataVersionIndexBase<KotlinJvmM
|
||||
|
||||
private const val VERSION = 5
|
||||
|
||||
private val kindsToIndex = setOf(
|
||||
KotlinClassHeader.Kind.CLASS,
|
||||
KotlinClassHeader.Kind.FILE_FACADE,
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS
|
||||
)
|
||||
private val kindsToIndex: Set<KotlinClassHeader.Kind> by lazy {
|
||||
setOf(
|
||||
KotlinClassHeader.Kind.CLASS,
|
||||
KotlinClassHeader.Kind.FILE_FACADE,
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS
|
||||
)
|
||||
}
|
||||
|
||||
private val INDEXER = DataIndexer<JvmMetadataVersion, Void, FileContent> { inputData: FileContent ->
|
||||
var versionArray: IntArray? = null
|
||||
var isStrictSemantics = false
|
||||
var annotationPresent = false
|
||||
var kind: KotlinClassHeader.Kind? = null
|
||||
private val INDEXER: DataIndexer<JvmMetadataVersion, Void, FileContent> by lazy {
|
||||
DataIndexer<JvmMetadataVersion, Void, FileContent> { 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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user