diff --git a/plugins/kotlin/libs/metadata.jar b/plugins/kotlin/libs/metadata.jar index e6cb285419..ddfe66f5b8 100644 Binary files a/plugins/kotlin/libs/metadata.jar and b/plugins/kotlin/libs/metadata.jar differ diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinChooser.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinChooser.java index 308d26d885..e521e2a4b9 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinChooser.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinChooser.java @@ -1,13 +1,11 @@ package org.vineflower.kotlin; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; -import kotlin.reflect.jvm.internal.impl.metadata.jvm.JvmProtoBuf; -import kotlin.reflect.jvm.internal.impl.protobuf.ExtensionRegistryLite; +import kotlinx.metadata.internal.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.jvm.JvmProtoBuf; +import kotlinx.metadata.internal.protobuf.ExtensionRegistryLite; import org.jetbrains.java.decompiler.api.plugin.LanguageChooser; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.util.Key; -import org.vineflower.kotlin.metadata.BitEncoding; import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; @@ -15,6 +13,8 @@ import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.attr.StructAnnotationAttribute; import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute; +import org.jetbrains.java.decompiler.util.Key; +import org.vineflower.kotlin.metadata.BitEncoding; import org.vineflower.kotlin.metadata.MetadataNameResolver; import java.io.ByteArrayInputStream; diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinDecompilationContext.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinDecompilationContext.java index 8594c8c31b..ebe8d99e06 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinDecompilationContext.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinDecompilationContext.java @@ -1,6 +1,6 @@ package org.vineflower.kotlin; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.ProtoBuf; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.util.Key; import org.vineflower.kotlin.metadata.MetadataNameResolver; diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinImportCollector.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinImportCollector.java index 2cf27d887f..f8a20b6b43 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinImportCollector.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinImportCollector.java @@ -1,12 +1,21 @@ package org.vineflower.kotlin; +import org.jetbrains.java.decompiler.main.ClassesProcessor; +import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.collectors.ImportCollector; +import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; +import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; +import org.jetbrains.java.decompiler.struct.StructContext; import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.util.KTypes; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; -public class KotlinImportCollector { - private static final String[] AUTO_KOTLIN_IMPORTS = { +public class KotlinImportCollector extends ImportCollector { + public static final String[] AUTO_KOTLIN_IMPORTS = { "annotation", "collections", "comparisons", @@ -17,45 +26,48 @@ public class KotlinImportCollector { "text", }; - private final ImportCollector parent; - public KotlinImportCollector(ImportCollector parent) { - this.parent = parent; - } + super(parent); - public void writeImports(TextBuffer buffer, boolean addSeparator) { - TextBuffer buf = new TextBuffer(); - parent.writeImports(buf, false); - String[] imports = buf.convertToStringAndAllowDataDiscard().split("\n"); - boolean imported = false; - for (String line : imports) { - if (line.isBlank()) { - continue; - } - line = line.trim(); - String importLine = line.substring(7, line.length() - 1); - String[] parts = importLine.split("\\."); - - // Don't include automatic kotlin imports - if (parts.length == 2 && parts[0].equals("kotlin")) { - continue; - } else if (parts.length == 3 && parts[0].equals("kotlin") && Arrays.binarySearch(AUTO_KOTLIN_IMPORTS, parts[1]) >= 0) { - continue; + // Any class that Kotlin "overrides" requires explicit non-imported references + for (String className : KTypes.KOTLIN_TO_JAVA_LANG.keySet()) { + String simpleName = className.substring(className.lastIndexOf('/') + 1); + String packageName = className.substring(0, className.lastIndexOf('/')).replace('/', '.'); + if (!mapSimpleNames.containsKey(simpleName)) { + mapSimpleNames.put(simpleName, packageName); } + } - buffer.append("import "); - boolean first = true; - for (String part : parts) { - if (!first) { - buffer.append("."); - } - first = false; - buffer.append(KotlinWriter.toValidKotlinIdentifier(part)); + for (String className : KTypes.KOTLIN_TO_JAVA_UTIL.keySet()) { + String simpleName = className.substring(className.lastIndexOf('/') + 1); + String packageName = className.substring(0, className.lastIndexOf('/')).replace('/', '.'); + if (!mapSimpleNames.containsKey(simpleName)) { + mapSimpleNames.put(simpleName, packageName); } - buffer.appendLineSeparator(); - imported = true; } - if (imported && addSeparator) { + } + + @Override + protected boolean keepImport(Map.Entry ent) { + if (!super.keepImport(ent)) return false; + if (ent.getValue().equals("kotlin")) return false; + for (String autoImport : AUTO_KOTLIN_IMPORTS) { + if (ent.getValue().equals("kotlin." + autoImport)) return false; + } + return true; + } + + @Override + public void writeImports(TextBuffer buffer, boolean addSeparator) { + if (DecompilerContext.getOption(IFernflowerPreferences.REMOVE_IMPORTS)) { + return; + } + + List imports = packImports(); + for (String imp : imports) { + buffer.append("import ").append(imp).appendLineSeparator(); + } + if (addSeparator && !imports.isEmpty()) { buffer.appendLineSeparator(); } } diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinWriter.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinWriter.java index c7358022d6..61dad6f0fc 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinWriter.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinWriter.java @@ -1,7 +1,7 @@ // Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.vineflower.kotlin; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.ProtoBuf; import net.fabricmc.fernflower.api.IFabricJavadocProvider; import org.jetbrains.java.decompiler.api.plugin.StatementWriter; import org.jetbrains.java.decompiler.code.CodeConstants; @@ -32,15 +32,13 @@ import org.jetbrains.java.decompiler.struct.gen.generics.GenericClassDescriptor; import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.generics.GenericMethodDescriptor; -import org.jetbrains.java.decompiler.util.InterpreterUtil; -import org.jetbrains.java.decompiler.util.Key; -import org.jetbrains.java.decompiler.util.TextBuffer; -import org.jetbrains.java.decompiler.util.TextUtil; +import org.jetbrains.java.decompiler.util.*; import org.jetbrains.java.decompiler.util.collections.VBStyleCollection; import org.vineflower.kotlin.expr.KAnnotationExprent; import org.vineflower.kotlin.metadata.MetadataNameResolver; -import org.vineflower.kotlin.struct.KProperty; +import org.vineflower.kotlin.struct.*; import org.vineflower.kotlin.util.KTypes; +import org.vineflower.kotlin.util.KUtils; import org.vineflower.kotlin.util.ProtobufFlags; import java.io.IOException; @@ -55,6 +53,7 @@ public class KotlinWriter implements StatementWriter { )); private static final String NOT_NULL_ANN_NAME = "org/jetbrains/annotations/NotNull"; private static final String NULLABLE_ANN_NAME = "org/jetbrains/annotations/Nullable"; + private static final String REPEATABLE_ANN_NAME = "java/lang/annotation/Repeatable"; private static final Set KT_HARD_KEYWORDS = new HashSet<>(Arrays.asList( "as", "break", @@ -85,7 +84,7 @@ public class KotlinWriter implements StatementWriter { "when", "while" )); - + private final PoolInterceptor interceptor; private final IFabricJavadocProvider javadocProvider; @@ -202,6 +201,7 @@ public void writeClassHeader(StructClass cl, TextBuffer buffer, ImportCollector public void writeClass(ClassNode node, TextBuffer buffer, int indent) { ClassNode outerNode = DecompilerContext.getContextProperty(DecompilerContext.CURRENT_CLASS_NODE); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node); + DecompilerContext.setImportCollector(new KotlinImportCollector(DecompilerContext.getImportCollector())); try { // last minute processing @@ -213,15 +213,21 @@ public void writeClass(ClassNode node, TextBuffer buffer, int indent) { ClassWrapper wrapper = node.getWrapper(); StructClass cl = wrapper.getClassStruct(); + ConstantPool pool = cl.getPool(); + + KotlinChooser.setContextVariables(cl); DecompilerContext.getLogger().startWriteClass(cl.qualifiedName); + KProperty.Data propertyData = KProperty.parse(node); + Map functions = KFunction.parse(node); + KConstructor.Data constructorData = KConstructor.parse(node); + if (DecompilerContext.getOption(IFernflowerPreferences.SOURCE_FILE_COMMENTS)) { StructSourceFileAttribute sourceFileAttr = node.classStruct .getAttribute(StructGeneralAttribute.ATTRIBUTE_SOURCE_FILE); if (sourceFileAttr != null) { - ConstantPool pool = node.classStruct.getPool(); String sourceFile = sourceFileAttr.getSourceFile(pool); buffer @@ -233,19 +239,17 @@ public void writeClass(ClassNode node, TextBuffer buffer, int indent) { if (cl.hasModifier(CodeConstants.ACC_ANNOTATION)) { // Kotlin's annotation classes are treated quite differently from other classes - writeAnnotationDefinition(node, buffer, indent); + writeAnnotationDefinition(node, buffer, indent, propertyData, functions, constructorData); return; } if (KotlinDecompilationContext.getCurrentType() == KotlinDecompilationContext.KotlinType.FILE) { - writeKotlinFile(node, buffer, indent); + writeKotlinFile(node, buffer, indent, propertyData, functions); // no constructors in top level file return; } // write class definition - writeClassDefinition(node, buffer, indent); - - KProperty.Data propertyData = KProperty.parse(node); + writeClassDefinition(node, buffer, indent, constructorData); boolean hasContent = false; boolean enumFields = false; @@ -294,8 +298,7 @@ public void writeClass(ClassNode node, TextBuffer buffer, int indent) { buffer.append(',').appendLineSeparator(); } enumFields = true; - } - else if (enumFields) { + } else if (enumFields) { buffer.append(';'); buffer.appendLineSeparator(); buffer.appendLineSeparator(); @@ -351,9 +354,31 @@ else if (enumFields) { boolean hide = mt.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || mt.hasModifier(CodeConstants.ACC_BRIDGE) && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_BRIDGE) || wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())) || - (propertyData != null && propertyData.associatedMethods.contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()))); + mt.getName().equals("") && mt.getDescriptor().equals("(Lkotlin/jvm/internal/DefaultConstructorMarker;)V") || + propertyData != null && propertyData.associatedMethods.contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); if (hide) continue; + KFunction function = functions.get(mt); + if (function != null) { + if (hasContent) { + buffer.appendLineSeparator(); + } + hasContent = true; + buffer.append(function.stringify(indent + 1)); + continue; + } + + if (constructorData != null) { + KConstructor constructor = constructorData.constructors.get(mt); + if (constructor != null) { + if (hasContent) { + buffer.appendLineSeparator(); + } + hasContent |= constructor.stringify(buffer, indent + 1); + continue; + } + } + TextBuffer methodBuffer = new TextBuffer(); boolean methodSkipped = !writeMethod(node, mt, i, methodBuffer, indent + 1); if (!methodSkipped) { @@ -388,17 +413,15 @@ else if (enumFields) { if (node.type != ClassNode.Type.ANONYMOUS) { buffer.appendLineSeparator(); } - } - finally { + } finally { DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, outerNode); DecompilerContext.getLogger().endWriteClass(); } } - private void writeKotlinFile(ClassNode node, TextBuffer buffer, int indent) { + private void writeKotlinFile(ClassNode node, TextBuffer buffer, int indent, KProperty.Data propertyData, Map functions) { ClassWrapper wrapper = node.getWrapper(); StructClass cl = wrapper.getClassStruct(); - KProperty.Data propertyData = KProperty.parse(node); for (KProperty property : propertyData.properties) { buffer.append(property.stringify(indent)); @@ -419,6 +442,12 @@ private void writeKotlinFile(ClassNode node, TextBuffer buffer, int indent) { for (int i = 0; i < cl.getMethods().size(); i++) { StructMethod mt = cl.getMethods().get(i); + if (functions.containsKey(mt)) { + buffer.append(functions.get(mt).stringify(indent)); + buffer.appendLineSeparator(); + continue; + } + String key = InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()); if (mt.getName().equals("") || propertyData.associatedMethods.contains(key)) continue; @@ -436,10 +465,23 @@ private void writeKotlinFile(ClassNode node, TextBuffer buffer, int indent) { } } - private void writeAnnotationDefinition(ClassesProcessor.ClassNode node, TextBuffer buffer, int indent) { + private void writeAnnotationDefinition(ClassNode node, TextBuffer buffer, int indent, KProperty.Data propertyData, Map functions, KConstructor.Data constructorData) { ClassWrapper wrapper = node.getWrapper(); StructClass cl = wrapper.getClassStruct(); + StructAnnotationAttribute runtimeAnnotations = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS); + AnnotationExprent repeatableAnnotation = runtimeAnnotations.getAnnotations().stream() + .filter(a -> REPEATABLE_ANN_NAME.equals(a.getClassName())) + .findFirst() + .orElse(null); + + String repeatableContainer = null; + + if (repeatableAnnotation != null) { + repeatableContainer = ((ConstExprent) repeatableAnnotation.getParValues().get(0)).getValue().toString(); + runtimeAnnotations.getAnnotations().remove(repeatableAnnotation); + } + appendAnnotations(buffer, indent, cl, -1); appendJvmAnnotations(buffer, indent, cl, true, cl.getPool(), TypeAnnotation.CLASS_TYPE_PARAMETER); @@ -453,89 +495,88 @@ private void writeAnnotationDefinition(ClassesProcessor.ClassNode node, TextBuff .append("(") .appendLineSeparator(); - boolean hasCompanion = !cl.getFields().isEmpty(); - - if (!cl.getMethods().isEmpty()) { - boolean first = true; - for (StructMethod mt : cl.getMethods()) { - if (mt.hasModifier(CodeConstants.ACC_STATIC)) { - hasCompanion = true; - continue; - } + List nonParameterProperties = new ArrayList<>(propertyData.properties); - if (first) { - first = false; - } else { - buffer.append(',').appendLineSeparator(); - } - - buffer.appendIndent(indent + 1) - .append("val ") - .append(mt.getName()) - .append(": "); - - String type = mt.getDescriptor().substring(2); - VarType varType = new VarType(type, false); - - buffer.append(KTypes.getKotlinType(varType)); - - if (mt.hasAttribute(StructGeneralAttribute.ATTRIBUTE_ANNOTATION_DEFAULT)) { - buffer.append(" = "); - StructAnnDefaultAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_ANNOTATION_DEFAULT); - KAnnotationExprent.writeAnnotationValue(attr.getDefaultValue(), buffer); + boolean first = true; + for (KParameter param : constructorData.primary.parameters) { + if (!first) { + buffer.append(",").appendLineSeparator(); + } + first = false; + buffer.appendIndent(indent + 1) + .append("val ") + .append(KotlinWriter.toValidKotlinIdentifier(param.name)) + .append(": ") + .append(param.type.stringify(indent + 1)); + + // Because Kotlin really doesn't like making this easy for us, defaults are still passed directly via attributes + KProperty prop = propertyData.properties.stream() + .filter(p -> p.name.equals(param.name)) + .findFirst() + .orElseThrow(); + + nonParameterProperties.remove(prop); + + KPropertyAccessor getter = prop.getter; + if (getter != null) { + StructMethod mt = getter.underlyingMethod.methodStruct; + StructAnnDefaultAttribute paramAttr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_ANNOTATION_DEFAULT); + if (paramAttr != null) { + Exprent kExpr = KUtils.replaceExprent(paramAttr.getDefaultValue()); + Exprent expr = kExpr != null ? kExpr : paramAttr.getDefaultValue(); + buffer.append(" = ").append(expr.toJava()); } } - - buffer.appendLineSeparator().appendIndent(indent).append(')'); } - if (hasCompanion || !node.nested.isEmpty()) { - buffer.append(" {").appendLineSeparator(); + buffer.appendLineSeparator() + .appendIndent(indent) + .append(")"); - // member classes - boolean first = false; - for (ClassNode inner : node.nested) { - if (inner.type == ClassNode.Type.MEMBER) { - StructClass innerCl = inner.classStruct; - boolean isSynthetic = (inner.access & CodeConstants.ACC_SYNTHETIC) != 0 || innerCl.isSynthetic(); - boolean hide = isSynthetic && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || - wrapper.getHiddenMembers().contains(innerCl.qualifiedName); - if (hide) continue; + boolean appended = false; - if (first) { - buffer.appendLineSeparator(); - } - writeClass(inner, buffer, indent + 1); + TextBuffer innerBuffer = new TextBuffer(); - first = true; - } - } + for (KProperty prop : nonParameterProperties) { + innerBuffer.append(prop.stringify(indent + 1)); + appended = true; + } - if (hasCompanion) { - buffer.appendIndent(indent + 1).append("companion object {").appendLineSeparator(); + first = true; + for (KFunction function : functions.values()) { + if (!first || appended) { + innerBuffer.appendLineSeparator(); + } + first = false; - for (StructField fd : cl.getFields()) { - if (!fd.hasModifier(CodeConstants.ACC_STATIC)) { - appendComment(buffer, "Illegal field (must be static): " + fd.getName(), indent + 2); - } + innerBuffer.append(function.stringify(indent + 1)); + appended = true; + } - writeField(wrapper, cl, fd, buffer, indent + 2); - buffer.appendLineSeparator(); + first = true; + for (ClassNode inner : node.nested) { + if (inner.type == ClassNode.Type.MEMBER) { + if (inner.classStruct.qualifiedName.equals(repeatableContainer)) { + // Skip the container class + continue; } - for (StructMethod mt : cl.getMethods()) { - if (!mt.hasModifier(CodeConstants.ACC_STATIC)) { - continue; - } - - writeMethod(node, mt, 0, buffer, indent + 2); - buffer.appendLineSeparator(); + if (!first || appended) { + innerBuffer.appendLineSeparator(); } + first = false; - buffer.appendIndent(indent + 1).append('}').appendLineSeparator(); + writeClass(inner, innerBuffer, indent + 1); + appended = true; } + } - buffer.appendIndent(indent).append('}'); + if (appended) { + buffer.append(" {") + .appendLineSeparator() + .append(innerBuffer) + .appendIndent(indent) + .append("}"); } buffer.appendLineSeparator(); @@ -545,7 +586,7 @@ private static boolean isGenerated(int flags) { return (flags & (CodeConstants.ACC_SYNTHETIC | CodeConstants.ACC_MANDATED)) != 0; } - private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) { + private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent, KConstructor.Data constructorData) { if (node.type == ClassNode.Type.ANONYMOUS) { buffer.append(" {").appendLineSeparator(); return; @@ -554,9 +595,6 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) ClassWrapper wrapper = node.getWrapper(); StructClass cl = wrapper.getClassStruct(); - // Ensure that the class data is put in place - KotlinChooser.setContextVariables(cl); - int flags = node.type == ClassNode.Type.ROOT ? cl.getAccessFlags() : node.access; boolean isDeprecated = cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_DEPRECATED); boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_SYNTHETIC); @@ -653,12 +691,16 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) boolean appendedColon = false; if (!isEnum && !isInterface && cl.superClass != null) { - VarType supertype = new VarType(cl.superClass.getString(), true); - if (!VarType.VARTYPE_OBJECT.equals(supertype)) { - buffer.append(" :"); - buffer.appendPossibleNewline(" "); - buffer.append(ExprProcessor.getCastTypeName(descriptor == null ? supertype : descriptor.superclass)); + if (constructorData != null && constructorData.primary != null && constructorData.primary.writePrimaryConstructor(buffer, indent)) { appendedColon = true; + } else { + VarType supertype = new VarType(cl.superClass.getString(), true); + if (!VarType.VARTYPE_OBJECT.equals(supertype)) { + buffer.appendPossibleNewline(" "); + buffer.append(": "); + buffer.append(ExprProcessor.getCastTypeName(descriptor == null ? supertype : descriptor.superclass)); + appendedColon = true; + } } } @@ -757,18 +799,16 @@ public void writeField(ClassWrapper wrapper, StructClass cl, StructField fd, Tex Exprent initializer; if (fd.hasModifier(CodeConstants.ACC_STATIC)) { initializer = wrapper.getStaticFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); - } - else { + } else { initializer = wrapper.getDynamicFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); } if (initializer != null) { if (isEnum && initializer instanceof NewExprent) { - NewExprent expr = (NewExprent)initializer; + NewExprent expr = (NewExprent) initializer; expr.setEnumConst(true); buffer.append(expr.toJava(indent)); - } - else { + } else { buffer.append(" = "); if (initializer instanceof ConstExprent) { @@ -778,8 +818,7 @@ public void writeField(ClassWrapper wrapper, StructClass cl, StructField fd, Tex // FIXME: special case field initializer. Can map to more than one method (constructor) and bytecode instruction. ExprProcessor.getCastedExprent(initializer, descriptor == null ? fieldType : descriptor.type, buffer, indent, false); } - } - else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) { + } else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) { StructConstantValueAttribute attr = fd.getAttribute(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE); if (attr != null) { PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex()); @@ -827,7 +866,7 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex boolean hideMethod = false; - MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getContextProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); + MethodWrapper outerWrapper = (MethodWrapper) DecompilerContext.getContextProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper); try { @@ -908,7 +947,7 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex } boolean didOverride = false; - if (!CodeConstants.INIT_NAME.equals(mt.getName()) && !CodeConstants.CLINIT_NAME.equals(mt.getName()) && !mt.hasModifier(CodeConstants.ACC_STATIC) && !mt.hasModifier(CodeConstants.ACC_PRIVATE)) { + if (!CodeConstants.INIT_NAME.equals(mt.getName()) && !CodeConstants.CLINIT_NAME.equals(mt.getName()) && !mt.hasModifier(CodeConstants.ACC_STATIC) && !mt.hasModifier(CodeConstants.ACC_PRIVATE)) { // Search superclasses for methods that match the name and descriptor of this one. // Make sure not to search the current class otherwise it will return the current method itself! // TODO: record overrides @@ -1014,38 +1053,36 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex buffer.appendPossibleNewline(" "); } first = false; - + // @PAnn vararg? pName: pTy boolean nullable = processParameterAnnotations(buffer, mt, paramCount); - + boolean isVarArg = i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0; if (isVarArg) { buffer.append("vararg "); } - + String parameterName; if (methodParameters != null && i < methodParameters.size()) { parameterName = methodParameters.get(i).myName; - } - else { + } else { parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0)); } - + if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { String newParameterName = methodWrapper.methodStruct.getVariableNamer().renameAbstractParameter(parameterName, index); parameterName = !newParameterName.equals(parameterName) ? newParameterName : DecompilerContext.getStructContext().renameAbstractParameter(methodWrapper.methodStruct.getClassQualifiedName(), mt.getName(), mt.getDescriptor(), index - (((flags & CodeConstants.ACC_STATIC) == 0) ? 1 : 0), parameterName); - + } parameterName = toValidKotlinIdentifier(parameterName); - + buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors buffer.append(": "); if (methodParameters != null && i < methodParameters.size()) { appendModifiers(buffer, methodParameters.get(i).myAccessFlags, CodeConstants.ACC_FINAL, isInterface, 0); - } - else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.FinalType.EXPLICIT_FINAL) { + } else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.FinalType.EXPLICIT_FINAL) { buffer.append("final "); } @@ -1094,8 +1131,7 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { // native or abstract method (explicit or interface) buffer.appendLineSeparator(); - } - else { + } else { if (!clInit && !dInit) { buffer.append(' '); } @@ -1104,8 +1140,7 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT hideMethod = !writeMethodBody(node, methodWrapper, buffer, indent, hideIfInit); } - } - finally { + } finally { DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, outerWrapper); } @@ -1136,8 +1171,7 @@ public static boolean writeMethodBody(ClassNode node, MethodWrapper methodWrappe hideMethod = code.length() == 0 && hideIfInit; buffer.append(code, cl.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); } - } - catch (Throwable t) { + } catch (Throwable t) { String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + node.classStruct.qualifiedName + " couldn't be written."; DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t); methodWrapper.decompileError = t; @@ -1151,7 +1185,7 @@ public static boolean writeMethodBody(ClassNode node, MethodWrapper methodWrappe return !hideMethod; } - private static void dumpError(TextBuffer buffer, MethodWrapper wrapper, int indent) { + public static void dumpError(TextBuffer buffer, MethodWrapper wrapper, int indent) { List lines = new ArrayList<>(); lines.add("$VF: Couldn't be decompiled"); boolean exceptions = DecompilerContext.getOption(IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR); @@ -1219,7 +1253,7 @@ public static void collectErrorLines(Throwable error, List lines) { } private static void collectBytecode(MethodWrapper wrapper, List lines) throws IOException { - ClassNode classNode = (ClassNode)DecompilerContext.getContextProperty(DecompilerContext.CURRENT_CLASS_NODE); + ClassNode classNode = (ClassNode) DecompilerContext.getContextProperty(DecompilerContext.CURRENT_CLASS_NODE); StructMethod method = wrapper.methodStruct; InstructionSequence instructions = method.getInstructionSequence(); if (instructions == null) { @@ -1337,7 +1371,7 @@ private static void appendConstant(StringBuilder sb, PooledConstant constant) { } } - private static boolean hideConstructor(ClassNode node, boolean init, boolean throwsExceptions, int paramCount, int methodAccessFlags) { + public static boolean hideConstructor(ClassNode node, boolean init, boolean throwsExceptions, int paramCount, int methodAccessFlags) { if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) { return false; } @@ -1349,7 +1383,7 @@ private static boolean hideConstructor(ClassNode node, boolean init, boolean thr boolean isEnum = cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); // default constructor requires same accessibility flags. Exception: enum constructor which is always private - if(!isEnum && ((classAccessFlags & ACCESSIBILITY_FLAGS) != (methodAccessFlags & ACCESSIBILITY_FLAGS))) { + if (!isEnum && ((classAccessFlags & ACCESSIBILITY_FLAGS) != (methodAccessFlags & ACCESSIBILITY_FLAGS))) { return false; } @@ -1469,7 +1503,7 @@ private static void appendJavadoc(TextBuffer buffer, String javaDoc, int indent) static final Key[] TYPE_ANNOTATION_ATTRIBUTES = { StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS}; - static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType) { + public static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType) { Set filter = new HashSet<>(); for (Key key : ANNOTATION_ATTRIBUTES) { @@ -1490,8 +1524,7 @@ static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, in buffer.append(text); if (indent < 0) { buffer.append(' '); - } - else { + } else { buffer.appendLineSeparator(); } } @@ -1501,7 +1534,7 @@ static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, in appendTypeAnnotations(buffer, indent, mb, targetType, -1, filter); } - private static void appendJvmAnnotations(TextBuffer buffer, int indent, StructMember mb, boolean isInterface, ConstantPool pool, int targetType) { + public static void appendJvmAnnotations(TextBuffer buffer, int indent, StructMember mb, boolean isInterface, ConstantPool pool, int targetType) { switch (targetType) { case TypeAnnotation.METHOD_RETURN_TYPE: if (isInterface && !mb.hasModifier(CodeConstants.ACC_ABSTRACT)) { @@ -1552,10 +1585,10 @@ private static void appendJvmAnnotations(TextBuffer buffer, int indent, StructMe buffer.appendIndent(indent).append("@JvmSynthetic").appendLineSeparator(); } } - - static boolean isNullable(StructMember mb){ - for (Key key : ANNOTATION_ATTRIBUTES){ - StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttribute(key); + + static boolean isNullable(StructMember mb) { + for (Key key : ANNOTATION_ATTRIBUTES) { + StructAnnotationAttribute attribute = (StructAnnotationAttribute) mb.getAttribute(key); if (attribute != null) { return attribute.getAnnotations().stream().anyMatch(annotation -> annotation.getClassName().equals(NULLABLE_ANN_NAME)); } @@ -1564,7 +1597,7 @@ static boolean isNullable(StructMember mb){ } // Returns true if a method with the given name and descriptor matches in the inheritance tree of the superclass. - private static boolean searchForMethod(StructClass cl, String name, MethodDescriptor md, boolean search) { + public static boolean searchForMethod(StructClass cl, String name, MethodDescriptor md, boolean search) { // Didn't find the class or the library containing the class wasn't loaded, can't search if (cl == null) { return false; @@ -1585,7 +1618,7 @@ private static boolean searchForMethod(StructClass cl, String name, MethodDescri // If we have a superclass that's not Object, search that as well if (cl.superClass != null) { - StructClass superClass = DecompilerContext.getStructContext().getClass((String)cl.superClass.value); + StructClass superClass = DecompilerContext.getStructContext().getClass((String) cl.superClass.value); boolean foundInSuperClass = searchForMethod(superClass, name, md, true); @@ -1609,12 +1642,12 @@ private static boolean searchForMethod(StructClass cl, String name, MethodDescri return false; } - private static boolean processParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) { + public static boolean processParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) { Set filter = new HashSet<>(); boolean ret = false; for (Key key : PARAMETER_ANNOTATION_ATTRIBUTES) { - StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttribute(key); + StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute) mt.getAttribute(key); if (attribute != null) { List> annotations = attribute.getParamAnnotations(); if (param < annotations.size()) { @@ -1639,7 +1672,7 @@ private static boolean processParameterAnnotations(TextBuffer buffer, StructMeth private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType, int index, Set filter) { for (Key key : TYPE_ANNOTATION_ATTRIBUTES) { - StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute)mb.getAttribute(key); + StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute) mb.getAttribute(key); if (attribute != null) { for (TypeAnnotation annotation : attribute.getAnnotations()) { if (annotation.isTopLevel() && annotation.getTargetType() == targetType && (index < 0 || annotation.getIndex() == index)) { @@ -1648,8 +1681,7 @@ private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructM buffer.append(text); if (indent < 0) { buffer.append(' '); - } - else { + } else { buffer.appendLineSeparator(); } } @@ -1660,6 +1692,7 @@ private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructM } private static final Map MODIFIERS; + static { MODIFIERS = new LinkedHashMap<>(); MODIFIERS.put(CodeConstants.ACC_PUBLIC, "public"); diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/expr/KFunctionExprent.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/expr/KFunctionExprent.java index 0f6a9a45dc..0aa6baad6a 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/expr/KFunctionExprent.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/expr/KFunctionExprent.java @@ -1,6 +1,7 @@ package org.vineflower.kotlin.expr; import org.jetbrains.java.decompiler.code.CodeConstants; +import org.jetbrains.java.decompiler.main.plugins.PluginImplementationException; import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent; @@ -42,7 +43,13 @@ public KFunctionExprent(FunctionType funcType, List operands, BitSet by public KFunctionExprent(FunctionExprent func) { super(func.getFuncType(), new ArrayList<>(KUtils.replaceExprents(func.getLstOperands())), func.bytecode); - setImplicitType(func.getExprType()); + if (func instanceof KFunctionExprent) { + KFunctionExprent kFunc = (KFunctionExprent) func; + this.kType = kFunc.kType; + } else { + setImplicitType(func.getExprType()); + } + setNeedsCast(func.doesCast()); if (getFuncType() == FunctionType.EQ) { diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/metadata/MetadataNameResolver.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/metadata/MetadataNameResolver.java index 4bc0cbcfa8..9108149bc5 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/metadata/MetadataNameResolver.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/metadata/MetadataNameResolver.java @@ -1,6 +1,6 @@ package org.vineflower.kotlin.metadata; -import kotlin.reflect.jvm.internal.impl.metadata.jvm.JvmProtoBuf; +import kotlinx.metadata.internal.metadata.jvm.JvmProtoBuf; import java.util.*; diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KConstructor.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KConstructor.java new file mode 100644 index 0000000000..c3af6c4163 --- /dev/null +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KConstructor.java @@ -0,0 +1,280 @@ +package org.vineflower.kotlin.struct; + +import kotlinx.metadata.internal.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.jvm.JvmProtoBuf; +import org.jetbrains.java.decompiler.main.ClassesProcessor; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.collectors.ImportCollector; +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.rels.ClassWrapper; +import org.jetbrains.java.decompiler.main.rels.MethodWrapper; +import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.TypeAnnotation; +import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.InterpreterUtil; +import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinDecompilationContext; +import org.vineflower.kotlin.KotlinOptions; +import org.vineflower.kotlin.KotlinWriter; +import org.vineflower.kotlin.metadata.MetadataNameResolver; +import org.vineflower.kotlin.util.KUtils; +import org.vineflower.kotlin.util.ProtobufFlags; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class KConstructor { + private static final VarType DEFAULT_CONSTRUCTOR_MARKER = new VarType("kotlin/jvm/internal/DefaultConstructorMarker", true); + + public final ProtobufFlags.Constructor flags; + public final KParameter[] parameters; + public final boolean isPrimary; + + public final MethodWrapper method; + private final ClassesProcessor.ClassNode node; + + private KConstructor( + KParameter[] parameters, + ProtobufFlags.Constructor flags, + MethodWrapper method, + boolean isPrimary, + ClassesProcessor.ClassNode node) { + this.parameters = parameters; + this.flags = flags; + this.method = method; + this.isPrimary = isPrimary; + this.node = node; + } + + public static Data parse(ClassesProcessor.ClassNode node) { + MetadataNameResolver resolver = KotlinDecompilationContext.getNameResolver(); + ClassWrapper wrapper = node.getWrapper(); + StructClass struct = wrapper.getClassStruct(); + + KotlinDecompilationContext.KotlinType type = KotlinDecompilationContext.getCurrentType(); + if (type != KotlinDecompilationContext.KotlinType.CLASS) return null; + + ProtobufFlags.Class classFlags = new ProtobufFlags.Class(KotlinDecompilationContext.getCurrentClass().getFlags()); + if (classFlags.modality == ProtoBuf.Modality.ABSTRACT) return null; + + List protoConstructors = KotlinDecompilationContext.getCurrentClass().getConstructorList(); + if (protoConstructors.isEmpty()) return null; + + Map constructors = new HashMap<>(); + KConstructor primary = null; + + for (ProtoBuf.Constructor constructor : protoConstructors) { + KParameter[] parameters = new KParameter[constructor.getValueParameterCount()]; + for (int i = 0; i < parameters.length; i++) { + ProtoBuf.ValueParameter protoParameter = constructor.getValueParameter(i); + parameters[i] = new KParameter( + new ProtobufFlags.ValueParameter(protoParameter.getFlags()), + resolver.resolve(protoParameter.getName()), + KType.from(protoParameter.getType(), resolver), + KType.from(protoParameter.getVarargElementType(), resolver), + protoParameter.getTypeId() + ); + } + + ProtobufFlags.Constructor flags = new ProtobufFlags.Constructor(constructor.getFlags()); + + JvmProtoBuf.JvmMethodSignature signature = constructor.getExtension(JvmProtoBuf.constructorSignature); + String desc = resolver.resolve(signature.getDesc()); + MethodWrapper method = wrapper.getMethodWrapper("", desc); + if (method == null) { + if (classFlags.kind == ProtoBuf.Class.Kind.ANNOTATION_CLASS) { + // Annotation classes are very odd and don't actually have a constructor under the hood + KConstructor kConstructor = new KConstructor(parameters, flags, null, false, node); + return new Data(null, kConstructor); + } + + DecompilerContext.getLogger().writeMessage("Method " + desc + " not found in " + struct.qualifiedName, IFernflowerLogger.Severity.WARN); + continue; + } + + boolean isPrimary = !flags.isSecondary; + + KConstructor kConstructor = new KConstructor(parameters, flags, method, isPrimary, node); + constructors.put(method.methodStruct, kConstructor); + + if (isPrimary) { + primary = kConstructor; + } + } + + return new Data(constructors, primary); + } + + public boolean stringify(TextBuffer buffer, int indent) { + if (KotlinWriter.hideConstructor(node, true, false, parameters.length, method.methodStruct.getAccessFlags())) { + return false; + } + + TextBuffer buf = new TextBuffer(); + RootStatement root = method.root; + + if (!isPrimary) { + if (flags.hasAnnotations) { + KotlinWriter.appendAnnotations(buf, indent, method.methodStruct, TypeAnnotation.METHOD_RETURN_TYPE); + KotlinWriter.appendJvmAnnotations(buf, indent, method.methodStruct, false, method.classStruct.getPool(), TypeAnnotation.METHOD_RETURN_TYPE); + } + + buf.appendIndent(indent); + + if (flags.visibility != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) { + KUtils.appendVisibility(buf, flags.visibility); + } + + buf.append("constructor"); + + buf.append("(").pushNewlineGroup(indent, 1); + + boolean first = true; + for (KParameter parameter : parameters) { + if (!first) { + buf.append(",").appendPossibleNewline(" "); + } + + first = false; + + parameter.stringify(indent + 1, buf); + } + + buf.appendPossibleNewline("", true).popNewlineGroup().append(") : "); + + Exprent firstExpr = method.getOrBuildGraph().first.exprents.get(0); + if (!(firstExpr instanceof InvocationExprent)) { + throw new IllegalStateException("First expression of constructor is not InvocationExprent"); + } + + InvocationExprent invocation = (InvocationExprent) firstExpr; + buf.append(invocation.toJava(indent + 1), node.classStruct.qualifiedName, InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor())); + + method.getOrBuildGraph().first.exprents.remove(0); + } + + if (method.getOrBuildGraph().first.exprents.isEmpty()) { + // There is no extra body so all done! + if (isPrimary) return false; // avoid extra empty line + + buffer.append(buf); + return true; + } + + if (isPrimary) { + buf.appendIndent(indent).append("init"); + } + + buf.append(" {").appendLineSeparator(); + + TextBuffer body = root.toJava(indent + 1); + body.addBytecodeMapping(root.getDummyExit().bytecode); + + StructMethod mt = method.methodStruct; + buf.append(body, node.classStruct.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); + + buf.appendIndent(indent).append("}").appendLineSeparator(); + + buffer.append(buf); + return true; + } + + public boolean writePrimaryConstructor(TextBuffer buffer, int indent) { + if (!isPrimary) return false; + + TextBuffer buf = new TextBuffer(); + boolean appended = false; + + if (flags.hasAnnotations) { + buf.append(" "); + // -1 for indent indicates inline + KotlinWriter.appendAnnotations(buf, -1, method.methodStruct, TypeAnnotation.METHOD_RETURN_TYPE); + KotlinWriter.appendJvmAnnotations(buf, -1, method.methodStruct, false, method.classStruct.getPool(), TypeAnnotation.METHOD_RETURN_TYPE); + appended = true; + } + + // For cleanliness, public primary constructors are not forced public by the config option + if (flags.visibility != ProtoBuf.Visibility.PUBLIC || (appended && DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY))) { + buf.append(" "); + KUtils.appendVisibility(buf, flags.visibility); + appended = true; + } + + if (appended) { + buf.append("constructor"); + } + + if (parameters.length > 0 || appended) { + buf.append("(").pushNewlineGroup(indent, 1); + + boolean first = true; + for (KParameter parameter : parameters) { + if (!first) { + buf.append(",").appendPossibleNewline(" "); + } + + first = false; + + parameter.stringify(indent + 1, buf); + } + + buf.appendPossibleNewline("", true).popNewlineGroup().append(")"); + } + + RootStatement root = method.root; + if (method.getOrBuildGraph().first.exprents.isEmpty()) { + // No ability to declare super constructor call + buffer.append(buf); + return false; + } + + Exprent firstExpr = method.getOrBuildGraph().first.exprents.get(0); + if (!(firstExpr instanceof InvocationExprent) || !((InvocationExprent) firstExpr).getName().equals("")) { + // no detected super constructor call + buffer.append(buf); + return false; +// throw new IllegalStateException("First expression of constructor is not InvocationExprent"); + } + + InvocationExprent invocation = (InvocationExprent) firstExpr; + if (invocation.getClassname().equals("java/lang/Object")) { + // No need to declare super constructor call + buffer.append(buf); + return false; + } + + ImportCollector imports = DecompilerContext.getImportCollector(); + String superClass = imports.getShortName(invocation.getClassname().replace('/', '.')); + buf.append(" : "); + + // replace "super" with the actual class name + buf.append(superClass).append('('); + + KUtils.removeArguments(invocation, DEFAULT_CONSTRUCTOR_MARKER); + + buf.append(invocation.appendParamList(indent + 1)); + buf.append(")"); + + buf.addBytecodeMapping(invocation.bytecode); + + method.getOrBuildGraph().first.exprents.remove(0); + + buffer.append(buf, node.classStruct.qualifiedName, InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor())); + return true; + } + + public static class Data { + public final Map constructors; + public final KConstructor primary; + + public Data(Map constructors, KConstructor primary) { + this.constructors = constructors; + this.primary = primary; + } + } +} diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KContract.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KContract.java new file mode 100644 index 0000000000..813361b7aa --- /dev/null +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KContract.java @@ -0,0 +1,247 @@ +package org.vineflower.kotlin.struct; + +import kotlinx.metadata.internal.metadata.ProtoBuf; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinWriter; +import org.vineflower.kotlin.metadata.MetadataNameResolver; +import org.vineflower.kotlin.util.ProtobufFlags; + +import java.util.List; +import java.util.stream.Collectors; + +public class KContract { + private static final String INVOCATION_KIND = "kotlin.contracts.InvocationKind"; + @NotNull + public final List effects; + + private KContract(@NotNull List effects) { + this.effects = effects; + } + + public static KContract from(ProtoBuf.Contract proto, List params, MetadataNameResolver nameResolver) { + return new KContract(proto.getEffectList().stream().map(it -> KEffect.from(it, params, nameResolver)).collect(Collectors.toList())); + } + + public TextBuffer stringify(int indent) { + TextBuffer buf = new TextBuffer(); + buf.appendIndent(indent).append("contract {").appendLineSeparator(); + for (KEffect effect : effects) { + effect.stringify(buf, indent + 1); + } + buf.appendIndent(indent).append("}").appendLineSeparator(); + return buf; + } + + public static class KEffect { + @Nullable + public final ProtoBuf.Effect.EffectType type; + @NotNull + public final List expressions; + @Nullable + public final KExpression conditionalConclusion; + @Nullable + public final ProtoBuf.Effect.InvocationKind kind; + + private KEffect( + @Nullable ProtoBuf.Effect.EffectType type, + @NotNull List expressions, + @Nullable KExpression conditionalConclusion, + @Nullable ProtoBuf.Effect.InvocationKind kind) { + this.expressions = expressions; + this.type = type; + this.conditionalConclusion = conditionalConclusion; + this.kind = kind; + } + + static KEffect from(ProtoBuf.Effect proto, List params, MetadataNameResolver nameResolver) { + ProtoBuf.Effect.EffectType type = proto.hasEffectType() ? proto.getEffectType() : null; + List expressions = proto.getEffectConstructorArgumentList().stream().map(it -> KExpression.from(it, params, nameResolver)).collect(Collectors.toList()); + KExpression conditionalConclusion = proto.hasConclusionOfConditionalEffect() ? KExpression.from(proto.getConclusionOfConditionalEffect(), params, nameResolver) : null; + ProtoBuf.Effect.InvocationKind kind = proto.hasKind() ? proto.getKind() : null; + return new KEffect(type, expressions, conditionalConclusion, kind); + } + + public void stringify(TextBuffer buf, int indent) { + if (type == null) return; + + buf.appendIndent(indent); + + switch (type) { + case RETURNS_NOT_NULL: + buf.append("returnsNotNull()"); + if (conditionalConclusion != null) { + buf.append(" implies ("); + conditionalConclusion.stringify(buf, indent, false); + buf.append(')'); + } + break; + case CALLS: + buf.append("callsInPlace("); + KExpression func = expressions.get(0); + String name = func.valueParameterReference.name; + buf.append(KotlinWriter.toValidKotlinIdentifier(name)); + if (kind != null) { + buf.append(", ") + .append(DecompilerContext.getImportCollector().getShortName(INVOCATION_KIND)) + .append(".") + .append(kind.name()); + } + buf.append(")"); + break; + case RETURNS_CONSTANT: + buf.append("returns("); + if (!expressions.isEmpty()) { + KExpression expr = expressions.get(0); + expr.stringify(buf, indent, false); + } + buf.append(")"); + if (conditionalConclusion != null) { + buf.append(" implies ("); + conditionalConclusion.stringify(buf, indent, false); + buf.append(')'); + } + break; + } + buf.appendLineSeparator(); + } + } + + public static class KExpression { + // Placeholder type for receiver type + private static final KParameter THIS_TYPE = new KParameter(new ProtobufFlags.ValueParameter(0), "this", KType.NOTHING, null, 0); + + @NotNull + public final ProtobufFlags.Expression flags; + @Nullable + public final KParameter valueParameterReference; + @Nullable + public final ProtoBuf.Expression.ConstantValue constantValue; + @Nullable + public final KType instanceofType; // isInstanceType + @NotNull + public final List andArguments; + @NotNull + public final List orArguments; + + private KExpression( + @NotNull ProtobufFlags.Expression flags, + @Nullable KParameter valueParameterReference, + @Nullable ProtoBuf.Expression.ConstantValue constantValue, + @Nullable KType instanceofType, + @NotNull List andArguments, + @NotNull List orArguments) { + this.flags = flags; + this.valueParameterReference = valueParameterReference; + this.constantValue = constantValue; + this.instanceofType = instanceofType; + this.andArguments = andArguments; + this.orArguments = orArguments; + } + + static KExpression from(ProtoBuf.Expression proto, List params, MetadataNameResolver nameResolver) { + ProtobufFlags.Expression flags = new ProtobufFlags.Expression(proto.getFlags()); + KParameter valueParameterReference = null; + if (proto.hasValueParameterReference()) { + int index = proto.getValueParameterReference(); + valueParameterReference = index == 0 ? THIS_TYPE : params.get(index - 1); + } + + ProtoBuf.Expression.ConstantValue constantValue = proto.hasConstantValue() ? proto.getConstantValue() : null; + KType instanceofType = null; + if (proto.hasIsInstanceType()) { + instanceofType = KType.from(proto.getIsInstanceType(), nameResolver); + } else if (proto.hasIsInstanceTypeId()) { + instanceofType = KType.from(proto.getIsInstanceTypeId(), nameResolver); + } + List andArguments = proto.getAndArgumentList().stream().map(it -> from(it, params, nameResolver)).collect(Collectors.toList()); + List orArguments = proto.getOrArgumentList().stream().map(it -> from(it, params, nameResolver)).collect(Collectors.toList()); + return new KExpression(flags, valueParameterReference, constantValue, instanceofType, andArguments, orArguments); + } + + public void stringify(TextBuffer buf, int indent, boolean partOfOr) { + if (!andArguments.isEmpty() && (!orArguments.isEmpty() || partOfOr)) { + // all `&&` predicates must be evaluated before any `||` predicates + buf.append('('); + } + + boolean appended = true; + + String paramName = null; + if (valueParameterReference == THIS_TYPE) { + paramName = "this"; + } else if (valueParameterReference != null) { + paramName = KotlinWriter.toValidKotlinIdentifier(valueParameterReference.name); + } + + if (instanceofType != null) { + buf.append(paramName) + .append(' ') + .append(flags.isNegated ? "!is" : "is") + .append(' ') + .append(instanceofType.stringify(indent)); + } else if (flags.isNullPredicate) { + buf.append(paramName) + .append(' ') + .append(flags.isNegated ? "!=" : "==") + .append(' ') + .append("null"); + } else if (constantValue != null) { + if (valueParameterReference != null && valueParameterReference.type.isNullable) { + buf.append(paramName) + .append(' ') + .append(flags.isNegated ? "!=" : "==") + .append(' ') + .append(constantValue.name().toLowerCase()); + } else { + String output = valueParameterReference != null && "kotlin/Boolean".equals(valueParameterReference.type.kotlinType) + ? paramName + : constantValue.name().toLowerCase(); + + if (flags.isNegated) { + buf.append('!'); + } + + buf.append(output); + } + } else if (valueParameterReference != null) { + if (!valueParameterReference.type.kotlinType.equals("kotlin/Boolean")) { + //TODO figure out why this happens + } + if (flags.isNegated) { + buf.append('!'); + } + buf.append(paramName); + } else { + appended = false; + } + + if (!andArguments.isEmpty()) { + for (KExpression andArgument : andArguments) { + if (appended) { + buf.append(" && "); + } + appended = true; + + andArgument.stringify(buf, indent, false); + } + } + + if (!orArguments.isEmpty()) { + if (!andArguments.isEmpty() || partOfOr) { + buf.append(')'); + } + for (KExpression orArgument : orArguments) { + if (appended) { + buf.append(" || "); + } + appended = true; + + orArgument.stringify(buf, indent, true); + } + } + } + } +} diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KFunction.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KFunction.java new file mode 100644 index 0000000000..cb4a1c5737 --- /dev/null +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KFunction.java @@ -0,0 +1,372 @@ +package org.vineflower.kotlin.struct; + +import kotlinx.metadata.internal.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.jvm.JvmProtoBuf; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.decompiler.main.ClassesProcessor; +import org.jetbrains.java.decompiler.main.DecompilerContext; +import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; +import org.jetbrains.java.decompiler.main.rels.ClassWrapper; +import org.jetbrains.java.decompiler.main.rels.MethodWrapper; +import org.jetbrains.java.decompiler.modules.decompiler.exps.TypeAnnotation; +import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.InterpreterUtil; +import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinDecompilationContext; +import org.vineflower.kotlin.KotlinOptions; +import org.vineflower.kotlin.KotlinWriter; +import org.vineflower.kotlin.metadata.MetadataNameResolver; +import org.vineflower.kotlin.util.KUtils; +import org.vineflower.kotlin.util.ProtobufFlags; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class KFunction { + public final String name; + public final ProtobufFlags.Function flags; + public final List contextReceiverTypes; + public final KParameter[] parameters; + public final List typeParameters; + public final KType returnType; + + public final MethodWrapper method; + + @Nullable + public final KType receiverType; + + @Nullable + public final KContract contract; + + public final boolean knownOverride; + + private final ClassesProcessor.ClassNode node; + + private KFunction( + String name, + KParameter[] parameters, + List typeParameters, + KType returnType, + ProtobufFlags.Function flags, + List contextReceiverTypes, MethodWrapper method, + @Nullable KType receiverType, + @Nullable KContract contract, + boolean knownOverride, + ClassesProcessor.ClassNode node) { + this.name = name; + this.parameters = parameters; + this.typeParameters = typeParameters; + this.returnType = returnType; + this.flags = flags; + this.contextReceiverTypes = contextReceiverTypes; + this.method = method; + this.receiverType = receiverType; + this.contract = contract; + this.knownOverride = knownOverride; + this.node = node; + } + + public static Map parse(ClassesProcessor.ClassNode node) { + MetadataNameResolver resolver = KotlinDecompilationContext.getNameResolver(); + ClassWrapper wrapper = node.getWrapper(); + StructClass struct = wrapper.getClassStruct(); + + List protoFunctions; + + KotlinDecompilationContext.KotlinType type = KotlinDecompilationContext.getCurrentType(); + if (type == null) return Map.of(); + + switch (type) { + case CLASS: + protoFunctions = KotlinDecompilationContext.getCurrentClass().getFunctionList(); + break; + case FILE: + protoFunctions = KotlinDecompilationContext.getFilePackage().getFunctionList(); + break; + case MULTIFILE_CLASS: + protoFunctions = KotlinDecompilationContext.getMultifilePackage().getFunctionList(); + break; + case SYNTHETIC_CLASS: + // indicating lambdas and such + protoFunctions = Collections.singletonList(KotlinDecompilationContext.getSyntheticClass()); + break; + default: + throw new IllegalStateException("Unexpected value: " + type); + } + + Map functions = new HashMap<>(protoFunctions.size(), 1f); + + for (ProtoBuf.Function function : protoFunctions) { + JvmProtoBuf.JvmMethodSignature jvmData = function.getExtension(JvmProtoBuf.methodSignature); + + ProtobufFlags.Function flags = new ProtobufFlags.Function(function.getFlags()); + + String name = resolver.resolve(function.getName()); + + KParameter[] parameters = new KParameter[function.getValueParameterCount()]; + for (int i = 0; i < parameters.length; i++) { + ProtoBuf.ValueParameter parameter = function.getValueParameter(i); + ProtobufFlags.ValueParameter paramFlags = new ProtobufFlags.ValueParameter(parameter.getFlags()); + String paramName = resolver.resolve(parameter.getName()); + KType paramType = KType.from(parameter.getType(), resolver); + KType varargType = parameter.hasVarargElementType() ? KType.from(parameter.getVarargElementType(), resolver) : null; + int typeId = parameter.getTypeId(); + parameters[i] = new KParameter(paramFlags, paramName, paramType, varargType, typeId); + } + + KType receiverType = null; + if (function.hasReceiverType()) { + receiverType = KType.from(function.getReceiverType(), resolver); + } + + KType returnType = KType.from(function.getReturnType(), resolver); + + MethodWrapper method = null; + + if (jvmData.hasDesc()) { + String lookupName = jvmData.hasName() ? resolver.resolve(jvmData.getName()) : name; + method = wrapper.getMethodWrapper(lookupName, resolver.resolve(jvmData.getDesc())); + } + + if (method == null) { + StringBuilder desc = new StringBuilder("("); + if (receiverType != null) { + desc.append(receiverType); + } + + for (KParameter parameter : parameters) { + desc.append(parameter.type); + } + + int endOfParams = desc.length(); + desc.append(")").append(returnType); + + method = wrapper.getMethodWrapper(name, desc.toString()); + + if (method == null) { + throw new IllegalStateException("Couldn't find method " + name + " " + desc + " in class " + struct.qualifiedName); + } + } + + List typeParameters = function.getTypeParameterList().stream() + .map(typeParameter -> KTypeParameter.from(typeParameter, resolver)) + .collect(Collectors.toList()); + + List contextReceiverTypes = function.getContextReceiverTypeList().stream() + .map(ctxType -> KType.from(ctxType, resolver)) + .collect(Collectors.toList()); + + boolean knownOverride = flags.visibility != ProtoBuf.Visibility.PRIVATE + && flags.visibility != ProtoBuf.Visibility.PRIVATE_TO_THIS + && flags.visibility != ProtoBuf.Visibility.LOCAL + && KotlinWriter.searchForMethod(struct, method.methodStruct.getName(), method.desc(), false); + + KContract contract = function.hasContract() ? KContract.from(function.getContract(), List.of(parameters), resolver) : null; + + functions.put(method.methodStruct, new KFunction(name, parameters, typeParameters, returnType, flags, contextReceiverTypes, method, receiverType, contract, knownOverride, node)); + } + + return functions; + } + + public TextBuffer stringify(int indent) { + TextBuffer buf = new TextBuffer(); + KotlinWriter.appendAnnotations(buf, indent, method.methodStruct, TypeAnnotation.METHOD_RETURN_TYPE); + KotlinWriter.appendJvmAnnotations(buf, indent, method.methodStruct, false, method.classStruct.getPool(), TypeAnnotation.METHOD_RETURN_TYPE); + + buf.appendIndent(indent); + + if (!contextReceiverTypes.isEmpty()) { + buf.append("context("); + boolean first = true; + for (KType contextReceiverType : contextReceiverTypes) { + if (!first) { + buf.append(", "); + } + + buf.append(contextReceiverType.stringify(indent + 1)); + first = false; + } + buf.append(")").appendLineSeparator().appendIndent(indent); + } + + if (flags.visibility != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) { + KUtils.appendVisibility(buf, flags.visibility); + } + + if (flags.isExpect) { + buf.append("expect "); + } + + if (flags.modality != ProtoBuf.Modality.FINAL) { + if (!knownOverride || flags.modality != ProtoBuf.Modality.OPEN) { + buf.append(flags.modality.name().toLowerCase()) + .append(' '); + } + } + + if (flags.isExternal) { + buf.append("external "); + } + + if (knownOverride) { + buf.append("override "); + } + + if (flags.isTailrec) { + buf.append("tailrec "); + } + + if (flags.isSuspend) { + buf.append("suspend "); + } + + if (flags.isInline) { + buf.append("inline "); + } + + if (flags.isInfix) { + buf.append("infix "); + } + + if (flags.isOperator) { + buf.append("operator "); + } + + buf.append("fun "); + + List complexTypeParams = typeParameters.stream() + .filter(typeParameter -> typeParameter.upperBounds.size() > 1) + .collect(Collectors.toList()); + + Map typeParamsById = typeParameters.stream() + .collect(Collectors.toMap(typeParameter -> typeParameter.id, Function.identity())); + + if (!typeParameters.isEmpty()) { + buf.append('<'); + + for (int i = 0; i < typeParameters.size(); i++) { + KTypeParameter typeParameter = typeParameters.get(i); + + if (typeParameter.reified) { + buf.append("reified "); + } + + buf.append(KotlinWriter.toValidKotlinIdentifier(typeParameter.name)); + + if (typeParameter.upperBounds.size() == 1) { + buf.append(" : ").append(typeParameter.upperBounds.get(0).stringify(indent + 1)); + } + + if (i < typeParameters.size() - 1) { + buf.append(", "); + } + } + + buf.append("> "); + } + + if (receiverType != null) { + // Function types need parentheses around the receiver type, but that happens in KType.stringify only if it's nullable + // so we need to wrap in the case of non-nullable function types + if (!receiverType.isNullable && receiverType.kotlinType.startsWith("kotlin/Function")) { + buf.append("("); + } + buf.append(receiverType.stringify(indent + 1)); + if (!receiverType.isNullable && receiverType.kotlinType.startsWith("kotlin/Function")) { + buf.append(")"); + } + + buf.append("."); + } + + buf.append(KotlinWriter.toValidKotlinIdentifier(name)) + .append('(') + .pushNewlineGroup(indent, 1) + .appendPossibleNewline(""); + + boolean first = true; + for (KParameter parameter : parameters) { + if (!first) { + buf.append(",").appendPossibleNewline(" "); + } + + first = false; + + parameter.stringify(indent + 1, buf); + } + + buf.appendPossibleNewline("", true) + .popNewlineGroup() + .append(')'); + + if (returnType != null && returnType.type != VarType.VARTYPE_VOID.type) { + buf.append(": ") + .append(returnType.stringify(indent + 1)); + } + + if (complexTypeParams.isEmpty()) { + buf.append(' '); + } else { + buf.pushNewlineGroup(indent, 1) + .appendPossibleNewline(" ") + .append("where "); + + first = true; + for (KTypeParameter typeParameter : complexTypeParams) { + for (KType upperBound : typeParameter.upperBounds) { + if (!first) { + buf.appendPossibleNewline(",").appendPossibleNewline(" "); + } + + buf.append(KotlinWriter.toValidKotlinIdentifier(typeParameter.name)) + .append(" : ") + .append(upperBound.stringify(indent + 1)); + + first = false; + } + } + + buf.appendPossibleNewline(" ", true) + .popNewlineGroup(); + } + + buf.append('{').appendLineSeparator(); + + if (contract != null) { + buf.append(contract.stringify(indent + 1)); + } + + RootStatement root = method.root; + if (root != null && method.decompileError == null) { + try { + TextBuffer body = root.toJava(indent + 1); + body.addBytecodeMapping(root.getDummyExit().bytecode); + if (body.length() != 0 && contract != null) { + buf.appendLineSeparator(); + } + + buf.append(body, node.classStruct.qualifiedName, InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor())); + } catch (Throwable t) { + String message = "Method " + method.methodStruct.getName() + " " + method.desc() + " in class " + node.classStruct.qualifiedName + " couldn't be written."; + DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t); + method.decompileError = t; + } + } + + if (method.decompileError != null) { + KotlinWriter.dumpError(buf, method, indent + 1); + } + + buf.appendIndent(indent).append('}').appendLineSeparator(); + + return buf; + } +} diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KParameter.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KParameter.java new file mode 100644 index 0000000000..cd4eb4af9b --- /dev/null +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KParameter.java @@ -0,0 +1,43 @@ +package org.vineflower.kotlin.struct; + +import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinWriter; +import org.vineflower.kotlin.util.ProtobufFlags; + +public class KParameter { + public final ProtobufFlags.ValueParameter flags; + public final String name; + public final KType type; + public final KType varargType; + public final int typeId; + + KParameter(ProtobufFlags.ValueParameter flags, String name, KType type, KType varargType, int typeId) { + this.flags = flags; + this.name = name; + this.type = type; + this.varargType = varargType; + this.typeId = typeId; + } + + public void stringify(int indent, TextBuffer buf) { + if (flags.isCrossinline) { + buf.append("crossinline "); + } + + if (flags.isNoinline) { + buf.append("noinline "); + } + + // Vararg types are a bit odd to say the least + boolean isVararg = varargType != null && type.kotlinType.equals("kotlin/Array"); + + if (isVararg) { + buf.append("vararg "); + } + + buf.append(KotlinWriter.toValidKotlinIdentifier(name)).append(": "); + + KType type = isVararg ? varargType : this.type; + buf.append(type.stringify(indent + 1)); + } +} diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KProperty.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KProperty.java index cbcb379179..0808b07627 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KProperty.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KProperty.java @@ -1,7 +1,7 @@ package org.vineflower.kotlin.struct; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; -import kotlin.reflect.jvm.internal.impl.metadata.jvm.JvmProtoBuf; +import kotlinx.metadata.internal.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.jvm.JvmProtoBuf; import org.jetbrains.annotations.Nullable; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.ClassesProcessor; @@ -25,6 +25,7 @@ import org.vineflower.kotlin.KotlinWriter; import org.vineflower.kotlin.metadata.MetadataNameResolver; import org.vineflower.kotlin.util.KTypes; +import org.vineflower.kotlin.util.KUtils; import org.vineflower.kotlin.util.ProtobufFlags; import java.util.*; @@ -78,7 +79,7 @@ public TextBuffer stringify(int indent) { buf.appendIndent(indent); // Modifiers in the order that Kotlin's coding conventions specify - appendVisibility(buf, flags.visibility); + KUtils.appendVisibility(buf, flags.visibility); if (flags.isExpect) { buf.append("expect "); @@ -122,10 +123,10 @@ public TextBuffer stringify(int indent) { // Custom getters and setters, and possible modifier differences if (getter != null && getter.flags.isNotDefault) { buf.pushNewlineGroup(indent, 1) - .append('\n') + .appendLineSeparator() .appendIndent(indent + 1); - appendVisibility(buf, getter.flags.visibility); + KUtils.appendVisibility(buf, getter.flags.visibility); buf.append(getter.flags.modality.name().toLowerCase()) .append(' '); @@ -144,17 +145,17 @@ public TextBuffer stringify(int indent) { buf.popNewlineGroup(); } else if (getter != null && getter.flags.isExternal) { - buf.append('\n') + buf.appendLineSeparator() .appendIndent(indent + 1) .append("external get"); } if (setter != null && setter.flags.isNotDefault) { buf.pushNewlineGroup(indent, 1) - .append('\n') + .appendLineSeparator() .appendIndent(indent + 1); - appendVisibility(buf, getter.flags.visibility); + KUtils.appendVisibility(buf, getter.flags.visibility); buf.append(setter.flags.modality.name().toLowerCase()) .append(' '); @@ -175,10 +176,10 @@ public TextBuffer stringify(int indent) { buf.popNewlineGroup(); } else if (setter != null && (setter.flags.isExternal || setter.flags.visibility != flags.visibility || setter.flags.modality != flags.modality)) { - buf.append('\n').appendIndent(indent + 1); + buf.appendLineSeparator().appendIndent(indent + 1); if (setter.flags.visibility != flags.visibility) { - appendVisibility(buf, setter.flags.visibility); + KUtils.appendVisibility(buf, setter.flags.visibility); } if (setter.flags.modality != flags.modality) { @@ -192,7 +193,7 @@ public TextBuffer stringify(int indent) { buf.append("set"); } else if (setter == null && flags.isVar && flags.visibility != ProtoBuf.Visibility.PRIVATE) { // Special case: no setter is generated if it's a var with a private setter - buf.append('\n') + buf.appendLineSeparator() .appendIndent(indent + 1) .append("private set"); } diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KType.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KType.java index d0951ef354..5d6f4728bb 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KType.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KType.java @@ -1,31 +1,58 @@ package org.vineflower.kotlin.struct; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.ProtoBuf; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinDecompilationContext; import org.vineflower.kotlin.metadata.MetadataNameResolver; import org.vineflower.kotlin.util.KTypes; +import java.util.Objects; + public class KType extends VarType { - public final String kotlinType; + public static final KType UNIT = new KType(VARTYPE_VOID, "kotlin/Unit", false, null, null, null); + public static final KType NOTHING = new KType(new VarType("java/lang/Void", true), "kotlin/Nothing", false, null, null, null); + public final String kotlinType; public final boolean isNullable; - public final TypeArgument @Nullable [] typeArguments; - public KType(VarType type, String kotlinType, boolean isNullable, TypeArgument @Nullable [] typeArguments) { + @Nullable + public final String typeParameterName; + + @Nullable + public final String typeAliasName; + + private KType( + VarType type, + String kotlinType, + boolean isNullable, + TypeArgument @Nullable [] typeArguments, + @Nullable String typeParameterName, + @Nullable String typeAliasName) { super(type.type, type.arrayDim, type.value, type.typeFamily, type.stackSize); this.kotlinType = kotlinType; this.isNullable = isNullable; this.typeArguments = typeArguments; + this.typeParameterName = typeParameterName; + this.typeAliasName = typeAliasName; } public static KType from(ProtoBuf.Type type, MetadataNameResolver nameResolver) { - String kotlinType = nameResolver.resolve(type.getClassName()); + String kotlinType = type.hasClassName() ? nameResolver.resolve(type.getClassName()) : "kotlin/Any"; boolean isNullable = type.getNullable(); - String jvmDesc = KTypes.getJavaSignature(kotlinType, isNullable); - VarType varType = new VarType(jvmDesc); + + // short-circuit for `Unit` + if ("kotlin/Unit".equals(kotlinType) && !isNullable) { + return UNIT; + } + + // similar short-circuit for `Nothing` + if ("kotlin/Nothing".equals(kotlinType) && !isNullable) { + return NOTHING; + } TypeArgument[] typeArguments = null; if (type.getArgumentCount() > 0) { @@ -36,14 +63,61 @@ public static KType from(ProtoBuf.Type type, MetadataNameResolver nameResolver) } } - return new KType(varType, kotlinType, isNullable, typeArguments); + String jvmDesc = KTypes.getJavaSignature(kotlinType, isNullable); + if ("kotlin/Array".equals(kotlinType)) { + TypeArgument arrayType = Objects.requireNonNull(typeArguments)[0]; + if (arrayType.typeProjection == ProtoBuf.Type.Argument.Projection.IN) { + jvmDesc = "[Ljava/lang/Object;"; // `in` variance is erased to `Object` (to allow any supertype to be passed in) + } else { + jvmDesc = "[" + arrayType.type.toString(); + } + } + VarType varType = new VarType(jvmDesc); + + String typeParameterName = type.hasTypeParameterName() ? nameResolver.resolve(type.getTypeParameterName()) : null; + String typeAliasName = type.hasTypeAliasName() ? nameResolver.resolve(type.getTypeAliasName()) : null; + + return new KType(varType, kotlinType, isNullable, typeArguments, typeParameterName, typeAliasName); + } + + public static KType from(int tableIndex, MetadataNameResolver resolver) { + ProtoBuf.TypeTable table; + switch (KotlinDecompilationContext.getCurrentType()) { + case CLASS: + table = KotlinDecompilationContext.getCurrentClass().getTypeTable(); + break; + case SYNTHETIC_CLASS: + table = KotlinDecompilationContext.getSyntheticClass().getTypeTable(); + break; + case FILE: + table = KotlinDecompilationContext.getFilePackage().getTypeTable(); + break; + case MULTIFILE_CLASS: + table = KotlinDecompilationContext.getMultifilePackage().getTypeTable(); + break; + default: + throw new IllegalStateException("No decompilation context found"); + } + + return from(table.getType(tableIndex), resolver); } + // stringify is for the decompiler output public TextBuffer stringify(int indent) { TextBuffer buf = new TextBuffer(); + if (typeParameterName != null) { + buf.append(typeParameterName); + if (isNullable) { + buf.append("?"); + } + + return buf; + } + if (!kotlinType.startsWith("kotlin/Function")) { // Non-functions are essentially equivalent to Java generic types - buf.append(KTypes.getKotlinType(this)); + String type = kotlinType.replace('/', '.'); + buf.append(DecompilerContext.getImportCollector().getShortName(type)); if (typeArguments != null) { buf.append("<"); diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KTypeParameter.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KTypeParameter.java new file mode 100644 index 0000000000..e802a58088 --- /dev/null +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KTypeParameter.java @@ -0,0 +1,38 @@ +package org.vineflower.kotlin.struct; + +import kotlinx.metadata.internal.metadata.ProtoBuf; +import org.vineflower.kotlin.metadata.MetadataNameResolver; + +import java.util.List; +import java.util.stream.Collectors; + +public class KTypeParameter { + public final boolean reified; + public final ProtoBuf.TypeParameter.Variance variance; + public final List upperBounds; + public final String name; + public final int id; + + private KTypeParameter( + boolean reified, + ProtoBuf.TypeParameter.Variance variance, + List upperBounds, + String name, + int id) { + this.reified = reified; + this.variance = variance; + this.upperBounds = upperBounds; + this.name = name; + this.id = id; + } + + public static KTypeParameter from(ProtoBuf.TypeParameter proto, MetadataNameResolver resolver) { + return new KTypeParameter( + proto.getReified(), + proto.getVariance(), + proto.getUpperBoundList().stream().map(type -> KType.from(type, resolver)).collect(Collectors.toList()), + resolver.resolve(proto.getName()), + proto.getId() + ); + } +} diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KTypes.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KTypes.java index 63e4530ec6..05e43a3144 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KTypes.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KTypes.java @@ -29,29 +29,36 @@ public final class KTypes { "java/util/Collection", "MutableCollection", "java/util/Iterator", "MutableIterator", "java/util/Map$Entry", "MutableMap.MutableEntry", - "java/util/Iterable", "MutableIterable" + "java/lang/Iterable", "MutableIterable" ); - private static final Map KOTLIN_TO_JAVA_LANG = Map.of( - "kotlin/Int", "java/lang/Integer", - "kotlin/Long", "java/lang/Long", - "kotlin/Short", "java/lang/Short", - "kotlin/Byte", "java/lang/Byte", - "kotlin/Boolean", "java/lang/Boolean", - "kotlin/Char", "java/lang/Character", - "kotlin/Float", "java/lang/Float", - "kotlin/Double", "java/lang/Double", - "kotlin/String", "java/lang/String", - "kotlin/Any", "java/lang/Object" + public static final Map KOTLIN_TO_JAVA_LANG = Map.ofEntries( + Map.entry("kotlin/Any", "java/lang/Object"), + Map.entry("kotlin/Boolean", "java/lang/Boolean"), + Map.entry("kotlin/Byte", "java/lang/Byte"), + Map.entry("kotlin/Char", "java/lang/Character"), + Map.entry("kotlin/CharSequence", "java/lang/CharSequence"), + Map.entry("kotlin/Comparable", "java/lang/Comparable"), + Map.entry("kotlin/Double", "java/lang/Double"), + Map.entry("kotlin/Enum", "java/lang/Enum"), + Map.entry("kotlin/Float", "java/lang/Float"), + Map.entry("kotlin/Int", "java/lang/Integer"), + Map.entry("kotlin/Long", "java/lang/Long"), + Map.entry("kotlin/Nothing", "java/lang/Void"), + Map.entry("kotlin/Number", "java/lang/Number"), + Map.entry("kotlin/Short", "java/lang/Short"), + Map.entry("kotlin/String", "java/lang/String"), + Map.entry("kotlin/Throwable", "java/lang/Throwable"), + Map.entry("kotlin/collections/MutableIterable", "java/lang/Iterable"), + Map.entry("kotlin/collections/Iterable", "java/lang/Iterable") ); - private static final Map KOTLIN_TO_JAVA_UTIL = Map.of( + public static final Map KOTLIN_TO_JAVA_UTIL = Map.of( "kotlin/collections/MutableMap", "java/util/Map", "kotlin/collections/MutableList", "java/util/List", "kotlin/collections/MutableSet", "java/util/Set", "kotlin/collections/MutableIterator", "java/util/Iterator", - "kotlin/collections/MutableIterable", "java/util/Iterable", - "kotlin/collections/MutableMap.MutableEntry", "java/util/Map$Entry" + "kotlin/collections/MutableMap$MutableEntry", "java/util/Map$Entry" ); private static final Map KOTLIN_PRIMITIVE_TYPES = Map.of( @@ -71,9 +78,18 @@ public static String getJavaSignature(String kotlinType, boolean isNullable) { kotlinType = kotlinType.substring(1, kotlinType.length() - 1); } + // Kotlin uses . instead of $ when referring to inner classes in metadata but keeps $ in the bytecode + if (kotlinType.contains(".")) { + kotlinType = kotlinType.replace('.', '$'); + } + if (kotlinType.startsWith("kotlin/")) { if (KOTLIN_PRIMITIVE_TYPES.containsKey(kotlinType) && !isNullable) { return KOTLIN_PRIMITIVE_TYPES.get(kotlinType); + } else if (kotlinType.endsWith("$Companion") && KOTLIN_PRIMITIVE_TYPES.containsKey(kotlinType.replace("$Companion", ""))) { + return "Lkotlin/jvm/internal/" + kotlinType.split("/")[1].split("\\$")[0] + "CompanionObject;"; + } else if (kotlinType.endsWith("Array") && KOTLIN_PRIMITIVE_TYPES.containsKey(kotlinType.replace("Array", ""))) { + return "[" + KOTLIN_PRIMITIVE_TYPES.get(kotlinType.replace("Array", "")); } else if (KOTLIN_TO_JAVA_LANG.containsKey(kotlinType)) { return "L" + KOTLIN_TO_JAVA_LANG.get(kotlinType) + ";"; } else if (KOTLIN_TO_JAVA_UTIL.containsKey(kotlinType)) { @@ -97,6 +113,11 @@ public static String getKotlinType(VarType type) { } public static String getKotlinType(VarType type, boolean includeOuterClasses) { + if (type == null) { + //TODO: prevent passing null + return "*"; + } + String typeStr; if (isFunctionType(type)) { typeStr = functionTypeToKotlin(type); diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KUtils.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KUtils.java index 042546c9fc..ca0879d7d2 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KUtils.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/KUtils.java @@ -1,10 +1,16 @@ package org.vineflower.kotlin.util; +import kotlinx.metadata.internal.metadata.ProtoBuf; +import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.modules.decompiler.exps.*; +import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.TextBuffer; +import org.vineflower.kotlin.KotlinOptions; import org.vineflower.kotlin.expr.*; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class KUtils { public static List replaceExprents(List exprs) { @@ -39,4 +45,66 @@ public static Exprent replaceExprent(Exprent ex) { return null; } + + public static void appendVisibility(TextBuffer buf, ProtoBuf.Visibility visibility) { + switch (visibility) { + case LOCAL: + buf.append("// QF: local property") + .appendLineSeparator() + .append("internal "); + break; + case PRIVATE_TO_THIS: + buf.append("private "); + break; + case PUBLIC: + if (DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) { + buf.append("public "); + } + break; + default: + buf.append(visibility.name().toLowerCase()) + .append(' '); + } + } + + public static void removeArguments(InvocationExprent expr, VarType toRemove) { + removeArguments(expr, toRemove, null); + } + + public static void removeArguments(InvocationExprent expr, VarType toRemove, VarType replaceReturnType) { + if (expr.getLstParameters().isEmpty()) { + return; + } + + if (expr.getLstParameters().size() == 1) { + VarType argType = expr.getDescriptor().params[0]; + if (argType.equals(toRemove)) { + expr.getLstParameters().clear(); + } + return; + } + + VarType[] params = expr.getDescriptor().params; + List lst = expr.getLstParameters(); + for (int i = 0; i < params.length; i++) { + VarType argType = params[i]; + if (argType.equals(toRemove)) { + lst.set(i, null); + } + } + lst.removeIf(Objects::isNull); + + String newDesc = expr.getStringDescriptor() + .replace(toRemove.toString(), ""); + + if (newDesc.endsWith(")")) { + if (replaceReturnType == null) { + throw new IllegalStateException("Invalid descriptor: " + newDesc); + } + + newDesc += replaceReturnType.toString(); + } + + expr.setStringDescriptor(newDesc); + } } diff --git a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/ProtobufFlags.java b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/ProtobufFlags.java index 37a43dcf08..8a32ad4edf 100644 --- a/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/ProtobufFlags.java +++ b/plugins/kotlin/src/main/java/org/vineflower/kotlin/util/ProtobufFlags.java @@ -1,9 +1,11 @@ package org.vineflower.kotlin.util; -import kotlin.reflect.jvm.internal.impl.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.ProtoBuf; +import kotlinx.metadata.internal.metadata.deserialization.Flags; public interface ProtobufFlags { //TODO: hasNonStableParameterNames + //TODO: Update everything to use Flags class int HAS_ANNOTATIONS = 0x0001; @@ -207,6 +209,18 @@ public Class(int flags) { } //endregion + //region: Contract + class Expression { + public final boolean isNegated; + public final boolean isNullPredicate; + + public Expression(int flags) { + isNegated = Flags.IS_NEGATED.get(flags); + isNullPredicate = Flags.IS_NULL_CHECK_PREDICATE.get(flags); + } + } + //endregion + static String toString(ProtoBuf.Visibility visibility) { switch (visibility) { case PRIVATE: diff --git a/plugins/kotlin/src/test/java/org/vineflower/kotlin/KotlinTests.java b/plugins/kotlin/src/test/java/org/vineflower/kotlin/KotlinTests.java index 6a8c372a86..cb6d438fa3 100644 --- a/plugins/kotlin/src/test/java/org/vineflower/kotlin/KotlinTests.java +++ b/plugins/kotlin/src/test/java/org/vineflower/kotlin/KotlinTests.java @@ -84,5 +84,6 @@ private void registerKotlinTests() { register(KOTLIN, "TestSynchronized"); register(KOTLIN, "TestReflection"); register(KOTLIN, "TestConstructors"); + register(KOTLIN, "TestContracts"); } } diff --git a/plugins/kotlin/testData/results/pkg/TestAnnotations.dec b/plugins/kotlin/testData/results/pkg/TestAnnotations.dec index 94bc96cd03..9fea29d521 100644 --- a/plugins/kotlin/testData/results/pkg/TestAnnotations.dec +++ b/plugins/kotlin/testData/results/pkg/TestAnnotations.dec @@ -2,29 +2,21 @@ package pkg import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy -import kotlin.jvm.internal.RepeatableContainer class TestAnnotations { @TestAnnotations.TestAnnotation(first = "test", second = 1) - fun test() { + public fun test() { }// 16 @TestAnnotations.RepeatableAnnotation.Container([@TestAnnotations.RepeatableAnnotation("test"), @TestAnnotations.RepeatableAnnotation("test2")]) - fun test2() { + public fun test2() { }// 21 @Repeatable @Retention(RetentionPolicy.RUNTIME) - @java.lang.annotation.Repeatable(TestAnnotations.RepeatableAnnotation.Container::class) annotation class RepeatableAnnotation( val value: String - ) { - @RepeatableContainer - @Retention(RetentionPolicy.RUNTIME) - annotation class Container( - val value: Array - ) - } + ) @Retention(RetentionPolicy.RUNTIME) annotation class TestAnnotation( @@ -35,14 +27,14 @@ class TestAnnotations { class 'pkg/TestAnnotations' { method 'test ()V' { - 0 9 + 0 8 } method 'test2 ()V' { - 0 13 + 0 12 } } Lines mapping: -16 <-> 10 -21 <-> 14 +16 <-> 9 +21 <-> 13 diff --git a/plugins/kotlin/testData/results/pkg/TestAnyType.dec b/plugins/kotlin/testData/results/pkg/TestAnyType.dec index 1d00d4bba4..40e0f17498 100644 --- a/plugins/kotlin/testData/results/pkg/TestAnyType.dec +++ b/plugins/kotlin/testData/results/pkg/TestAnyType.dec @@ -1,9 +1,9 @@ package pkg class TestAnyType { - fun test(param: Any): Int { - if (param is String) {// 5 - return (param as String).length();// 6 + public fun test(param: Any): Int { + if (param is java.lang.String) {// 5 + return (param as java.lang.String).length();// 6 } else { System.out.println(param);// 9 return 0;// 11 diff --git a/plugins/kotlin/testData/results/pkg/TestBitwiseFunctions.dec b/plugins/kotlin/testData/results/pkg/TestBitwiseFunctions.dec index 59ca9dc8d6..ecec103da9 100644 --- a/plugins/kotlin/testData/results/pkg/TestBitwiseFunctions.dec +++ b/plugins/kotlin/testData/results/pkg/TestBitwiseFunctions.dec @@ -1,27 +1,27 @@ package pkg class TestBitwiseFunctions { - fun and(a: Int, b: Int): Int { + public fun and(a: Int, b: Int): Int { return a and b;// 5 } - fun or(a: Int, b: Int): Int { + public fun or(a: Int, b: Int): Int { return a or b;// 9 } - fun xor(a: Int, b: Int): Int { + public fun xor(a: Int, b: Int): Int { return a xor b;// 13 } - fun shl(a: Int, b: Int): Int { + public fun shl(a: Int, b: Int): Int { return a shl b;// 17 } - fun shr(a: Int, b: Int): Int { + public fun shr(a: Int, b: Int): Int { return a shr b;// 21 } - fun ushr(a: Int, b: Int): Int { + public fun ushr(a: Int, b: Int): Int { return a ushr b;// 25 } } diff --git a/plugins/kotlin/testData/results/pkg/TestClassDec.dec b/plugins/kotlin/testData/results/pkg/TestClassDec.dec index 0e0774fa9d..05fc5b7a6b 100644 --- a/plugins/kotlin/testData/results/pkg/TestClassDec.dec +++ b/plugins/kotlin/testData/results/pkg/TestClassDec.dec @@ -1,11 +1,11 @@ package pkg class TestClassDec { - fun TestClassDec.Vec2iVal.dot(v: TestClassDec.Vec2iVal): Int { + public fun pkg.TestClassDec.Vec2iVal.dot(v: pkg.TestClassDec.Vec2iVal): Int { return `$this$dot`.getX() * v.getX() + `$this$dot`.getY() * v.getY();// 11 } - fun test() { + public fun test() { new TestClassDec.EmptyDec(); var vec: TestClassDec.Vec2iVal = new TestClassDec.Vec2iVal(1, 2);// 16 var vec1: TestClassDec.Vec2iVal = new TestClassDec.Vec2iVal(2, 4);// 17 @@ -16,28 +16,26 @@ class TestClassDec { class EmptyDec { } - class Vec2i { - fun Vec2i(x: Int, y: Int) { - }// 8 + class Vec2i(x: Int, y: Int) { } - class Vec2iVal { + class Vec2iVal(x: Int, y: Int) { public final val x: Int public final val y: Int - fun Vec2iVal(x: Int, y: Int) { + init { this.x = x;// 7 this.y = y; } } - class Vec2iVar { + class Vec2iVar(x: Int, y: Int) { public final var x: Int internal set public final var y: Int internal set - fun Vec2iVar(x: Int, y: Int) { + init { this.x = x;// 6 this.y = y; } @@ -105,48 +103,41 @@ class 'pkg/TestClassDec' { } } -class 'pkg/TestClassDec$Vec2i' { - method ' (II)V' { - 4 20 - } -} - class 'pkg/TestClassDec$Vec2iVal' { method ' (II)V' { - 4 28 - 5 28 - 6 28 - 7 28 - 8 28 - 9 29 - a 29 - b 29 - c 29 - d 29 - e 30 + 4 26 + 5 26 + 6 26 + 7 26 + 8 26 + 9 27 + a 27 + b 27 + c 27 + d 27 + e 28 } } class 'pkg/TestClassDec$Vec2iVar' { method ' (II)V' { - 4 40 - 5 40 - 6 40 - 7 40 - 8 40 - 9 41 - a 41 - b 41 - c 41 - d 41 - e 42 + 4 38 + 5 38 + 6 38 + 7 38 + 8 38 + 9 39 + a 39 + b 39 + c 39 + d 39 + e 40 } } Lines mapping: -6 <-> 41 -7 <-> 29 -8 <-> 21 +6 <-> 39 +7 <-> 27 11 <-> 5 16 <-> 10 17 <-> 11 diff --git a/plugins/kotlin/testData/results/pkg/TestComparison.dec b/plugins/kotlin/testData/results/pkg/TestComparison.dec index 0d336a916b..deae0a7218 100644 --- a/plugins/kotlin/testData/results/pkg/TestComparison.dec +++ b/plugins/kotlin/testData/results/pkg/TestComparison.dec @@ -1,27 +1,27 @@ package pkg class TestComparison { - fun test2(a: Any, b: Any): Boolean { + public fun test2(a: Any, b: Any): Boolean { return a == b;// 5 } - fun test3(a: Any, b: Any): Boolean { + public fun test3(a: Any, b: Any): Boolean { return a === b;// 9 } - fun testNull2(a: Any?): Boolean { + public fun testNull2(a: Any?): Boolean { return a == null;// 13 } - fun testNull3(a: Any?): Boolean { + public fun testNull3(a: Any?): Boolean { return a == null;// 17 } - fun testNullDouble2(a: Any?, b: Any?): Boolean { + public fun testNullDouble2(a: Any?, b: Any?): Boolean { return a == b;// 21 } - fun testNullDouble3(a: Any?, b: Any?): Boolean { + public fun testNullDouble3(a: Any?, b: Any?): Boolean { return a === b;// 25 } } diff --git a/plugins/kotlin/testData/results/pkg/TestCompileTimeErrors.dec b/plugins/kotlin/testData/results/pkg/TestCompileTimeErrors.dec index fb9a7c5902..b39d3dee40 100644 --- a/plugins/kotlin/testData/results/pkg/TestCompileTimeErrors.dec +++ b/plugins/kotlin/testData/results/pkg/TestCompileTimeErrors.dec @@ -3,11 +3,11 @@ package pkg import org.jetbrains.annotations.Nullable class TestCompileTimeErrors { - fun test(i: I): O { + public fun test(i: I): O where O : I, O : pkg.TestCompileTimeErrors.Test { throw new NotImplementedError(null, 1, null);// 10 } - fun test2(i: Int?): TestCompileTimeErrors.Test? { + public fun test2(i: Int?): pkg.TestCompileTimeErrors.Test? { return if (i == null) null else new TestCompileTimeErrors.Test(i) { @Nullable private final Integer testValue; diff --git a/plugins/kotlin/testData/results/pkg/TestConstructors.dec b/plugins/kotlin/testData/results/pkg/TestConstructors.dec index 527d01a9d1..734acf7b17 100644 --- a/plugins/kotlin/testData/results/pkg/TestConstructors.dec +++ b/plugins/kotlin/testData/results/pkg/TestConstructors.dec @@ -1,30 +1,40 @@ package pkg -class TestConstructors { - fun TestConstructors() { - }// 3 - - fun TestConstructors(a: Int) { - this();// 4 +class TestConstructors private constructor() { + public constructor(a: Int) : this() {// 4 System.out.println("a = " + a);// 5 }// 6 - fun TestConstructors(a: Int, b: Int) { - this(a);// 8 + public constructor(a: Int, b: Int) : this(a) {// 8 System.out.println("b = " + b);// 9 }// 10 } class 'pkg/TestConstructors' { - method ' ()V' { + method ' (I)V' { + 1 3 + 2 3 + 3 3 4 4 + 5 4 + 6 4 + 7 4 + 8 4 + 9 4 + a 4 + b 4 + c 4 + e 4 + f 4 + 10 4 + 11 5 } - method ' (I)V' { + method ' (II)V' { 1 7 2 7 3 7 - 4 8 + 4 7 5 8 6 8 7 8 @@ -33,38 +43,18 @@ class 'pkg/TestConstructors' { a 8 b 8 c 8 - e 8 + d 8 f 8 10 8 - 11 9 - } - - method ' (II)V' { - 1 12 - 2 12 - 3 12 - 4 12 - 5 13 - 6 13 - 7 13 - 8 13 - 9 13 - a 13 - b 13 - c 13 - d 13 - f 13 - 10 13 - 11 13 - 12 14 + 11 8 + 12 9 } } Lines mapping: -3 <-> 5 -4 <-> 8 -5 <-> 9 -6 <-> 10 -8 <-> 13 -9 <-> 14 -10 <-> 15 +4 <-> 4 +5 <-> 5 +6 <-> 6 +8 <-> 8 +9 <-> 9 +10 <-> 10 diff --git a/plugins/kotlin/testData/results/pkg/TestContracts.dec b/plugins/kotlin/testData/results/pkg/TestContracts.dec new file mode 100644 index 0000000000..26f6a6f008 --- /dev/null +++ b/plugins/kotlin/testData/results/pkg/TestContracts.dec @@ -0,0 +1,233 @@ +package pkg + +import java.util.Iterator +import kotlin.contracts.InvocationKind + +class TestContracts { + public fun testSimpleContract(x: Int?): Int { + contract { + returns() implies (x != null) + } + + if (x == null) {// 13 + throw new IllegalStateException("x is null".toString()); + } else { + return x;// 14 + } + } + + public fun testBooleanContract(a: Boolean, b: Boolean): Boolean? { + contract { + returns(true) implies (!a && !b) + returns(null) implies (a && b) + returns(false) implies ((a && !b || (!a && b) + } + + return if (a && b) null else a || b;// 24 + } + + public fun testTypeContract(x: Any?): Int { + contract { + returns() implies (x is Int) + } + + if (x !is Integer) {// 31 + throw new IllegalStateException("x is not Int".toString()); + } else { + return (x as java.lang.Number).intValue();// 32 + } + } + + public fun testFunctionalContract(f: () -> Int): Int { + contract { + callsInPlace(f, InvocationKind.EXACTLY_ONCE) + } + + return (f.invoke() as java.lang.Number).intValue();// 39 + } + + public fun testFunctionalContract2(f: () -> Int, b: Boolean): Int { + contract { + callsInPlace(f, InvocationKind.AT_MOST_ONCE) + } + + return if (b) (f.invoke() as java.lang.Number).intValue() else 0;// 46 + } + + public fun testFunctionalContract3(f: () -> Int, i: Int): Int { + contract { + callsInPlace(f) + } + + var var3: java.lang.Iterable = (new IntRange(0, i)) as java.lang.Iterable; + var var4: Int = 0; + var var5: Iterator = var3.iterator(); + + while (var5.hasNext()) { + var var6: Int = (var5 as IntIterator).nextInt(); + var4 += (f.invoke() as java.lang.Number).intValue(); + } + + return var4;// 53 + } +} + +class 'pkg/TestContracts' { + method 'testSimpleContract (Ljava/lang/Integer;)I' { + 1 11 + 2 11 + 9 12 + a 12 + b 12 + c 12 + d 12 + 11 12 + 12 14 + 13 14 + 14 14 + 15 14 + 16 14 + } + + method 'testBooleanContract (ZZ)Ljava/lang/Boolean;' { + 1 25 + 2 25 + 5 25 + 6 25 + 9 25 + d 25 + e 25 + 11 25 + 12 25 + 1a 25 + 1d 25 + } + + method 'testTypeContract (Ljava/lang/Object;)I' { + 1 33 + 5 33 + c 34 + d 34 + e 34 + f 34 + 10 34 + 14 34 + 15 36 + 16 36 + 17 36 + 18 36 + 19 36 + 1a 36 + 1b 36 + 1c 36 + } + + method 'testFunctionalContract (Lkotlin/jvm/functions/Function0;)I' { + 7 45 + 8 45 + 9 45 + a 45 + b 45 + c 45 + d 45 + e 45 + f 45 + 10 45 + 11 45 + 12 45 + 13 45 + } + + method 'testFunctionalContract2 (Lkotlin/jvm/functions/Function0;Z)I' { + 7 53 + 8 53 + b 53 + c 53 + d 53 + e 53 + f 53 + 10 53 + 11 53 + 12 53 + 13 53 + 14 53 + 15 53 + 16 53 + 1a 53 + 1b 53 + } + + method 'testFunctionalContract3 (Lkotlin/jvm/functions/Function0;I)I' { + b 61 + c 61 + 10 61 + 11 61 + 12 61 + 13 61 + 14 62 + 15 62 + 16 62 + 17 63 + 18 63 + 19 63 + 1a 63 + 1b 63 + 1c 63 + 1d 63 + 1e 63 + 1f 65 + 20 65 + 21 65 + 22 65 + 23 65 + 24 65 + 25 65 + 29 66 + 2a 66 + 2b 66 + 2c 66 + 2d 66 + 2e 66 + 2f 66 + 30 66 + 31 66 + 32 66 + 3e 67 + 3f 67 + 40 67 + 41 67 + 42 67 + 43 67 + 44 67 + 45 67 + 46 67 + 47 67 + 48 67 + 49 67 + 4e 67 + 4f 67 + 51 67 + 52 67 + 56 70 + 57 70 + 58 70 + } +} + +Lines mapping: +13 <-> 12 +14 <-> 15 +24 <-> 26 +31 <-> 34 +32 <-> 37 +39 <-> 46 +46 <-> 54 +53 <-> 71 +Not mapped: +10 +18 +28 +36 +43 +50 +57 diff --git a/plugins/kotlin/testData/results/pkg/TestConvertedK2JOps.dec b/plugins/kotlin/testData/results/pkg/TestConvertedK2JOps.dec index 323be91852..8e0855be92 100644 --- a/plugins/kotlin/testData/results/pkg/TestConvertedK2JOps.dec +++ b/plugins/kotlin/testData/results/pkg/TestConvertedK2JOps.dec @@ -1,36 +1,33 @@ package pkg -import java.util.List -import java.util.Map -import java.util.Set - class TestConvertedK2JOps { public final val any: Any = new Object() - public final val list: List = CollectionsKt.listOf(new String[]{"a", "b", "c"}) + public final val list: List = CollectionsKt.listOf(new java.lang.String[]{"a", "b", "c"}) public final val map: Map = MapsKt.mapOf(new Pair[]{TuplesKt.to("a", "b"), TuplesKt.to("c", "d")}) - public final val set: Set = SetsKt.setOf(new String[]{"a", "b", "c"}) + public final val set: Set = SetsKt.setOf(new java.lang.String[]{"a", "b", "c"}) + - fun codeConstructs() { + public fun codeConstructs() { System.out.println("Hello, world!");// 10 }// 12 } class 'pkg/TestConvertedK2JOps' { method 'codeConstructs ()V' { - 0 13 - 1 13 - 2 13 - 3 13 - 4 13 - 6 13 - 7 13 - 8 13 - c 14 + 0 10 + 1 10 + 2 10 + 3 10 + 4 10 + 6 10 + 7 10 + 8 10 + c 11 } } Lines mapping: -10 <-> 14 -12 <-> 15 +10 <-> 11 +12 <-> 12 Not mapped: 11 diff --git a/plugins/kotlin/testData/results/pkg/TestDataClass.dec b/plugins/kotlin/testData/results/pkg/TestDataClass.dec index 54ef427ddd..29e6c123f9 100644 --- a/plugins/kotlin/testData/results/pkg/TestDataClass.dec +++ b/plugins/kotlin/testData/results/pkg/TestDataClass.dec @@ -1,43 +1,41 @@ package pkg -import java.util.List - -data class TestDataClass { +data class TestDataClass(dataClassVal: Regex, variableWithVeryLongName: Int, requestLineWrapsIfTheParamListIsTooLong: List, nullability: String?) { public final val dataClassVal: Regex public final val nullability: String? public final val requestLineWrapsIfTheParamListIsTooLong: List public final val variableWithVeryLongName: Int - fun TestDataClass(dataClassVal: Regex, variableWithVeryLongName: Int, requestLineWrapsIfTheParamListIsTooLong: MutableList, nullability: String?) { + init { this.dataClassVal = dataClassVal;// 4 this.variableWithVeryLongName = variableWithVeryLongName;// 5 this.requestLineWrapsIfTheParamListIsTooLong = requestLineWrapsIfTheParamListIsTooLong;// 6 this.nullability = nullability;// 7 }// 3 - fun component1(): Regex { + public operator fun component1(): Regex { return this.dataClassVal; } - fun component2(): Int { + public operator fun component2(): Int { return this.variableWithVeryLongName; } - fun component3(): MutableList { + public operator fun component3(): List { return this.requestLineWrapsIfTheParamListIsTooLong; } - fun component4(): String? { + public operator fun component4(): String? { return this.nullability; } - fun copy(dataClassVal: Regex, variableWithVeryLongName: Int, requestLineWrapsIfTheParamListIsTooLong: MutableList, nullability: String?): TestDataClass { + public fun copy(dataClassVal: Regex, variableWithVeryLongName: Int, requestLineWrapsIfTheParamListIsTooLong: List, nullability: String?): TestDataClass { return new TestDataClass(dataClassVal, variableWithVeryLongName, requestLineWrapsIfTheParamListIsTooLong, nullability); } @JvmStatic @JvmSynthetic - fun `copy$default`(var0: TestDataClass, var1: Regex, var2: Int, var3: List, var4: String, var5: Int, var6: Any): TestDataClass { + fun `copy$default`(var0: TestDataClass, var1: Regex, var2: Int, var3: java.util.List, var4: java.lang.String, var5: Int, var6: Any): TestDataClass { if ((var5 and 1) != 0) { var1 = var0.dataClassVal; } @@ -57,7 +55,7 @@ data class TestDataClass { return var0.copy(var1, var2, var3, var4); } - fun toString(): String { + public open fun toString(): String { return "TestDataClass(dataClassVal=" + this.dataClassVal + ", variableWithVeryLongName=" @@ -69,7 +67,7 @@ data class TestDataClass { + ")"; } - fun hashCode(): Int { + public open fun hashCode(): Int { return ( (this.dataClassVal.hashCode() * 31 + Integer.hashCode(this.variableWithVeryLongName)) * 31 + this.requestLineWrapsIfTheParamListIsTooLong.hashCode() @@ -78,7 +76,7 @@ data class TestDataClass { + (if (this.nullability == null) 0 else this.nullability.hashCode()); } - fun equals(other: Any?): Boolean { + public open operator fun equals(other: Any?): Boolean { if (this === other) { return true; } else if (other !is TestDataClass) { @@ -100,265 +98,265 @@ data class TestDataClass { class 'pkg/TestDataClass' { method ' (Lkotlin/text/Regex;ILjava/util/List;Ljava/lang/String;)V' { - 10 11 - 11 11 - 12 11 - 13 11 - 14 11 - 15 12 - 16 12 - 17 12 - 18 12 - 19 12 - 1a 13 - 1b 13 - 1c 13 - 1d 13 - 1e 13 - 1f 14 - 20 14 - 21 14 - 22 14 - 23 14 - 24 14 - 25 15 + 10 9 + 11 9 + 12 9 + 13 9 + 14 9 + 15 10 + 16 10 + 17 10 + 18 10 + 19 10 + 1a 11 + 1b 11 + 1c 11 + 1d 11 + 1e 11 + 1f 12 + 20 12 + 21 12 + 22 12 + 23 12 + 24 12 + 25 13 } method 'component1 ()Lkotlin/text/Regex;' { - 0 18 - 1 18 - 2 18 - 3 18 - 4 18 + 0 16 + 1 16 + 2 16 + 3 16 + 4 16 } method 'component2 ()I' { - 0 22 - 1 22 - 2 22 - 3 22 - 4 22 + 0 20 + 1 20 + 2 20 + 3 20 + 4 20 } method 'component3 ()Ljava/util/List;' { - 0 26 - 1 26 - 2 26 - 3 26 - 4 26 + 0 24 + 1 24 + 2 24 + 3 24 + 4 24 } method 'component4 ()Ljava/lang/String;' { - 0 30 - 1 30 - 2 30 - 3 30 - 4 30 + 0 28 + 1 28 + 2 28 + 3 28 + 4 28 } method 'copy (Lkotlin/text/Regex;ILjava/util/List;Ljava/lang/String;)Lpkg/TestDataClass;' { - 10 34 - 11 34 - 12 34 - 13 34 - 14 34 - 18 34 + 10 32 + 11 32 + 12 32 + 13 32 + 14 32 + 18 32 } method 'copy$default (Lpkg/TestDataClass;Lkotlin/text/Regex;ILjava/util/List;Ljava/lang/String;ILjava/lang/Object;)Lpkg/TestDataClass;' { - 0 40 - 1 40 - 2 40 - 3 40 - 4 40 - 7 41 - 8 41 - 9 41 - a 41 - b 41 - c 44 - d 44 - e 44 - f 44 - 10 44 - 13 45 - 14 45 - 15 45 - 16 45 - 17 45 - 18 48 - 19 48 - 1a 48 - 1b 48 - 1c 48 - 1f 49 - 20 49 - 21 49 - 22 49 - 23 49 - 24 52 - 25 52 - 26 52 - 27 52 - 28 52 - 29 52 - 2c 53 - 2d 53 - 2e 53 - 2f 53 - 30 53 - 31 53 - 32 56 - 33 56 - 34 56 - 35 56 - 36 56 - 37 56 - 38 56 - 39 56 - 3a 56 - 3b 56 + 0 38 + 1 38 + 2 38 + 3 38 + 4 38 + 7 39 + 8 39 + 9 39 + a 39 + b 39 + c 42 + d 42 + e 42 + f 42 + 10 42 + 13 43 + 14 43 + 15 43 + 16 43 + 17 43 + 18 46 + 19 46 + 1a 46 + 1b 46 + 1c 46 + 1f 47 + 20 47 + 21 47 + 22 47 + 23 47 + 24 50 + 25 50 + 26 50 + 27 50 + 28 50 + 29 50 + 2c 51 + 2d 51 + 2e 51 + 2f 51 + 30 51 + 31 51 + 32 54 + 33 54 + 34 54 + 35 54 + 36 54 + 37 54 + 38 54 + 39 54 + 3a 54 + 3b 54 } method 'toString ()Ljava/lang/String;' { - 0 61 - 1 61 - 2 61 - 3 61 - 4 63 - 5 63 - 6 63 - 7 63 - 8 65 - 9 65 - a 65 - b 65 - c 67 - d 67 - e 67 - f 67 - 10 60 - 11 60 - 12 60 - 13 60 - 14 60 - 15 60 + 0 59 + 1 59 + 2 59 + 3 59 + 4 61 + 5 61 + 6 61 + 7 61 + 8 63 + 9 63 + a 63 + b 63 + c 65 + d 65 + e 65 + f 65 + 10 58 + 11 58 + 12 58 + 13 58 + 14 58 + 15 58 } method 'hashCode ()I' { - 0 73 - 1 73 - 2 73 - 3 73 - 4 73 - 5 73 - 6 73 - 8 73 - 9 73 - a 73 - b 73 - c 73 - d 73 - e 73 - f 73 - 10 73 - 11 73 - 12 73 - 13 73 - 15 73 - 16 73 - 17 73 - 18 73 - 19 74 - 1a 74 - 1b 74 - 1c 74 - 1d 74 - 1e 74 - 1f 74 - 20 73 - 22 73 - 23 76 - 24 76 - 25 72 - 26 77 - 27 77 - 28 77 - 29 77 - 2a 77 - 2d 77 - 31 77 - 32 77 - 33 77 - 34 77 - 35 77 - 38 72 - 3b 72 + 0 71 + 1 71 + 2 71 + 3 71 + 4 71 + 5 71 + 6 71 + 8 71 + 9 71 + a 71 + b 71 + c 71 + d 71 + e 71 + f 71 + 10 71 + 11 71 + 12 71 + 13 71 + 15 71 + 16 71 + 17 71 + 18 71 + 19 72 + 1a 72 + 1b 72 + 1c 72 + 1d 72 + 1e 72 + 1f 72 + 20 71 + 22 71 + 23 74 + 24 74 + 25 70 + 26 75 + 27 75 + 28 75 + 29 75 + 2a 75 + 2d 75 + 31 75 + 32 75 + 33 75 + 34 75 + 35 75 + 38 70 + 3b 70 } method 'equals (Ljava/lang/Object;)Z' { - 0 81 - 1 81 - 2 81 - 5 82 - 6 82 - 7 83 - b 83 - e 84 - f 84 - 10 86 - 11 86 - 12 86 - 13 86 - 14 86 - 15 87 - 16 87 - 17 87 - 18 87 - 19 87 - 1a 87 - 1b 87 - 1c 87 - 20 87 - 23 88 - 24 88 - 25 89 - 26 89 - 27 89 - 28 89 - 29 89 - 2a 89 - 2b 89 - 2c 89 - 2d 89 - 30 90 - 31 90 - 32 91 - 33 91 - 34 91 - 35 91 - 36 91 - 37 91 - 38 91 - 39 91 - 3d 91 - 40 92 - 41 92 - 42 94 - 43 94 - 44 94 - 45 94 - 46 94 - 47 94 - 48 94 - 49 94 - 4d 94 + 0 79 + 1 79 + 2 79 + 5 80 + 6 80 + 7 81 + b 81 + e 82 + f 82 + 10 84 + 11 84 + 12 84 + 13 84 + 14 84 + 15 85 + 16 85 + 17 85 + 18 85 + 19 85 + 1a 85 + 1b 85 + 1c 85 + 20 85 + 23 86 + 24 86 + 25 87 + 26 87 + 27 87 + 28 87 + 29 87 + 2a 87 + 2b 87 + 2c 87 + 2d 87 + 30 88 + 31 88 + 32 89 + 33 89 + 34 89 + 35 89 + 36 89 + 37 89 + 38 89 + 39 89 + 3d 89 + 40 90 + 41 90 + 42 92 + 43 92 + 44 92 + 45 92 + 46 92 + 47 92 + 48 92 + 49 92 + 4d 92 } } Lines mapping: -3 <-> 16 -4 <-> 12 -5 <-> 13 -6 <-> 14 -7 <-> 15 +3 <-> 14 +4 <-> 10 +5 <-> 11 +6 <-> 12 +7 <-> 13 diff --git a/plugins/kotlin/testData/results/pkg/TestDestructors.dec b/plugins/kotlin/testData/results/pkg/TestDestructors.dec index d94952f45d..cf9eb96cff 100644 --- a/plugins/kotlin/testData/results/pkg/TestDestructors.dec +++ b/plugins/kotlin/testData/results/pkg/TestDestructors.dec @@ -1,52 +1,51 @@ package pkg -import java.util.List import kotlin.jvm.functions.Function0 class TestDestructors { - fun destructDataClasses(x: Pair, y: Triple) { - System.out.println(x.component1() as String + " " + x.component2() as Integer);// 8 9 - System.out.println(y.component1() as Number + " " + y.component2() as Boolean + " " + y.component3() as String);// 11 12 + public fun destructDataClasses(x: Pair, y: Triple) { + System.out.println(x.component1() as java.lang.String + " " + x.component2() as Integer);// 8 9 + System.out.println(y.component1() as java.lang.Number + " " + y.component2() as java.lang.Boolean + " " + y.component3() as java.lang.String);// 11 12 }// 13 - fun destructDataClassesSpecial(x: Pair, y: Triple) { - System.out.println((x.component1() as Number).intValue() + " " + x.component2() as String);// 19 20 - var c: List = y.component1() as List;// 22 + public fun destructDataClassesSpecial(x: Pair, y: Triple, Nothing?, Unit>) { + System.out.println((x.component1() as java.lang.Number).intValue() + " " + x.component2() as java.lang.String);// 19 20 + var c: java.util.List = y.component1() as java.util.List;// 22 var d: Void = y.component2() as Void; y.component3(); System.out.println(c + " " + d + " " + Unit.INSTANCE);// 23 }// 24 - fun destructDataClassesSkip(x: Triple, y: Triple) { + public fun destructDataClassesSkip(x: Triple, y: Triple) { System.out.println(x.component2() as Integer);// 30 31 - System.out.println(y.component1() as Number + " " + y.component3() as String);// 33 34 + System.out.println(y.component1() as java.lang.Number + " " + y.component3() as java.lang.String);// 33 34 }// 35 - fun destructorImpossible(x: Pair): String { - var a: String = x.component1() as String;// 38 + public fun destructorImpossible(x: Pair): String { + var a: java.lang.String = x.component1() as java.lang.String;// 38 x.component2(); throw new KotlinNothingValueException(); } - fun destructExtensionFunction(x: Int) { + public fun destructExtensionFunction(x: Int) { System.out.println("" + this.component1(x) + this.component2(x) + this.component3(x));// 44 45 }// 46 - fun destructInlineLambda(x: () -> Int) { + public inline fun destructInlineLambda(x: () -> Int) { System.out .println( "" - + this.component1((x.invoke() as Number).intValue())// 49 50 85 - + this.component2((x.invoke() as Number).intValue())// 86 - + this.component3((x.invoke() as Number).intValue())// 87 + + this.component1((x.invoke() as java.lang.Number).intValue())// 49 50 85 + + this.component2((x.invoke() as java.lang.Number).intValue())// 86 + + this.component3((x.invoke() as java.lang.Number).intValue())// 87 ); }// 51 - fun callDestructInlineLambda() { + public fun callDestructInlineLambda() { System.out.println("" + this.component1(123) + this.component2(123) + this.component3(123));// 54 88 89 90 91 92 }// 55 - fun callDestructInlineLambdaWithControlFlow(x: Int) { + public fun callDestructInlineLambdaWithControlFlow(x: Int) { if (100 <= x && x < 1000) { var `a$iv`: Int = this.component1(x);// 95 if (100 <= x && x < 1000) {// 96 @@ -58,852 +57,852 @@ class TestDestructors { } }// 99 - fun destructInlineLambdaNoInline(x: () -> Int) { + public fun destructInlineLambdaNoInline(x: () -> Int) { System.out .println( "" - + this.component1((x.invoke() as Number).intValue())// 62 63 100 - + this.component2((x.invoke() as Number).intValue())// 101 - + this.component3((x.invoke() as Number).intValue())// 102 + + this.component1((x.invoke() as java.lang.Number).intValue())// 62 63 100 + + this.component2((x.invoke() as java.lang.Number).intValue())// 101 + + this.component3((x.invoke() as java.lang.Number).intValue())// 102 ); }// 64 - fun destructLambdaInline(x: Int) { + public fun destructLambdaInline(x: Int) { var var2: Function0 = new (x);// 67 System.out .println( "" - + this.component1((var2.invoke() as Number).intValue())// 68 103 - + this.component2((var2.invoke() as Number).intValue())// 104 - + this.component3((var2.invoke() as Number).intValue())// 105 + + this.component1((var2.invoke() as java.lang.Number).intValue())// 68 103 + + this.component2((var2.invoke() as java.lang.Number).intValue())// 104 + + this.component3((var2.invoke() as java.lang.Number).intValue())// 105 ); }// 69 - fun Int.component1(): Int { - return String.valueOf(`$this$component1`).charAt(0) - 48;// 77 + public operator fun Int.component1(): Int { + return java.lang.String.valueOf(`$this$component1`).charAt(0) - 48;// 77 } - fun Int.component2(): Int { - return String.valueOf(`$this$component2`).charAt(1) - 48;// 78 + public operator fun Int.component2(): Int { + return java.lang.String.valueOf(`$this$component2`).charAt(1) - 48;// 78 } - fun Int.component3(): Int { - return String.valueOf(`$this$component3`).charAt(2) - 48;// 79 + public operator fun Int.component3(): Int { + return java.lang.String.valueOf(`$this$component3`).charAt(2) - 48;// 79 } - fun (() -> Int).component1(): Int { - return this.component1((`$this$component1`.invoke() as Number).intValue());// 81 + public inline operator fun (() -> Int).component1(): Int { + return this.component1((`$this$component1`.invoke() as java.lang.Number).intValue());// 81 } - fun (() -> Int).component2(): Int { - return this.component2((`$this$component2`.invoke() as Number).intValue());// 82 + public inline operator fun (() -> Int).component2(): Int { + return this.component2((`$this$component2`.invoke() as java.lang.Number).intValue());// 82 } - fun (() -> Int).component3(): Int { - return this.component3((`$this$component3`.invoke() as Number).intValue());// 83 + public inline operator fun (() -> Int).component3(): Int { + return this.component3((`$this$component3`.invoke() as java.lang.Number).intValue());// 83 } } class 'pkg/TestDestructors' { method 'destructDataClasses (Lkotlin/Pair;Lkotlin/Triple;)V' { - c 7 - d 7 - e 7 - f 7 - 10 7 - 11 7 - 12 7 - 14 7 - 15 7 - 16 7 - 17 7 - 18 7 - 19 7 - 1a 7 - 1d 7 - 1e 7 - 1f 7 - 20 7 - 21 7 - 22 7 - 23 7 - 24 7 - 25 7 - 26 7 - 27 7 - 29 7 - 2a 7 - 2b 7 - 2c 8 - 2d 8 - 2e 8 - 2f 8 - 30 8 - 31 8 - 32 8 - 35 8 - 36 8 - 37 8 - 38 8 - 39 8 - 3a 8 - 3b 8 - 3e 8 - 3f 8 - 40 8 - 41 8 - 42 8 - 43 8 - 44 8 - 47 8 - 48 8 - 49 8 - 4a 8 - 4b 8 - 4c 8 - 4d 8 - 4e 8 - 4f 8 - 50 8 - 51 8 - 52 8 - 53 8 - 54 8 - 56 8 - 57 8 - 58 8 - 59 9 + c 6 + d 6 + e 6 + f 6 + 10 6 + 11 6 + 12 6 + 14 6 + 15 6 + 16 6 + 17 6 + 18 6 + 19 6 + 1a 6 + 1d 6 + 1e 6 + 1f 6 + 20 6 + 21 6 + 22 6 + 23 6 + 24 6 + 25 6 + 26 6 + 27 6 + 29 6 + 2a 6 + 2b 6 + 2c 7 + 2d 7 + 2e 7 + 2f 7 + 30 7 + 31 7 + 32 7 + 35 7 + 36 7 + 37 7 + 38 7 + 39 7 + 3a 7 + 3b 7 + 3e 7 + 3f 7 + 40 7 + 41 7 + 42 7 + 43 7 + 44 7 + 47 7 + 48 7 + 49 7 + 4a 7 + 4b 7 + 4c 7 + 4d 7 + 4e 7 + 4f 7 + 50 7 + 51 7 + 52 7 + 53 7 + 54 7 + 56 7 + 57 7 + 58 7 + 59 8 } method 'destructDataClassesSpecial (Lkotlin/Pair;Lkotlin/Triple;)V' { - c 12 - d 12 - e 12 - f 12 - 10 12 - 11 12 - 12 12 - 13 12 - 14 12 - 15 12 - 17 12 - 18 12 - 19 12 - 1a 12 - 1b 12 - 1c 12 - 1d 12 - 20 12 - 21 12 - 22 12 - 23 12 - 24 12 - 25 12 - 26 12 - 27 12 - 28 12 - 29 12 - 2a 12 - 2c 12 - 2d 12 - 2e 12 - 2f 13 - 30 13 - 31 13 - 32 13 - 33 13 - 34 13 - 35 13 - 36 13 - 37 13 - 38 14 - 39 14 - 3a 14 - 3b 14 - 3c 14 - 3d 14 - 3e 14 - 3f 14 - 40 14 - 41 15 - 42 15 - 43 15 - 44 15 - 46 16 - 47 16 - 48 16 - 4b 16 - 4c 16 - 4d 16 - 4e 16 - 4f 16 - 50 16 - 51 16 - 52 16 - 53 16 - 54 16 - 55 16 - 56 16 - 57 16 - 58 16 - 5a 16 - 5b 16 - 5c 16 - 5d 17 + c 11 + d 11 + e 11 + f 11 + 10 11 + 11 11 + 12 11 + 13 11 + 14 11 + 15 11 + 17 11 + 18 11 + 19 11 + 1a 11 + 1b 11 + 1c 11 + 1d 11 + 20 11 + 21 11 + 22 11 + 23 11 + 24 11 + 25 11 + 26 11 + 27 11 + 28 11 + 29 11 + 2a 11 + 2c 11 + 2d 11 + 2e 11 + 2f 12 + 30 12 + 31 12 + 32 12 + 33 12 + 34 12 + 35 12 + 36 12 + 37 12 + 38 13 + 39 13 + 3a 13 + 3b 13 + 3c 13 + 3d 13 + 3e 13 + 3f 13 + 40 13 + 41 14 + 42 14 + 43 14 + 44 14 + 46 15 + 47 15 + 48 15 + 4b 15 + 4c 15 + 4d 15 + 4e 15 + 4f 15 + 50 15 + 51 15 + 52 15 + 53 15 + 54 15 + 55 15 + 56 15 + 57 15 + 58 15 + 5a 15 + 5b 15 + 5c 15 + 5d 16 } method 'destructDataClassesSkip (Lkotlin/Triple;Lkotlin/Triple;)V' { - c 20 - d 20 - e 20 - f 20 - 10 20 - 11 20 - 12 20 - 14 20 - 15 20 - 16 20 - 17 20 - 18 20 - 19 20 - 1a 20 - 1b 21 - 1c 21 - 1d 21 - 1e 21 - 1f 21 - 20 21 - 21 21 - 24 21 - 25 21 - 26 21 - 27 21 - 28 21 - 29 21 - 2a 21 - 2d 21 - 2e 21 - 2f 21 - 30 21 - 31 21 - 32 21 - 33 21 - 34 21 - 35 21 - 36 21 - 37 21 - 38 21 - 3a 21 - 3b 21 - 3c 21 - 3d 22 + c 19 + d 19 + e 19 + f 19 + 10 19 + 11 19 + 12 19 + 14 19 + 15 19 + 16 19 + 17 19 + 18 19 + 19 19 + 1a 19 + 1b 20 + 1c 20 + 1d 20 + 1e 20 + 1f 20 + 20 20 + 21 20 + 24 20 + 25 20 + 26 20 + 27 20 + 28 20 + 29 20 + 2a 20 + 2d 20 + 2e 20 + 2f 20 + 30 20 + 31 20 + 32 20 + 33 20 + 34 20 + 35 20 + 36 20 + 37 20 + 38 20 + 3a 20 + 3b 20 + 3c 20 + 3d 21 } method 'destructorImpossible (Lkotlin/Pair;)Ljava/lang/String;' { - 6 25 - 7 25 - 8 25 - 9 25 - a 25 - b 25 - c 25 - d 25 - e 26 - f 26 - 10 26 - 11 26 - 1a 27 + 6 24 + 7 24 + 8 24 + 9 24 + a 24 + b 24 + c 24 + d 24 + e 25 + f 25 + 10 25 + 11 25 + 1a 26 } method 'destructExtensionFunction (I)V' { - 0 31 - 1 31 - 2 31 - 3 31 - 4 31 - 6 31 - 7 31 - 8 31 - 9 31 - a 31 - c 31 - d 31 - e 31 - f 31 - 10 31 - 13 31 - 14 31 - 15 31 - 16 31 - 17 31 - 18 31 - 19 31 - 1a 31 - 1b 31 - 1c 31 - 1d 31 - 1e 31 - 20 31 - 21 31 - 22 31 - 23 32 + 0 30 + 1 30 + 2 30 + 3 30 + 4 30 + 6 30 + 7 30 + 8 30 + 9 30 + a 30 + c 30 + d 30 + e 30 + f 30 + 10 30 + 13 30 + 14 30 + 15 30 + 16 30 + 17 30 + 18 30 + 19 30 + 1a 30 + 1b 30 + 1c 30 + 1d 30 + 1e 30 + 20 30 + 21 30 + 22 30 + 23 31 } method 'destructInlineLambda (Lkotlin/jvm/functions/Function0;)V' { - 8 38 - b 38 - 11 38 - 12 38 - 13 38 - 14 38 - 15 38 - 16 38 - 17 38 - 18 38 - 19 38 - 1a 38 - 1b 38 - 1c 38 - 1d 38 - 1e 38 - 1f 38 - 20 38 - 21 38 - 22 38 - 24 39 - 27 39 - 2d 39 - 2e 39 - 2f 39 - 30 39 - 31 39 - 32 39 - 33 39 - 34 39 - 35 39 - 36 39 - 37 39 - 38 39 - 39 39 - 3a 39 - 3b 39 - 3c 39 - 3d 39 - 3e 39 - 41 40 - 44 40 - 4a 40 - 4b 40 - 4c 40 - 4d 40 - 4e 40 - 4f 40 - 50 40 - 51 40 - 52 40 - 53 40 - 54 40 - 55 40 - 56 40 - 57 40 - 58 40 - 59 40 - 5a 40 - 5b 40 - 5e 38 - 5f 39 - 60 39 - 61 40 - 62 40 - 63 37 - 64 37 - 65 37 - 66 37 - 67 37 - 68 35 - 69 35 - 6a 35 - 6c 36 - 6d 36 - 6e 36 - 6f 42 + 8 37 + b 37 + 11 37 + 12 37 + 13 37 + 14 37 + 15 37 + 16 37 + 17 37 + 18 37 + 19 37 + 1a 37 + 1b 37 + 1c 37 + 1d 37 + 1e 37 + 1f 37 + 20 37 + 21 37 + 22 37 + 24 38 + 27 38 + 2d 38 + 2e 38 + 2f 38 + 30 38 + 31 38 + 32 38 + 33 38 + 34 38 + 35 38 + 36 38 + 37 38 + 38 38 + 39 38 + 3a 38 + 3b 38 + 3c 38 + 3d 38 + 3e 38 + 41 39 + 44 39 + 4a 39 + 4b 39 + 4c 39 + 4d 39 + 4e 39 + 4f 39 + 50 39 + 51 39 + 52 39 + 53 39 + 54 39 + 55 39 + 56 39 + 57 39 + 58 39 + 59 39 + 5a 39 + 5b 39 + 5e 37 + 5f 38 + 60 38 + 61 39 + 62 39 + 63 36 + 64 36 + 65 36 + 66 36 + 67 36 + 68 34 + 69 34 + 6a 34 + 6c 35 + 6d 35 + 6e 35 + 6f 41 } method 'callDestructInlineLambda ()V' { - 0 45 - 4 45 - 9 45 - f 45 - 10 45 - 13 45 - 14 45 - 15 45 - 16 45 - 17 45 - 18 45 - 19 45 - 1c 45 - 22 45 - 23 45 - 29 45 - 2a 45 - 2d 45 - 2e 45 - 2f 45 - 30 45 - 31 45 - 32 45 - 33 45 - 35 45 - 3b 45 - 3c 45 - 42 45 - 43 45 - 46 45 - 47 45 - 48 45 - 49 45 - 4a 45 - 4b 45 - 4c 45 - 4f 45 - 50 45 - 51 45 - 52 45 - 53 45 - 54 45 - 55 45 - 56 45 - 57 45 - 58 45 - 59 45 - 5a 45 - 5b 45 - 5d 45 - 5e 45 - 5f 45 - 61 46 + 0 44 + 4 44 + 9 44 + f 44 + 10 44 + 13 44 + 14 44 + 15 44 + 16 44 + 17 44 + 18 44 + 19 44 + 1c 44 + 22 44 + 23 44 + 29 44 + 2a 44 + 2d 44 + 2e 44 + 2f 44 + 30 44 + 31 44 + 32 44 + 33 44 + 35 44 + 3b 44 + 3c 44 + 42 44 + 43 44 + 46 44 + 47 44 + 48 44 + 49 44 + 4a 44 + 4b 44 + 4c 44 + 4f 44 + 50 44 + 51 44 + 52 44 + 53 44 + 54 44 + 55 44 + 56 44 + 57 44 + 58 44 + 59 44 + 5a 44 + 5b 44 + 5d 44 + 5e 44 + 5f 44 + 61 45 } method 'callDestructInlineLambdaWithControlFlow (I)V' { - 0 50 - 4 50 - a 50 - b 50 - 11 49 - 12 49 - 13 49 - 14 49 - 17 49 - 18 49 - 19 49 - 1a 49 - 1b 49 - 27 49 - 2a 50 - 2e 58 - 2f 50 - 30 50 - 31 50 - 32 50 - 33 50 - 34 50 - 35 50 - 36 50 - 37 50 - 38 52 - 39 52 - 3e 52 - 3f 52 - 45 51 - 46 51 - 47 51 - 48 51 - 49 51 - 4d 51 - 4e 51 - 4f 51 - 50 51 - 51 51 - 5d 51 - 60 52 - 64 58 - 65 52 - 66 52 - 67 52 - 68 52 - 69 52 - 6a 52 - 6b 52 - 6c 52 - 6d 52 - 6e 54 - 6f 54 - 74 54 - 75 54 - 7b 53 - 7c 53 - 7d 53 - 7e 53 - 7f 53 - 83 53 - 84 53 - 85 53 - 86 53 - 87 53 - 93 53 - 96 54 - 9a 58 - 9b 54 - 9c 54 - 9d 54 - 9e 54 - 9f 54 - a0 54 - a4 54 - a5 54 - a6 54 - a7 54 - a8 54 - a9 54 - aa 54 - ab 54 - ac 54 - ad 54 - ae 54 - af 54 - b0 54 - b4 54 - b8 58 + 0 49 + 4 49 + a 49 + b 49 + 11 48 + 12 48 + 13 48 + 14 48 + 17 48 + 18 48 + 19 48 + 1a 48 + 1b 48 + 27 48 + 2a 49 + 2e 57 + 2f 49 + 30 49 + 31 49 + 32 49 + 33 49 + 34 49 + 35 49 + 36 49 + 37 49 + 38 51 + 39 51 + 3e 51 + 3f 51 + 45 50 + 46 50 + 47 50 + 48 50 + 49 50 + 4d 50 + 4e 50 + 4f 50 + 50 50 + 51 50 + 5d 50 + 60 51 + 64 57 + 65 51 + 66 51 + 67 51 + 68 51 + 69 51 + 6a 51 + 6b 51 + 6c 51 + 6d 51 + 6e 53 + 6f 53 + 74 53 + 75 53 + 7b 52 + 7c 52 + 7d 52 + 7e 52 + 7f 52 + 83 52 + 84 52 + 85 52 + 86 52 + 87 52 + 93 52 + 96 53 + 9a 57 + 9b 53 + 9c 53 + 9d 53 + 9e 53 + 9f 53 + a0 53 + a4 53 + a5 53 + a6 53 + a7 53 + a8 53 + a9 53 + aa 53 + ab 53 + ac 53 + ad 53 + ae 53 + af 53 + b0 53 + b4 53 + b8 57 } method 'destructInlineLambdaNoInline (Lkotlin/jvm/functions/Function0;)V' { - 6 64 - 8 64 - e 64 - f 64 - 10 64 - 11 64 - 12 64 - 13 64 - 14 64 - 15 64 - 16 64 - 17 64 - 18 64 - 19 64 - 1a 64 - 1b 64 - 1c 64 - 1d 64 - 1e 64 - 20 65 - 23 65 - 29 65 - 2a 65 - 2b 65 - 2c 65 - 2d 65 - 2e 65 - 2f 65 - 30 65 - 31 65 - 32 65 - 33 65 - 34 65 - 35 65 - 36 65 - 37 65 - 38 65 - 39 65 - 3a 65 - 3c 66 - 3f 66 - 45 66 - 46 66 - 47 66 - 48 66 - 49 66 - 4a 66 - 4b 66 - 4c 66 - 4d 66 - 4e 66 - 4f 66 - 50 66 - 51 66 - 52 66 - 53 66 - 54 66 - 55 66 - 56 66 - 59 64 - 5a 65 - 5b 66 - 5c 66 - 5d 63 - 5e 63 - 5f 63 - 60 63 - 61 63 - 62 61 - 63 61 - 64 61 - 66 62 - 67 62 - 68 62 - 69 68 + 6 63 + 8 63 + e 63 + f 63 + 10 63 + 11 63 + 12 63 + 13 63 + 14 63 + 15 63 + 16 63 + 17 63 + 18 63 + 19 63 + 1a 63 + 1b 63 + 1c 63 + 1d 63 + 1e 63 + 20 64 + 23 64 + 29 64 + 2a 64 + 2b 64 + 2c 64 + 2d 64 + 2e 64 + 2f 64 + 30 64 + 31 64 + 32 64 + 33 64 + 34 64 + 35 64 + 36 64 + 37 64 + 38 64 + 39 64 + 3a 64 + 3c 65 + 3f 65 + 45 65 + 46 65 + 47 65 + 48 65 + 49 65 + 4a 65 + 4b 65 + 4c 65 + 4d 65 + 4e 65 + 4f 65 + 50 65 + 51 65 + 52 65 + 53 65 + 54 65 + 55 65 + 56 65 + 59 63 + 5a 64 + 5b 65 + 5c 65 + 5d 62 + 5e 62 + 5f 62 + 60 62 + 61 62 + 62 60 + 63 60 + 64 60 + 66 61 + 67 61 + 68 61 + 69 67 } method 'destructLambdaInline (I)V' { - 4 71 - 8 71 - 9 71 - a 71 - b 71 - c 75 - f 75 - 15 75 - 16 75 - 17 75 - 18 75 - 19 75 - 1a 75 - 1b 75 - 1c 75 - 1d 75 - 1e 75 - 1f 75 - 20 75 - 21 75 - 22 75 - 23 75 - 24 75 - 25 75 - 26 75 - 28 76 - 2b 76 - 31 76 - 32 76 - 33 76 - 34 76 - 35 76 - 36 76 - 37 76 - 38 76 - 39 76 - 3a 76 - 3b 76 - 3c 76 - 3d 76 - 3e 76 - 3f 76 - 40 76 - 41 76 - 42 76 - 45 77 - 48 77 - 4e 77 - 4f 77 - 50 77 - 51 77 - 52 77 - 53 77 - 54 77 - 55 77 - 56 77 - 57 77 - 58 77 - 59 77 - 5a 77 - 5b 77 - 5c 77 - 5d 77 - 5e 77 - 5f 77 - 62 75 - 63 76 - 64 76 - 65 77 - 66 77 - 67 74 - 68 74 - 69 74 - 6a 74 - 6b 74 - 6c 72 - 6d 72 - 6e 72 - 70 73 - 71 73 - 72 73 - 73 79 + 4 70 + 8 70 + 9 70 + a 70 + b 70 + c 74 + f 74 + 15 74 + 16 74 + 17 74 + 18 74 + 19 74 + 1a 74 + 1b 74 + 1c 74 + 1d 74 + 1e 74 + 1f 74 + 20 74 + 21 74 + 22 74 + 23 74 + 24 74 + 25 74 + 26 74 + 28 75 + 2b 75 + 31 75 + 32 75 + 33 75 + 34 75 + 35 75 + 36 75 + 37 75 + 38 75 + 39 75 + 3a 75 + 3b 75 + 3c 75 + 3d 75 + 3e 75 + 3f 75 + 40 75 + 41 75 + 42 75 + 45 76 + 48 76 + 4e 76 + 4f 76 + 50 76 + 51 76 + 52 76 + 53 76 + 54 76 + 55 76 + 56 76 + 57 76 + 58 76 + 59 76 + 5a 76 + 5b 76 + 5c 76 + 5d 76 + 5e 76 + 5f 76 + 62 74 + 63 75 + 64 75 + 65 76 + 66 76 + 67 73 + 68 73 + 69 73 + 6a 73 + 6b 73 + 6c 71 + 6d 71 + 6e 71 + 70 72 + 71 72 + 72 72 + 73 78 } method 'component1 (I)I' { - 0 82 - 1 82 - 2 82 - 3 82 - 4 82 - 5 82 - 6 82 - 7 82 - 8 82 - 9 82 - a 82 - b 82 + 0 81 + 1 81 + 2 81 + 3 81 + 4 81 + 5 81 + 6 81 + 7 81 + 8 81 + 9 81 + a 81 + b 81 } method 'component2 (I)I' { - 0 86 - 1 86 - 2 86 - 3 86 - 4 86 - 5 86 - 6 86 - 7 86 - 8 86 - 9 86 - a 86 - b 86 + 0 85 + 1 85 + 2 85 + 3 85 + 4 85 + 5 85 + 6 85 + 7 85 + 8 85 + 9 85 + a 85 + b 85 } method 'component3 (I)I' { - 0 90 - 1 90 - 2 90 - 3 90 - 4 90 - 5 90 - 6 90 - 7 90 - 8 90 - 9 90 - a 90 - b 90 + 0 89 + 1 89 + 2 89 + 3 89 + 4 89 + 5 89 + 6 89 + 7 89 + 8 89 + 9 89 + a 89 + b 89 } method 'component1 (Lkotlin/jvm/functions/Function0;)I' { - 8 94 - 9 94 - a 94 - b 94 - c 94 - d 94 - e 94 - f 94 - 10 94 - 11 94 - 12 94 - 13 94 - 14 94 - 15 94 - 16 94 - 17 94 - 18 94 + 8 93 + 9 93 + a 93 + b 93 + c 93 + d 93 + e 93 + f 93 + 10 93 + 11 93 + 12 93 + 13 93 + 14 93 + 15 93 + 16 93 + 17 93 + 18 93 } method 'component2 (Lkotlin/jvm/functions/Function0;)I' { - 8 98 - 9 98 - a 98 - b 98 - c 98 - d 98 - e 98 - f 98 - 10 98 - 11 98 - 12 98 - 13 98 - 14 98 - 15 98 - 16 98 - 17 98 - 18 98 + 8 97 + 9 97 + a 97 + b 97 + c 97 + d 97 + e 97 + f 97 + 10 97 + 11 97 + 12 97 + 13 97 + 14 97 + 15 97 + 16 97 + 17 97 + 18 97 } method 'component3 (Lkotlin/jvm/functions/Function0;)I' { - 8 102 - 9 102 - a 102 - b 102 - c 102 - d 102 - e 102 - f 102 - 10 102 - 11 102 - 12 102 - 13 102 - 14 102 - 15 102 - 16 102 - 17 102 - 18 102 + 8 101 + 9 101 + a 101 + b 101 + c 101 + d 101 + e 101 + f 101 + 10 101 + 11 101 + 12 101 + 13 101 + 14 101 + 15 101 + 16 101 + 17 101 + 18 101 } } Lines mapping: -8 <-> 8 -9 <-> 8 -11 <-> 9 -12 <-> 9 -13 <-> 10 -19 <-> 13 -20 <-> 13 -22 <-> 14 -23 <-> 17 -24 <-> 18 -30 <-> 21 -31 <-> 21 -33 <-> 22 -34 <-> 22 -35 <-> 23 -38 <-> 26 -44 <-> 32 -45 <-> 32 -46 <-> 33 -49 <-> 39 -50 <-> 39 -51 <-> 43 -54 <-> 46 -55 <-> 47 -58 <-> 54 -62 <-> 65 -63 <-> 65 -64 <-> 69 -67 <-> 72 -68 <-> 76 -69 <-> 80 -77 <-> 83 -78 <-> 87 -79 <-> 91 -81 <-> 95 -82 <-> 99 -83 <-> 103 -85 <-> 39 -86 <-> 40 -87 <-> 41 -88 <-> 46 -89 <-> 46 -90 <-> 46 -91 <-> 46 -92 <-> 46 -94 <-> 55 -95 <-> 51 -96 <-> 52 -97 <-> 54 -98 <-> 55 -99 <-> 59 -100 <-> 65 -101 <-> 66 -102 <-> 67 -103 <-> 76 -104 <-> 77 -105 <-> 78 +8 <-> 7 +9 <-> 7 +11 <-> 8 +12 <-> 8 +13 <-> 9 +19 <-> 12 +20 <-> 12 +22 <-> 13 +23 <-> 16 +24 <-> 17 +30 <-> 20 +31 <-> 20 +33 <-> 21 +34 <-> 21 +35 <-> 22 +38 <-> 25 +44 <-> 31 +45 <-> 31 +46 <-> 32 +49 <-> 38 +50 <-> 38 +51 <-> 42 +54 <-> 45 +55 <-> 46 +58 <-> 53 +62 <-> 64 +63 <-> 64 +64 <-> 68 +67 <-> 71 +68 <-> 75 +69 <-> 79 +77 <-> 82 +78 <-> 86 +79 <-> 90 +81 <-> 94 +82 <-> 98 +83 <-> 102 +85 <-> 38 +86 <-> 39 +87 <-> 40 +88 <-> 45 +89 <-> 45 +90 <-> 45 +91 <-> 45 +92 <-> 45 +94 <-> 54 +95 <-> 50 +96 <-> 51 +97 <-> 53 +98 <-> 54 +99 <-> 58 +100 <-> 64 +101 <-> 65 +102 <-> 66 +103 <-> 75 +104 <-> 76 +105 <-> 77 Not mapped: 59 93 diff --git a/plugins/kotlin/testData/results/pkg/TestExtensionFun.dec b/plugins/kotlin/testData/results/pkg/TestExtensionFun.dec index 2ca0acb77f..1439805c84 100644 --- a/plugins/kotlin/testData/results/pkg/TestExtensionFun.dec +++ b/plugins/kotlin/testData/results/pkg/TestExtensionFun.dec @@ -1,12 +1,12 @@ package pkg class TestExtensionFun { - fun CharSequence.repeat2(n: Int): String { + public fun CharSequence.repeat2(n: Int): String { return StringsKt.repeat(`$this$repeat2`, n);// 5 } - fun test() { - System.out.println(this.repeat2("Bye " as CharSequence, 2));// 9 + public fun test() { + System.out.println(this.repeat2("Bye " as java.lang.CharSequence, 2));// 9 }// 10 } diff --git a/plugins/kotlin/testData/results/pkg/TestForRange.dec b/plugins/kotlin/testData/results/pkg/TestForRange.dec index fcf3892904..c09d5857d9 100644 --- a/plugins/kotlin/testData/results/pkg/TestForRange.dec +++ b/plugins/kotlin/testData/results/pkg/TestForRange.dec @@ -3,19 +3,19 @@ package pkg import kotlin.internal.ProgressionUtilKt class TestForRange { - fun testInt() { + public fun testInt() { for (int i = 1; i < 11; i++) {// 5 System.out.println(i);// 6 } }// 8 - fun testChar() { + public fun testChar() { for (char c = 'a'; c < '{'; c++) {// 11 System.out.println(c);// 12 } }// 14 - fun testIntStep() { + public fun testIntStep() { var i: Int = 1; var var2: Int = ProgressionUtilKt.getProgressionLastElement(1, 10, 2); if (1 <= var2) { @@ -30,7 +30,7 @@ class TestForRange { } }// 20 - fun testIntStepX(x: Int) { + public fun testIntStepX(x: Int) { if (x <= 0) { throw new IllegalArgumentException("Step must be positive, was: " + x + "."); } else { @@ -49,13 +49,13 @@ class TestForRange { } }// 26 - fun testIntDownTo() { + public fun testIntDownTo() { for (int i = 10; 0 < i; i--) {// 29 System.out.println(i);// 30 } }// 32 - fun testIntDownToStep() { + public fun testIntDownToStep() { var i: Int = 10; var var2: Int = ProgressionUtilKt.getProgressionLastElement(10, 1, -2); if (var2 <= 10) { @@ -70,7 +70,7 @@ class TestForRange { } }// 38 - fun testIntDownToStepX(x: Int) { + public fun testIntDownToStepX(x: Int) { if (x <= 0) { throw new IllegalArgumentException("Step must be positive, was: " + x + "."); } else { @@ -90,13 +90,13 @@ class TestForRange { } }// 44 - fun testUntil() { + public fun testUntil() { for (int i = 1; i < 10; i++) {// 47 System.out.println(i);// 48 } }// 50 - fun testUntilStep() { + public fun testUntilStep() { var var1: IntProgression = RangesKt.step(RangesKt.until(1, 100) as IntProgression, 2); var i: Int = var1.getFirst(); var var3: Int = var1.getLast(); @@ -113,7 +113,7 @@ class TestForRange { } }// 56 - fun testUntilStepX(x: Int) { + public fun testUntilStepX(x: Int) { var var2: IntProgression = RangesKt.step(RangesKt.until(1, 100) as IntProgression, x); var i: Int = var2.getFirst(); var var4: Int = var2.getLast(); @@ -130,7 +130,7 @@ class TestForRange { } }// 62 - fun testIntY(x: Int, y: Int) { + public fun testIntY(x: Int, y: Int) { var i: Int = x; if (x <= y) { while (true) { @@ -144,7 +144,7 @@ class TestForRange { } }// 68 - fun testIntYStep(x: Int, y: Int) { + public fun testIntYStep(x: Int, y: Int) { var i: Int = x; var var4: Int = ProgressionUtilKt.getProgressionLastElement(x, y, 2); if (x <= var4) { @@ -159,7 +159,7 @@ class TestForRange { } }// 74 - fun testIntYStepX(x: Int, y: Int, z: Int) { + public fun testIntYStepX(x: Int, y: Int, z: Int) { if (z <= 0) { throw new IllegalArgumentException("Step must be positive, was: " + z + "."); } else { diff --git a/plugins/kotlin/testData/results/pkg/TestFunVarargs.dec b/plugins/kotlin/testData/results/pkg/TestFunVarargs.dec index 447babc1eb..84b88115fd 100644 --- a/plugins/kotlin/testData/results/pkg/TestFunVarargs.dec +++ b/plugins/kotlin/testData/results/pkg/TestFunVarargs.dec @@ -3,28 +3,28 @@ package pkg import java.util.Arrays class TestFunVarargs { - fun printAll(vararg messages: String) { - for (String m : messages) {// 5 + public fun printAll(vararg messages: String) { + for (java.lang.String m : messages) {// 5 System.out.println(m); } }// 6 - fun printAllArray(messages: Array) { - for (String m : messages) {// 9 + public fun printAllArray(messages: Array) { + for (java.lang.String m : messages) {// 9 System.out.println(m); } }// 10 - fun log(vararg entries: String) { - this.printAll(Arrays.copyOf(entries, entries.length) as String[]);// 13 + public fun log(vararg entries: String) { + this.printAll(Arrays.copyOf(entries, entries.length) as java.lang.String[]);// 13 this.printAllArray(entries);// 14 }// 15 - fun test() { + public fun test() { this.log("a", "b", "c");// 18 }// 19 - fun nestedArrays(e0: Array, e1: Array, e2: Array>>) { + public fun nestedArrays(e0: Array, e1: Array, e2: Array>>) { }// 23 } diff --git a/plugins/kotlin/testData/results/pkg/TestFuncRef.dec b/plugins/kotlin/testData/results/pkg/TestFuncRef.dec index bff6216931..b9060c2077 100644 --- a/plugins/kotlin/testData/results/pkg/TestFuncRef.dec +++ b/plugins/kotlin/testData/results/pkg/TestFuncRef.dec @@ -1,14 +1,14 @@ package pkg -fun accept(f: (Int?) -> String) { +public fun accept(f: (Int) -> String) { System.out.println(f.invoke(5)); }// 3 -fun function(r: Int): String { - return StringsKt.repeat("OK" as CharSequence, r);// 6 +public fun function(r: Int): String { + return StringsKt.repeat("OK" as java.lang.CharSequence, r);// 6 } -fun test() { +public fun test() { accept(.INSTANCE);// 10 }// 11 diff --git a/plugins/kotlin/testData/results/pkg/TestGenerics.dec b/plugins/kotlin/testData/results/pkg/TestGenerics.dec index 4b619f6881..7a8687b667 100644 --- a/plugins/kotlin/testData/results/pkg/TestGenerics.dec +++ b/plugins/kotlin/testData/results/pkg/TestGenerics.dec @@ -1,21 +1,21 @@ package pkg class TestGenerics { - fun genericFun(v: T): T { + public fun genericFun(v: T): T { return (T)v;// 5 } - fun nullableGeneric(v: T): T? { + public fun nullableGeneric(v: T): T? { return null;// 9 } - fun subType(v: TestGenerics) { + public fun subType(v: TestGenerics) { }// 13 - fun superType(v: TestGenerics) { + public fun superType(v: TestGenerics) { }// 16 - fun any(v: TestGenerics) { + public fun any(v: TestGenerics<*>) { }// 19 } diff --git a/plugins/kotlin/testData/results/pkg/TestIfRange.dec b/plugins/kotlin/testData/results/pkg/TestIfRange.dec index fca0b8da14..b1b89609e5 100644 --- a/plugins/kotlin/testData/results/pkg/TestIfRange.dec +++ b/plugins/kotlin/testData/results/pkg/TestIfRange.dec @@ -1,73 +1,73 @@ package pkg class TestIfRange { - fun testInt(x: Int) { + public fun testInt(x: Int) { if (1 <= x && x < 11) {// 5 System.out.println(x);// 6 } }// 8 - fun testChar(x: Char) { + public fun testChar(x: Char) { if ('a' <= x && x < '{') {// 11 System.out.println(x);// 12 } }// 14 - fun testInvertedInt(x: Int) { + public fun testInvertedInt(x: Int) { if (1 > x || x >= 11) {// 17 System.out.println(x);// 18 } }// 20 - fun testIntStep(x: Int) { - if (CollectionsKt.contains(RangesKt.step((new IntRange(1, 100)) as IntProgression, 2) as Iterable, x)) {// 23 + public fun testIntStep(x: Int) { + if (CollectionsKt.contains(RangesKt.step((new IntRange(1, 100)) as IntProgression, 2) as java.lang.Iterable, x)) {// 23 System.out.println(x);// 24 } }// 26 - fun testIntStepY(x: Int, y: Int) { - if (CollectionsKt.contains(RangesKt.step((new IntRange(1, 100)) as IntProgression, y) as Iterable, x)) {// 28 + public fun testIntStepY(x: Int, y: Int) { + if (CollectionsKt.contains(RangesKt.step((new IntRange(1, 100)) as IntProgression, y) as java.lang.Iterable, x)) {// 28 System.out.println(x);// 29 } }// 31 - fun testIntY(x: Int, y: Int) { + public fun testIntY(x: Int, y: Int) { if (1 <= x && x <= y) {// 34 System.out.println(x);// 35 } }// 37 - fun testIntDownTo(x: Int) { - if (CollectionsKt.contains(RangesKt.downTo(10, 1) as Iterable, x)) {// 40 + public fun testIntDownTo(x: Int) { + if (CollectionsKt.contains(RangesKt.downTo(10, 1) as java.lang.Iterable, x)) {// 40 System.out.println(x);// 41 } }// 43 - fun testIntDownToStep(x: Int) { - if (CollectionsKt.contains(RangesKt.step(RangesKt.downTo(10, 1), 2) as Iterable, x)) {// 46 + public fun testIntDownToStep(x: Int) { + if (CollectionsKt.contains(RangesKt.step(RangesKt.downTo(10, 1), 2) as java.lang.Iterable, x)) {// 46 System.out.println(x);// 47 } }// 49 - fun testIntUntil(x: Int) { + public fun testIntUntil(x: Int) { if (1 <= x && x < 10) {// 52 System.out.println(x);// 53 } }// 55 - fun testIntUntilStep(x: Int) { - if (CollectionsKt.contains(RangesKt.step(RangesKt.until(1, 100) as IntProgression, 2) as Iterable, x)) {// 58 + public fun testIntUntilStep(x: Int) { + if (CollectionsKt.contains(RangesKt.step(RangesKt.until(1, 100) as IntProgression, 2) as java.lang.Iterable, x)) {// 58 System.out.println(x);// 59 } }// 61 - fun testIntUntilY(x: Int, y: Int) { + public fun testIntUntilY(x: Int, y: Int) { if (1 <= x && x < y) {// 64 System.out.println(x);// 65 } }// 67 - fun testIntUntilSelf(x: Int) { + public fun testIntUntilSelf(x: Int) { if (1 <= x && x < x) {// 70 System.out.println(x);// 71 } diff --git a/plugins/kotlin/testData/results/pkg/TestInfixFun.dec b/plugins/kotlin/testData/results/pkg/TestInfixFun.dec index 2a3841903c..abfe471ee7 100644 --- a/plugins/kotlin/testData/results/pkg/TestInfixFun.dec +++ b/plugins/kotlin/testData/results/pkg/TestInfixFun.dec @@ -1,30 +1,30 @@ package pkg class TestInfixFun { - fun test() { + public fun test() { System.out.println(test$times(2, "Bye "));// 7 }// 8 - fun Int.mult(str: String): String { - return StringsKt.repeat(str as CharSequence, `$this$mult`);// 10 + public infix fun Int.mult(str: String): String { + return StringsKt.repeat(str as java.lang.CharSequence, `$this$mult`);// 10 } - fun testOuter() { + public fun testOuter() { System.out.println(this.mult(2, "Bye "));// 14 }// 15 - fun testDuplicate() { + public fun testDuplicate() { System.out.println(testDuplicate$mult(2, "Bye "));// 20 }// 21 @JvmStatic - fun Int.`test$times`(str: String): String { - return StringsKt.repeat(str as CharSequence, `$this$test_u24times`);// 5 + fun Int.`test$times`(str: java.lang.String): java.lang.String { + return StringsKt.repeat(str as java.lang.CharSequence, `$this$test_u24times`);// 5 } @JvmStatic - fun Int.`testDuplicate$mult`(str: String): String { - return StringsKt.repeat(str as CharSequence, `$this$testDuplicate_u24mult` + 1);// 18 + fun Int.`testDuplicate$mult`(str: java.lang.String): java.lang.String { + return StringsKt.repeat(str as java.lang.CharSequence, `$this$testDuplicate_u24mult` + 1);// 18 } } diff --git a/plugins/kotlin/testData/results/pkg/TestKotlinTypes.dec b/plugins/kotlin/testData/results/pkg/TestKotlinTypes.dec index 6c8c0d080c..4f22fe26c0 100644 --- a/plugins/kotlin/testData/results/pkg/TestKotlinTypes.dec +++ b/plugins/kotlin/testData/results/pkg/TestKotlinTypes.dec @@ -5,16 +5,17 @@ import kotlin.jvm.functions.Function1 class TestKotlinTypes { public final val consumer: (Int) -> Unit = .INSTANCE as Function1 - fun throwAlways(): Void { + + public fun throwAlways(): Nothing { throw new Exception();// 5 } } class 'pkg/TestKotlinTypes' { method 'throwAlways ()Ljava/lang/Void;' { - 7 8 + 7 9 } } Lines mapping: -5 <-> 9 +5 <-> 10 diff --git a/plugins/kotlin/testData/results/pkg/TestKt.dec b/plugins/kotlin/testData/results/pkg/TestKt.dec index 4004cf8360..df4e6f6630 100644 --- a/plugins/kotlin/testData/results/pkg/TestKt.dec +++ b/plugins/kotlin/testData/results/pkg/TestKt.dec @@ -1,7 +1,7 @@ package pkg class TestKt { - fun test() { + public fun test() { System.out.println("Hello, world!");// 5 }// 6 } diff --git a/plugins/kotlin/testData/results/pkg/TestLabeledJumps.dec b/plugins/kotlin/testData/results/pkg/TestLabeledJumps.dec index 21a61d4bc9..b6d221b59c 100644 --- a/plugins/kotlin/testData/results/pkg/TestLabeledJumps.dec +++ b/plugins/kotlin/testData/results/pkg/TestLabeledJumps.dec @@ -1,11 +1,11 @@ package pkg class TestLabeledJumps { - fun testContinue(tester: (Int?) -> Boolean) { + public fun testContinue(tester: (Int) -> Boolean) { label24: for (int i = 1; i < 101; i++) {// 5 for (int j = 1; j < 101; j++) {// 6 - if (tester.invoke(j) as Boolean) {// 7 + if (tester.invoke(j) as java.lang.Boolean) {// 7 continue label24; } @@ -16,11 +16,11 @@ class TestLabeledJumps { } }// 16 - fun testBreak(tester: (Int?) -> Boolean) { + public fun testBreak(tester: (Int) -> Boolean) { label22: for (int i = 1; i < 101; i++) {// 19 for (int j = 1; j < 101; j++) {// 20 - if (tester.invoke(j) as Boolean) {// 21 + if (tester.invoke(j) as java.lang.Boolean) {// 21 break label22; } diff --git a/plugins/kotlin/testData/results/pkg/TestNonInlineLambda.dec b/plugins/kotlin/testData/results/pkg/TestNonInlineLambda.dec index 3ffbe26cda..2cb91f1ab6 100644 --- a/plugins/kotlin/testData/results/pkg/TestNonInlineLambda.dec +++ b/plugins/kotlin/testData/results/pkg/TestNonInlineLambda.dec @@ -12,29 +12,30 @@ open class TestNonInlineLambda { public final var stringField: String = "" internal set - fun testCaptureInt(x: Int) { + + public fun testCaptureInt(x: Int) { this.execute(new (x));// 7 8 }// 11 - fun testCaptureObject(x: String) { + public fun testCaptureObject(x: String) { this.execute(new (x));// 14 15 }// 18 - fun testCaptureIntIterationValue(x: Iterable) { + public fun testCaptureIntIterationValue(x: Iterable) { var var2: Iterator = x.iterator();// 21 while (var2.hasNext()) { - this.execute(new ((var2.next() as Number).intValue()));// 22 + this.execute(new ((var2.next() as java.lang.Number).intValue()));// 22 } }// 26 - fun testCaptureObjectIterationValue(x: Iterable) { - for (String i : x) {// 29 + public fun testCaptureObjectIterationValue(x: Iterable) { + for (java.lang.String i : x) {// 29 this.execute(new (i));// 30 } }// 34 - fun testCaptureMutableInt(x: Int) { + public fun testCaptureMutableInt(x: Int) { var y: IntRef = new IntRef();// 37 y.element = x; this.execute(new (y));// 38 @@ -48,7 +49,7 @@ open class TestNonInlineLambda { this.execute(new (y));// 54 }// 57 - fun testCaptureMutableObject(x: String) { + public fun testCaptureMutableObject(x: String) { var y: ObjectRef = new ObjectRef();// 60 y.element = x; this.execute(new (y));// 61 @@ -62,14 +63,14 @@ open class TestNonInlineLambda { this.execute(new (y));// 77 }// 80 - fun testCaptureAndMutateInt(x: Int) { + public fun testCaptureAndMutateInt(x: Int) { var y: IntRef = new IntRef();// 83 this.execute(new (y));// 84 y.element = 5 + x;// 89 this.execute(new (y));// 90 }// 95 - fun testCaptureAndMutateString(x: String) { + public fun testCaptureAndMutateString(x: String) { var y: ObjectRef = new ObjectRef();// 98 y.element = ""; this.execute(new (y));// 99 @@ -77,23 +78,23 @@ open class TestNonInlineLambda { this.execute(new (y));// 106 }// 112 - fun testCapturePublicMutableIntField() { + public fun testCapturePublicMutableIntField() { this.execute(new (this));// 117 }// 118 - fun testCapturePublicMutableStringField() { + public fun testCapturePublicMutableStringField() { this.execute(new (this));// 123 }// 124 - fun testCapturePrivateMutableIntField() { + public fun testCapturePrivateMutableIntField() { this.execute(new (this));// 129 }// 130 - fun testCapturePrivateMutableStringField() { + public fun testCapturePrivateMutableStringField() { this.execute(new (this));// 135 }// 136 - open fun execute(block: () -> Unit) { + public open fun execute(block: () -> Unit) { }// 141 @JvmStatic @@ -110,492 +111,492 @@ open class TestNonInlineLambda { @JvmStatic @JvmSynthetic - fun `access$setPrivateStringField$p`(`$this`: TestNonInlineLambda, var1: String) { + fun `access$setPrivateStringField$p`(`$this`: TestNonInlineLambda, var1: java.lang.String) { `$this`.privateStringField = var1; } @JvmStatic @JvmSynthetic - fun `access$getPrivateStringField$p`(`$this`: TestNonInlineLambda): String { + fun `access$getPrivateStringField$p`(`$this`: TestNonInlineLambda): java.lang.String { return `$this`.privateStringField;// 3 } } class 'pkg/TestNonInlineLambda' { method 'testCaptureInt (I)V' { - 0 15 - 2 15 - 7 15 - b 15 - c 15 - d 15 - e 15 - f 15 - 10 15 - 11 16 + 0 16 + 2 16 + 7 16 + b 16 + c 16 + d 16 + e 16 + f 16 + 10 16 + 11 17 } method 'testCaptureObject (Ljava/lang/String;)V' { - 6 19 - 8 19 - d 19 - 11 19 - 12 19 - 13 19 - 14 19 - 15 19 - 16 19 - 17 20 + 6 20 + 8 20 + d 20 + 11 20 + 12 20 + 13 20 + 14 20 + 15 20 + 16 20 + 17 21 } method 'testCaptureIntIterationValue (Ljava/lang/Iterable;)V' { - 6 23 - 7 23 - 8 23 - 9 23 - a 23 - b 23 - c 23 - d 25 - e 25 - f 25 - 10 25 - 11 25 - 12 25 - 16 26 - 17 26 - 18 26 - 19 26 - 1a 26 - 1b 26 - 1c 26 - 1d 26 - 1e 26 - 1f 26 - 20 26 - 21 26 - 23 26 - 28 26 - 2c 26 - 2d 26 - 2e 26 - 2f 26 - 30 26 - 31 26 - 35 28 + 6 24 + 7 24 + 8 24 + 9 24 + a 24 + b 24 + c 24 + d 26 + e 26 + f 26 + 10 26 + 11 26 + 12 26 + 16 27 + 17 27 + 18 27 + 19 27 + 1a 27 + 1b 27 + 1c 27 + 1d 27 + 1e 27 + 1f 27 + 20 27 + 21 27 + 23 27 + 28 27 + 2c 27 + 2d 27 + 2e 27 + 2f 27 + 30 27 + 31 27 + 35 29 } method 'testCaptureObjectIterationValue (Ljava/lang/Iterable;)V' { - 6 31 - 7 31 - 8 31 - 9 31 - a 31 - b 31 - c 31 - 16 31 - 17 31 - 18 31 - 19 31 - 1a 31 - 1b 31 - 1c 31 - 1d 31 - 1e 31 - 1f 31 - 20 32 - 25 32 - 29 32 - 2a 32 - 2b 32 - 2c 32 - 2d 32 - 2e 32 - 32 34 + 6 32 + 7 32 + 8 32 + 9 32 + a 32 + b 32 + c 32 + 16 32 + 17 32 + 18 32 + 19 32 + 1a 32 + 1b 32 + 1c 32 + 1d 32 + 1e 32 + 1f 32 + 20 33 + 25 33 + 29 33 + 2a 33 + 2b 33 + 2c 33 + 2d 33 + 2e 33 + 32 35 } method 'testCaptureMutableInt (I)V' { - 7 37 - 8 38 - 9 38 - a 38 - b 38 - c 38 - d 39 - 12 39 - 16 39 - 17 39 - 18 39 - 19 39 - 1a 39 - 1b 39 - 1c 40 - 1d 40 - 1e 40 - 1f 40 - 20 40 - 24 40 - 28 41 - 2d 41 - 31 41 - 32 41 - 33 41 - 34 41 - 35 41 - 36 41 - 37 42 - 3c 42 - 3d 42 - 3e 42 - 40 42 - 41 42 - 42 42 - 43 43 - 48 43 - 4c 43 - 4d 43 - 4e 43 - 4f 43 - 50 43 - 51 43 - 52 44 - 53 44 - 54 44 - 55 44 - 56 44 - 57 44 - 58 45 - 5d 45 - 61 45 - 62 45 - 63 45 - 64 45 - 65 45 - 66 45 - 67 46 - 6c 46 - 6e 46 - 6f 46 - 70 46 - 71 47 - 76 47 - 7a 47 - 7b 47 - 7c 47 - 7d 47 - 7e 47 - 7f 47 - 80 48 + 7 38 + 8 39 + 9 39 + a 39 + b 39 + c 39 + d 40 + 12 40 + 16 40 + 17 40 + 18 40 + 19 40 + 1a 40 + 1b 40 + 1c 41 + 1d 41 + 1e 41 + 1f 41 + 20 41 + 24 41 + 28 42 + 2d 42 + 31 42 + 32 42 + 33 42 + 34 42 + 35 42 + 36 42 + 37 43 + 3c 43 + 3d 43 + 3e 43 + 40 43 + 41 43 + 42 43 + 43 44 + 48 44 + 4c 44 + 4d 44 + 4e 44 + 4f 44 + 50 44 + 51 44 + 52 45 + 53 45 + 54 45 + 55 45 + 56 45 + 57 45 + 58 46 + 5d 46 + 61 46 + 62 46 + 63 46 + 64 46 + 65 46 + 66 46 + 67 47 + 6c 47 + 6e 47 + 6f 47 + 70 47 + 71 48 + 76 48 + 7a 48 + 7b 48 + 7c 48 + 7d 48 + 7e 48 + 7f 48 + 80 49 } method 'testCaptureMutableObject (Ljava/lang/String;)V' { - d 51 - e 52 - f 52 - 10 52 - 11 52 - 12 52 - 13 53 - 18 53 - 1c 53 - 1d 53 - 1e 53 - 1f 53 - 20 53 - 21 53 - 22 54 - 23 54 - 24 54 - 25 54 - 26 54 - 27 54 - 28 54 - 29 54 - 2a 54 - 2b 54 - 2c 54 - 2d 54 - 2e 54 - 2f 55 - 34 55 - 38 55 - 39 55 - 3a 55 - 3b 55 - 3c 55 - 3d 55 - 3e 56 - 3f 56 - 40 56 - 41 56 - 42 56 - 43 56 - 44 56 - 45 56 - 46 56 - 47 56 - 48 56 - 49 56 - 4a 56 - 4b 56 - 4c 56 - 4d 56 - 4e 56 - 4f 56 - 50 56 - 51 56 - 52 56 - 53 57 - 58 57 - 5c 57 - 5d 57 - 5e 57 - 5f 57 - 60 57 - 61 57 - 62 58 - 63 58 - 64 58 - 65 58 - 66 58 - 67 58 - 68 59 - 6d 59 - 71 59 - 72 59 - 73 59 - 74 59 - 75 59 - 76 59 - 77 60 - 78 60 - 79 60 - 7a 60 - 7b 60 - 7c 60 - 7d 60 - 7e 60 - 7f 60 - 80 60 - 81 60 - 82 60 - 83 60 - 84 60 - 85 61 - 8a 61 - 8e 61 - 8f 61 - 90 61 - 91 61 - 92 61 - 93 61 - 94 62 + d 52 + e 53 + f 53 + 10 53 + 11 53 + 12 53 + 13 54 + 18 54 + 1c 54 + 1d 54 + 1e 54 + 1f 54 + 20 54 + 21 54 + 22 55 + 23 55 + 24 55 + 25 55 + 26 55 + 27 55 + 28 55 + 29 55 + 2a 55 + 2b 55 + 2c 55 + 2d 55 + 2e 55 + 2f 56 + 34 56 + 38 56 + 39 56 + 3a 56 + 3b 56 + 3c 56 + 3d 56 + 3e 57 + 3f 57 + 40 57 + 41 57 + 42 57 + 43 57 + 44 57 + 45 57 + 46 57 + 47 57 + 48 57 + 49 57 + 4a 57 + 4b 57 + 4c 57 + 4d 57 + 4e 57 + 4f 57 + 50 57 + 51 57 + 52 57 + 53 58 + 58 58 + 5c 58 + 5d 58 + 5e 58 + 5f 58 + 60 58 + 61 58 + 62 59 + 63 59 + 64 59 + 65 59 + 66 59 + 67 59 + 68 60 + 6d 60 + 71 60 + 72 60 + 73 60 + 74 60 + 75 60 + 76 60 + 77 61 + 78 61 + 79 61 + 7a 61 + 7b 61 + 7c 61 + 7d 61 + 7e 61 + 7f 61 + 80 61 + 81 61 + 82 61 + 83 61 + 84 61 + 85 62 + 8a 62 + 8e 62 + 8f 62 + 90 62 + 91 62 + 92 62 + 93 62 + 94 63 } method 'testCaptureAndMutateInt (I)V' { - 7 65 - 8 66 - d 66 - 11 66 - 12 66 - 13 66 - 14 66 - 15 66 - 16 66 - 17 67 - 18 67 - 19 67 - 1a 67 - 1b 67 - 1c 67 - 1d 67 - 1e 68 - 23 68 - 27 68 - 28 68 - 29 68 - 2a 68 - 2b 68 - 2c 68 - 2d 69 + 7 66 + 8 67 + d 67 + 11 67 + 12 67 + 13 67 + 14 67 + 15 67 + 16 67 + 17 68 + 18 68 + 19 68 + 1a 68 + 1b 68 + 1c 68 + 1d 68 + 1e 69 + 23 69 + 27 69 + 28 69 + 29 69 + 2a 69 + 2b 69 + 2c 69 + 2d 70 } method 'testCaptureAndMutateString (Ljava/lang/String;)V' { - d 72 - e 73 - f 73 - 10 73 - 11 73 - 12 73 - 13 73 - 14 74 - 19 74 - 1d 74 - 1e 74 - 1f 74 - 20 74 - 21 74 - 22 74 - 23 75 - 24 75 - 25 75 - 26 75 - 27 75 - 28 75 - 29 75 - 2a 75 - 2b 75 - 2c 75 - 2d 76 - 32 76 - 36 76 - 37 76 - 38 76 - 39 76 - 3a 76 - 3b 76 - 3c 77 + d 73 + e 74 + f 74 + 10 74 + 11 74 + 12 74 + 13 74 + 14 75 + 19 75 + 1d 75 + 1e 75 + 1f 75 + 20 75 + 21 75 + 22 75 + 23 76 + 24 76 + 25 76 + 26 76 + 27 76 + 28 76 + 29 76 + 2a 76 + 2b 76 + 2c 76 + 2d 77 + 32 77 + 36 77 + 37 77 + 38 77 + 39 77 + 3a 77 + 3b 77 + 3c 78 } method 'testCapturePublicMutableIntField ()V' { - 0 80 - 5 80 - 9 80 - a 80 - b 80 - c 80 - d 80 - e 80 - f 81 + 0 81 + 5 81 + 9 81 + a 81 + b 81 + c 81 + d 81 + e 81 + f 82 } method 'testCapturePublicMutableStringField ()V' { - 0 84 - 5 84 - 9 84 - a 84 - b 84 - c 84 - d 84 - e 84 - f 85 + 0 85 + 5 85 + 9 85 + a 85 + b 85 + c 85 + d 85 + e 85 + f 86 } method 'testCapturePrivateMutableIntField ()V' { - 0 88 - 5 88 - 9 88 - a 88 - b 88 - c 88 - d 88 - e 88 - f 89 + 0 89 + 5 89 + 9 89 + a 89 + b 89 + c 89 + d 89 + e 89 + f 90 } method 'testCapturePrivateMutableStringField ()V' { - 0 92 - 5 92 - 9 92 - a 92 - b 92 - c 92 - d 92 - e 92 - f 93 + 0 93 + 5 93 + 9 93 + a 93 + b 93 + c 93 + d 93 + e 93 + f 94 } method 'execute (Lkotlin/jvm/functions/Function0;)V' { - 6 96 + 6 97 } method 'access$getPrivateIntField$p (Lpkg/TestNonInlineLambda;)I' { - 0 101 - 1 101 - 2 101 - 3 101 - 4 101 + 0 102 + 1 102 + 2 102 + 3 102 + 4 102 } method 'access$setPrivateIntField$p (Lpkg/TestNonInlineLambda;I)V' { - 0 107 - 1 107 - 2 107 - 3 107 - 4 107 - 5 108 + 0 108 + 1 108 + 2 108 + 3 108 + 4 108 + 5 109 } method 'access$setPrivateStringField$p (Lpkg/TestNonInlineLambda;Ljava/lang/String;)V' { - 0 113 - 1 113 - 2 113 - 3 113 - 4 113 - 5 114 + 0 114 + 1 114 + 2 114 + 3 114 + 4 114 + 5 115 } method 'access$getPrivateStringField$p (Lpkg/TestNonInlineLambda;)Ljava/lang/String;' { - 0 119 - 1 119 - 2 119 - 3 119 - 4 119 + 0 120 + 1 120 + 2 120 + 3 120 + 4 120 } } Lines mapping: -3 <-> 120 -7 <-> 16 -8 <-> 16 -11 <-> 17 -14 <-> 20 -15 <-> 20 -18 <-> 21 -21 <-> 24 -22 <-> 27 -26 <-> 29 -29 <-> 32 -30 <-> 33 -34 <-> 35 -37 <-> 38 -38 <-> 40 -41 <-> 41 -42 <-> 42 -45 <-> 43 -46 <-> 44 -49 <-> 45 -50 <-> 46 -53 <-> 47 -54 <-> 48 -57 <-> 49 -60 <-> 52 -61 <-> 54 -64 <-> 55 -65 <-> 56 -68 <-> 57 -69 <-> 58 -72 <-> 59 -73 <-> 60 -76 <-> 61 -77 <-> 62 -80 <-> 63 -83 <-> 66 -84 <-> 67 -89 <-> 68 -90 <-> 69 -95 <-> 70 -98 <-> 73 -99 <-> 75 -105 <-> 76 -106 <-> 77 -112 <-> 78 -117 <-> 81 -118 <-> 82 -123 <-> 85 -124 <-> 86 -129 <-> 89 -130 <-> 90 -135 <-> 93 -136 <-> 94 -141 <-> 97 +3 <-> 121 +7 <-> 17 +8 <-> 17 +11 <-> 18 +14 <-> 21 +15 <-> 21 +18 <-> 22 +21 <-> 25 +22 <-> 28 +26 <-> 30 +29 <-> 33 +30 <-> 34 +34 <-> 36 +37 <-> 39 +38 <-> 41 +41 <-> 42 +42 <-> 43 +45 <-> 44 +46 <-> 45 +49 <-> 46 +50 <-> 47 +53 <-> 48 +54 <-> 49 +57 <-> 50 +60 <-> 53 +61 <-> 55 +64 <-> 56 +65 <-> 57 +68 <-> 58 +69 <-> 59 +72 <-> 60 +73 <-> 61 +76 <-> 62 +77 <-> 63 +80 <-> 64 +83 <-> 67 +84 <-> 68 +89 <-> 69 +90 <-> 70 +95 <-> 71 +98 <-> 74 +99 <-> 76 +105 <-> 77 +106 <-> 78 +112 <-> 79 +117 <-> 82 +118 <-> 83 +123 <-> 86 +124 <-> 87 +129 <-> 90 +130 <-> 91 +135 <-> 94 +136 <-> 95 +141 <-> 98 diff --git a/plugins/kotlin/testData/results/pkg/TestNothingReturns.dec b/plugins/kotlin/testData/results/pkg/TestNothingReturns.dec index dcd0ebccc2..26e29647a7 100644 --- a/plugins/kotlin/testData/results/pkg/TestNothingReturns.dec +++ b/plugins/kotlin/testData/results/pkg/TestNothingReturns.dec @@ -1,23 +1,23 @@ package pkg class TestNothingReturns { - fun loop(): Void { + public fun loop(): Nothing { while (true) { System.out.println("loop");// 6 } } - fun test1(): Void { + public fun test1(): Nothing { this.loop();// 11 throw new KotlinNothingValueException(); } - fun test2(): Long { + public fun test2(): Long { this.test1();// 15 throw new KotlinNothingValueException(); } - fun test3(i: Int): Int { + public fun test3(i: Int): Int { if (i == 0) {// 19 this.loop();// 20 throw new KotlinNothingValueException(); @@ -26,18 +26,18 @@ class TestNothingReturns { } } - fun test4() { + public fun test4() { this.loop();// 27 throw new KotlinNothingValueException(); } - fun test5(s: String): String { - StringsKt.repeat(s as CharSequence, 5);// 32 + public fun test5(s: String): String { + StringsKt.repeat(s as java.lang.CharSequence, 5);// 32 this.loop(); throw new KotlinNothingValueException(); } - fun test6(s: String?): String { + public fun test6(s: String?): String { if (s == null) {// 36 this.loop(); throw new KotlinNothingValueException(); diff --git a/plugins/kotlin/testData/results/pkg/TestNullable.dec b/plugins/kotlin/testData/results/pkg/TestNullable.dec index fefb588154..5cda97427b 100644 --- a/plugins/kotlin/testData/results/pkg/TestNullable.dec +++ b/plugins/kotlin/testData/results/pkg/TestNullable.dec @@ -1,14 +1,14 @@ package pkg class TestNullable { - fun nullableParams(v: String, vn: String?) { + public fun nullableParams(v: String, vn: String?) { }// 6 - fun nullableReturn(): String? { + public fun nullableReturn(): String? { return null;// 9 } - fun nullableGenerics(v: MutableList): MutableList? { + public fun nullableGenerics(v: List): List? { return v;// 13 } } diff --git a/plugins/kotlin/testData/results/pkg/TestNullableOperator.dec b/plugins/kotlin/testData/results/pkg/TestNullableOperator.dec index f52d0ff005..a8636ad41c 100644 --- a/plugins/kotlin/testData/results/pkg/TestNullableOperator.dec +++ b/plugins/kotlin/testData/results/pkg/TestNullableOperator.dec @@ -1,12 +1,12 @@ package pkg class TestNullableOperator { - fun test(x: Int?): Int { + public fun test(x: Int?): Int { return x ?: 0;// 5 } - fun test2(x: String?): String { - var var10000: String = x;// 9 + public fun test2(x: String?): String { + var var10000: java.lang.String = x;// 9 if (x == null) { var10000 = "default"; } @@ -14,7 +14,7 @@ class TestNullableOperator { return var10000; } - fun test2_1(x: Any?): Any { + public fun test2_1(x: Any?): Any { var var10000: Any = x;// 13 if (x == null) { var10000 = "default"; @@ -23,7 +23,7 @@ class TestNullableOperator { return var10000; } - fun test2_2(x: Any?): Any { + public fun test2_2(x: Any?): Any { var var10000: Any = x;// 17 if (x == null) { var10000 = "default"; @@ -32,7 +32,7 @@ class TestNullableOperator { return var10000; } - fun test3(x: Int?): Int { + public fun test3(x: Int?): Int { if (x != null) {// 21 return x; } else { @@ -40,13 +40,13 @@ class TestNullableOperator { } } - fun test4(x: Exception?) { + public fun test4(x: Exception?) { if (x != null) {// 25 x.printStackTrace(); } }// 26 - fun test5(x: Exception?) { + public fun test5(x: Exception?) { var var10000: Unit; if (x != null) {// 29 x.printStackTrace(); @@ -60,7 +60,7 @@ class TestNullableOperator { } }// 30 - fun test6(x: Int?): Int { + public fun test6(x: Int?): Int { if (x != null) {// 33 var y: Int = x; System.out.println(y);// 35 @@ -70,7 +70,7 @@ class TestNullableOperator { } } - fun test6_1(x: Int?) { + public fun test6_1(x: Int?) { if (x != null) {// 41 System.out.println(x);// 43 } diff --git a/plugins/kotlin/testData/results/pkg/TestObject.dec b/plugins/kotlin/testData/results/pkg/TestObject.dec index c2e3102094..3e7e6e42c7 100644 --- a/plugins/kotlin/testData/results/pkg/TestObject.dec +++ b/plugins/kotlin/testData/results/pkg/TestObject.dec @@ -1,6 +1,6 @@ package pkg -object TestObject { +object TestObject private constructor() { @JvmStatic public TestObject INSTANCE = new TestObject(); @@ -8,45 +8,38 @@ object TestObject { public final val objectVal: Regex = new Regex("") private final var objectVar: Int = 42 - fun TestObject() { - }// 3 - fun objectFun() { + public fun objectFun() { objectVar += -1;// 5 }// 6 @JvmStatic - fun objectJvmStaticFun() { + public fun objectJvmStaticFun() { var var0: Int = objectVar++;// 16 }// 17 } class 'pkg/TestObject' { - method ' ()V' { - 4 11 - } - method 'objectFun ()V' { - 5 14 - 7 14 - 8 14 - 9 14 - a 15 + 5 12 + 7 12 + 8 12 + 9 12 + a 13 } method 'objectJvmStaticFun ()V' { - 4 19 - 5 19 - 6 19 - 7 19 - a 19 - e 20 + 4 17 + 5 17 + 6 17 + 7 17 + a 17 + e 18 } } Lines mapping: -3 <-> 12 -5 <-> 15 -6 <-> 16 -16 <-> 20 -17 <-> 21 +5 <-> 13 +6 <-> 14 +16 <-> 18 +17 <-> 19 diff --git a/plugins/kotlin/testData/results/pkg/TestParams.dec b/plugins/kotlin/testData/results/pkg/TestParams.dec index dabf8830ba..d35e235e6b 100644 --- a/plugins/kotlin/testData/results/pkg/TestParams.dec +++ b/plugins/kotlin/testData/results/pkg/TestParams.dec @@ -1,29 +1,29 @@ package pkg class TestParams { - fun printMessageUnit(message: String) { + public fun printMessageUnit(message: String) { System.out.println(message);// 5 }// 6 - fun printMessageVoid(message: String) { + public fun printMessageVoid(message: String) { System.out.println(message);// 9 }// 10 - fun multiply(x: Int, y: Int): Int { + public fun multiply(x: Int, y: Int): Int { return x * y;// 12 } - fun multiplyBraces(x: Int, y: Int): Int { + public fun multiplyBraces(x: Int, y: Int): Int { return x * y;// 15 } - fun printMessageWithPrefix(message: String, prefix: String) { + public fun printMessageWithPrefix(message: String, prefix: String) { System.out.println("[" + prefix + "] " + message);// 19 }// 20 @JvmStatic @JvmSynthetic - fun `printMessageWithPrefix$default`(var0: TestParams, var1: String, var2: String, var3: Int, var4: Any) { + fun `printMessageWithPrefix$default`(var0: TestParams, var1: java.lang.String, var2: java.lang.String, var3: Int, var4: Any) { if ((var3 and 2) != 0) {// 18 var2 = "Info"; } @@ -31,7 +31,7 @@ class TestParams { var0.printMessageWithPrefix(var1, var2); } - fun callPrintMessage() { + public fun callPrintMessage() { printMessageWithPrefix$default(this, "Test", null, 2, null);// 23 this.printMessageWithPrefix("Test", "Debug");// 24 }// 25 diff --git a/plugins/kotlin/testData/results/pkg/TestPoorNames.dec b/plugins/kotlin/testData/results/pkg/TestPoorNames.dec index 213c7117b9..2af7540612 100644 --- a/plugins/kotlin/testData/results/pkg/TestPoorNames.dec +++ b/plugins/kotlin/testData/results/pkg/TestPoorNames.dec @@ -4,19 +4,20 @@ class TestPoorNames { public final val `Dangerous property name?!`: String = "test" public final val `Property with spaces`: Int = 42 - fun `Function with spaces`() { + + public fun `Function with spaces`() { }// 5 - fun `Dangerous function name?!`() { + public fun `Dangerous function name?!`() { }// 8 - fun `functionWith$Dollar`() { + public fun `functionWith$Dollar`() { }// 14 - fun functionWithParameters(var1: Int, var2: String) { + public fun functionWithParameters(`Parameter with spaces`: Int, `Dangerous parameter name?!`: String) { }// 17 - fun test() { + public fun test() { new TestPoorNames.Class with spaces(); this.Dangerous function name?!();// 23 this.functionWithParameters(42, "test");// 24 @@ -28,45 +29,45 @@ class TestPoorNames { class 'pkg/TestPoorNames' { method 'Function with spaces ()V' { - 0 7 + 0 8 } method 'Dangerous function name?! ()V' { - 0 10 + 0 11 } method 'functionWith$Dollar ()V' { - 0 13 + 0 14 } method 'functionWithParameters (ILjava/lang/String;)V' { - 6 16 + 6 17 } method 'test ()V' { - 8 20 - 9 20 - a 20 - b 20 - c 21 - d 21 - e 21 - f 21 - 10 21 - 11 21 - 12 21 - 13 21 - 14 22 + 8 21 + 9 21 + a 21 + b 21 + c 22 + d 22 + e 22 + f 22 + 10 22 + 11 22 + 12 22 + 13 22 + 14 23 } } Lines mapping: -5 <-> 8 -8 <-> 11 -14 <-> 14 -17 <-> 17 -23 <-> 21 -24 <-> 22 -25 <-> 23 +5 <-> 9 +8 <-> 12 +14 <-> 15 +17 <-> 18 +23 <-> 22 +24 <-> 23 +25 <-> 24 Not mapped: 22 diff --git a/plugins/kotlin/testData/results/pkg/TestReflection.dec b/plugins/kotlin/testData/results/pkg/TestReflection.dec index eafa653fc3..9126567a5b 100644 --- a/plugins/kotlin/testData/results/pkg/TestReflection.dec +++ b/plugins/kotlin/testData/results/pkg/TestReflection.dec @@ -4,25 +4,25 @@ import kotlin.jvm.functions.Function1 import kotlin.reflect.KFunction class TestReflection { - fun testClassReference() { + public fun testClassReference() { System.out.println(TestReflection::class);// 5 System.out.println(TestReflection::class.java);// 6 }// 7 - fun testPrimitiveWrapper() { + public fun testPrimitiveWrapper() { System.out.println(Int::class);// 10 System.out.println(Integer::class.javaObjectType);// 11 }// 12 - fun testPrimitiveType() { + public fun testPrimitiveType() { System.out.println(Int::class.javaPrimitiveType);// 15 }// 16 - fun testInferredPrimitive() { + public fun testInferredPrimitive() { System.out.println(Int::class.javaPrimitiveType);// 19 }// 20 - fun testFunctionReference() { + public fun testFunctionReference() { var f: KFunction = .INSTANCE as KFunction;// 23 System.out.println(.INSTANCE as KFunction);// 24 (f as Function1).invoke(new TestReflection());// 25 diff --git a/plugins/kotlin/testData/results/pkg/TestSafeCasts.dec b/plugins/kotlin/testData/results/pkg/TestSafeCasts.dec index 875bbb1db8..f8429bc7fe 100644 --- a/plugins/kotlin/testData/results/pkg/TestSafeCasts.dec +++ b/plugins/kotlin/testData/results/pkg/TestSafeCasts.dec @@ -1,7 +1,7 @@ package pkg class TestSafeCasts { - fun test(obj: Any): Boolean { + public fun test(obj: Any): Boolean { var t: Int = obj as? Integer;// 5 if ((obj as? Integer) != null) {// 7 if (t == 1) { @@ -12,7 +12,7 @@ class TestSafeCasts { return false; } - fun testTestBefore(obj: Any): Boolean? { + public fun testTestBefore(obj: Any): Boolean? { if (obj !is Integer) {// 11 return null;// 12 } else { @@ -27,15 +27,15 @@ class TestSafeCasts { } } - fun testHardIncompatible(obj: Int): Boolean { - return (obj as? String) == "1";// 21 23 + public fun testHardIncompatible(obj: Int): Boolean { + return (obj as? java.lang.String) == "1";// 21 23 } - fun testSmartCastIncompatible(obj: Any): Boolean { - return obj is Integer && (obj as? String) == "1";// 27 31 33 + public fun testSmartCastIncompatible(obj: Any): Boolean { + return obj is Integer && (obj as? java.lang.String) == "1";// 27 31 33 } - fun testCastNonNullToNullable(obj: Any): Boolean { + public fun testCastNonNullToNullable(obj: Any): Boolean { var t: Int = obj as? Integer;// 37 if ((obj as? Integer) != null) {// 39 if (t == 1) { @@ -46,7 +46,7 @@ class TestSafeCasts { return false; } - fun testBeforeNonNullToNullable(obj: Any): Boolean? { + public fun testBeforeNonNullToNullable(obj: Any): Boolean? { if (obj !is Integer) {// 43 return null;// 44 } else { @@ -61,7 +61,7 @@ class TestSafeCasts { } } - fun testCastNullableToNullable(obj: Any?): Boolean { + public fun testCastNullableToNullable(obj: Any?): Boolean { var t: Int = obj as? Integer;// 53 if ((obj as? Integer) != null) {// 55 if (t == 1) { @@ -72,7 +72,7 @@ class TestSafeCasts { return false; } - fun testBeforeNullableToNullable(obj: Any?): Boolean? { + public fun testBeforeNullableToNullable(obj: Any?): Boolean? { if (obj != null && obj !is Integer) {// 59 return null;// 60 } else { diff --git a/plugins/kotlin/testData/results/pkg/TestSealedHierarchy.dec b/plugins/kotlin/testData/results/pkg/TestSealedHierarchy.dec index 46ecc356a4..2e488973aa 100644 --- a/plugins/kotlin/testData/results/pkg/TestSealedHierarchy.dec +++ b/plugins/kotlin/testData/results/pkg/TestSealedHierarchy.dec @@ -1,74 +1,43 @@ package pkg -import kotlin.jvm.internal.DefaultConstructorMarker - -sealed class TestSealedHierarchy { - fun TestSealedHierarchy() { - }// 3 - - @JvmSynthetic - open fun TestSealedHierarchy(`$constructor_marker`: DefaultConstructorMarker) { - this(); - } - - class TestClass : TestSealedHierarchy { +sealed class TestSealedHierarchy protected constructor() { + class TestClass(x: Int) : TestSealedHierarchy() {// 5 public final val x: Int - fun TestClass(x: Int) { - super(null);// 5 + init { this.x = x; } } - object TestObject : TestSealedHierarchy { + object TestObject private constructor() : TestSealedHierarchy() {// 4 @JvmStatic public TestSealedHierarchy.TestObject INSTANCE = new TestSealedHierarchy.TestObject(); - fun TestObject() { - super(null);// 4 - } - } -} - -class 'pkg/TestSealedHierarchy' { - method ' ()V' { - 4 6 - } - - method ' (Lkotlin/jvm/internal/DefaultConstructorMarker;)V' { - 1 10 - 2 10 - 3 10 - 4 11 } } class 'pkg/TestSealedHierarchy$TestClass' { method ' (I)V' { - 1 17 - 2 17 - 3 17 - 4 17 - 5 18 - 6 18 - 7 18 - 8 18 - 9 18 - a 19 + 2 3 + 3 3 + 4 3 + 5 7 + 6 7 + 7 7 + 8 7 + 9 7 + a 8 } } class 'pkg/TestSealedHierarchy$TestObject' { method ' ()V' { - 1 27 - 2 27 - 3 27 - 4 27 - 5 28 + 2 11 + 3 11 + 4 11 } } Lines mapping: -3 <-> 7 -4 <-> 28 -5 <-> 18 +4 <-> 12 +5 <-> 4 diff --git a/plugins/kotlin/testData/results/pkg/TestShadowParam.dec b/plugins/kotlin/testData/results/pkg/TestShadowParam.dec index 9bf21e3239..ac3433aacf 100644 --- a/plugins/kotlin/testData/results/pkg/TestShadowParam.dec +++ b/plugins/kotlin/testData/results/pkg/TestShadowParam.dec @@ -1,7 +1,7 @@ package pkg class TestShadowParam { - fun test(x: Int) { + public fun test(x: Int) { var xx: Int = x - 1;// 5 6 System.out.println(x - 1);// 7 if (xx < 0) {// 8 diff --git a/plugins/kotlin/testData/results/pkg/TestSmartCasts.dec b/plugins/kotlin/testData/results/pkg/TestSmartCasts.dec index c3e0ef24f2..0d58d4ecce 100644 --- a/plugins/kotlin/testData/results/pkg/TestSmartCasts.dec +++ b/plugins/kotlin/testData/results/pkg/TestSmartCasts.dec @@ -1,11 +1,9 @@ package pkg -import kotlin.jvm.internal.DefaultConstructorMarker - class TestSmartCasts { - fun testWhen(o: Any?): String { - if (o is String) {// 19 20 - return o as String;// 21 + public fun testWhen(o: Any?): String { + if (o is java.lang.String) {// 19 20 + return o as java.lang.String;// 21 } else { if (o is TestSmartCasts.A.B) {// 24 System.out.println("B: " + o); @@ -33,11 +31,11 @@ class TestSmartCasts { } } - fun testIf(a: Any?): String { + public fun testIf(a: Any?): String { return if (a !is TestSmartCasts.A.B && a !is TestSmartCasts.A.C) "else: " + a else (a as TestSmartCasts.A).test();// 35 36 39 } - fun testIf2(a: Any?): String { + public fun testIf2(a: Any?): String { if (a is TestSmartCasts.A) {// 43 if (a is TestSmartCasts.A.B || a is TestSmartCasts.A.C) {// 44 System.out.println((a as TestSmartCasts.A).test());// 45 @@ -58,19 +56,19 @@ class TestSmartCasts { return "else: " + a;// 60 } - fun testCast(a: Any?) { + public fun testCast(a: Any?) { System.out.println(a);// 64 if (a == null) {// 65 throw new NullPointerException("null cannot be cast to non-null type kotlin.String"); } else { System.out.println("hello");// 66 System.out.println(a);// 67 - (a as String).charAt(0);// 68 - System.out.println((a as String).charAt(0));// 69 + (a as java.lang.String).charAt(0);// 68 + System.out.println((a as java.lang.String).charAt(0));// 69 } }// 70 - fun testSealedIf(a: TestSmartCasts.A): String { + public fun testSealedIf(a: pkg.TestSmartCasts.A): String { if (a is TestSmartCasts.A.B) {// 73 return (a as TestSmartCasts.A.B).testB();// 74 } else { @@ -78,51 +76,36 @@ class TestSmartCasts { } } - fun testDoubleType(t: MutableList): String { - return if (t is TestSmartCasts.X) (t as TestSmartCasts.X).woo(t as Iterable) else t.get(0) as String;// 83 84 87 + public fun testDoubleType(t: List): String { + return if (t is TestSmartCasts.X) (t as TestSmartCasts.X).woo(t as java.lang.Iterable) else t.get(0) as java.lang.String;// 83 84 87 } - sealed class A { - fun A() { - }// 7 - - fun test(): String { + sealed class A protected constructor() { + public fun test(): String { return "";// 15 } - @JvmSynthetic - open fun A(`$constructor_marker`: DefaultConstructorMarker) { - this(); - } - - class B : TestSmartCasts.A { - fun B() { - super(null);// 8 - } - - fun testB(): String { + class B : TestSmartCasts.A() {// 8 + public fun testB(): String { return "B";// 9 } } - class C : TestSmartCasts.A { - fun C() { - super(null);// 11 - } - - fun testC(): String { + class C : TestSmartCasts.A() {// 11 + public fun testC(): String { return "C";// 12 } } } interface X { - fun woo(var1: Iterable): String + public open fun Iterable<*>.woo(): String { + } // $VF: Class flags could not be determined internal class DefaultImpls { @JvmStatic - fun woo(var0: TestSmartCasts.X, receiver: Iterable): String { + fun woo(var0: TestSmartCasts.X, receiver: MutableIterable<*>): java.lang.String { return "A";// 5 } } @@ -131,448 +114,432 @@ class TestSmartCasts { class 'pkg/TestSmartCasts' { method 'testWhen (Ljava/lang/Object;)Ljava/lang/String;' { - 0 6 - 2 6 - 3 6 - 4 6 - 5 6 - 6 6 - 9 7 - a 7 - b 7 - c 7 - d 7 - e 9 - f 9 - 10 9 - 11 9 - 12 9 - 15 10 - 16 10 - 17 10 - 18 10 - 19 10 - 1a 10 - 1b 10 - 1c 10 - 1d 10 - 1f 10 - 20 10 - 21 10 - 25 12 - 29 12 - 2c 24 - 2d 24 - 2e 24 - 2f 24 - 30 24 - 31 24 - 32 24 - 33 24 - 34 24 - 36 24 - 37 24 - 38 24 - 3c 13 - 3d 13 - 3e 13 - 3f 13 - 40 13 - 43 14 - 44 14 - 45 14 - 46 14 - 47 14 - 48 14 - 49 14 - 4a 14 - 4b 14 - 4c 14 - 4d 14 - 4e 14 - 4f 14 - 50 14 - 51 14 - 52 14 - 53 14 - 54 14 - 55 14 - 56 14 - 57 14 - 58 14 - 59 14 - 5a 14 - 5b 14 - 5c 14 - 5d 14 - 5e 14 - 5f 17 - 60 17 - 63 18 - 64 18 - 65 18 - 66 21 - 67 21 - 68 21 - 69 21 - 6a 21 - 6b 21 - 6c 21 - 6d 27 - 6f 27 - 77 28 - 78 28 - 7c 28 - 7d 30 - 7e 30 - 7f 30 - 80 30 - 81 30 - 82 30 - 83 30 + 0 4 + 2 4 + 3 4 + 4 4 + 5 4 + 6 4 + 9 5 + a 5 + b 5 + c 5 + d 5 + e 7 + f 7 + 10 7 + 11 7 + 12 7 + 15 8 + 16 8 + 17 8 + 18 8 + 19 8 + 1a 8 + 1b 8 + 1c 8 + 1d 8 + 1f 8 + 20 8 + 21 8 + 25 10 + 29 10 + 2c 22 + 2d 22 + 2e 22 + 2f 22 + 30 22 + 31 22 + 32 22 + 33 22 + 34 22 + 36 22 + 37 22 + 38 22 + 3c 11 + 3d 11 + 3e 11 + 3f 11 + 40 11 + 43 12 + 44 12 + 45 12 + 46 12 + 47 12 + 48 12 + 49 12 + 4a 12 + 4b 12 + 4c 12 + 4d 12 + 4e 12 + 4f 12 + 50 12 + 51 12 + 52 12 + 53 12 + 54 12 + 55 12 + 56 12 + 57 12 + 58 12 + 59 12 + 5a 12 + 5b 12 + 5c 12 + 5d 12 + 5e 12 + 5f 15 + 60 15 + 63 16 + 64 16 + 65 16 + 66 19 + 67 19 + 68 19 + 69 19 + 6a 19 + 6b 19 + 6c 19 + 6d 25 + 6f 25 + 77 26 + 78 26 + 7c 26 + 7d 28 + 7e 28 + 7f 28 + 80 28 + 81 28 + 82 28 + 83 28 } method 'testIf (Ljava/lang/Object;)Ljava/lang/String;' { - 0 36 - 4 36 - 7 36 - b 36 - e 36 - f 36 - 10 36 - 11 36 - 12 36 - 13 36 - 14 36 - 16 36 - 17 36 - 18 36 - 19 36 - 1a 36 - 1b 36 + 0 34 + 4 34 + 7 34 + b 34 + e 34 + f 34 + 10 34 + 11 34 + 12 34 + 13 34 + 14 34 + 16 34 + 17 34 + 18 34 + 19 34 + 1a 34 + 1b 34 } method 'testIf2 (Ljava/lang/Object;)Ljava/lang/String;' { - 0 40 - 1 40 - 2 40 - 3 40 - 4 40 - 7 41 - 8 41 - 9 41 - a 41 - b 41 - e 41 - f 41 - 10 41 - 11 41 - 12 41 - 15 42 - 16 42 - 17 42 - 18 42 - 19 42 - 1a 42 - 1b 42 - 1c 42 - 1d 42 - 1e 42 - 20 42 - 23 45 - 24 45 - 25 45 - 26 45 - 27 45 - 2a 46 - 2b 46 - 2c 46 - 2d 46 - 2e 46 - 31 47 - 32 47 - 33 47 - 34 47 - 35 47 - 36 47 - 37 47 - 38 47 - 39 47 - 3a 47 - 3c 47 - 3d 47 - 3e 47 - 3f 48 - 40 48 - 41 48 - 42 48 - 43 48 - 44 48 - 45 48 - 46 48 - 47 48 - 48 48 - 4a 48 - 4d 51 - 4e 51 - 4f 51 - 50 51 - 51 51 - 54 51 - 55 51 - 56 51 - 57 51 - 58 51 - 59 51 - 5a 51 - 5b 51 - 5c 51 - 60 51 - 63 51 - 64 51 - 65 51 - 66 51 - 67 51 - 6a 52 - 6b 52 - 6c 52 - 6d 52 - 6e 52 - 6f 52 - 70 52 - 71 52 - 72 52 - 73 52 - 75 52 - 78 57 - 79 57 - 7a 57 - 7b 57 - 7c 57 - 7d 57 - 7e 57 + 0 38 + 1 38 + 2 38 + 3 38 + 4 38 + 7 39 + 8 39 + 9 39 + a 39 + b 39 + e 39 + f 39 + 10 39 + 11 39 + 12 39 + 15 40 + 16 40 + 17 40 + 18 40 + 19 40 + 1a 40 + 1b 40 + 1c 40 + 1d 40 + 1e 40 + 20 40 + 23 43 + 24 43 + 25 43 + 26 43 + 27 43 + 2a 44 + 2b 44 + 2c 44 + 2d 44 + 2e 44 + 31 45 + 32 45 + 33 45 + 34 45 + 35 45 + 36 45 + 37 45 + 38 45 + 39 45 + 3a 45 + 3c 45 + 3d 45 + 3e 45 + 3f 46 + 40 46 + 41 46 + 42 46 + 43 46 + 44 46 + 45 46 + 46 46 + 47 46 + 48 46 + 4a 46 + 4d 49 + 4e 49 + 4f 49 + 50 49 + 51 49 + 54 49 + 55 49 + 56 49 + 57 49 + 58 49 + 59 49 + 5a 49 + 5b 49 + 5c 49 + 60 49 + 63 49 + 64 49 + 65 49 + 66 49 + 67 49 + 6a 50 + 6b 50 + 6c 50 + 6d 50 + 6e 50 + 6f 50 + 70 50 + 71 50 + 72 50 + 73 50 + 75 50 + 78 55 + 79 55 + 7a 55 + 7b 55 + 7c 55 + 7d 55 + 7e 55 } method 'testCast (Ljava/lang/Object;)V' { - 0 61 - 1 61 - 2 61 - 3 61 - 4 61 - 5 61 - 6 61 - 7 62 - 9 62 - 11 63 - 12 63 - 16 63 - 1b 65 - 1c 65 - 1d 65 - 1e 65 - 1f 65 - 21 65 - 22 65 - 23 65 - 24 66 - 25 66 - 26 66 - 27 66 - 28 66 - 29 66 - 2a 66 - 2b 67 - 2c 67 - 2d 67 - 2e 67 - 2f 67 - 30 67 - 31 67 - 32 67 - 34 68 - 35 68 - 36 68 - 37 68 - 38 68 - 39 68 - 3a 68 - 3b 68 - 3d 68 - 3e 68 - 3f 68 - 40 68 - 41 68 - 42 68 - 43 68 - 44 70 + 0 59 + 1 59 + 2 59 + 3 59 + 4 59 + 5 59 + 6 59 + 7 60 + 9 60 + 11 61 + 12 61 + 16 61 + 1b 63 + 1c 63 + 1d 63 + 1e 63 + 1f 63 + 21 63 + 22 63 + 23 63 + 24 64 + 25 64 + 26 64 + 27 64 + 28 64 + 29 64 + 2a 64 + 2b 65 + 2c 65 + 2d 65 + 2e 65 + 2f 65 + 30 65 + 31 65 + 32 65 + 34 66 + 35 66 + 36 66 + 37 66 + 38 66 + 39 66 + 3a 66 + 3b 66 + 3d 66 + 3e 66 + 3f 66 + 40 66 + 41 66 + 42 66 + 43 66 + 44 68 } method 'testSealedIf (Lpkg/TestSmartCasts$A;)Ljava/lang/String;' { - 6 73 - 7 73 - 8 73 - 9 73 - a 73 - d 74 - e 74 - f 74 - 10 74 - 11 74 - 12 74 - 13 74 - 14 74 - 15 76 - 16 76 - 17 76 - 18 76 - 19 76 - 1c 76 - 1d 76 - 1e 76 - 1f 76 - 20 76 - 21 76 - 22 76 - 24 76 - 25 76 - 26 76 - 27 76 + 6 71 + 7 71 + 8 71 + 9 71 + a 71 + d 72 + e 72 + f 72 + 10 72 + 11 72 + 12 72 + 13 72 + 14 72 + 15 74 + 16 74 + 17 74 + 18 74 + 19 74 + 1c 74 + 1d 74 + 1e 74 + 1f 74 + 20 74 + 21 74 + 22 74 + 24 74 + 25 74 + 26 74 + 27 74 } method 'testDoubleType (Ljava/util/List;)Ljava/lang/String;' { - 6 81 - 7 81 - 8 81 - 9 81 - a 81 - d 81 - 11 81 - 12 81 - 13 81 - 14 81 - 15 81 - 16 81 - 17 81 - 18 81 - 19 81 - 1a 81 - 1b 81 - 1c 81 - 1d 81 - 1f 81 - 20 81 - 21 81 - 22 81 - 23 81 - 24 81 - 25 81 - 26 81 - 27 81 - 28 81 + 6 79 + 7 79 + 8 79 + 9 79 + a 79 + d 79 + 11 79 + 12 79 + 13 79 + 14 79 + 15 79 + 16 79 + 17 79 + 18 79 + 19 79 + 1a 79 + 1b 79 + 1c 79 + 1d 79 + 1f 79 + 20 79 + 21 79 + 22 79 + 23 79 + 24 79 + 25 79 + 26 79 + 27 79 + 28 79 } } class 'pkg/TestSmartCasts$A' { - method ' ()V' { - 4 86 - } - method 'test ()Ljava/lang/String;' { - 0 89 - 1 89 - 2 89 - } - - method ' (Lkotlin/jvm/internal/DefaultConstructorMarker;)V' { - 1 94 - 2 94 - 3 94 - 4 95 + 0 84 + 1 84 + 2 84 } } class 'pkg/TestSmartCasts$A$B' { method ' ()V' { - 1 99 - 2 99 - 3 99 - 4 99 - 5 100 + 2 87 + 3 87 + 4 87 } method 'testB ()Ljava/lang/String;' { - 0 103 - 1 103 - 2 103 + 0 89 + 1 89 + 2 89 } } class 'pkg/TestSmartCasts$A$C' { method ' ()V' { - 1 109 - 2 109 - 3 109 - 4 109 - 5 110 + 2 93 + 3 93 + 4 93 } method 'testC ()Ljava/lang/String;' { - 0 113 - 1 113 - 2 113 + 0 95 + 1 95 + 2 95 } } class 'pkg/TestSmartCasts$X$DefaultImpls' { method 'woo (Lpkg/TestSmartCasts$X;Ljava/lang/Iterable;)Ljava/lang/String;' { - 6 125 - 7 125 - 8 125 + 6 108 + 7 108 + 8 108 } } Lines mapping: -5 <-> 126 -7 <-> 87 -8 <-> 100 -9 <-> 104 -11 <-> 110 -12 <-> 114 -15 <-> 90 -19 <-> 7 -20 <-> 7 -21 <-> 8 -24 <-> 10 -25 <-> 13 -26 <-> 14 -27 <-> 18 -28 <-> 22 -31 <-> 28 -35 <-> 37 -36 <-> 37 -39 <-> 37 -43 <-> 41 -44 <-> 42 -45 <-> 43 -48 <-> 46 -49 <-> 47 -50 <-> 48 -51 <-> 49 -54 <-> 52 -55 <-> 53 -60 <-> 58 -64 <-> 62 -65 <-> 63 -66 <-> 66 -67 <-> 67 -68 <-> 68 -69 <-> 69 -70 <-> 71 -73 <-> 74 -74 <-> 75 -75 <-> 77 -76 <-> 77 -78 <-> 77 -83 <-> 82 -84 <-> 82 -87 <-> 82 +5 <-> 109 +8 <-> 88 +9 <-> 90 +11 <-> 94 +12 <-> 96 +15 <-> 85 +19 <-> 5 +20 <-> 5 +21 <-> 6 +24 <-> 8 +25 <-> 11 +26 <-> 12 +27 <-> 16 +28 <-> 20 +31 <-> 26 +35 <-> 35 +36 <-> 35 +39 <-> 35 +43 <-> 39 +44 <-> 40 +45 <-> 41 +48 <-> 44 +49 <-> 45 +50 <-> 46 +51 <-> 47 +54 <-> 50 +55 <-> 51 +60 <-> 56 +64 <-> 60 +65 <-> 61 +66 <-> 64 +67 <-> 65 +68 <-> 66 +69 <-> 67 +70 <-> 69 +73 <-> 72 +74 <-> 73 +75 <-> 75 +76 <-> 75 +78 <-> 75 +83 <-> 80 +84 <-> 80 +87 <-> 80 diff --git a/plugins/kotlin/testData/results/pkg/TestSynchronized.dec b/plugins/kotlin/testData/results/pkg/TestSynchronized.dec index 4e27036e62..0d166bac19 100644 --- a/plugins/kotlin/testData/results/pkg/TestSynchronized.dec +++ b/plugins/kotlin/testData/results/pkg/TestSynchronized.dec @@ -1,8 +1,7 @@ package pkg class TestSynchronized { - // $VF: Extended synchronized range to monitorexit - fun test() { + public fun test() { synchronized (this) {// 5 System.out.println("Hello");// 6 } @@ -11,31 +10,31 @@ class TestSynchronized { class 'pkg/TestSynchronized' { method 'test ()V' { - 0 5 - 2 5 - 3 5 - 7 6 - 8 6 - 9 6 - a 6 - b 6 - d 6 - e 6 - f 6 - 17 8 - 18 8 - 19 8 - 1a 8 - 1b 8 - 1c 8 - 1d 8 - 1e 8 + 0 4 + 2 4 + 3 4 + 7 5 + 8 5 + 9 5 + a 5 + b 5 + d 5 + e 5 + f 5 + 17 7 + 18 7 + 19 7 + 1a 7 + 1b 7 + 1c 7 + 1d 7 + 1e 7 } } Lines mapping: -5 <-> 6 -6 <-> 7 +5 <-> 5 +6 <-> 6 Not mapped: 7 8 diff --git a/plugins/kotlin/testData/results/pkg/TestTailrecFunctions.dec b/plugins/kotlin/testData/results/pkg/TestTailrecFunctions.dec index 6c30303995..39e7eeff61 100644 --- a/plugins/kotlin/testData/results/pkg/TestTailrecFunctions.dec +++ b/plugins/kotlin/testData/results/pkg/TestTailrecFunctions.dec @@ -1,7 +1,7 @@ package pkg class TestTailrecFunctions { - fun sum(x: Long, sum: Long): Long { + public tailrec fun sum(x: Long, sum: Long): Long { var var5: TestTailrecFunctions = this;// 4 var var6: Long = x; var var8: Long = sum; @@ -17,11 +17,11 @@ class TestTailrecFunctions { return var8; } - fun testFinally() { + public tailrec fun testFinally() { label12: { try { ; - } catch (Throwable var2) { + } catch (java.lang.Throwable var2) { this.testFinally();// 13 } @@ -29,24 +29,24 @@ class TestTailrecFunctions { } } - fun testFinallyReturn(): Int { + public tailrec fun testFinallyReturn(): Int { try { ; - } catch (Throwable var2) { + } catch (java.lang.Throwable var2) { return this.testFinallyReturn();// 21 } return this.testFinallyReturn(); } - fun fooTry() { + public tailrec fun fooTry() { try { this.fooTry();// 27 - } catch (Throwable var2) {// 29 + } catch (java.lang.Throwable var2) {// 29 } }// 31 - fun testTryCatchFinally() { + public tailrec fun testTryCatchFinally() { label31: { label32: { try { @@ -56,7 +56,7 @@ class TestTailrecFunctions { } catch (Exception var2) {// 36 this.testTryCatchFinally();// 37 } - } catch (Throwable var3) { + } catch (java.lang.Throwable var3) { this.testTryCatchFinally();// 39 } @@ -68,7 +68,7 @@ class TestTailrecFunctions { } } - fun fastPow(x: Long, n: Long, acc: Long): Long { + public tailrec fun fastPow(x: Long, n: Long, acc: Long): Long { var var7: TestTailrecFunctions = this; var var8: Long = x; var var10: Long = n; @@ -105,7 +105,7 @@ class TestTailrecFunctions { return var0.fastPow(var1, var3, var5); } - fun fastPow(x: Long, n: Long): Long { + public tailrec fun fastPow(x: Long, n: Long): Long { var var5: TestTailrecFunctions = this;// 49 var var6: Long = x; var var8: Long = n; diff --git a/plugins/kotlin/testData/results/pkg/TestTopLevelKt.dec b/plugins/kotlin/testData/results/pkg/TestTopLevelKt.dec index bb9b18cb43..6c4f34d637 100644 --- a/plugins/kotlin/testData/results/pkg/TestTopLevelKt.dec +++ b/plugins/kotlin/testData/results/pkg/TestTopLevelKt.dec @@ -5,7 +5,7 @@ public final val topLevelVal: Regex = new Regex("") public final var topLevelVar: Int = 42 internal set -fun topLevelFun() { +public fun topLevelFun() { }// 5 diff --git a/plugins/kotlin/testData/results/pkg/TestTryCatchExpressions.dec b/plugins/kotlin/testData/results/pkg/TestTryCatchExpressions.dec index 11071ce530..53bf0f58a2 100644 --- a/plugins/kotlin/testData/results/pkg/TestTryCatchExpressions.dec +++ b/plugins/kotlin/testData/results/pkg/TestTryCatchExpressions.dec @@ -3,12 +3,12 @@ package pkg import java.io.IOException class TestTryCatchExpressions { - fun test0(s: String) { - var var2: String; + public fun test0(s: String) { + var var2: java.lang.String; try { - var2 = StringsKt.repeat(s as CharSequence, 5);// 9 + var2 = StringsKt.repeat(s as java.lang.CharSequence, 5);// 9 } catch (RuntimeException var4) {// 10 - var var10000: String = var4.getMessage();// 11 + var var10000: java.lang.String = var4.getMessage();// 11 if (var10000 == null) { var10000 = "ERROR"; } @@ -19,19 +19,19 @@ class TestTryCatchExpressions { System.out.print(var2);// 7 }// 14 - fun test1(a: String, b: String) { - var x: String = a;// 17 + public fun test1(a: String, b: String) { + var x: java.lang.String = a;// 17 var var6: TestTryCatchExpressions = this;// 19 - var var4: String; + var var4: java.lang.String; var var10000: TestTryCatchExpressions; try { var10000 = var6; - var4 = StringsKt.repeat(x as CharSequence, 5);// 20 + var4 = StringsKt.repeat(x as java.lang.CharSequence, 5);// 20 } catch (RuntimeException var9) {// 21 var10000 = this; x = b;// 22 - var var10001: String = var9.getMessage();// 23 + var var10001: java.lang.String = var9.getMessage();// 23 if (var10001 == null) { var10001 = "ERROR"; } @@ -39,18 +39,18 @@ class TestTryCatchExpressions { var4 = var10001; } - var var7: String = var4;// 24 + var var7: java.lang.String = var4;// 24 var6 = var10000; - var var13: String; + var var13: java.lang.String; try { var10000 = var6; var13 = var7; - var4 = StringsKt.repeat(x as CharSequence, 5);// 25 + var4 = StringsKt.repeat(x as java.lang.CharSequence, 5);// 25 } catch (RuntimeException var8) {// 26 var10000 = var10000; var13 = var4; - var var10002: String = var8.getMessage();// 27 + var var10002: java.lang.String = var8.getMessage();// 27 if (var10002 == null) { var10002 = "ERROR"; } @@ -61,11 +61,11 @@ class TestTryCatchExpressions { var10000.test0(var13 + var4);// 18 }// 30 - fun test2(a: String, b: String) { - var var15: Any = a;// 33 + public fun test2(a: String, b: String) { + var var15: java.lang.String = a;// 33 var var7: TestTryCatchExpressions = this; - var var4: String; + var var4: java.lang.String; var var10000: TestTryCatchExpressions; try { var10000 = var7; @@ -87,12 +87,12 @@ class TestTryCatchExpressions { var4 = var15;// 51 } - var var8: String = var4;// 52 + var var8: java.lang.String = var4;// 52 var7 = var10000; - var var10001: String; + var var10001: java.lang.String; try { - var4 = StringsKt.repeat(var15 as CharSequence, 5); + var4 = StringsKt.repeat(var15 as java.lang.CharSequence, 5); var15 = var4; var10000 = var7; var10001 = var8; @@ -101,7 +101,7 @@ class TestTryCatchExpressions { var10000 = var10000; var10001 = var4; System.out.println(var15);// 55 - var var10003: String = var12.getMessage(); + var var10003: java.lang.String = var12.getMessage(); if (var10003 == null) { var10003 = ""; } diff --git a/plugins/kotlin/testData/results/pkg/TestTryFinallyExpressions.dec b/plugins/kotlin/testData/results/pkg/TestTryFinallyExpressions.dec index c06ead4362..f90533dff6 100644 --- a/plugins/kotlin/testData/results/pkg/TestTryFinallyExpressions.dec +++ b/plugins/kotlin/testData/results/pkg/TestTryFinallyExpressions.dec @@ -3,11 +3,11 @@ package pkg import java.io.IOException class TestTryFinallyExpressions { - fun test0(s: String) { + public fun test0(s: String) { label15: { try { - var var2: String = StringsKt.repeat(s as CharSequence, 5);// 8 - } catch (Throwable var4) { + var var2: java.lang.String = StringsKt.repeat(s as java.lang.CharSequence, 5);// 8 + } catch (java.lang.Throwable var4) { System.out.println("bye");// 10 } @@ -15,21 +15,21 @@ class TestTryFinallyExpressions { } } - fun test1(a: String, b: String) { + public fun test1(a: String, b: String) { label24: { - var x: String = a;// 15 + var x: java.lang.String = a;// 15 try { - var var4: String = StringsKt.repeat(x as CharSequence, 5);// 17 - } catch (Throwable var9) { + var var4: java.lang.String = StringsKt.repeat(x as java.lang.CharSequence, 5);// 17 + } catch (java.lang.Throwable var9) { ; } x = b;// 18 19 20 try { - var var15: String = StringsKt.repeat(x as CharSequence, 5);// 21 - } catch (Throwable var8) { + var var15: java.lang.String = StringsKt.repeat(x as java.lang.CharSequence, 5);// 21 + } catch (java.lang.Throwable var8) { System.out.println(a);// 23 } @@ -37,9 +37,9 @@ class TestTryFinallyExpressions { } } - fun test2(a: String, b: String) { + public fun test2(a: String, b: String) { label68: { - var var19: Any = a;// 28 + var var19: java.lang.String = a;// 28 label69: { label70: { @@ -56,9 +56,9 @@ class TestTryFinallyExpressions { } catch (IOException var11) {// 36 var19 = a;// 37 this.test1(a, a);// 38 - var var4: String = a;// 39 + var var4: java.lang.String = a;// 39 } - } catch (Throwable var12) { + } catch (java.lang.Throwable var12) { var19 = if (var19 == a) b else a;// 41 42 44 } @@ -70,8 +70,8 @@ class TestTryFinallyExpressions { } try { - var19 = StringsKt.repeat(var19 as CharSequence, 5);// 47 - } catch (Throwable var10) { + var19 = StringsKt.repeat(var19 as java.lang.CharSequence, 5);// 47 + } catch (java.lang.Throwable var10) { System.out.println(var19);// 49 } diff --git a/plugins/kotlin/testData/results/pkg/TestVars.dec b/plugins/kotlin/testData/results/pkg/TestVars.dec index 20576f4fea..e2eb7f5894 100644 --- a/plugins/kotlin/testData/results/pkg/TestVars.dec +++ b/plugins/kotlin/testData/results/pkg/TestVars.dec @@ -1,15 +1,15 @@ package pkg class TestVars { - fun testVar() { + public fun testVar() { System.out.println("initial");// 5 6 }// 9 - fun testVal() { + public fun testVal() { System.out.println("initial");// 12 13 }// 16 - fun testPhi(bl: Boolean) { + public fun testPhi(bl: Boolean) { var var3: Byte; if (bl) {// 21 var3 = 1;// 22 @@ -20,7 +20,7 @@ class TestVars { System.out.println(var3);// 27 }// 28 - fun testIfExpr(bl: Boolean) { + public fun testIfExpr(bl: Boolean) { System.out.println(if (bl) 1 else 2);// 31 32 34 37 }// 38 } diff --git a/plugins/kotlin/testData/results/pkg/TestWhen.dec b/plugins/kotlin/testData/results/pkg/TestWhen.dec index 76d811f80d..a29a8ffc73 100644 --- a/plugins/kotlin/testData/results/pkg/TestWhen.dec +++ b/plugins/kotlin/testData/results/pkg/TestWhen.dec @@ -1,34 +1,34 @@ package pkg class TestWhen { - fun testStatement(obj: Any) { + public fun testStatement(obj: Any) { if (obj == 1) {// 5 6 System.out.println("1"); } else if (obj == "2") {// 7 System.out.println("2"); - } else if (obj is Double) {// 8 + } else if (obj is java.lang.Double) {// 8 System.out.println("Double"); - } else if (obj !is Long) {// 9 + } else if (obj !is java.lang.Long) {// 9 System.out.println("Not Long"); } else { System.out.println("else");// 10 } }// 12 - fun testExpression(obj: Any): Int { - return if (obj == 1) 1 else (if (obj is Double) 2 else (if (obj == "4") 4 else (if (obj !is Long) 3 else 5)));// 15 16 17 18 19 20 + public fun testExpression(obj: Any): Int { + return if (obj == 1) 1 else (if (obj is java.lang.Double) 2 else (if (obj == "4") 4 else (if (obj !is java.lang.Long) 3 else 5)));// 15 16 17 18 19 20 } - fun testStatement2(a: Any, b: Any) { + public fun testStatement2(a: Any, b: Any) { if (a == 15) {// 26 System.out.println("a == 15"); } else if (a == "!!") {// 27 System.out.println("a == !!"); } else if (a is Integer) {// 28 System.out.println("a is Int"); - } else if (a is String) {// 29 + } else if (a is java.lang.String) {// 29 System.out.println("a is String"); - } else if (b is Double) {// 30 + } else if (b is java.lang.Double) {// 30 System.out.println("b is Double"); } else if (a is Unit) {// 31 System.out.println("a is Unit"); @@ -37,7 +37,7 @@ class TestWhen { } }// 34 - fun booleanNightmares(a: Boolean, b: Boolean, c: Boolean, d: Boolean, e: Boolean, f: Boolean, g: Boolean) { + public fun booleanNightmares(a: Boolean, b: Boolean, c: Boolean, d: Boolean, e: Boolean, f: Boolean, g: Boolean) { if (a == (b != c)) {// 37 38 System.out.println("-_-"); } else if (a == (b && !e)) {// 39 diff --git a/plugins/kotlin/testData/results/pkg/TestWhenBoolean.dec b/plugins/kotlin/testData/results/pkg/TestWhenBoolean.dec index fddb00ed10..e288eca3d1 100644 --- a/plugins/kotlin/testData/results/pkg/TestWhenBoolean.dec +++ b/plugins/kotlin/testData/results/pkg/TestWhenBoolean.dec @@ -1,7 +1,7 @@ package pkg class TestWhenBoolean { - fun testIf(a: Int, b: Int, c: Int, d: Int) { + public fun testIf(a: Int, b: Int, c: Int, d: Int) { if (a == 1// 6 18 || b == 2// 7 || c != 3// 8 diff --git a/plugins/kotlin/testData/results/pkg/TestWhenControlFlow.dec b/plugins/kotlin/testData/results/pkg/TestWhenControlFlow.dec index 40d0b29a8d..850f632e23 100644 --- a/plugins/kotlin/testData/results/pkg/TestWhenControlFlow.dec +++ b/plugins/kotlin/testData/results/pkg/TestWhenControlFlow.dec @@ -1,7 +1,7 @@ package pkg class TestWhenControlFlow { - fun test1(x: Int) { + public fun test1(x: Int) { var xx: Int = x;// 5 while (xx > 0) {// 7 diff --git a/plugins/kotlin/testData/src/kt/pkg/TestContracts.kt b/plugins/kotlin/testData/src/kt/pkg/TestContracts.kt new file mode 100644 index 0000000000..70b75e4084 --- /dev/null +++ b/plugins/kotlin/testData/src/kt/pkg/TestContracts.kt @@ -0,0 +1,55 @@ +package pkg + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +@OptIn(ExperimentalContracts::class) +class TestContracts { + fun testSimpleContract(x: Int?): Int { + contract { + returns() implies (x != null) + } + if (x == null) error("x is null") + return x + } + + fun testBooleanContract(a: Boolean, b: Boolean): Boolean? { + contract { + returns(true) implies (!a && !b) + returns(null) implies (a && b) + returns(false) implies ((a && !b) || (!a && b)) + } + + return if (a && b) null else a || b + } + + fun testTypeContract(x: Any?): Int { + contract { + returns() implies (x is Int) + } + if (x !is Int) error("x is not Int") + return x + } + + fun testFunctionalContract(f: () -> Int): Int { + contract { + callsInPlace(f, InvocationKind.EXACTLY_ONCE) + } + return f() + } + + fun testFunctionalContract2(f: () -> Int, b: Boolean): Int { + contract { + callsInPlace(f, InvocationKind.AT_MOST_ONCE) + } + return if (b) f() else 0 + } + + fun testFunctionalContract3(f: () -> Int, i: Int): Int { + contract { + callsInPlace(f) + } + return (0..i).sumOf { f() } + } +} diff --git a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java index 9ebc8e85a3..70a5fe4ce4 100644 --- a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java +++ b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java @@ -96,6 +96,10 @@ public static void startMethod(VarProcessor varProcessor) { context.counterContainer = new CounterContainer(); } + public static void setImportCollector(ImportCollector importCollector) { + getCurrentContext().importCollector = importCollector; + } + // ***************************************************************************** // context access // ***************************************************************************** diff --git a/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java b/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java index 8f0dd8013a..e681ace76d 100644 --- a/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java +++ b/src/org/jetbrains/java/decompiler/main/collectors/ImportCollector.java @@ -18,14 +18,14 @@ public class ImportCollector { private static final String JAVA_LANG_PACKAGE = "java.lang"; - private final Map mapSimpleNames = new HashMap<>(); - private final Set setNotImportedNames = new HashSet<>(); + protected final Map mapSimpleNames = new HashMap<>(); + protected final Set setNotImportedNames = new HashSet<>(); // set of field names in this class and all its predecessors. - private final Set setFieldNames = new HashSet<>(); - private final Map> mapInnerClassNames = new HashMap<>(); - private final String currentPackageSlash; - private final String currentPackagePoint; - private boolean writeLocked = false; + protected final Set setFieldNames = new HashSet<>(); + protected final Map> mapInnerClassNames = new HashMap<>(); + protected final String currentPackageSlash; + protected final String currentPackagePoint; + protected boolean writeLocked = false; public ImportCollector(ClassNode root) { String clName = root.classStruct.qualifiedName; @@ -64,6 +64,16 @@ public ImportCollector(ClassNode root) { collectConflictingShortNames(root, new HashMap<>()); } + + public ImportCollector(ImportCollector other) { + this.mapSimpleNames.putAll(other.mapSimpleNames); + this.setNotImportedNames.addAll(other.setNotImportedNames); + this.setFieldNames.addAll(other.setFieldNames); + this.mapInnerClassNames.putAll(other.mapInnerClassNames); + this.currentPackageSlash = other.currentPackageSlash; + this.currentPackagePoint = other.currentPackagePoint; + this.writeLocked = other.writeLocked; + } /** * Check whether the package-less name ClassName is shaded by variable in a context of @@ -190,21 +200,27 @@ public void writeImports(TextBuffer buffer, boolean addSeparator) { } } - private List packImports() { + protected List packImports() { return mapSimpleNames.entrySet().stream() - .filter(ent -> - // exclude the current class or one of the nested ones - // empty, java.lang and the current packages - !setNotImportedNames.contains(ent.getKey()) && - !ent.getValue().isEmpty() && - !JAVA_LANG_PACKAGE.equals(ent.getValue()) && - !ent.getValue().equals(currentPackagePoint) - ) + .filter(this::keepImport) .sorted(Map.Entry.comparingByValue().thenComparing(Map.Entry.comparingByKey())) .map(ent -> ent.getValue() + "." + ent.getKey()) .collect(Collectors.toList()); } + /** + * Check whether to keep the given entry in the import list. + * + * @param ent the entry in the map containing the class name and its corresponding package name + * @return true if the entry should be kept for importing, false otherwise + */ + protected boolean keepImport(Map.Entry ent) { + return !setNotImportedNames.contains(ent.getKey()) && + !ent.getValue().isEmpty() && + !JAVA_LANG_PACKAGE.equals(ent.getValue()) && + !ent.getValue().equals(currentPackagePoint); + } + private void collectConflictingShortNames(ClassNode root, Map rootNames) { Map names = new HashMap<>(rootNames); getSuperClassInnerClasses(root, names);