Faster startup avoiding unnecessary class loading

This commit is contained in:
Alexander Podkhalyuzin
2019-05-29 09:35:12 +02:00
committed by Vladimir Dolzhenko
parent f7d0be980b
commit c853ae49a2
22 changed files with 147 additions and 119 deletions
@@ -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
}
@@ -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
}
@@ -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
}
}
}
@@ -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))
@@ -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)
@@ -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
) {
@@ -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())
}
}
}
@@ -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
)
@@ -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
@@ -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()
}
}