mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-11 15:51:26 +00:00
Compare commits
143 Commits
push/pdn_b
...
rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe4400c768 | ||
|
|
3cbd0b3496 | ||
|
|
e3beb060f7 | ||
|
|
360e1ed0d6 | ||
|
|
63771c6368 | ||
|
|
8549ec7645 | ||
|
|
4b3970ec58 | ||
|
|
bded4842ee | ||
|
|
1d00a58922 | ||
|
|
d332f0f236 | ||
|
|
b40afdbe19 | ||
|
|
90e158f54c | ||
|
|
05b880f9a3 | ||
|
|
9d53f5f7d7 | ||
|
|
966b1dbb7f | ||
|
|
59c24718c2 | ||
|
|
a406a897d7 | ||
|
|
dde3b3a245 | ||
|
|
9915356c1f | ||
|
|
075ff1a92c | ||
|
|
2a26b1bc01 | ||
|
|
15e73d1260 | ||
|
|
219afa4f9f | ||
|
|
b82f04053f | ||
|
|
8a6b2dbbfc | ||
|
|
21d2548073 | ||
|
|
bf23dd3aaa | ||
|
|
5beb4bd340 | ||
|
|
0121860b64 | ||
|
|
a42c8d811a | ||
|
|
b986297a90 | ||
|
|
a86e1d18c9 | ||
|
|
7cdf677368 | ||
|
|
8200c0ff21 | ||
|
|
7ae324657d | ||
|
|
082f7709b5 | ||
|
|
eae19c52b9 | ||
|
|
29759e0712 | ||
|
|
f168c401b3 | ||
|
|
43232f4167 | ||
|
|
e0533892a7 | ||
|
|
eff6863d11 | ||
|
|
b0292cc3a7 | ||
|
|
de72511c04 | ||
|
|
28a84b7370 | ||
|
|
e89819047b | ||
|
|
5995f73662 | ||
|
|
9ff208d840 | ||
|
|
21392e6b21 | ||
|
|
3ebf25fe5c | ||
|
|
67f4f8fde2 | ||
|
|
4d349c8623 | ||
|
|
eabe9b5ae8 | ||
|
|
0d3a2e7c54 | ||
|
|
8ae57107c4 | ||
|
|
b7c4c23da1 | ||
|
|
6c51df9fec | ||
|
|
981523ce03 | ||
|
|
981bb30707 | ||
|
|
9914f0ee65 | ||
|
|
6fb246a352 | ||
|
|
32a1e7dc82 | ||
|
|
ad2d1ea15b | ||
|
|
ce0f22d299 | ||
|
|
0fb369f6ae | ||
|
|
7ad2732d3e | ||
|
|
ba67067629 | ||
|
|
601b18a4d8 | ||
|
|
25351185d4 | ||
|
|
5e4b94a3ca | ||
|
|
e3a16098e4 | ||
|
|
056def876e | ||
|
|
05437aed3d | ||
|
|
18461f067b | ||
|
|
c04f3bfbf1 | ||
|
|
ab3268957c | ||
|
|
bf2449876a | ||
|
|
07b2cff0aa | ||
|
|
aec9bd7d52 | ||
|
|
1523c95379 | ||
|
|
7c9efb1f4f | ||
|
|
1360d75849 | ||
|
|
5028859097 | ||
|
|
1b03ba305a | ||
|
|
def8d30322 | ||
|
|
500cc0c33c | ||
|
|
ed09405d2e | ||
|
|
8c6a32cd0b | ||
|
|
fefa08bfc9 | ||
|
|
53564770f2 | ||
|
|
d89a3024ac | ||
|
|
23105b1c7e | ||
|
|
80034fce1b | ||
|
|
933b4b2645 | ||
|
|
ebe9b23dcc | ||
|
|
dd81988a58 | ||
|
|
1800869ed5 | ||
|
|
c8c36d7d56 | ||
|
|
25cdcd6dd9 | ||
|
|
d9a81aa8fc | ||
|
|
a93ce4aa80 | ||
|
|
7e31c16983 | ||
|
|
92e1fd6cfb | ||
|
|
ee29f8294e | ||
|
|
d76f55396a | ||
|
|
a1bed57179 | ||
|
|
fa7eac71f1 | ||
|
|
ef5b692f9b | ||
|
|
b9a4890a14 | ||
|
|
d3c612a035 | ||
|
|
9ba7338a9c | ||
|
|
30a1a95a3a | ||
|
|
525bce6cc5 | ||
|
|
2e0412679c | ||
|
|
85d4cf8fc5 | ||
|
|
de853b8961 | ||
|
|
19685e9974 | ||
|
|
4e46b0ca90 | ||
|
|
47b2adbb78 | ||
|
|
d19e59576c | ||
|
|
4095c54028 | ||
|
|
ec3ef1bb03 | ||
|
|
a497b1fbf7 | ||
|
|
27a013de2a | ||
|
|
f36a68dcd4 | ||
|
|
8a68bc4061 | ||
|
|
d6a7780971 | ||
|
|
1ac8602bc8 | ||
|
|
503053dfb2 | ||
|
|
6b62d18da0 | ||
|
|
b181e3095d | ||
|
|
d2108f5dea | ||
|
|
0989a202b4 | ||
|
|
6f7091291e | ||
|
|
f08f917160 | ||
|
|
eab81dab2d | ||
|
|
02aa1246b8 | ||
|
|
18a17249c7 | ||
|
|
f96265b06f | ||
|
|
23152df154 | ||
|
|
c36275787e | ||
|
|
d729c8ce7d | ||
|
|
3a19f77408 |
@@ -1154,6 +1154,7 @@
|
||||
<delete dir="${output}/mock-runtime-src" failonerror="false"/>
|
||||
<mkdir dir="${output}/mock-runtime-src"/>
|
||||
<copy file="${basedir}/libraries/stdlib/src/kotlin/util/Standard.kt" todir="${output}/mock-runtime-src"/>
|
||||
<copy file="${basedir}/libraries/stdlib/src/kotlin/internal/Annotations.kt" todir="${output}/mock-runtime-src"/>
|
||||
|
||||
<new-kotlinc output="${output}/classes/mock-runtime" moduleName="kotlin-stdlib">
|
||||
<src>
|
||||
|
||||
@@ -108,6 +108,16 @@ public abstract class AnnotationCodegen {
|
||||
"Inconsistent target list for lambda annotation: " + applicableTargets + " on " + annotated;
|
||||
continue;
|
||||
}
|
||||
if (annotated instanceof ClassDescriptor
|
||||
&& !applicableTargets.contains(KotlinTarget.CLASS)
|
||||
&& !applicableTargets.contains(KotlinTarget.ANNOTATION_CLASS)) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) annotated;
|
||||
if (classDescriptor.getVisibility() == Visibilities.LOCAL) {
|
||||
assert applicableTargets.contains(KotlinTarget.EXPRESSION) :
|
||||
"Inconsistent target list for object literal annotation: " + applicableTargets + " on " + annotated;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String descriptor = genAnnotation(annotation);
|
||||
if (descriptor != null) {
|
||||
|
||||
@@ -63,7 +63,6 @@ import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.isNullableType;
|
||||
@@ -257,8 +256,7 @@ public class AsmUtil {
|
||||
Classes in byte code should be public or package private
|
||||
*/
|
||||
public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) {
|
||||
if (DescriptorUtils.isTopLevelDeclaration(descriptor) ||
|
||||
descriptor.getVisibility() == Visibilities.PUBLIC ||
|
||||
if (descriptor.getVisibility() == Visibilities.PUBLIC ||
|
||||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
|
||||
descriptor.getVisibility() == Visibilities.LOCAL ||
|
||||
descriptor.getVisibility() == Visibilities.INTERNAL) {
|
||||
@@ -782,39 +780,26 @@ public class AsmUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull GenerationState state) {
|
||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), true);
|
||||
JvmCodegenUtil.writeAbiVersion(av);
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
public static void writeAnnotationData(
|
||||
@NotNull AnnotationVisitor av,
|
||||
@NotNull DescriptorSerializer serializer,
|
||||
@NotNull MessageLite message,
|
||||
boolean old
|
||||
@NotNull MessageLite message
|
||||
) {
|
||||
byte[] bytes = serializer.serialize(message);
|
||||
|
||||
AnnotationVisitor data = av.visitArray(old ? JvmAnnotationNames.DATA_FIELD_NAME : JvmAnnotationNames.METADATA_DATA_FIELD_NAME);
|
||||
AnnotationVisitor data = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME);
|
||||
for (String string : BitEncoding.encodeBytes(bytes)) {
|
||||
data.visit(null, string);
|
||||
}
|
||||
data.visitEnd();
|
||||
AnnotationVisitor strings = av.visitArray(
|
||||
old ? JvmAnnotationNames.STRINGS_FIELD_NAME : JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME
|
||||
);
|
||||
|
||||
AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME);
|
||||
for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) {
|
||||
strings.visit(null, string);
|
||||
}
|
||||
strings.visitEnd();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
||||
return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) {
|
||||
return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName));
|
||||
|
||||
@@ -286,13 +286,23 @@ public class ClassFileFactory implements OutputFileCollection {
|
||||
@NotNull
|
||||
@Override
|
||||
public byte[] asByteArray() {
|
||||
return generators.get(relativeClassFilePath).asBytes(builderFactory);
|
||||
try {
|
||||
return generators.get(relativeClassFilePath).asBytes(builderFactory);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error generating class file " + this.toString() + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String asText() {
|
||||
return generators.get(relativeClassFilePath).asText(builderFactory);
|
||||
try {
|
||||
return generators.get(relativeClassFilePath).asText(builderFactory);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error generating class file " + this.toString() + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -60,7 +59,6 @@ import java.util.List;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.ExpressionCodegen.generateClassLiteralReference;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.writeAbiVersion;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||
@@ -219,9 +217,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
writeKotlinSyntheticClassAnnotation(v, state);
|
||||
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
final DescriptorSerializer serializer =
|
||||
DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
|
||||
|
||||
@@ -230,15 +226,10 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.SYNTHETIC_CLASS, new Function1<AnnotationVisitor, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(AnnotationVisitor av) {
|
||||
writeAnnotationData(av, serializer, functionProto, false);
|
||||
writeAnnotationData(av, serializer, functionProto);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FUNCTION), true);
|
||||
writeAbiVersion(av);
|
||||
writeAnnotationData(av, serializer, functionProto, true);
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,8 +25,8 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import kotlin.Pair;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.Unit;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -2118,7 +2118,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
FieldAccessorKind fieldAccessorKind = FieldAccessorKind.NORMAL;
|
||||
boolean isBackingFieldInClassCompanion = JvmAbi.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
if (isBackingFieldInClassCompanion && forceField) {
|
||||
if (isBackingFieldInClassCompanion && (forceField || propertyDescriptor.isConst() && Visibilities.isPrivate(propertyDescriptor.getVisibility()))) {
|
||||
fieldAccessorKind = FieldAccessorKind.IN_CLASS_COMPANION;
|
||||
}
|
||||
else if (syntheticBackingField && context.getFirstCrossInlineOrNonInlineContext().getParentContext().getContextDescriptor() != containingDeclaration) {
|
||||
@@ -2425,24 +2425,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private CallGenerator getOrCreateCallGenerator(
|
||||
@NotNull CallableDescriptor descriptor,
|
||||
@Nullable KtElement callElement,
|
||||
@Nullable TypeParameterMappings typeParameterMappings
|
||||
@Nullable TypeParameterMappings typeParameterMappings,
|
||||
boolean isDefaultCompilation
|
||||
) {
|
||||
if (callElement == null) return defaultCallGenerator;
|
||||
|
||||
// We should inline callable containing reified type parameters even if inline is disabled
|
||||
// because they may contain something to reify and straight call will probably fail at runtime
|
||||
boolean isInline = (state.isInlineEnabled() || InlineUtil.containsReifiedTypeParameters(descriptor)) &&
|
||||
InlineUtil.isInline(descriptor);
|
||||
(InlineUtil.isInline(descriptor) || InlineUtil.isArrayConstructorWithLambda(descriptor));
|
||||
|
||||
if (!isInline) return defaultCallGenerator;
|
||||
|
||||
SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal());
|
||||
return new InlineCodegen(this, state, original, callElement, typeParameterMappings);
|
||||
FunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((FunctionDescriptor) descriptor.getOriginal());
|
||||
return new InlineCodegen(this, state, original, callElement, typeParameterMappings, isDefaultCompilation);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected CallGenerator getOrCreateCallGeneratorForDefaultImplBody(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) {
|
||||
return getOrCreateCallGenerator(descriptor, function, null);
|
||||
return getOrCreateCallGenerator(descriptor, function, null, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -2454,6 +2455,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
KotlinType type = TypeUtils.uncaptureTypeForInlineMapping(entry.getValue());
|
||||
|
||||
boolean isReified = key.isReified() || InlineUtil.isArrayConstructorWithLambda(resolvedCall.getResultingDescriptor());
|
||||
|
||||
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||
if (typeParameterAndReificationArgument == null) {
|
||||
// type is not generic
|
||||
@@ -2461,21 +2464,17 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type asmType = typeMapper.mapTypeParameter(type, signatureWriter);
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.getName().getIdentifier(),
|
||||
type,
|
||||
asmType,
|
||||
signatureWriter.toString(),
|
||||
key.isReified());
|
||||
key.getName().getIdentifier(), type, asmType, signatureWriter.toString(), isReified
|
||||
);
|
||||
}
|
||||
else {
|
||||
mappings.addParameterMappingForFurtherReification(
|
||||
key.getName().getIdentifier(), type,
|
||||
typeParameterAndReificationArgument.getSecond(), key.isReified());
|
||||
key.getName().getIdentifier(), type, typeParameterAndReificationArgument.getSecond(), isReified
|
||||
);
|
||||
}
|
||||
}
|
||||
return getOrCreateCallGenerator(
|
||||
resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings
|
||||
);
|
||||
resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -3345,7 +3344,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
Type type = expressionType(expression);
|
||||
if (type.getSort() == Type.ARRAY) {
|
||||
//noinspection ConstantConditions
|
||||
return generateNewArray(expression, bindingContext.getType(expression));
|
||||
return generateNewArray(expression, bindingContext.getType(expression), resolvedCall);
|
||||
}
|
||||
|
||||
return generateConstructorCall(resolvedCall, type);
|
||||
@@ -3391,20 +3390,25 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
});
|
||||
}
|
||||
|
||||
public StackValue generateNewArray(@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType) {
|
||||
assert expression.getValueArguments().size() == 1 : "Size argument expected";
|
||||
public StackValue generateNewArray(
|
||||
@NotNull KtCallExpression expression, @NotNull final KotlinType arrayType, @NotNull ResolvedCall<?> resolvedCall
|
||||
) {
|
||||
List<KtValueArgument> args = expression.getValueArguments();
|
||||
assert args.size() == 1 || args.size() == 2 : "Unknown constructor called: " + args.size() + " arguments";
|
||||
|
||||
final KtExpression sizeExpression = expression.getValueArguments().get(0).getArgumentExpression();
|
||||
Type type = typeMapper.mapType(arrayType);
|
||||
if (args.size() == 1) {
|
||||
final KtExpression sizeExpression = args.get(0).getArgumentExpression();
|
||||
return StackValue.operation(typeMapper.mapType(arrayType), new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
gen(sizeExpression, Type.INT_TYPE);
|
||||
newArrayInstruction(arrayType);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(InstructionAdapter v) {
|
||||
gen(sizeExpression, Type.INT_TYPE);
|
||||
newArrayInstruction(arrayType);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
return invokeFunction(resolvedCall, StackValue.none());
|
||||
}
|
||||
|
||||
public void newArrayInstruction(@NotNull KotlinType arrayType) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.bridges.Bridge;
|
||||
@@ -672,18 +673,9 @@ public class FunctionCodegen {
|
||||
}
|
||||
else {
|
||||
mv.visitCode();
|
||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen);
|
||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
|
||||
endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
|
||||
generateOldDefaultForFun(defaultMethod,
|
||||
JvmDeclarationOriginKt.Synthetic(function, functionDescriptor),
|
||||
flags,
|
||||
getThrownExceptions(functionDescriptor, typeMapper),
|
||||
(owner.getContextKind() == OwnerKind.DEFAULT_IMPLS ?
|
||||
typeMapper.mapDefaultImpls((ClassDescriptor) functionDescriptor.getContainingDeclaration()) :
|
||||
typeMapper.mapImplementationOwner(functionDescriptor)).getInternalName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,7 +685,8 @@ public class FunctionCodegen {
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull DefaultParameterValueLoader loadStrategy,
|
||||
@Nullable KtNamedFunction function,
|
||||
@NotNull MemberCodegen<?> parentCodegen
|
||||
@NotNull MemberCodegen<?> parentCodegen,
|
||||
@NotNull Method defaultMethod
|
||||
) {
|
||||
GenerationState state = parentCodegen.state;
|
||||
JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());
|
||||
@@ -705,6 +698,9 @@ public class FunctionCodegen {
|
||||
|
||||
CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
genDefaultSuperCallCheckIfNeeded(iv, defaultMethod);
|
||||
|
||||
loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
|
||||
|
||||
List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
|
||||
@@ -714,8 +710,6 @@ public class FunctionCodegen {
|
||||
capturedArgumentsCount++;
|
||||
}
|
||||
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
int maskIndex = 0;
|
||||
List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
|
||||
for (int index = 0; index < valueParameters.size(); index++) {
|
||||
@@ -748,36 +742,20 @@ public class FunctionCodegen {
|
||||
iv.areturn(signature.getReturnType());
|
||||
}
|
||||
|
||||
private void generateOldDefaultForFun(
|
||||
Method newDefaultMethod,
|
||||
JvmDeclarationOrigin origin,
|
||||
int flags,
|
||||
String[] exceptions,
|
||||
String owner
|
||||
) {
|
||||
if ("<init>".equals(newDefaultMethod.getName())) {
|
||||
private static void genDefaultSuperCallCheckIfNeeded(@NotNull InstructionAdapter iv, @NotNull Method defaultMethod) {
|
||||
String defaultMethodName = defaultMethod.getName();
|
||||
if ("<init>".equals(defaultMethodName)) {
|
||||
return;
|
||||
}
|
||||
String oldSignature = newDefaultMethod.getDescriptor().replaceFirst("Ljava/lang/Object;\\)", ")");
|
||||
MethodVisitor mv = v.newMethod(
|
||||
origin,
|
||||
flags,
|
||||
newDefaultMethod.getName(),
|
||||
oldSignature,
|
||||
null,
|
||||
exceptions
|
||||
);
|
||||
mv.visitCode();
|
||||
int index = 0;
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
for (Type type: Type.getArgumentTypes(oldSignature)) {
|
||||
iv.load(index, type);
|
||||
index += type.getSize();
|
||||
}
|
||||
iv.aconst(null);
|
||||
iv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, newDefaultMethod.getName(), newDefaultMethod.getDescriptor(), false);
|
||||
iv.areturn(newDefaultMethod.getReturnType());
|
||||
mv.visitEnd();
|
||||
Label end = new Label();
|
||||
int handleIndex = (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2) - 2; /*-1 for this, and -1 for handle*/
|
||||
iv.load(handleIndex, OBJECT_TYPE);
|
||||
iv.ifnull(end);
|
||||
AsmUtil.genThrow(iv,
|
||||
"java/lang/UnsupportedOperationException",
|
||||
"Super calls with default arguments not supported in this target, function: " +
|
||||
StringsKt.substringBeforeLast(defaultMethodName, JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodName));
|
||||
iv.visitLabel(end);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -110,7 +110,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
if (referencedFunction instanceof ConstructorDescriptor) {
|
||||
if (returnType.getSort() == Type.ARRAY) {
|
||||
//noinspection ConstantConditions
|
||||
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType());
|
||||
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
|
||||
}
|
||||
else {
|
||||
result = codegen.generateConstructorCall(fakeResolvedCall, returnType);
|
||||
|
||||
@@ -41,7 +41,6 @@ import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -248,7 +247,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
final DescriptorSerializer serializer =
|
||||
DescriptorSerializer.create(descriptor, new JvmSerializerExtension(v.getSerializationBindings(), state));
|
||||
|
||||
@@ -257,15 +256,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.CLASS, new Function1<AnnotationVisitor, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(AnnotationVisitor av) {
|
||||
writeAnnotationData(av, serializer, classProto, false);
|
||||
writeAnnotationData(av, serializer, classProto);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
|
||||
AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
|
||||
writeAbiVersion(av);
|
||||
writeAnnotationData(av, serializer, classProto, true);
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
private void writeEnclosingMethod() {
|
||||
|
||||
@@ -146,11 +146,9 @@ class InterfaceImplBodyCodegen(
|
||||
})
|
||||
}
|
||||
|
||||
override fun generateKotlinAnnotation() {
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
(v as InterfaceImplClassBuilder).stopCounting()
|
||||
|
||||
AsmUtil.writeKotlinSyntheticClassAnnotation(v, state)
|
||||
|
||||
writeSyntheticClassMetadata(v);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.context.RootContext;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -43,7 +41,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -220,8 +217,4 @@ public class JvmCodegenUtil {
|
||||
public static String getMappingFileName(@NotNull String moduleName) {
|
||||
return "META-INF/" + moduleName + "." + ModuleMapping.MAPPING_FILE_EXT;
|
||||
}
|
||||
|
||||
public static void writeAbiVersion(@NotNull AnnotationVisitor av) {
|
||||
av.visit(JvmAnnotationNames.VERSION_FIELD_NAME, JvmMetadataVersion.INSTANCE.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
generateSyntheticParts();
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
generateKotlinAnnotation();
|
||||
generateKotlinMetadataAnnotation();
|
||||
}
|
||||
|
||||
done();
|
||||
@@ -132,7 +132,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
protected void generateSyntheticParts() {
|
||||
}
|
||||
|
||||
protected abstract void generateKotlinAnnotation();
|
||||
protected abstract void generateKotlinMetadataAnnotation();
|
||||
|
||||
@Nullable
|
||||
protected ClassDescriptor classForInnerClassRecord() {
|
||||
@@ -601,12 +601,13 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
|
||||
boolean forceField = (JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration())) ||
|
||||
boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) &&
|
||||
!isCompanionObject(accessor.getContainingDeclaration());
|
||||
boolean forceField = forceFieldForCompanionProperty ||
|
||||
syntheticBackingField ||
|
||||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
|
||||
StackValue property = codegen.intermediateValueForProperty(
|
||||
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), true, StackValue.none()
|
||||
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), forceFieldForCompanionProperty, StackValue.none()
|
||||
);
|
||||
|
||||
InstructionAdapter iv = codegen.v;
|
||||
|
||||
@@ -49,7 +49,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -113,7 +112,7 @@ class MultifileClassCodegen(
|
||||
|
||||
generateDelegatesToPreviouslyCompiledParts(generateCallableMemberTasks, partFqNames)
|
||||
|
||||
if (!generateCallableMemberTasks.isEmpty()) {
|
||||
if (!partFqNames.isEmpty()) {
|
||||
generateMultifileFacadeClass(generateCallableMemberTasks, partFqNames)
|
||||
}
|
||||
}
|
||||
@@ -213,7 +212,8 @@ class MultifileClassCodegen(
|
||||
if (declaration is KtNamedFunction || declaration is KtProperty) {
|
||||
val descriptor = state.bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration)
|
||||
assert(descriptor is CallableMemberDescriptor) { "Expected callable member, was " + descriptor + " for " + declaration.text }
|
||||
if (!Visibilities.isPrivate((descriptor as CallableMemberDescriptor).visibility)) {
|
||||
if (!Visibilities.isPrivate((descriptor as CallableMemberDescriptor).visibility)
|
||||
&& AsmUtil.getVisibilityAccessFlag(descriptor) != Opcodes.ACC_PRIVATE) {
|
||||
generateCallableMemberTasks.put(descriptor, { memberCodegen.genFunctionOrProperty(declaration) })
|
||||
}
|
||||
}
|
||||
@@ -273,31 +273,20 @@ class MultifileClassCodegen(
|
||||
if (state.classBuilderMode != ClassBuilderMode.FULL) return
|
||||
if (files.any { it.isScript }) return
|
||||
|
||||
val partInternalNames = partFqNames.map(AsmUtil::internalNameByFqNameWithoutInnerClasses).sorted()
|
||||
|
||||
fun writePartNames(av: AnnotationVisitor, fieldName: String) {
|
||||
val arv = av.visitArray(fieldName)
|
||||
for (internalName in partInternalNames) {
|
||||
writeKotlinMetadata(classBuilder, KotlinClassHeader.Kind.MULTIFILE_CLASS) { av ->
|
||||
val arv = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME)
|
||||
for (internalName in partFqNames.map(AsmUtil::internalNameByFqNameWithoutInnerClasses).sorted()) {
|
||||
arv.visit(null, internalName)
|
||||
}
|
||||
arv.visitEnd()
|
||||
}
|
||||
|
||||
writeKotlinMetadata(classBuilder, KotlinClassHeader.Kind.MULTIFILE_CLASS) { av ->
|
||||
writePartNames(av, JvmAnnotationNames.METADATA_DATA_FIELD_NAME)
|
||||
}
|
||||
|
||||
val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true)
|
||||
JvmCodegenUtil.writeAbiVersion(av)
|
||||
writePartNames(av, JvmAnnotationNames.FILE_PART_CLASS_NAMES_FIELD_NAME)
|
||||
av.visitEnd()
|
||||
}
|
||||
|
||||
private fun createCodegenForPartOfMultifileFacade(facadeContext: FieldOwnerContext<*>): MemberCodegen<KtFile> =
|
||||
object : MemberCodegen<KtFile>(state, null, facadeContext, null, classBuilder) {
|
||||
override fun generateDeclaration() = throw UnsupportedOperationException()
|
||||
override fun generateBody() = throw UnsupportedOperationException()
|
||||
override fun generateKotlinAnnotation() = throw UnsupportedOperationException()
|
||||
override fun generateKotlinMetadataAnnotation() = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
fun done() {
|
||||
|
||||
@@ -69,7 +69,7 @@ class MultifileClassPartCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateKotlinAnnotation() {
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
val members = ArrayList<DeclarationDescriptor>()
|
||||
for (declaration in element.declarations) {
|
||||
when (declaration) {
|
||||
@@ -88,15 +88,9 @@ class MultifileClassPartCodegen(
|
||||
val packageProto = serializer.packagePartProto(members).build()
|
||||
|
||||
writeKotlinMetadata(v, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART) { av ->
|
||||
AsmUtil.writeAnnotationData(av, serializer, packageProto, false)
|
||||
AsmUtil.writeAnnotationData(av, serializer, packageProto)
|
||||
av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassType.internalName)
|
||||
}
|
||||
|
||||
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
|
||||
JvmCodegenUtil.writeAbiVersion(av)
|
||||
AsmUtil.writeAnnotationData(av, serializer, packageProto, true)
|
||||
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassType.internalName)
|
||||
av.visitEnd()
|
||||
}
|
||||
|
||||
override fun generateSyntheticParts() {
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
@@ -43,9 +42,7 @@ import org.jetbrains.org.objectweb.asm.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.writeAnnotationData;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.writeAbiVersion;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
@@ -109,7 +106,7 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
List<DeclarationDescriptor> members = new ArrayList<DeclarationDescriptor>();
|
||||
for (KtDeclaration declaration : element.getDeclarations()) {
|
||||
if (declaration instanceof KtNamedFunction) {
|
||||
@@ -128,15 +125,10 @@ public class PackagePartCodegen extends MemberCodegen<KtFile> {
|
||||
WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.FILE_FACADE, new Function1<AnnotationVisitor, Unit>() {
|
||||
@Override
|
||||
public Unit invoke(AnnotationVisitor av) {
|
||||
writeAnnotationData(av, serializer, packageProto, false);
|
||||
writeAnnotationData(av, serializer, packageProto);
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
|
||||
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_FILE_FACADE), true);
|
||||
writeAbiVersion(av);
|
||||
writeAnnotationData(av, serializer, packageProto, true);
|
||||
av.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -114,7 +114,7 @@ public class PropertyCodegen {
|
||||
assert kind == OwnerKind.PACKAGE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DEFAULT_IMPLS
|
||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
||||
|
||||
if (CodegenContextUtil.isImplClassOwner(context)) {
|
||||
if (isBackingFieldOwner(descriptor)) {
|
||||
assert declaration != null : "Declaration is null for different context: " + context;
|
||||
|
||||
genBackingFieldAndAnnotations(declaration, descriptor, false);
|
||||
@@ -128,6 +128,13 @@ public class PropertyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBackingFieldOwner(@NotNull PropertyDescriptor descriptor) {
|
||||
if (descriptor.isConst()) {
|
||||
return !(context instanceof MultifileClassPartContext);
|
||||
}
|
||||
return CodegenContextUtil.isImplClassOwner(context);
|
||||
}
|
||||
|
||||
private void genBackingFieldAndAnnotations(@NotNull KtNamedDeclaration declaration, @NotNull PropertyDescriptor descriptor, boolean isParameter) {
|
||||
boolean hasBackingField = hasBackingField(declaration, descriptor);
|
||||
boolean hasDelegate = declaration instanceof KtProperty && ((KtProperty) declaration).hasDelegate();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.method
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation
|
||||
import org.jetbrains.kotlin.codegen.context.ClassContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
@@ -158,9 +157,7 @@ class PropertyReferenceCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateKotlinAnnotation() {
|
||||
writeKotlinSyntheticClassAnnotation(v, state)
|
||||
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
writeSyntheticClassMetadata(v)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.NO_FLAG_PACKAGE_PRIVATE;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -94,8 +95,6 @@ public class SamWrapperCodegen {
|
||||
);
|
||||
cv.visitSource(file.getName(), null);
|
||||
|
||||
writeKotlinSyntheticClassAnnotation(cv, state);
|
||||
|
||||
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv);
|
||||
|
||||
// e.g. ASM type for Function2
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
|
||||
internal class FictitiousArrayConstructor(arrayClass: ClassDescriptor) : SimpleFunctionDescriptorImpl(
|
||||
arrayClass.containingDeclaration, null, Annotations.EMPTY, arrayClass.name, CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE
|
||||
) {
|
||||
companion object Factory {
|
||||
@JvmStatic
|
||||
fun create(arrayConstructor: ConstructorDescriptor): FictitiousArrayConstructor {
|
||||
val arrayClass = arrayConstructor.containingDeclaration
|
||||
return FictitiousArrayConstructor(arrayClass).apply {
|
||||
this.initialize(null, null, arrayConstructor.typeParameters, arrayConstructor.valueParameters, arrayClass.defaultType,
|
||||
Modality.FINAL, Visibilities.PUBLIC)
|
||||
this.isInline = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.context.*;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -69,7 +70,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
private final GenerationState state;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private final SimpleFunctionDescriptor functionDescriptor;
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final JvmMethodSignature jvmSignature;
|
||||
private final KtElement callElement;
|
||||
private final MethodContext context;
|
||||
@@ -84,6 +85,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
private final ReifiedTypeInliner reifiedTypeInliner;
|
||||
@Nullable private final TypeParameterMappings typeParameterMappings;
|
||||
private final boolean isDefaultCompilation;
|
||||
|
||||
private LambdaInfo activeLambda;
|
||||
|
||||
@@ -92,17 +94,22 @@ public class InlineCodegen extends CallGenerator {
|
||||
public InlineCodegen(
|
||||
@NotNull ExpressionCodegen codegen,
|
||||
@NotNull GenerationState state,
|
||||
@NotNull SimpleFunctionDescriptor functionDescriptor,
|
||||
@NotNull FunctionDescriptor function,
|
||||
@NotNull KtElement callElement,
|
||||
@Nullable TypeParameterMappings typeParameterMappings
|
||||
@Nullable TypeParameterMappings typeParameterMappings,
|
||||
boolean isDefaultCompilation
|
||||
) {
|
||||
assert InlineUtil.isInline(functionDescriptor) : "InlineCodegen could inline only inline function: " + functionDescriptor;
|
||||
|
||||
assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) :
|
||||
"InlineCodegen can inline only inline functions and array constructors: " + function;
|
||||
this.isDefaultCompilation = isDefaultCompilation;
|
||||
this.state = state;
|
||||
this.typeMapper = state.getTypeMapper();
|
||||
this.codegen = codegen;
|
||||
this.callElement = callElement;
|
||||
this.functionDescriptor = functionDescriptor.getOriginal();
|
||||
this.functionDescriptor =
|
||||
InlineUtil.isArrayConstructorWithLambda(function)
|
||||
? FictitiousArrayConstructor.create((ConstructorDescriptor) function)
|
||||
: function.getOriginal();
|
||||
this.typeParameterMappings = typeParameterMappings;
|
||||
|
||||
reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
|
||||
@@ -119,13 +126,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
|
||||
|
||||
sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
|
||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
||||
|
||||
if (!(functionDescriptor instanceof FictitiousArrayConstructor)) {
|
||||
reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void genCallWithoutAssertions(
|
||||
@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen
|
||||
) {
|
||||
public void genCallWithoutAssertions(@NotNull CallableMethod callableMethod, @NotNull ExpressionCodegen codegen) {
|
||||
genCall(callableMethod, null, false, codegen);
|
||||
}
|
||||
|
||||
@@ -176,19 +184,25 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws ClassNotFoundException, IOException {
|
||||
JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
|
||||
|
||||
Method asmMethod;
|
||||
if (callDefault) {
|
||||
asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
|
||||
}
|
||||
else {
|
||||
asmMethod = jvmSignature.getAsmMethod();
|
||||
}
|
||||
private SMAPAndMethodNode createMethodNode(boolean callDefault) throws IOException {
|
||||
Method asmMethod = callDefault
|
||||
? typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind())
|
||||
: jvmSignature.getAsmMethod();
|
||||
|
||||
SMAPAndMethodNode nodeAndSMAP;
|
||||
if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
|
||||
if (functionDescriptor instanceof FictitiousArrayConstructor) {
|
||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(
|
||||
IntrinsicArrayConstructorsKt.getBytecode(),
|
||||
asmMethod.getName(),
|
||||
asmMethod.getDescriptor(),
|
||||
IntrinsicArrayConstructorsKt.getClassId()
|
||||
);
|
||||
|
||||
if (nodeAndSMAP == null) {
|
||||
throw new IllegalStateException("Couldn't obtain array constructor body for " + descriptorName(functionDescriptor));
|
||||
}
|
||||
}
|
||||
else if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
|
||||
JetTypeMapper.ContainingClassesInfo containingClasses = typeMapper.getContainingClassesForDeserializedCallable(
|
||||
(DeserializedSimpleFunctionDescriptor) functionDescriptor);
|
||||
|
||||
@@ -203,14 +217,14 @@ public class InlineCodegen extends CallGenerator {
|
||||
);
|
||||
|
||||
if (nodeAndSMAP == null) {
|
||||
throw new RuntimeException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
|
||||
throw new IllegalStateException("Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
|
||||
|
||||
if (element == null || !(element instanceof KtNamedFunction)) {
|
||||
throw new RuntimeException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
||||
if (!(element instanceof KtNamedFunction)) {
|
||||
throw new IllegalStateException("Couldn't find declaration for function " + descriptorName(functionDescriptor));
|
||||
}
|
||||
KtNamedFunction inliningFunction = (KtNamedFunction) element;
|
||||
|
||||
@@ -233,7 +247,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
implementationOwner.getInternalName());
|
||||
FunctionCodegen.generateDefaultImplBody(
|
||||
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
|
||||
inliningFunction, parentCodegen
|
||||
inliningFunction, parentCodegen, asmMethod
|
||||
);
|
||||
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
|
||||
}
|
||||
@@ -260,14 +274,10 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
Parameters parameters = invocationParamBuilder.buildParameters();
|
||||
|
||||
InliningContext info = new RootInliningContext(expressionMap,
|
||||
state,
|
||||
codegen.getInlineNameGenerator()
|
||||
.subGenerator(functionDescriptor.getName().asString()),
|
||||
codegen.getContext(),
|
||||
callElement,
|
||||
getInlineCallSiteInfo(), reifiedTypeInliner,
|
||||
typeParameterMappings);
|
||||
InliningContext info = new RootInliningContext(
|
||||
expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()),
|
||||
codegen.getContext(), callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings, isDefaultCompilation
|
||||
);
|
||||
|
||||
MethodInliner inliner = new MethodInliner(node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
|
||||
"Method inlining " + callElement.getText(),
|
||||
@@ -415,7 +425,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@@ -529,13 +539,11 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
@Override
|
||||
public void putHiddenParams() {
|
||||
List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters();
|
||||
|
||||
if (!isStaticMethod(functionDescriptor, context)) {
|
||||
if ((getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) == 0) {
|
||||
invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
|
||||
}
|
||||
|
||||
for (JvmMethodParameterSignature param : valueParameters) {
|
||||
for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) {
|
||||
if (param.getKind() == JvmMethodParameterKind.VALUE) {
|
||||
break;
|
||||
}
|
||||
@@ -643,10 +651,6 @@ public class InlineCodegen extends CallGenerator {
|
||||
throw new IllegalStateException("Couldn't build context for " + descriptorName(descriptor));
|
||||
}
|
||||
|
||||
private static boolean isStaticMethod(FunctionDescriptor functionDescriptor, MethodContext context) {
|
||||
return (getMethodAsmFlags(functionDescriptor, context.getContextKind()) & Opcodes.ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
private static String descriptorName(DeclarationDescriptor descriptor) {
|
||||
return DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContextUtil;
|
||||
import org.jetbrains.kotlin.codegen.context.InlineLambdaContext;
|
||||
import org.jetbrains.kotlin.codegen.context.MethodContext;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
@@ -84,7 +85,7 @@ public class InlineCodegenUtil {
|
||||
final String methodName,
|
||||
final String methodDescriptor,
|
||||
ClassId classId
|
||||
) throws ClassNotFoundException, IOException {
|
||||
) throws IOException {
|
||||
ClassReader cr = new ClassReader(classData);
|
||||
final MethodNode[] node = new MethodNode[1];
|
||||
final String[] debugInfo = new String[2];
|
||||
@@ -127,6 +128,15 @@ public class InlineCodegenUtil {
|
||||
}
|
||||
}, ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));
|
||||
|
||||
if (node[0] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (classId.equals(IntrinsicArrayConstructorsKt.getClassId())) {
|
||||
// Don't load source map for intrinsic array constructors
|
||||
debugInfo[0] = null;
|
||||
}
|
||||
|
||||
SMAP smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classId.asString(), lines[0], lines[1]);
|
||||
return new SMAPAndMethodNode(node[0], smap);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
class InstructionsAndFrames(val frames: Array<Frame<SourceValue>>, ins: InsnList) {
|
||||
|
||||
val indexes = (0..ins.size() - 1).associate { Pair(ins.get(it), it) }
|
||||
|
||||
operator fun get(node: AbstractInsnNode): Frame<SourceValue>? = frames[indexes[node]!!]
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.SmartHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.ClosureCodegen;
|
||||
@@ -370,7 +371,10 @@ public class MethodInliner {
|
||||
@NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
|
||||
) {
|
||||
if (isInliningLambda || InlineCodegenUtil.GENERATE_SMAP) {
|
||||
String varSuffix = inliningContext.isRoot() && !InlineCodegenUtil.isFakeLocalVariableForInline(name) ? INLINE_FUN_VAR_SUFFIX : "";
|
||||
String varSuffix = inliningContext.isRoot() &&
|
||||
!((RootInliningContext) inliningContext).isDefaultCompilation &&
|
||||
!InlineCodegenUtil.isFakeLocalVariableForInline(name) ?
|
||||
INLINE_FUN_VAR_SUFFIX : "";
|
||||
String varName = !varSuffix.isEmpty() && name.equals("this") ? name + "_" : name;
|
||||
super.visitLocalVariable(varName + varSuffix, desc, signature, start, end, getNewIndex(index));
|
||||
}
|
||||
@@ -424,7 +428,8 @@ public class MethodInliner {
|
||||
catch (AnalyzerException e) {
|
||||
throw wrapException(e, node, "couldn't inline method call");
|
||||
}
|
||||
|
||||
Set<AbstractInsnNode> toDelete = new SmartHashSet<AbstractInsnNode>();
|
||||
InstructionsAndFrames instructionsAndFrames = new InstructionsAndFrames(sources, node.instructions);
|
||||
AbstractInsnNode cur = node.instructions.getFirst();
|
||||
int index = 0;
|
||||
|
||||
@@ -465,7 +470,7 @@ public class MethodInliner {
|
||||
if (insnNode.getOpcode() == Opcodes.SWAP) {
|
||||
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
|
||||
}
|
||||
lambdaInfo = getLambdaIfExists(processingInstruction);
|
||||
lambdaInfo = getLambdaIfExistsAndMarkInstructions(processingInstruction, frame, instructionsAndFrames, toDelete);
|
||||
if (lambdaInfo != null) {
|
||||
//remove inlinable access
|
||||
assert processingInstruction != null;
|
||||
@@ -483,7 +488,7 @@ public class MethodInliner {
|
||||
SourceValue sourceValue = frame.getStack(firstParameterIndex + i);
|
||||
if (sourceValue.insns.size() == 1) {
|
||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||
LambdaInfo lambdaInfo = getLambdaIfExists(insnNode);
|
||||
LambdaInfo lambdaInfo = getLambdaIfExistsAndMarkInstructions(insnNode, frame, instructionsAndFrames, toDelete);
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo);
|
||||
node.instructions.remove(insnNode);
|
||||
@@ -530,6 +535,10 @@ public class MethodInliner {
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractInsnNode insnNode : toDelete) {
|
||||
node.instructions.remove(insnNode);
|
||||
}
|
||||
|
||||
//clean dead try/catch blocks
|
||||
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
|
||||
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
|
||||
@@ -572,7 +581,41 @@ public class MethodInliner {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
private LambdaInfo getLambdaIfExistsAndMarkInstructions(
|
||||
@Nullable AbstractInsnNode insnNode,
|
||||
@NotNull Frame<SourceValue> localFrame,
|
||||
@NotNull InstructionsAndFrames insAndFrames,
|
||||
@NotNull Set<AbstractInsnNode> toDelete
|
||||
) {
|
||||
LambdaInfo lambdaInfo = getLambdaIfExists(insnNode);
|
||||
|
||||
if (lambdaInfo == null && insnNode instanceof VarInsnNode && insnNode.getOpcode() == Opcodes.ALOAD) {
|
||||
int varIndex = ((VarInsnNode) insnNode).var;
|
||||
SourceValue local = localFrame.getLocal(varIndex);
|
||||
if (local.insns.size() == 1) {
|
||||
AbstractInsnNode storeIns = local.insns.iterator().next();
|
||||
if (storeIns instanceof VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
|
||||
Frame<SourceValue> frame = insAndFrames.get(storeIns);
|
||||
if (frame != null) {
|
||||
SourceValue topOfStack = frame.getStack(frame.getStackSize() - 1);
|
||||
if(topOfStack.insns.size() == 1) {
|
||||
AbstractInsnNode lambdaAload = topOfStack.insns.iterator().next();
|
||||
lambdaInfo = getLambdaIfExistsAndMarkInstructions(lambdaAload, frame, insAndFrames, toDelete);
|
||||
if (lambdaInfo != null) {
|
||||
toDelete.add(storeIns);
|
||||
toDelete.add(lambdaAload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lambdaInfo;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
if (insnNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public class RootInliningContext extends InliningContext {
|
||||
public final CodegenContext startContext;
|
||||
private final InlineCallSiteInfo inlineCallSiteInfo;
|
||||
public final TypeParameterMappings typeParameterMappings;
|
||||
public final boolean isDefaultCompilation;
|
||||
public final KtElement callElement;
|
||||
|
||||
public RootInliningContext(
|
||||
@@ -38,13 +39,15 @@ public class RootInliningContext extends InliningContext {
|
||||
@NotNull KtElement callElement,
|
||||
@NotNull InlineCallSiteInfo classNameToInline,
|
||||
@NotNull ReifiedTypeInliner inliner,
|
||||
@Nullable TypeParameterMappings typeParameterMappings
|
||||
@Nullable TypeParameterMappings typeParameterMappings,
|
||||
boolean isDefaultCompilation
|
||||
) {
|
||||
super(null, map, state, nameGenerator, TypeRemapper.createRoot(typeParameterMappings), inliner, false, false);
|
||||
this.callElement = callElement;
|
||||
this.startContext = startContext;
|
||||
this.inlineCallSiteInfo = classNameToInline;
|
||||
this.typeParameterMappings = typeParameterMappings;
|
||||
this.isDefaultCompilation = isDefaultCompilation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,11 +24,12 @@ import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import java.util.*
|
||||
|
||||
//TODO join parameter
|
||||
class SMAPBuilder(val source: String,
|
||||
val path: String,
|
||||
val fileMappings: List<FileMapping>) {
|
||||
|
||||
val header = "SMAP\n$source\nKotlin\n*S Kotlin"
|
||||
class SMAPBuilder(
|
||||
val source: String,
|
||||
val path: String,
|
||||
val fileMappings: List<FileMapping>
|
||||
) {
|
||||
private val header = "SMAP\n$source\nKotlin\n*S Kotlin"
|
||||
|
||||
fun build(): String? {
|
||||
var realMappings = fileMappings.filter {
|
||||
@@ -37,7 +38,7 @@ class SMAPBuilder(val source: String,
|
||||
}
|
||||
|
||||
if (realMappings.isEmpty()) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
val fileIds = "*F" + realMappings.mapIndexed { id, file -> "\n${file.toSMAPFile(id + 1)}" }.joinToString("")
|
||||
@@ -46,29 +47,29 @@ class SMAPBuilder(val source: String,
|
||||
return "$header\n$fileIds\n$lineMappings\n*E\n"
|
||||
}
|
||||
|
||||
|
||||
fun RangeMapping.toSMAP(fileId: Int): String {
|
||||
private fun RangeMapping.toSMAP(fileId: Int): String {
|
||||
return if (range == 1) "$source#$fileId:$dest" else "$source#$fileId,$range:$dest"
|
||||
}
|
||||
|
||||
fun FileMapping.toSMAPFile(id: Int): String {
|
||||
this.id = id;
|
||||
private fun FileMapping.toSMAPFile(id: Int): String {
|
||||
this.id = id
|
||||
return "+ $id $name\n$path"
|
||||
}
|
||||
|
||||
//TODO inline
|
||||
fun FileMapping.toSMAPMapping(): String {
|
||||
private fun FileMapping.toSMAPMapping(): String {
|
||||
return lineMappings.joinToString("") { "\n${it.toSMAP(id)}" }
|
||||
}
|
||||
}
|
||||
|
||||
open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo) : DefaultSourceMapper(sourceInfo, parent) {
|
||||
|
||||
open class NestedSourceMapper(
|
||||
parent: SourceMapper, val ranges: List<RangeMapping>, sourceInfo: SourceInfo
|
||||
) : DefaultSourceMapper(sourceInfo, parent) {
|
||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
||||
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
|
||||
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
||||
value, key ->
|
||||
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
}
|
||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
})
|
||||
if (index < 0) {
|
||||
parent!!.visitSource(sourceInfo.source, sourceInfo.pathOrCleanFQN)
|
||||
parent!!.visitLineNumber(iv, lineNumber, start)
|
||||
@@ -81,8 +82,9 @@ open class NestedSourceMapper(parent: SourceMapper, val ranges: List<RangeMappin
|
||||
}
|
||||
}
|
||||
|
||||
open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNode) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
||||
|
||||
open class InlineLambdaSourceMapper(
|
||||
parent: SourceMapper, smap: SMAPAndMethodNode
|
||||
) : NestedSourceMapper(parent, smap.ranges, smap.classSMAP.sourceInfo) {
|
||||
override fun visitSource(name: String, path: String) {
|
||||
super.visitSource(name, path)
|
||||
if (isOriginalVisited()) {
|
||||
@@ -100,13 +102,13 @@ open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNod
|
||||
}
|
||||
|
||||
override fun visitLineNumber(iv: MethodVisitor, lineNumber: Int, start: Label) {
|
||||
val index = Collections.binarySearch(ranges, RangeMapping(lineNumber, lineNumber, 1)) {
|
||||
val index = ranges.binarySearch(RangeMapping(lineNumber, lineNumber, 1), Comparator {
|
||||
value, key ->
|
||||
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
}
|
||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
})
|
||||
if (index >= 0) {
|
||||
val fmapping = ranges[index].parent!!
|
||||
if (fmapping.path == origin.path && fmapping.name == origin.name) {
|
||||
val mapping = ranges[index].parent!!
|
||||
if (mapping.path == origin.path && mapping.name == origin.name) {
|
||||
parent!!.visitOrigin()
|
||||
parent!!.visitLineNumber(iv, lineNumber, start)
|
||||
return
|
||||
@@ -117,7 +119,6 @@ open class InlineLambdaSourceMapper(parent: SourceMapper, smap: SMAPAndMethodNod
|
||||
}
|
||||
|
||||
interface SourceMapper {
|
||||
|
||||
val resultMappings: List<FileMapping>
|
||||
val parent: SourceMapper?
|
||||
|
||||
@@ -138,7 +139,6 @@ interface SourceMapper {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun flushToClassBuilder(mapper: SourceMapper, v: ClassBuilder) {
|
||||
for (fileMapping in mapper.resultMappings) {
|
||||
v.addSMAP(fileMapping)
|
||||
@@ -179,15 +179,10 @@ object IdenticalSourceMapper : SourceMapper {
|
||||
}
|
||||
|
||||
open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent: SourceMapper?): SourceMapper {
|
||||
|
||||
protected var maxUsedValue: Int = sourceInfo.linesInFile
|
||||
|
||||
var lastVisited: RawFileMapping? = null
|
||||
|
||||
private var lastMappedWithChanges: RawFileMapping? = null
|
||||
|
||||
var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
|
||||
|
||||
private var fileMappings: LinkedHashMap<String, RawFileMapping> = linkedMapOf()
|
||||
protected val origin: RawFileMapping
|
||||
|
||||
init {
|
||||
@@ -205,7 +200,7 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
|
||||
get() = fileMappings.values.map { it.toFileMapping() }
|
||||
|
||||
override fun visitSource(name: String, path: String) {
|
||||
lastVisited = fileMappings.getOrPut(createKey(name, path), { RawFileMapping(name, path) })
|
||||
lastVisited = fileMappings.getOrPut(createKey(name, path)) { RawFileMapping(name, path) }
|
||||
}
|
||||
|
||||
override fun visitOrigin() {
|
||||
@@ -232,7 +227,6 @@ open class DefaultSourceMapper(val sourceInfo: SourceInfo, override val parent:
|
||||
}
|
||||
}
|
||||
|
||||
/*Source Mapping*/
|
||||
class SMAP(val fileMappings: List<FileMapping>) {
|
||||
init {
|
||||
assert(fileMappings.isNotEmpty()) { "File Mappings shouldn't be empty" }
|
||||
@@ -251,9 +245,7 @@ class SMAP(val fileMappings: List<FileMapping>) {
|
||||
|
||||
companion object {
|
||||
val FILE_SECTION = "*F"
|
||||
|
||||
val LINE_SECTION = "*L"
|
||||
|
||||
val END = "*E"
|
||||
}
|
||||
}
|
||||
@@ -262,15 +254,14 @@ class RawFileMapping(val name: String, val path: String) {
|
||||
private val lineMappings = TIntIntHashMap()
|
||||
private val rangeMappings = arrayListOf<RangeMapping>()
|
||||
|
||||
private var lastMappedWithNewIndex = -1000;
|
||||
private var lastMappedWithNewIndex = -1000
|
||||
|
||||
fun toFileMapping(): FileMapping {
|
||||
val fileMapping = FileMapping(name, path)
|
||||
for (range in rangeMappings) {
|
||||
fileMapping.addRangeMapping(range)
|
||||
}
|
||||
return fileMapping
|
||||
}
|
||||
fun toFileMapping() =
|
||||
FileMapping(name, path).apply {
|
||||
for (range in rangeMappings) {
|
||||
addRangeMapping(range)
|
||||
}
|
||||
}
|
||||
|
||||
fun initRange(start: Int, end: Int) {
|
||||
assert(lineMappings.isEmpty) { "initRange should only be called for empty mapping" }
|
||||
@@ -315,14 +306,13 @@ class RawFileMapping(val name: String, val path: String) {
|
||||
private fun couldFoldInRange(first: Int, second: Int): Boolean {
|
||||
//TODO
|
||||
val delta = second - first
|
||||
return delta > 0 && delta <= 10;
|
||||
return delta > 0 && delta <= 10
|
||||
}
|
||||
}
|
||||
|
||||
open class FileMapping(val name: String, val path: String) {
|
||||
val lineMappings = arrayListOf<RangeMapping>()
|
||||
|
||||
var id = -1;
|
||||
var id = -1
|
||||
|
||||
fun addRangeMapping(lineMapping: RangeMapping) {
|
||||
lineMappings.add(lineMapping)
|
||||
@@ -338,12 +328,10 @@ open class FileMapping(val name: String, val path: String) {
|
||||
|
||||
//TODO comparable
|
||||
data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
|
||||
|
||||
var parent: FileMapping? = null;
|
||||
|
||||
var parent: FileMapping? = null
|
||||
private val skip = source == -1 && dest == -1
|
||||
|
||||
fun contains(destLine: Int): Boolean {
|
||||
operator fun contains(destLine: Int): Boolean {
|
||||
return if (skip) true else dest <= destLine && destLine < dest + range
|
||||
}
|
||||
|
||||
@@ -368,4 +356,4 @@ data class RangeMapping(val source: Int, val dest: Int, var range: Int = 1) {
|
||||
companion object {
|
||||
val SKIP = RangeMapping(-1, -1, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,30 +16,26 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.org.objectweb.asm.tree.LineNumberNode
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import kotlin.properties.Delegates
|
||||
import java.util.Collections
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import java.util.*
|
||||
|
||||
//TODO comment
|
||||
class SMAPAndMethodNode(val node: MethodNode, val classSMAP: SMAP) {
|
||||
|
||||
val lineNumbers =
|
||||
InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map {
|
||||
val index = Collections.binarySearch(classSMAP.intervals, RangeMapping(it.line, it.line, 1)) {
|
||||
private val lineNumbers =
|
||||
InsnSequence(node.instructions.first, null).filterIsInstance<LineNumberNode>().map { node ->
|
||||
val index = classSMAP.intervals.binarySearch(RangeMapping(node.line, node.line, 1), Comparator {
|
||||
value, key ->
|
||||
if (value.contains(key.dest)) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
if (key.dest in value) 0 else RangeMapping.Comparator.compare(value, key)
|
||||
})
|
||||
if (index < 0) {
|
||||
error("Unmapped label in inlined function $node ${node.line}")
|
||||
}
|
||||
if (index < 0)
|
||||
throw IllegalStateException("Unmapped label in inlined function $it ${it.line}")
|
||||
LabelAndMapping(it, classSMAP.intervals[index])
|
||||
LabelAndMapping(node, classSMAP.intervals[index])
|
||||
}.toList()
|
||||
|
||||
val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList();
|
||||
val ranges = lineNumbers.asSequence().map { it.mapper }.distinct().toList()
|
||||
}
|
||||
|
||||
class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping)
|
||||
class LabelAndMapping(val lineNumberNode: LineNumberNode, val mapper: RangeMapping)
|
||||
|
||||
@@ -16,51 +16,49 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import com.intellij.util.SmartFMap
|
||||
|
||||
object SMAPParser {
|
||||
|
||||
/*null smap means that there is no any debug info in file (e.g. sourceName)*/
|
||||
@JvmStatic
|
||||
/*null smap means that there is no any debug info in file (e.g. sourceName)*/ fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
|
||||
if (mappingInfo == null || mappingInfo.isEmpty()) {
|
||||
val fm: FileMapping
|
||||
if (source == null || source.isEmpty()) {
|
||||
fm = FileMapping.SKIP
|
||||
}
|
||||
else {
|
||||
fm = FileMapping(source, path)
|
||||
if (methodStartLine <= methodEndLine) {
|
||||
//one to one
|
||||
fm.addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
|
||||
}
|
||||
}
|
||||
return SMAP(listOf(fm))
|
||||
fun parseOrCreateDefault(mappingInfo: String?, source: String?, path: String, methodStartLine: Int, methodEndLine: Int): SMAP {
|
||||
if (mappingInfo != null && mappingInfo.isNotEmpty()) {
|
||||
return parse(mappingInfo)
|
||||
}
|
||||
return parse(mappingInfo)
|
||||
|
||||
val mapping =
|
||||
if (source == null || source.isEmpty())
|
||||
FileMapping.SKIP
|
||||
else
|
||||
FileMapping(source, path).apply {
|
||||
if (methodStartLine <= methodEndLine) {
|
||||
//one to one
|
||||
addRangeMapping(RangeMapping(methodStartLine, methodStartLine, methodEndLine - methodStartLine + 1))
|
||||
}
|
||||
}
|
||||
|
||||
return SMAP(listOf(mapping))
|
||||
}
|
||||
|
||||
@JvmStatic fun parse(mappingInfo: String): SMAP {
|
||||
@JvmStatic
|
||||
fun parse(mappingInfo: String): SMAP {
|
||||
val fileMappings = linkedMapOf<Int, FileMapping>()
|
||||
|
||||
val fileSectionStart = mappingInfo.indexOf(SMAP.FILE_SECTION) + SMAP.FILE_SECTION.length
|
||||
val lineSectionAnchor = mappingInfo.indexOf(SMAP.LINE_SECTION)
|
||||
val files = mappingInfo.substring(fileSectionStart, lineSectionAnchor)
|
||||
|
||||
|
||||
val fileEntries = files.trim().split('+')
|
||||
|
||||
for (fileDeclaration in fileEntries) {
|
||||
if (fileDeclaration == "") continue;
|
||||
if (fileDeclaration == "") continue
|
||||
val fileInternalName = fileDeclaration.trim()
|
||||
|
||||
val indexEnd = fileInternalName.indexOf(' ')
|
||||
val fileIndex = Integer.valueOf(fileInternalName.substring(0, indexEnd))
|
||||
val fileIndex = fileInternalName.substring(0, indexEnd).toInt()
|
||||
val newLine = fileInternalName.indexOf('\n')
|
||||
val fileName = fileInternalName.substring(indexEnd + 1, newLine)
|
||||
fileMappings.put(fileIndex, FileMapping(fileName, fileInternalName.substring(newLine + 1).trim()))
|
||||
fileMappings[fileIndex] = FileMapping(fileName, fileInternalName.substring(newLine + 1).trim())
|
||||
}
|
||||
|
||||
|
||||
val lines = mappingInfo.substring(lineSectionAnchor + SMAP.LINE_SECTION.length, mappingInfo.indexOf(SMAP.END)).trim().split('\n')
|
||||
for (lineMapping in lines) {
|
||||
/*only simple mapping now*/
|
||||
@@ -69,14 +67,14 @@ object SMAPParser {
|
||||
var rangeSeparator = originalPart.indexOf(',').let { if (it < 0) targetSplit else it }
|
||||
|
||||
val fileSeparator = lineMapping.indexOf('#')
|
||||
val originalIndex = Integer.valueOf(originalPart.substring(0, fileSeparator))
|
||||
val range = if (rangeSeparator == targetSplit) 1 else Integer.valueOf(originalPart.substring(rangeSeparator + 1, targetSplit))
|
||||
val originalIndex = originalPart.substring(0, fileSeparator).toInt()
|
||||
val range = if (rangeSeparator == targetSplit) 1 else originalPart.substring(rangeSeparator + 1, targetSplit).toInt()
|
||||
|
||||
val fileIndex = Integer.valueOf(lineMapping.substring(fileSeparator + 1, rangeSeparator))
|
||||
val targetIndex = Integer.valueOf(lineMapping.substring(targetSplit + 1))
|
||||
val fileIndex = lineMapping.substring(fileSeparator + 1, rangeSeparator).toInt()
|
||||
val targetIndex = lineMapping.substring(targetSplit + 1).toInt()
|
||||
fileMappings[fileIndex]!!.addRangeMapping(RangeMapping(originalIndex, targetIndex, range))
|
||||
}
|
||||
|
||||
return SMAP(fileMappings.values.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,14 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.jvm.internal;
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface KotlinLocalClass {
|
||||
object ArrayConstructor : IntrinsicMethod() {
|
||||
override fun toCallable(method: CallableMethod): Callable {
|
||||
return object : IntrinsicCallable(method.owner, method.valueParameterTypes, null, null) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
// Bodies of methods in this file are used in InlineCodegen to inline array constructors. It is loaded via reflection at runtime.
|
||||
// TODO: generate the bytecode manually instead, do not depend on the previous compiler working correctly here
|
||||
|
||||
internal val classId: ClassId =
|
||||
ClassId.topLevel(FqName("org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt"))
|
||||
|
||||
internal val bytecode: ByteArray by lazy {
|
||||
val stream = object {}.javaClass.classLoader.getResourceAsStream("${classId.asString()}.class")
|
||||
stream.readBytes().apply {
|
||||
stream.close()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Array(size: Int, init: (Int) -> T): Array<T> {
|
||||
val result = arrayOfNulls<T>(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result as Array<T>
|
||||
}
|
||||
|
||||
private inline fun DoubleArray(size: Int, init: (Int) -> Double): DoubleArray {
|
||||
val result = DoubleArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun FloatArray(size: Int, init: (Int) -> Float): FloatArray {
|
||||
val result = FloatArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun LongArray(size: Int, init: (Int) -> Long): LongArray {
|
||||
val result = LongArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun IntArray(size: Int, init: (Int) -> Int): IntArray {
|
||||
val result = IntArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun CharArray(size: Int, init: (Int) -> Char): CharArray {
|
||||
val result = CharArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun ShortArray(size: Int, init: (Int) -> Short): ShortArray {
|
||||
val result = ShortArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun ByteArray(size: Int, init: (Int) -> Byte): ByteArray {
|
||||
val result = ByteArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private inline fun BooleanArray(size: Int, init: (Int) -> Boolean): BooleanArray {
|
||||
val result = BooleanArray(size)
|
||||
for (i in 0..size - 1) {
|
||||
result[i] = init(i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -29,9 +29,7 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME;
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class IntrinsicMethods {
|
||||
@@ -150,6 +148,7 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
|
||||
declareIntrinsicFunction(arrayTypeFqName, "<init>", 2, ArrayConstructor.INSTANCE);
|
||||
}
|
||||
|
||||
private void declareBinaryOp(@NotNull String methodName, int opcode) {
|
||||
|
||||
@@ -159,7 +159,7 @@ public class JetTypeMapper {
|
||||
if (file != null) {
|
||||
Visibility visibility = descriptor.getVisibility();
|
||||
if (!publicFacade ||
|
||||
descriptor instanceof PropertyDescriptor ||
|
||||
isNonConstProperty(descriptor) ||
|
||||
Visibilities.isPrivate(visibility) ||
|
||||
isAccessor/*Cause of KT-9603*/
|
||||
) {
|
||||
@@ -181,6 +181,12 @@ public class JetTypeMapper {
|
||||
" in package fragment " + descriptor.getContainingDeclaration());
|
||||
}
|
||||
|
||||
private static boolean isNonConstProperty(@NotNull CallableMemberDescriptor descriptor) {
|
||||
if (!(descriptor instanceof PropertyDescriptor)) return false;
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
return !propertyDescriptor.isConst();
|
||||
}
|
||||
|
||||
public static class ContainingClassesInfo {
|
||||
private final ClassId facadeClassId;
|
||||
private final ClassId implClassId;
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
@@ -58,8 +57,6 @@ public class MappingClassesForWhenByEnumCodegen {
|
||||
generateFields(cb, mappings);
|
||||
generateInitialization(cb, mappings);
|
||||
|
||||
writeKotlinSyntheticClassAnnotation(cb, state);
|
||||
|
||||
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cb);
|
||||
|
||||
cb.done();
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
|
||||
fun writeKotlinMetadata(cb: ClassBuilder, kind: KotlinClassHeader.Kind, action: (AnnotationVisitor) -> Unit) {
|
||||
val av = cb.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.METADATA), true)
|
||||
val av = cb.newAnnotation(JvmAnnotationNames.METADATA_DESC, true)
|
||||
av.visit(JvmAnnotationNames.METADATA_VERSION_FIELD_NAME, JvmMetadataVersion.INSTANCE.toArray())
|
||||
av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray())
|
||||
av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id)
|
||||
|
||||
@@ -28,6 +28,8 @@ public class CLIConfigurationKeys {
|
||||
CompilerConfigurationKey.create("compiler plugins");
|
||||
public static final CompilerConfigurationKey<Boolean> ALLOW_KOTLIN_PACKAGE =
|
||||
CompilerConfigurationKey.create("allow kotlin package");
|
||||
public static final CompilerConfigurationKey<Boolean> REPORT_PERF =
|
||||
CompilerConfigurationKey.create("report performance information");
|
||||
|
||||
private CLIConfigurationKeys() {
|
||||
}
|
||||
|
||||
@@ -124,10 +124,7 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
return ExitCode.OK
|
||||
}
|
||||
|
||||
if (arguments.script) {
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
|
||||
shouldReportPerf = false
|
||||
}
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
|
||||
|
||||
if (arguments.skipMetadataVersionCheck) {
|
||||
JvmMetadataVersion.skipCheck = true
|
||||
@@ -238,7 +235,6 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
// allows to track GC time for each run when repeated compilation is used
|
||||
private val elapsedGCTime = hashMapOf<String, Long>()
|
||||
private var elapsedJITTime = 0L
|
||||
private var shouldReportPerf = true
|
||||
|
||||
fun resetInitStartTime() {
|
||||
if (initStartNanos == 0L) {
|
||||
@@ -251,7 +247,9 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
|
||||
fun reportPerf(configuration: CompilerConfiguration, message: String) {
|
||||
if (!shouldReportPerf) return
|
||||
if (!configuration.get(CLIConfigurationKeys.REPORT_PERF, false)) {
|
||||
return
|
||||
}
|
||||
|
||||
val collector = configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]!!
|
||||
collector.report(CompilerMessageSeverity.INFO, "PERF: " + message, CompilerMessageLocation.NO_LOCATION)
|
||||
@@ -281,6 +279,7 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
configuration.put(JVMConfigurationKeys.DISABLE_OPTIMIZATION, arguments.noOptimize)
|
||||
configuration.put(JVMConfigurationKeys.MULTIFILE_FACADES_OPEN, arguments.multifileFacadesOpen);
|
||||
configuration.put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage);
|
||||
configuration.put(CLIConfigurationKeys.REPORT_PERF, arguments.reportPerf);
|
||||
}
|
||||
|
||||
private fun getClasspath(paths: KotlinPaths, arguments: K2JVMCompilerArguments): List<File> {
|
||||
|
||||
@@ -69,6 +69,8 @@ messages/**)
|
||||
public protected *;
|
||||
}
|
||||
|
||||
-keep class org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt { *; }
|
||||
|
||||
-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; }
|
||||
|
||||
-keep class org.jetbrains.kotlin.codegen.extensions.** {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm.checkers
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
@@ -28,11 +29,14 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
|
||||
class JvmSyntheticApplicabilityChecker : DeclarationChecker {
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
val annotation = descriptor.findJvmSyntheticAnnotation() ?: return
|
||||
if (declaration is KtProperty && declaration.hasDelegate()) {
|
||||
if (declaration is KtProperty && descriptor is VariableDescriptor && declaration.hasDelegate()) {
|
||||
val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation) ?: return
|
||||
diagnosticHolder.report(ErrorsJvm.JVM_SYNTHETIC_ON_DELEGATE.on(annotationEntry))
|
||||
}
|
||||
|
||||
@@ -99,7 +99,12 @@ class PlatformStaticAnnotationChecker : DeclarationChecker {
|
||||
}
|
||||
|
||||
class JvmNameAnnotationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
val platformNameAnnotation = DescriptorUtils.getJvmNameAnnotation(descriptor)
|
||||
if (platformNameAnnotation != null) {
|
||||
checkDeclaration(descriptor, platformNameAnnotation, diagnosticHolder)
|
||||
|
||||
@@ -98,7 +98,7 @@ class ResolverForProjectImpl<M : ModuleInfo>(
|
||||
}
|
||||
|
||||
private fun doGetDescriptorForModule(moduleInfo: M): ModuleDescriptorImpl {
|
||||
return descriptorByModule[moduleInfo] ?: return delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
|
||||
return descriptorByModule[moduleInfo] ?: delegateResolver.descriptorForModule(moduleInfo) as ModuleDescriptorImpl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ interface ModuleInfo {
|
||||
get() = false
|
||||
val name: Name
|
||||
fun dependencies(): List<ModuleInfo>
|
||||
fun friends(): Collection<ModuleInfo> = listOf()
|
||||
fun modulesWhichInternalsAreVisible(): Collection<ModuleInfo> = listOf()
|
||||
fun dependencyOnBuiltins(): DependencyOnBuiltins = DependenciesOnBuiltins.LAST
|
||||
val capabilities: Map<ModuleDescriptor.Capability<*>, Any?>
|
||||
get() = emptyMap()
|
||||
@@ -193,8 +193,8 @@ abstract class AnalyzerFacade<in P : PlatformAnalysisParameters> {
|
||||
modules.forEach {
|
||||
module ->
|
||||
val descriptor = resolverForProject.descriptorForModule(module)
|
||||
module.friends().forEach {
|
||||
descriptor.addFriend(resolverForProject.descriptorForModule(it as M))
|
||||
module.modulesWhichInternalsAreVisible().forEach {
|
||||
resolverForProject.descriptorForModule(it as M).addFriend(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,4 +249,4 @@ private class DelegatingPackageFragmentProvider(
|
||||
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
|
||||
return delegate().getSubPackagesOf(fqName, nameFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +360,14 @@ public class ControlFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDefinitelyInitialized(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
if (propertyDescriptor.isLateInit()) return true;
|
||||
if (trace.get(BACKING_FIELD_REQUIRED, propertyDescriptor) == Boolean.TRUE) return false;
|
||||
PsiElement property = DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor);
|
||||
if (property instanceof KtProperty && ((KtProperty) property).hasDelegate()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void checkIsInitialized(
|
||||
@NotNull VariableInitContext ctxt,
|
||||
@NotNull KtElement element,
|
||||
@@ -370,11 +378,8 @@ public class ControlFlowInformationProvider {
|
||||
|
||||
boolean isDefinitelyInitialized = ctxt.exitInitState.definitelyInitialized();
|
||||
VariableDescriptor variableDescriptor = ctxt.variableDescriptor;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
||||
if (propertyDescriptor.isLateInit() || !trace.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
isDefinitelyInitialized = true;
|
||||
}
|
||||
if (!isDefinitelyInitialized && variableDescriptor instanceof PropertyDescriptor) {
|
||||
isDefinitelyInitialized = isDefinitelyInitialized((PropertyDescriptor) variableDescriptor);
|
||||
}
|
||||
if (!isDefinitelyInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
|
||||
if (!(variableDescriptor instanceof PropertyDescriptor)) {
|
||||
|
||||
@@ -1146,6 +1146,8 @@ public class ControlFlowProcessor {
|
||||
}
|
||||
KtExpression delegate = property.getDelegateExpression();
|
||||
if (delegate != null) {
|
||||
// We do not want to have getDeferredValue(delegate) here, because delegate value will be read anyway later
|
||||
visitAssignment(property, getDeferredValue(null), property);
|
||||
generateInstructions(delegate);
|
||||
if (builder.getBoundValue(delegate) != null) {
|
||||
createSyntheticValue(property, MagicKind.VALUE_CONSUMER, delegate);
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker.VarianceConflictDiagnosticData;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -769,7 +768,8 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtClass> NESTED_CLASS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, DECLARATION_NAME);
|
||||
|
||||
//Inline and inlinable parameters
|
||||
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
|
||||
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_PUBLIC_CALL_FROM_PUBLIC_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
|
||||
DiagnosticFactory2<KtElement, DeclarationDescriptor, DeclarationDescriptor> PRIVATE_CLASS_MEMBER_FROM_INLINE = DiagnosticFactory2.create(ERROR, CALL_ELEMENT);
|
||||
DiagnosticFactory3<KtElement, KtElement, DeclarationDescriptor, DeclarationDescriptor> NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory3.create(ERROR, CALL_ELEMENT);
|
||||
DiagnosticFactory2<KtElement, KtNamedDeclaration, DeclarationDescriptor> NOT_YET_SUPPORTED_IN_INLINE = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, DeclarationDescriptor> NOTHING_TO_INLINE = DiagnosticFactory1.create(WARNING);
|
||||
@@ -785,7 +785,7 @@ public interface Errors {
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> UNRESOLVED_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
|
||||
UNRESOLVED_REFERENCE, NAMED_PARAMETER_NOT_FOUND, UNRESOLVED_REFERENCE_WRONG_RECEIVER);
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> INVISIBLE_REFERENCE_DIAGNOSTICS = ImmutableSet.of(
|
||||
INVISIBLE_MEMBER, INVISIBLE_MEMBER_FROM_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
|
||||
INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
|
||||
ImmutableSet<? extends DiagnosticFactory<?>> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of(
|
||||
UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER,
|
||||
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS);
|
||||
|
||||
@@ -728,7 +728,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT, "kotlin.Array class literal requires a type argument, please specify one in angle brackets");
|
||||
|
||||
//Inline
|
||||
MAP.put(INVISIBLE_MEMBER_FROM_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(PRIVATE_CLASS_MEMBER_FROM_INLINE, "Non-private inline function cannot access members of private classes: ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(NOT_YET_SUPPORTED_IN_INLINE, "''{0}'' construction is not yet supported in inline functions", ELEMENT_TEXT, SHORT_NAMES_IN_TYPES);
|
||||
MAP.put(DECLARATION_CANT_BE_INLINED, "''inline'' modifier is not allowed on virtual members. Only private or final members can be inlined");
|
||||
MAP.put(NOTHING_TO_INLINE, "Expected performance impact of inlining ''{0}'' can be insignificant. Inlining works best for functions with lambda parameters", SHORT_NAMES_IN_TYPES);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.parsing;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.WhitespacesBinders;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
@@ -112,9 +113,23 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
parseTopLevelDeclaration();
|
||||
}
|
||||
|
||||
checkUnclosedBlockComment();
|
||||
fileMarker.done(KT_FILE);
|
||||
}
|
||||
|
||||
private void checkUnclosedBlockComment() {
|
||||
if (TokenSet.create(BLOCK_COMMENT, DOC_COMMENT).contains(myBuilder.rawLookup(-1))) {
|
||||
int startOffset = myBuilder.rawTokenTypeStart(-1);
|
||||
int endOffset = myBuilder.rawTokenTypeStart(0);
|
||||
CharSequence tokenChars = myBuilder.getOriginalText().subSequence(startOffset, endOffset);
|
||||
if (!(tokenChars.length() > 2 && tokenChars.subSequence(tokenChars.length() - 2, tokenChars.length()).toString().equals("*/"))) {
|
||||
PsiBuilder.Marker marker = myBuilder.mark();
|
||||
marker.error("Unclosed comment");
|
||||
marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_RIGHT_BINDER, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parseTypeCodeFragment() {
|
||||
PsiBuilder.Marker marker = mark();
|
||||
parseTypeRef();
|
||||
@@ -171,7 +186,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
|
||||
private void checkForUnexpectedSymbols() {
|
||||
while (!eof()) {
|
||||
errorAndAdvance("unexpected symbol");
|
||||
errorAndAdvance("Unexpected symbol");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ErrorValue
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
|
||||
private val JVM_STATIC_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmStatic")
|
||||
|
||||
@@ -69,5 +70,8 @@ private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly"
|
||||
|
||||
fun MemberDescriptor.isInlineOnly(): Boolean {
|
||||
if (this !is FunctionDescriptor) return false
|
||||
return typeParameters.any { it.isReified } || annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||
return typeParameters.any { it.isReified } ||
|
||||
annotations.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME) && InlineUtil.isInline(this).apply {
|
||||
assert(this) { "Function is not inline: ${this@isInlineOnly}"; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -727,12 +727,16 @@ class DeclarationsChecker(
|
||||
}
|
||||
|
||||
private fun checkAccessors(property: KtProperty, propertyDescriptor: PropertyDescriptor) {
|
||||
for (accessor in property.accessors) {
|
||||
val propertyAccessorDescriptor = (if (accessor.isGetter) propertyDescriptor.getter else propertyDescriptor.setter)
|
||||
?: throw AssertionError("No property accessor descriptor for ${property.text}")
|
||||
accessor.checkTypeReferences()
|
||||
modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor)
|
||||
identifierChecker.checkDeclaration(accessor, trace)
|
||||
for (accessorDescriptor in propertyDescriptor.accessors) {
|
||||
val accessor = if (accessorDescriptor is PropertyGetterDescriptor) property.getter else property.setter
|
||||
if (accessor != null) {
|
||||
accessor.checkTypeReferences()
|
||||
modifiersChecker.checkModifiersForDeclaration(accessor, accessorDescriptor)
|
||||
identifierChecker.checkDeclaration(accessor, trace)
|
||||
}
|
||||
else {
|
||||
modifiersChecker.runDeclarationCheckers(property, accessorDescriptor)
|
||||
}
|
||||
}
|
||||
checkAccessor(propertyDescriptor, property.getter, propertyDescriptor.getter)
|
||||
checkAccessor(propertyDescriptor, property.setter, propertyDescriptor.setter)
|
||||
|
||||
@@ -228,7 +228,10 @@ public class ModifiersChecker {
|
||||
}
|
||||
|
||||
|
||||
private void runDeclarationCheckers(@NotNull KtDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
|
||||
public void runDeclarationCheckers(
|
||||
@NotNull KtDeclaration declaration,
|
||||
@NotNull DeclarationDescriptor descriptor
|
||||
) {
|
||||
for (DeclarationChecker checker : declarationCheckers) {
|
||||
checker.check(declaration, descriptor, trace, trace.getBindingContext());
|
||||
}
|
||||
|
||||
@@ -18,12 +18,10 @@ package org.jetbrains.kotlin.resolve
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtCallableDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
object UnderscoreChecker : DeclarationChecker {
|
||||
|
||||
@@ -44,6 +42,7 @@ object UnderscoreChecker : DeclarationChecker {
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
if (declaration is KtProperty && descriptor !is VariableDescriptor) return
|
||||
if (declaration is KtCallableDeclaration) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
checkNamed(parameter, diagnosticHolder)
|
||||
|
||||
@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.resolve.calls
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInvokeCallOnVariable
|
||||
@@ -285,7 +283,7 @@ class CallCompleter(
|
||||
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, expression) ?: updatedType
|
||||
}
|
||||
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.trace)
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context.statementFilter, context.trace)
|
||||
|
||||
// While the expected type is not known, the function literal arguments are not analyzed (to analyze function literal bodies once),
|
||||
// but they should be analyzed when the expected type is known (during the call completion).
|
||||
@@ -320,6 +318,7 @@ class CallCompleter(
|
||||
updatedType: KotlinType?,
|
||||
recordedType: KotlinType?,
|
||||
argumentExpression: KtExpression,
|
||||
statementFilter: StatementFilter,
|
||||
trace: BindingTrace
|
||||
): KotlinType? {
|
||||
//workaround for KT-8218
|
||||
@@ -329,6 +328,11 @@ class CallCompleter(
|
||||
val deparenthesized = KtPsiUtil.deparenthesizeOnce(expression)
|
||||
if (deparenthesized != expression) return deparenthesized
|
||||
|
||||
// see KtPsiUtil.getLastElementDeparenthesized
|
||||
if (expression is KtBlockExpression) {
|
||||
return statementFilter.getLastStatementInABlock(expression)
|
||||
}
|
||||
|
||||
return (expression as? KtQualifiedExpression)?.selectorExpression
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ class InlineChecker implements CallChecker {
|
||||
}
|
||||
}
|
||||
|
||||
checkVisibility(targetDescriptor, expression, context);
|
||||
checkVisibilityAndAccess(targetDescriptor, expression, context);
|
||||
checkRecursion(context, targetDescriptor, expression);
|
||||
}
|
||||
|
||||
@@ -248,10 +248,25 @@ class InlineChecker implements CallChecker {
|
||||
return isInvoke || InlineUtil.isInline(descriptor);
|
||||
}
|
||||
|
||||
private void checkVisibility(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){
|
||||
private void checkVisibilityAndAccess(@NotNull CallableDescriptor declarationDescriptor, @NotNull KtElement expression, @NotNull BasicCallResolutionContext context){
|
||||
boolean declarationDescriptorIsPublicApi = DescriptorUtilsKt.isEffectivelyPublicApi(declarationDescriptor) || isDefinedInInlineFunction(declarationDescriptor);
|
||||
if (isEffectivelyPublicApiFunction && !declarationDescriptorIsPublicApi && declarationDescriptor.getVisibility() != Visibilities.LOCAL) {
|
||||
context.trace.report(Errors.INVISIBLE_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
context.trace.report(Errors.NON_PUBLIC_CALL_FROM_PUBLIC_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
}
|
||||
else {
|
||||
checkPrivateClassMemberAccess(declarationDescriptor, expression, context);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkPrivateClassMemberAccess(
|
||||
@NotNull DeclarationDescriptor declarationDescriptor,
|
||||
@NotNull KtElement expression,
|
||||
@NotNull BasicCallResolutionContext context
|
||||
) {
|
||||
if (!Visibilities.isPrivate(descriptor.getVisibility())) {
|
||||
if (DescriptorUtilsKt.isInsidePrivateClass(declarationDescriptor)) {
|
||||
context.trace.report(Errors.PRIVATE_CLASS_MEMBER_FROM_INLINE.on(expression, declarationDescriptor, descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,8 @@ package org.jetbrains.kotlin.resolve.calls.checkers;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
@@ -40,32 +39,40 @@ public class ReifiedTypeParameterSubstitutionChecker implements CallChecker {
|
||||
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
|
||||
TypeParameterDescriptor parameter = entry.getKey();
|
||||
KotlinType argument = entry.getValue();
|
||||
ClassifierDescriptor argumentDeclarationDescription = argument.getConstructor().getDeclarationDescriptor();
|
||||
ClassifierDescriptor argumentDeclarationDescriptor = argument.getConstructor().getDeclarationDescriptor();
|
||||
|
||||
if (parameter.isReified()) {
|
||||
if (argumentDeclarationDescription instanceof TypeParameterDescriptor &&
|
||||
!((TypeParameterDescriptor) argumentDeclarationDescription).isReified()
|
||||
) {
|
||||
context.trace.report(
|
||||
Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter)
|
||||
);
|
||||
}
|
||||
else if (TypeUtilsKt.cannotBeReified(argument)) {
|
||||
context.trace.report(
|
||||
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
}
|
||||
else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
|
||||
context.trace.report(
|
||||
Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
}
|
||||
if (!parameter.isReified() && !isTypeParameterOfKotlinArray(parameter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argumentDeclarationDescriptor instanceof TypeParameterDescriptor &&
|
||||
!((TypeParameterDescriptor) argumentDeclarationDescriptor).isReified()) {
|
||||
context.trace.report(
|
||||
Errors.TYPE_PARAMETER_AS_REIFIED.on(getElementToReport(context, parameter.getIndex()), parameter)
|
||||
);
|
||||
}
|
||||
else if (TypeUtilsKt.cannotBeReified(argument)) {
|
||||
context.trace.report(
|
||||
Errors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
}
|
||||
// REIFIED_TYPE_UNSAFE_SUBSTITUTION is temporary disabled because it seems too strict now (see KT-10847)
|
||||
//else if (TypeUtilsKt.unsafeAsReifiedArgument(argument) && !hasPureReifiableAnnotation(parameter)) {
|
||||
// context.trace.report(
|
||||
// Errors.REIFIED_TYPE_UNSAFE_SUBSTITUTION.on(getElementToReport(context, parameter.getIndex()), argument));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
private static final FqName PURE_REIFIABLE_ANNOTATION_FQ_NAME = new FqName("kotlin.internal.PureReifiable");
|
||||
|
||||
private static boolean hasPureReifiableAnnotation(@NotNull TypeParameterDescriptor parameter) {
|
||||
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME);
|
||||
return parameter.getAnnotations().hasAnnotation(PURE_REIFIABLE_ANNOTATION_FQ_NAME) ||
|
||||
isTypeParameterOfKotlinArray(parameter);
|
||||
}
|
||||
|
||||
private static boolean isTypeParameterOfKotlinArray(@NotNull TypeParameterDescriptor parameter) {
|
||||
DeclarationDescriptor container = parameter.getContainingDeclaration();
|
||||
return container instanceof ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray((ClassDescriptor) container);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -69,6 +69,7 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
|
||||
val argumentsToParameters = hashMapOf<K, ValueParameterDescriptor>()
|
||||
var parametersWithDefaultValuesCount = 0
|
||||
|
||||
val unsubstitutedValueParameters = call.candidateDescriptor.original.valueParameters
|
||||
for ((valueParameterDescriptor, resolvedValueArgument) in call.unsubstitutedValueArguments.entries) {
|
||||
if (resolvedValueArgument is DefaultValueArgument) {
|
||||
parametersWithDefaultValuesCount++
|
||||
@@ -76,7 +77,10 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
|
||||
else {
|
||||
val keys = resolvedArgumentToKeys(resolvedValueArgument)
|
||||
for (argumentKey in keys) {
|
||||
argumentsToParameters[argumentKey] = valueParameterDescriptor.original
|
||||
// TODO fix 'original' for value parameters of Java generic descriptors.
|
||||
// Should be able to use just 'valueParameterDescriptor' below.
|
||||
// Doesn't work for Java generic descriptors. See also KT-10939.
|
||||
argumentsToParameters[argumentKey] = unsubstitutedValueParameters[valueParameterDescriptor.index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,9 +307,6 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
private fun getVarargElementTypeOrType(parameterDescriptor: ValueParameterDescriptor): KotlinType =
|
||||
parameterDescriptor.varargElementType ?: parameterDescriptor.type
|
||||
|
||||
private val CallableDescriptor.hasVarargs: Boolean get() =
|
||||
this.valueParameters.any { it.varargElementType != null }
|
||||
|
||||
private fun typeNotLessSpecific(specific: KotlinType, general: KotlinType): Boolean {
|
||||
val isSubtype = KotlinTypeChecker.DEFAULT.isSubtypeOf(specific, general) || numericTypeMoreSpecific(specific, general)
|
||||
|
||||
|
||||
@@ -300,8 +300,8 @@ internal class DelegatingDataFlowInfo private constructor(
|
||||
val toDelete = newTypeInfo()
|
||||
for (value in typeInfo.keys()) {
|
||||
for (type in typeInfo[value]) {
|
||||
// Remove original type and for not flexible type also all its supertypes (see also KT-10666)
|
||||
if (if (value.type.isFlexible()) value.type == type else value.type.isSubtypeOf(type)) {
|
||||
// Remove original type (see also KT-10666)
|
||||
if (value.type == type) {
|
||||
toDelete.put(value, type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,13 @@ fun Call.getValueArgumentsInParentheses(): List<ValueArgument> = valueArguments.
|
||||
|
||||
fun KtCallElement.getValueArgumentsInParentheses(): List<ValueArgument> = valueArguments.filterArgsInParentheses()
|
||||
|
||||
fun Call.getValueArgumentListOrElement(): KtElement = valueArgumentList ?: calleeExpression ?: callElement
|
||||
fun Call.getValueArgumentListOrElement(): KtElement =
|
||||
if (this is CallTransformer.CallForImplicitInvoke) {
|
||||
outerCall.getValueArgumentListOrElement()
|
||||
}
|
||||
else {
|
||||
valueArgumentList ?: calleeExpression ?: callElement
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun List<ValueArgument?>.filterArgsInParentheses() = filter { it !is KtLambdaArgument } as List<ValueArgument>
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.FunctionAnalyzerExtension;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
|
||||
import java.util.List;
|
||||
@@ -125,7 +126,7 @@ public class InlineAnalyzerExtension implements FunctionAnalyzerExtension.Analyz
|
||||
|
||||
hasInlinable |= InlineUtil.containsReifiedTypeParameters(functionDescriptor);
|
||||
|
||||
if (!hasInlinable) {
|
||||
if (!hasInlinable && !AnnotationUtilKt.isInlineOnly(functionDescriptor)) {
|
||||
KtModifierList modifierList = function.getModifierList();
|
||||
PsiElement inlineModifier = modifierList == null ? null : modifierList.getModifier(KtTokens.INLINE_KEYWORD);
|
||||
PsiElement reportOn = inlineModifier == null ? function : inlineModifier;
|
||||
|
||||
@@ -111,28 +111,39 @@ public class InlineUtil {
|
||||
if (!canBeInlineArgument(argument)) return null;
|
||||
|
||||
KtExpression call = KtPsiUtil.getParentCallIfPresent(argument);
|
||||
if (call != null) {
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(call, bindingContext);
|
||||
if (resolvedCall != null && isInline(resolvedCall.getResultingDescriptor())) {
|
||||
ValueArgument valueArgument = CallUtilKt.getValueArgumentForExpression(resolvedCall.getCall(), argument);
|
||||
if (valueArgument != null) {
|
||||
ArgumentMapping mapping = resolvedCall.getArgumentMapping(valueArgument);
|
||||
if (mapping instanceof ArgumentMatch) {
|
||||
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
|
||||
if (isInlineLambdaParameter(parameter)) {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
if (call == null) return null;
|
||||
|
||||
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(call, bindingContext);
|
||||
if (resolvedCall == null) return null;
|
||||
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
if (!isInline(descriptor) && !isArrayConstructorWithLambda(descriptor)) return null;
|
||||
|
||||
ValueArgument valueArgument = CallUtilKt.getValueArgumentForExpression(resolvedCall.getCall(), argument);
|
||||
if (valueArgument == null) return null;
|
||||
|
||||
ArgumentMapping mapping = resolvedCall.getArgumentMapping(valueArgument);
|
||||
if (!(mapping instanceof ArgumentMatch)) return null;
|
||||
|
||||
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
|
||||
return isInlineLambdaParameter(parameter) ? parameter : null;
|
||||
}
|
||||
|
||||
public static boolean canBeInlineArgument(@Nullable PsiElement functionalExpression) {
|
||||
return functionalExpression instanceof KtFunctionLiteral || functionalExpression instanceof KtNamedFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the descriptor is the constructor of one of 9 array classes (Array<T>, IntArray, FloatArray, ...)
|
||||
* which takes the size and an initializer lambda as parameters. Such constructors are marked as 'inline' but they are not loaded
|
||||
* as such because the 'inline' flag is not stored for constructors in the binary metadata. Therefore we pretend that they are inline
|
||||
*/
|
||||
public static boolean isArrayConstructorWithLambda(@NotNull CallableDescriptor descriptor) {
|
||||
return descriptor.getValueParameters().size() == 2 &&
|
||||
descriptor instanceof ConstructorDescriptor &&
|
||||
KotlinBuiltIns.isArrayOrPrimitiveArray(((ConstructorDescriptor) descriptor).getContainingDeclaration());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
|
||||
DeclarationDescriptor current = strict ? descriptor.getContainingDeclaration() : descriptor;
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
|
||||
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
|
||||
@@ -172,8 +173,16 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
|
||||
}
|
||||
});
|
||||
|
||||
// Annotation entries are taken from both own annotations (if any) and object literal annotations (if any)
|
||||
List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
|
||||
if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
|
||||
// TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
|
||||
annotationEntries.addAll(KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
|
||||
}
|
||||
if (modifierList != null) {
|
||||
annotationEntries.addAll(modifierList.getAnnotationEntries());
|
||||
}
|
||||
if (!annotationEntries.isEmpty()) {
|
||||
this.annotations = new LazyAnnotations(
|
||||
new LazyAnnotationsContext(
|
||||
c.getAnnotationResolver(),
|
||||
@@ -186,7 +195,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
return getOuterScope();
|
||||
}
|
||||
},
|
||||
modifierList.getAnnotationEntries()
|
||||
annotationEntries
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -940,6 +940,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
if (ArgumentTypeResolver.isFunctionLiteralArgument(baseExpression, context)) {
|
||||
context.trace.report(NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION.on(operationSign));
|
||||
if (baseTypeInfo == null) {
|
||||
return TypeInfoFactoryKt.createTypeInfo(ErrorUtils.createErrorType("Unresolved lambda expression"), context);
|
||||
}
|
||||
return baseTypeInfo;
|
||||
}
|
||||
assert baseTypeInfo != null : "Base expression was not processed: " + expression;
|
||||
@@ -1584,7 +1587,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
public KotlinTypeInfo visitAnnotatedExpression(KtAnnotatedExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
|
||||
if (!(expression.getBaseExpression() instanceof KtObjectLiteralExpression)) {
|
||||
// annotations on object literals are resolved later inside LazyClassDescriptor
|
||||
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace);
|
||||
}
|
||||
|
||||
KtExpression baseExpression = expression.getBaseExpression();
|
||||
if (baseExpression == null) {
|
||||
|
||||
@@ -187,7 +187,7 @@ public class ControlStructureTypingUtils {
|
||||
|
||||
@Override
|
||||
public void updateInfo(@NotNull ValueArgument valueArgument, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
//todo
|
||||
dataFlowInfoForArgumentsMap.put(valueArgument, dataFlowInfo);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -109,7 +109,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (elseBranch == null) {
|
||||
if (thenBranch != null) {
|
||||
KotlinTypeInfo result = getTypeInfoWhenOnlyOneBranchIsPresent(
|
||||
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression, isStatement);
|
||||
thenBranch, thenScope, thenInfo, elseInfo, contextWithExpectedType, ifExpression);
|
||||
// If jump was possible, take condition check info as the jump info
|
||||
return result.getJumpOutPossible()
|
||||
? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
|
||||
@@ -119,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
if (thenBranch == null) {
|
||||
return getTypeInfoWhenOnlyOneBranchIsPresent(
|
||||
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression, isStatement);
|
||||
elseBranch, elseScope, elseInfo, thenInfo, contextWithExpectedType, ifExpression);
|
||||
}
|
||||
KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
|
||||
KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
|
||||
@@ -135,42 +135,51 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
BindingContext bindingContext = context.trace.getBindingContext();
|
||||
KotlinTypeInfo thenTypeInfo = BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
|
||||
KotlinTypeInfo elseTypeInfo = BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
|
||||
assert thenTypeInfo != null : "'Then' branch of if expression was not processed: " + ifExpression;
|
||||
assert elseTypeInfo != null : "'Else' branch of if expression was not processed: " + ifExpression;
|
||||
assert thenTypeInfo != null || elseTypeInfo != null : "Both branches of if expression were not processed: " + ifExpression.getText();
|
||||
|
||||
KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
|
||||
KotlinType thenType = thenTypeInfo.getType();
|
||||
KotlinType elseType = elseTypeInfo.getType();
|
||||
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
|
||||
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
|
||||
if (resultType != null && thenType != null && elseType != null) {
|
||||
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
|
||||
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
|
||||
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
|
||||
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
|
||||
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
|
||||
}
|
||||
|
||||
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition ||
|
||||
thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
|
||||
|
||||
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
|
||||
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
|
||||
|
||||
boolean loopBreakContinuePossible = loopBreakContinuePossibleInCondition;
|
||||
DataFlowInfo resultDataFlowInfo;
|
||||
if (thenType == null && elseType == null) {
|
||||
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
|
||||
|
||||
if (elseTypeInfo == null) {
|
||||
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible();
|
||||
resultDataFlowInfo = thenTypeInfo.getDataFlowInfo();
|
||||
}
|
||||
else if (thenType == null || (jumpInThen && !jumpInElse)) {
|
||||
resultDataFlowInfo = elseDataFlowInfo;
|
||||
}
|
||||
else if (elseType == null || (jumpInElse && !jumpInThen)) {
|
||||
resultDataFlowInfo = thenDataFlowInfo;
|
||||
else if (thenTypeInfo == null) {
|
||||
loopBreakContinuePossible |= elseTypeInfo.getJumpOutPossible();
|
||||
resultDataFlowInfo = elseTypeInfo.getDataFlowInfo();
|
||||
}
|
||||
else {
|
||||
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
|
||||
}
|
||||
KotlinType thenType = thenTypeInfo.getType();
|
||||
KotlinType elseType = elseTypeInfo.getType();
|
||||
DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
|
||||
DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();
|
||||
if (resultType != null && thenType != null && elseType != null) {
|
||||
DataFlowValue resultValue = DataFlowValueFactory.createDataFlowValue(ifExpression, resultType, context);
|
||||
DataFlowValue thenValue = DataFlowValueFactory.createDataFlowValue(thenBranch, thenType, context);
|
||||
thenDataFlowInfo = thenDataFlowInfo.assign(resultValue, thenValue);
|
||||
DataFlowValue elseValue = DataFlowValueFactory.createDataFlowValue(elseBranch, elseType, context);
|
||||
elseDataFlowInfo = elseDataFlowInfo.assign(resultValue, elseValue);
|
||||
}
|
||||
|
||||
loopBreakContinuePossible |= thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();
|
||||
|
||||
boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
|
||||
boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);
|
||||
|
||||
if (thenType == null && elseType == null) {
|
||||
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
|
||||
}
|
||||
else if (thenType == null || (jumpInThen && !jumpInElse)) {
|
||||
resultDataFlowInfo = elseDataFlowInfo;
|
||||
}
|
||||
else if (elseType == null || (jumpInElse && !jumpInThen)) {
|
||||
resultDataFlowInfo = thenDataFlowInfo;
|
||||
}
|
||||
else {
|
||||
resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
|
||||
}
|
||||
}
|
||||
// If break or continue was possible, take condition check info as the jump info
|
||||
return TypeInfoFactoryKt.createTypeInfo(resultType, resultDataFlowInfo, loopBreakContinuePossible,
|
||||
loopBreakContinuePossibleInCondition ? context.dataFlowInfo : conditionDataFlowInfo);
|
||||
@@ -183,8 +192,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
@NotNull DataFlowInfo presentInfo,
|
||||
@NotNull DataFlowInfo otherInfo,
|
||||
@NotNull ExpressionTypingContext context,
|
||||
@NotNull KtIfExpression ifExpression,
|
||||
boolean isStatement
|
||||
@NotNull KtIfExpression ifExpression
|
||||
) {
|
||||
ExpressionTypingContext newContext = context.replaceDataFlowInfo(presentInfo).replaceExpectedType(NO_EXPECTED_TYPE)
|
||||
.replaceContextDependency(INDEPENDENT);
|
||||
@@ -561,8 +569,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
|
||||
}
|
||||
|
||||
assert parentDeclaration != null : "Can't find parent declaration for " + expression.getText();
|
||||
// Parent declaration can be null in code fragments or in some bad error expressions
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
|
||||
|
||||
Pair<FunctionDescriptor, PsiElement> containingFunInfo =
|
||||
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(declarationDescriptor, false);
|
||||
FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();
|
||||
|
||||
@@ -194,7 +194,15 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
|
||||
// todo save scope before analyze and fix debugger: see CodeFragmentAnalyzer.correctContextForExpression
|
||||
BindingContextUtilsKt.recordScope(context.trace, context.scope, expression);
|
||||
BindingContextUtilsKt.recordDataFlowInfo(context.replaceDataFlowInfo(result.getDataFlowInfo()), expression);
|
||||
recordTypeInfo(expression, result);
|
||||
try {
|
||||
// Here we have to resolve some types, so the following exception is possible
|
||||
// Example: val a = ::a, fun foo() = ::foo
|
||||
recordTypeInfo(expression, result);
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
|
||||
return TypeInfoFactoryKt.noTypeInfo(context);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
public class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
public static final Key<LightElementOrigin> ORIGIN = Key.create("ORIGIN");
|
||||
private final StubPsiFactory delegate = new ClsStubPsiFactory();
|
||||
|
||||
@@ -51,13 +51,19 @@ class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
@Override
|
||||
public PsiClass createClass(@NotNull PsiClassStub stub) {
|
||||
final PsiElement origin = getOriginalElement(stub);
|
||||
if (origin == null) return delegate.createClass(stub);
|
||||
|
||||
return new ClsClassImpl(stub) {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return origin;
|
||||
if (origin != null) return origin;
|
||||
|
||||
return super.getNavigationElement();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass getSourceMirrorClass() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -284,13 +284,12 @@ open class KtLightClassForExplicitDeclaration(
|
||||
}
|
||||
|
||||
if (classOrObject.hasModifier(PRIVATE_KEYWORD)) {
|
||||
// Top-level private class has PUBLIC visibility in Java
|
||||
// Top-level private class has PACKAGE_LOCAL visibility in Java
|
||||
// Nested private class has PRIVATE visibility
|
||||
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PUBLIC else PsiModifier.PRIVATE)
|
||||
psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PACKAGE_LOCAL else PsiModifier.PRIVATE)
|
||||
}
|
||||
|
||||
if (!psiModifiers.contains(PsiModifier.PRIVATE) && !psiModifiers.contains(PsiModifier.PROTECTED)) {
|
||||
psiModifiers.add(PsiModifier.PUBLIC) // For internal (default) visibility
|
||||
else if (!psiModifiers.contains(PsiModifier.PROTECTED)) {
|
||||
psiModifiers.add(PsiModifier.PUBLIC)
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
compiler/testData/builtin-classes-kotlin.txt
vendored
27
compiler/testData/builtin-classes-kotlin.txt
vendored
@@ -1,14 +1,5 @@
|
||||
package-fragment kotlin
|
||||
|
||||
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> Array(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, T>): kotlin.Array<T>
|
||||
public inline fun BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Boolean>): kotlin.BooleanArray
|
||||
public inline fun ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Byte>): kotlin.ByteArray
|
||||
public inline fun CharArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Char>): kotlin.CharArray
|
||||
public inline fun DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Double>): kotlin.DoubleArray
|
||||
public inline fun FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Float>): kotlin.FloatArray
|
||||
public inline fun IntArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Int>): kotlin.IntArray
|
||||
public inline fun LongArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Long>): kotlin.LongArray
|
||||
public inline fun ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: kotlin.Function1<kotlin.Int, kotlin.Short>): kotlin.ShortArray
|
||||
public inline fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOf(/*0*/ vararg elements: T /*kotlin.Array<out T>*/): kotlin.Array<T>
|
||||
public fun </*0*/ reified @kotlin.internal.PureReifiable() T> arrayOfNulls(/*0*/ size: kotlin.Int): kotlin.Array<T?>
|
||||
public fun booleanArrayOf(/*0*/ vararg elements: kotlin.Boolean /*kotlin.BooleanArray*/): kotlin.BooleanArray
|
||||
@@ -31,7 +22,7 @@ public open class Any {
|
||||
}
|
||||
|
||||
public final class Array</*0*/ T> : kotlin.Cloneable {
|
||||
/*primary*/ private constructor Array</*0*/ T>()
|
||||
public constructor Array</*0*/ T>(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> T)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.Array<T>
|
||||
@@ -51,6 +42,7 @@ public final class Boolean : kotlin.Comparable<kotlin.Boolean> {
|
||||
|
||||
public final class BooleanArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor BooleanArray(/*0*/ size: kotlin.Int)
|
||||
public constructor BooleanArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Boolean)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.BooleanArray
|
||||
@@ -124,6 +116,7 @@ public final class Byte : kotlin.Number, kotlin.Comparable<kotlin.Byte> {
|
||||
|
||||
public final class ByteArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor ByteArray(/*0*/ size: kotlin.Int)
|
||||
public constructor ByteArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Byte)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.ByteArray
|
||||
@@ -168,6 +161,7 @@ public final class Char : kotlin.Comparable<kotlin.Char> {
|
||||
|
||||
public final class CharArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor CharArray(/*0*/ size: kotlin.Int)
|
||||
public constructor CharArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Char)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.CharArray
|
||||
@@ -290,6 +284,7 @@ public final class Double : kotlin.Number, kotlin.Comparable<kotlin.Double> {
|
||||
|
||||
public final class DoubleArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor DoubleArray(/*0*/ size: kotlin.Int)
|
||||
public constructor DoubleArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Double)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.DoubleArray
|
||||
@@ -383,6 +378,7 @@ public final class Float : kotlin.Number, kotlin.Comparable<kotlin.Float> {
|
||||
|
||||
public final class FloatArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor FloatArray(/*0*/ size: kotlin.Int)
|
||||
public constructor FloatArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Float)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.FloatArray
|
||||
@@ -466,6 +462,7 @@ public final class Int : kotlin.Number, kotlin.Comparable<kotlin.Int> {
|
||||
|
||||
public final class IntArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor IntArray(/*0*/ size: kotlin.Int)
|
||||
public constructor IntArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Int)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.IntArray
|
||||
@@ -546,6 +543,7 @@ public final class Long : kotlin.Number, kotlin.Comparable<kotlin.Long> {
|
||||
|
||||
public final class LongArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor LongArray(/*0*/ size: kotlin.Int)
|
||||
public constructor LongArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Long)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.LongArray
|
||||
@@ -642,6 +640,7 @@ public final class Short : kotlin.Number, kotlin.Comparable<kotlin.Short> {
|
||||
|
||||
public final class ShortArray : kotlin.Cloneable {
|
||||
/*primary*/ public constructor ShortArray(/*0*/ size: kotlin.Int)
|
||||
public constructor ShortArray(/*0*/ size: kotlin.Int, /*1*/ init: (kotlin.Int) -> kotlin.Short)
|
||||
public final val size: kotlin.Int
|
||||
public final fun <get-size>(): kotlin.Int
|
||||
public open override /*1*/ fun clone(): kotlin.ShortArray
|
||||
@@ -675,10 +674,10 @@ public open class Throwable {
|
||||
public constructor Throwable(/*0*/ message: kotlin.String?)
|
||||
/*primary*/ public constructor Throwable(/*0*/ message: kotlin.String?, /*1*/ cause: kotlin.Throwable?)
|
||||
public constructor Throwable(/*0*/ cause: kotlin.Throwable?)
|
||||
public final val cause: kotlin.Throwable?
|
||||
public final fun <get-cause>(): kotlin.Throwable?
|
||||
public final val message: kotlin.String?
|
||||
public final fun <get-message>(): kotlin.String?
|
||||
public open val cause: kotlin.Throwable?
|
||||
public open fun <get-cause>(): kotlin.Throwable?
|
||||
public open val message: kotlin.String?
|
||||
public open fun <get-message>(): kotlin.String?
|
||||
}
|
||||
|
||||
public object Unit {
|
||||
|
||||
@@ -54,12 +54,14 @@ val b by a
|
||||
L0:
|
||||
1 <START>
|
||||
v(val b by a)
|
||||
r(a) -> <v0>
|
||||
magic[VALUE_CONSUMER](val b by a|<v0>) -> <v1>
|
||||
magic[UNRECOGNIZED_WRITE_RHS](val b by a) -> <v0>
|
||||
w(b|<v0>)
|
||||
r(a) -> <v1>
|
||||
magic[VALUE_CONSUMER](val b by a|<v1>) -> <v2>
|
||||
L1:
|
||||
<END> NEXT:[<SINK>]
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -19,6 +19,7 @@ Delegate() <v0>: Delegate NEW: call(Delegate(), <init>) -> <v0>
|
||||
== b ==
|
||||
val b by a
|
||||
---------------------
|
||||
<v1>: * NEW: magic[VALUE_CONSUMER](val b by a|<v0>) -> <v1>
|
||||
a <v0>: Delegate NEW: r(a) -> <v0>
|
||||
<v0>: Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val b by a) -> <v0>
|
||||
<v2>: * NEW: magic[VALUE_CONSUMER](val b by a|<v1>) -> <v2>
|
||||
a <v1>: Delegate NEW: r(a) -> <v1>
|
||||
=====================
|
||||
|
||||
@@ -4,14 +4,16 @@ val foo: Int by throw NullPointerException()
|
||||
L0:
|
||||
1 <START>
|
||||
v(val foo: Int by throw NullPointerException())
|
||||
magic[UNRECOGNIZED_WRITE_RHS](val foo: Int by throw NullPointerException()) -> <v0>
|
||||
w(foo|<v0>)
|
||||
mark(throw NullPointerException())
|
||||
mark(NullPointerException())
|
||||
call(NullPointerException(), <init>) -> <v0>
|
||||
throw (throw NullPointerException()|<v0>) NEXT:[<ERROR>]
|
||||
call(NullPointerException(), <init>) -> <v1>
|
||||
throw (throw NullPointerException()|<v1>) NEXT:[<ERROR>]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[]
|
||||
<END> NEXT:[<SINK>] PREV:[]
|
||||
error:
|
||||
<ERROR> PREV:[throw (throw NullPointerException()|<v0>)]
|
||||
<ERROR> PREV:[throw (throw NullPointerException()|<v1>)]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
== foo ==
|
||||
val foo: Int by throw NullPointerException()
|
||||
---------------------
|
||||
NullPointerException() <v0>: {<: Throwable} NEW: call(NullPointerException(), <init>) -> <v0>
|
||||
=====================
|
||||
<v0>: Int NEW: magic[UNRECOGNIZED_WRITE_RHS](val foo: Int by throw NullPointerException()) -> <v0>
|
||||
NullPointerException() <v1>: {<: Throwable} NEW: call(NullPointerException(), <init>) -> <v1>
|
||||
=====================
|
||||
|
||||
@@ -2,6 +2,8 @@ public fun <T> Iterable<T>.myforEach(operation: (T) -> Unit) : Unit {
|
||||
for (element in this) operation(element)
|
||||
}
|
||||
|
||||
public fun println(v: Any?) {}
|
||||
|
||||
fun foo1() {
|
||||
(1..5).myforEach {
|
||||
println(it)
|
||||
|
||||
2
compiler/testData/cli/jvm/wrongAbiVersion.kt
vendored
2
compiler/testData/cli/jvm/wrongAbiVersion.kt
vendored
@@ -3,5 +3,5 @@ import wrong.*
|
||||
fun foo(x: ClassWithWrongAbiVersion) {
|
||||
bar()
|
||||
|
||||
1.printStackTrace(2, 3)
|
||||
1.replaceIndent(2, 3)
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ compiler/testData/cli/jvm/wrongAbiVersion.kt:4:5: error: unresolved reference: b
|
||||
bar()
|
||||
^
|
||||
compiler/testData/cli/jvm/wrongAbiVersion.kt:6:7: error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
|
||||
public fun kotlin.Throwable.printStackTrace(): kotlin.Unit defined in kotlin
|
||||
public fun kotlin.Throwable.printStackTrace(stream: java.io.PrintStream): kotlin.Unit defined in kotlin
|
||||
public fun kotlin.Throwable.printStackTrace(writer: java.io.PrintWriter): kotlin.Unit defined in kotlin
|
||||
public fun kotlin.String.replaceIndent(newIndent: kotlin.String = ...): kotlin.String defined in kotlin.text
|
||||
(note: this may be caused by the fact that some classes compiled with an incompatible version of Kotlin were found in the classpath. Such classes cannot be loaded properly by this version of Kotlin compiler. See below for more information)
|
||||
1.printStackTrace(2, 3)
|
||||
1.replaceIndent(2, 3)
|
||||
^
|
||||
compiler/testData/cli/jvm/wrongAbiVersionLib/bin/ClassWithWrongAbiVersion.class: error: class 'ClassWithWrongAbiVersion' was compiled with an incompatible version of Kotlin. The binary version of its metadata is 0.30.0, expected version is $ABI_VERSION$
|
||||
COMPILATION_ERROR
|
||||
10
compiler/testData/codegen/box/properties/companionPrivateField.kt
vendored
Normal file
10
compiler/testData/codegen/box/properties/companionPrivateField.kt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
class My {
|
||||
companion object {
|
||||
private val my: String = "O"
|
||||
get() = field + "K"
|
||||
|
||||
fun getValue() = my
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = My.getValue()
|
||||
10
compiler/testData/codegen/box/properties/companionPrivateFieldInsideLambda.kt
vendored
Normal file
10
compiler/testData/codegen/box/properties/companionPrivateFieldInsideLambda.kt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
class My {
|
||||
companion object {
|
||||
private val my: String = "O"
|
||||
get() = { field }() + "K"
|
||||
|
||||
fun getValue() = my
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = My.getValue()
|
||||
20
compiler/testData/codegen/box/properties/kt10729.kt
vendored
Normal file
20
compiler/testData/codegen/box/properties/kt10729.kt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
class IntentionsBundle {
|
||||
companion object {
|
||||
fun message(key: String): String {
|
||||
return key + BUNDLE
|
||||
}
|
||||
|
||||
fun message2(key: String): String {
|
||||
return { key + BUNDLE }()
|
||||
}
|
||||
|
||||
private const val BUNDLE = "K"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
if (IntentionsBundle.message("O") != "OK") return "fail 1: ${IntentionsBundle.message("O")}"
|
||||
|
||||
return IntentionsBundle.message2("O")
|
||||
}
|
||||
38
compiler/testData/codegen/box/regressions/kt10934.kt
vendored
Normal file
38
compiler/testData/codegen/box/regressions/kt10934.kt
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
//KT-10934 compiler throws UninferredParameterTypeConstructor in when block that covers all types
|
||||
|
||||
class Parser<TInput, TValue>(val f: (TInput) -> Result<TInput, TValue>) {
|
||||
|
||||
operator fun invoke(input: TInput): Result<TInput, TValue> = f(input)
|
||||
|
||||
fun <TIntermediate, TValue2> mapJoin(
|
||||
selector: (TValue) -> Parser<TInput, TIntermediate>,
|
||||
projector: (TValue, TIntermediate) -> TValue2
|
||||
): Parser<TInput, TValue2> {
|
||||
return Parser({ input ->
|
||||
val res = this(input)
|
||||
when (res) {
|
||||
is Result.ParseError -> Result.ParseError(res.productionLabel, res.child, res.rest)
|
||||
is Result.Value -> {
|
||||
val v = res.value
|
||||
val res2 = selector(v)(res.rest)
|
||||
when (res2) {
|
||||
is Result.ParseError -> Result.ParseError(res2.productionLabel, res2.child, res2.rest)
|
||||
is Result.Value -> Result.Value(projector(v, res2.value), res2.rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/** A parser can return one of two Results */
|
||||
sealed class Result<TInput, TValue> {
|
||||
|
||||
class Value<TInput, TValue>(val value: TValue, val rest: TInput) : Result<TInput, TValue>() {}
|
||||
|
||||
class ParseError<TInput, TValue>(val productionLabel: String,
|
||||
val child: ParseError<TInput, *>?,
|
||||
val rest: TInput) : Result<TInput, TValue>() {}
|
||||
}
|
||||
|
||||
fun box() = "OK"
|
||||
15
compiler/testData/codegen/box/smartCasts/smartCastInsideIf.kt
vendored
Normal file
15
compiler/testData/codegen/box/smartCasts/smartCastInsideIf.kt
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
class A(val s: String = "FAIL")
|
||||
|
||||
private fun foo(a: A?, aOther: A?): A {
|
||||
return if (a == null) {
|
||||
A()
|
||||
}
|
||||
else {
|
||||
if (aOther == null) {
|
||||
return A()
|
||||
}
|
||||
aOther
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = foo(A("???"), A("OK")).s
|
||||
21
compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt
vendored
Normal file
21
compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
class MyThrowable(message: String? = null, cause: Throwable? = null) : Throwable(message, cause) {
|
||||
|
||||
override val message: String?
|
||||
get() = "My message: " + super.message
|
||||
|
||||
override val cause: Throwable?
|
||||
get() = super.cause ?: this
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
throw MyThrowable("test")
|
||||
} catch (t: MyThrowable) {
|
||||
if (t.cause != t) return "fail t.cause"
|
||||
if (t.message != "My message: test") return "fail t.message"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
return "fail: MyThrowable wasn't catched."
|
||||
}
|
||||
26
compiler/testData/codegen/box/typeInfo/ifOrWhenSpecialCall.kt
vendored
Normal file
26
compiler/testData/codegen/box/typeInfo/ifOrWhenSpecialCall.kt
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
interface Option<out T> {
|
||||
val s: String
|
||||
}
|
||||
class Some<T>(override val s: String) : Option<T>
|
||||
class None(override val s: String = "None") : Option<Int>
|
||||
|
||||
fun whenTest(a: Int): Option<Any> = when (a) {
|
||||
239 -> {
|
||||
if (a == 239) Some("239") else None()
|
||||
}
|
||||
else -> if (a != 239) Some("$a") else None()
|
||||
}
|
||||
|
||||
fun ifTest(a: Int): Option<Any> = if (a == 239) {
|
||||
if (a == 239) Some("239") else None()
|
||||
} else if (a != 239) Some("$a") else None()
|
||||
|
||||
fun box(): String {
|
||||
if (whenTest(2).s != "2") return "Fail 1"
|
||||
if (whenTest(239).s != "239") return "Fail 2"
|
||||
|
||||
if (ifTest(2).s != "2") return "Fail 3"
|
||||
if (ifTest(239).s != "239") return "Fail 4"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
5
compiler/testData/codegen/boxInline/compexStack/asCheck.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/asCheck.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return ContentTypeByExtension.processRecords { ext -> ext }
|
||||
}
|
||||
18
compiler/testData/codegen/boxInline/compexStack/asCheck.2.kt
vendored
Normal file
18
compiler/testData/codegen/boxInline/compexStack/asCheck.2.kt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package test
|
||||
|
||||
object ContentTypeByExtension {
|
||||
inline fun processRecords(crossinline operation: (String) -> String) =
|
||||
listOf("O", "K").map {
|
||||
val ext = B(it)
|
||||
operation(ext.toLowerCase())
|
||||
}.joinToString("")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline fun A.toLowerCase(): String = (this as B).value
|
||||
|
||||
open class A
|
||||
|
||||
open class B(val value: String) : A()
|
||||
5
compiler/testData/codegen/boxInline/compexStack/asCheck2.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/asCheck2.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return ContentTypeByExtension.processRecords { ext -> ext }
|
||||
}
|
||||
18
compiler/testData/codegen/boxInline/compexStack/asCheck2.2.kt
vendored
Normal file
18
compiler/testData/codegen/boxInline/compexStack/asCheck2.2.kt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package test
|
||||
|
||||
object ContentTypeByExtension {
|
||||
inline fun processRecords(crossinline operation: (String) -> String) =
|
||||
{
|
||||
val ext = B("OK")
|
||||
operation(ext.toLowerCase())
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline fun A.toLowerCase(): String = (this as B).value
|
||||
|
||||
open class A
|
||||
|
||||
open class B(val value: String) : A()
|
||||
5
compiler/testData/codegen/boxInline/compexStack/simple.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/simple.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return processRecords { ext -> ext + "K" }
|
||||
}
|
||||
5
compiler/testData/codegen/boxInline/compexStack/simple.2.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/simple.2.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
package test
|
||||
|
||||
inline fun foo(x: String) = x
|
||||
|
||||
inline fun processRecords(block: (String) -> String) = block(foo("O"))
|
||||
5
compiler/testData/codegen/boxInline/compexStack/simple2.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/simple2.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return processRecords { "O" + it }
|
||||
}
|
||||
11
compiler/testData/codegen/boxInline/compexStack/simple2.2.kt
vendored
Normal file
11
compiler/testData/codegen/boxInline/compexStack/simple2.2.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
inline fun foo(x: String) = x
|
||||
|
||||
class A {
|
||||
fun test(s: String) = s
|
||||
}
|
||||
|
||||
inline fun processRecords(block: (String) -> String): String {
|
||||
return A().test(block(foo("K")))
|
||||
}
|
||||
7
compiler/testData/codegen/boxInline/compexStack/simple3.1.kt
vendored
Normal file
7
compiler/testData/codegen/boxInline/compexStack/simple3.1.kt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
val result = processRecords { "B" + it }
|
||||
|
||||
return if (result == "BOK1") "OK" else "fail: $result"
|
||||
}
|
||||
11
compiler/testData/codegen/boxInline/compexStack/simple3.2.kt
vendored
Normal file
11
compiler/testData/codegen/boxInline/compexStack/simple3.2.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
inline fun foo(x: String, y: String) = x + y
|
||||
|
||||
class A {
|
||||
fun test(s: String) = s
|
||||
}
|
||||
|
||||
inline fun processRecords(block: (String) -> String): String {
|
||||
return A().test(block(foo("O", foo("K", "1"))))
|
||||
}
|
||||
5
compiler/testData/codegen/boxInline/compexStack/simple4.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/compexStack/simple4.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return processRecords { a, b -> a + b}
|
||||
}
|
||||
10
compiler/testData/codegen/boxInline/compexStack/simple4.2.kt
vendored
Normal file
10
compiler/testData/codegen/boxInline/compexStack/simple4.2.kt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
inline fun foo(x: String) = x
|
||||
|
||||
fun test(a: String, s: String) = s
|
||||
|
||||
|
||||
inline fun processRecords(block: (String, String) -> String): String {
|
||||
return test("stub", block(foo("O"), foo("K")))
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
import a.foo
|
||||
import a.inlineOnly
|
||||
|
||||
fun box(): String = foo { "OK" }
|
||||
fun box(): String {
|
||||
if (!a.inlineOnly<String>("OK")) return "fail 1"
|
||||
return foo { "OK" }
|
||||
}
|
||||
|
||||
@@ -3,4 +3,6 @@ package a
|
||||
|
||||
inline fun foo(body: () -> String): String = bar(body())
|
||||
|
||||
public fun bar(x: String): String = x
|
||||
public fun bar(x: String): String = x
|
||||
|
||||
inline fun <reified T> inlineOnly(x: Any?): Boolean = x is T
|
||||
5
compiler/testData/codegen/boxInline/private/accessorForConst.1.kt
vendored
Normal file
5
compiler/testData/codegen/boxInline/private/accessorForConst.1.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return IntentionsBundle.message()
|
||||
}
|
||||
14
compiler/testData/codegen/boxInline/private/accessorForConst.2.kt
vendored
Normal file
14
compiler/testData/codegen/boxInline/private/accessorForConst.2.kt
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package test
|
||||
|
||||
class IntentionsBundle {
|
||||
companion object {
|
||||
internal inline fun message(): String {
|
||||
return KEY + BUNDLE
|
||||
}
|
||||
|
||||
private const val BUNDLE = "K"
|
||||
protected const val KEY = "O"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
compiler/testData/codegen/boxInline/private/nestedInPrivateClass.1.kt
vendored
Normal file
7
compiler/testData/codegen/boxInline/private/nestedInPrivateClass.1.kt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return call {
|
||||
"O"
|
||||
}
|
||||
}
|
||||
18
compiler/testData/codegen/boxInline/private/nestedInPrivateClass.2.kt
vendored
Normal file
18
compiler/testData/codegen/boxInline/private/nestedInPrivateClass.2.kt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package test
|
||||
|
||||
private class S public constructor() {
|
||||
class Z {
|
||||
fun a(): String {
|
||||
return "K"
|
||||
}
|
||||
}
|
||||
}
|
||||
// This function exposes S.Z which is a class nested into a private class S (package-private in the byte code)
|
||||
// It can be accessed outside the `test` package now that S.Z. is public in the byte code, but it may be changed later
|
||||
internal inline fun call(s: () -> String): String {
|
||||
return s() + test().a()
|
||||
}
|
||||
|
||||
private fun test(): S.Z {
|
||||
return S.Z()
|
||||
}
|
||||
7
compiler/testData/codegen/boxInline/private/privateClass.1.kt
vendored
Normal file
7
compiler/testData/codegen/boxInline/private/privateClass.1.kt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return call {
|
||||
"O"
|
||||
}
|
||||
}
|
||||
23
compiler/testData/codegen/boxInline/private/privateClass.2.kt
vendored
Normal file
23
compiler/testData/codegen/boxInline/private/privateClass.2.kt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package test
|
||||
|
||||
private class S {
|
||||
fun a(): String {
|
||||
return "K"
|
||||
}
|
||||
}
|
||||
|
||||
// This function exposes S which is a private class (package-private in the byte code)
|
||||
// It can be accessed outside the `test` package, which may lead to IllegalAccessError.
|
||||
// This behavior may be changed later
|
||||
internal inline fun call(s: () -> String): String {
|
||||
val s = test()
|
||||
return s() + test2(s)
|
||||
}
|
||||
|
||||
private fun test(): S {
|
||||
return S()
|
||||
}
|
||||
|
||||
private fun test2(s: S): String {
|
||||
return s.a()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user