mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-01 08:31:31 +00:00
Compare commits
177 Commits
stdlib/sat
...
build-1.0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9070eff6ad | ||
|
|
9ac2da8c96 | ||
|
|
b9e677fef4 | ||
|
|
de3f507744 | ||
|
|
a08b8f43b2 | ||
|
|
5ae394fec0 | ||
|
|
1f6894cdd4 | ||
|
|
5c6c1173a6 | ||
|
|
e2f1a5c092 | ||
|
|
cf173d6963 | ||
|
|
f6e7f8c3c0 | ||
|
|
4ec3865830 | ||
|
|
1fca1cc607 | ||
|
|
6c7cefaae3 | ||
|
|
8b5e9d1685 | ||
|
|
6e1705dd16 | ||
|
|
daf26f4db3 | ||
|
|
bb2a5b00b7 | ||
|
|
792d9c1ae2 | ||
|
|
eacd50c4dc | ||
|
|
0f90dc1649 | ||
|
|
c75b514551 | ||
|
|
b8ee2ecdac | ||
|
|
78b7fb15f3 | ||
|
|
b4ebaad8f5 | ||
|
|
434bd0707d | ||
|
|
74b2c8cd31 | ||
|
|
17ebb36128 | ||
|
|
5361f6e941 | ||
|
|
f12c653aed | ||
|
|
f59a4c537e | ||
|
|
909ced5fa2 | ||
|
|
99a693a14b | ||
|
|
ff2029035e | ||
|
|
cd3f7df28c | ||
|
|
c879f83037 | ||
|
|
68110f5859 | ||
|
|
18e7272a1e | ||
|
|
9e3d381eb3 | ||
|
|
fae6de9acd | ||
|
|
c1f57b743b | ||
|
|
924d706e79 | ||
|
|
beea2d5d10 | ||
|
|
848549dd5d | ||
|
|
9e5c387d6c | ||
|
|
25b8e4f1b2 | ||
|
|
d238df8525 | ||
|
|
3c4cb54573 | ||
|
|
e328c24857 | ||
|
|
21e69a0a4c | ||
|
|
d5030335b6 | ||
|
|
2c1d1e84a6 | ||
|
|
5968ce96df | ||
|
|
9f786c00a7 | ||
|
|
938a435346 | ||
|
|
1e50847985 | ||
|
|
e82d549853 | ||
|
|
8800782c83 | ||
|
|
2f5a6ac465 | ||
|
|
5de1cf3bb4 | ||
|
|
ba80e8ba81 | ||
|
|
7da981e12c | ||
|
|
0efe28a12a | ||
|
|
f2edcd99a8 | ||
|
|
8d87800a05 | ||
|
|
affbefdfbe | ||
|
|
ce8e2d7a65 | ||
|
|
3fe6f9cad2 | ||
|
|
9c426e70e1 | ||
|
|
c914ca0626 | ||
|
|
eca581ef43 | ||
|
|
8b6338ce62 | ||
|
|
bc2077bfaf | ||
|
|
16f412f993 | ||
|
|
889b136a68 | ||
|
|
e4583fd275 | ||
|
|
fa8706b46a | ||
|
|
6038bde3c1 | ||
|
|
8c17c5f40b | ||
|
|
c600fe1dc3 | ||
|
|
9c72a388b2 | ||
|
|
63a50ca3a9 | ||
|
|
7c84225cc4 | ||
|
|
a4e3dd7030 | ||
|
|
ba6c738cb5 | ||
|
|
bcc3102e05 | ||
|
|
37976e516c | ||
|
|
abcdae8e69 | ||
|
|
5f037d372d | ||
|
|
d13ac6b5a4 | ||
|
|
fe8a0ec2bc | ||
|
|
48b538cebf | ||
|
|
b5145ea68b | ||
|
|
0a46033d40 | ||
|
|
e9d5d8f0fe | ||
|
|
6ee4071462 | ||
|
|
2fa00f87e0 | ||
|
|
9b978377d0 | ||
|
|
b5b2bbc9ab | ||
|
|
ccd22cd5ca | ||
|
|
f28f7eaa3b | ||
|
|
876e458c04 | ||
|
|
e89638f937 | ||
|
|
c808f4ec2a | ||
|
|
60d56b30bf | ||
|
|
187694d1b0 | ||
|
|
34d8dd9127 | ||
|
|
ec991b4ced | ||
|
|
030c55ebb2 | ||
|
|
805410bb19 | ||
|
|
c243a2bdd5 | ||
|
|
7105c7c182 | ||
|
|
0c32fab690 | ||
|
|
c5be8ce1d3 | ||
|
|
4afe98a0f6 | ||
|
|
130301aa27 | ||
|
|
e227f6fc74 | ||
|
|
394221fefb | ||
|
|
6ae6f72156 | ||
|
|
4b203de608 | ||
|
|
d1db404959 | ||
|
|
71c2a6e792 | ||
|
|
751ac3912d | ||
|
|
f19ef6e3d5 | ||
|
|
947fd84f1e | ||
|
|
7a50562a4e | ||
|
|
477b57cdfd | ||
|
|
57cfa54957 | ||
|
|
c881cd1070 | ||
|
|
45a387668b | ||
|
|
db5191041f | ||
|
|
45298e0bad | ||
|
|
65f754ffca | ||
|
|
7dd725f0a4 | ||
|
|
4a1d282de6 | ||
|
|
8df05c6c4c | ||
|
|
148b53fc62 | ||
|
|
f29efc2ca2 | ||
|
|
893c2495fe | ||
|
|
51ea804d88 | ||
|
|
45f96f8f32 | ||
|
|
4f76207a27 | ||
|
|
b19d32e4f2 | ||
|
|
d60a5e65c1 | ||
|
|
bad8320038 | ||
|
|
970d6f6834 | ||
|
|
da7acd5e73 | ||
|
|
7e528da00a | ||
|
|
816c66063b | ||
|
|
829a5639f1 | ||
|
|
9b3f557337 | ||
|
|
05192547da | ||
|
|
801a26a544 | ||
|
|
a192915c82 | ||
|
|
dccae6c3ff | ||
|
|
dacf25fdec | ||
|
|
c763b592a5 | ||
|
|
1cef327880 | ||
|
|
a12fe2c18a | ||
|
|
8a00db5661 | ||
|
|
fc3f98dae2 | ||
|
|
42bd8df2ca | ||
|
|
1eee1fa803 | ||
|
|
abe927056b | ||
|
|
54977ee09a | ||
|
|
47d580cbc5 | ||
|
|
56c5758db1 | ||
|
|
40fae0463f | ||
|
|
ce5fd3ee77 | ||
|
|
c7bd70732c | ||
|
|
8c0008aa2e | ||
|
|
38b58db4f9 | ||
|
|
84f9cb9bfd | ||
|
|
3ae4c033b6 | ||
|
|
5f38c1d571 | ||
|
|
9790afb1bd | ||
|
|
328b9bfeda |
2
.idea/runConfigurations/Update_Dist_Run.xml
generated
2
.idea/runConfigurations/Update_Dist_Run.xml
generated
@@ -15,7 +15,7 @@
|
||||
<method>
|
||||
<option name="Make" enabled="false" />
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/build.xml" target="clean_idea_output" />
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/update_dependencies.xml" target="update" />
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/update_dependencies.xml" target="update_teamcity" />
|
||||
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/build.xml" target="dist" />
|
||||
<option name="MakeProject" enabled="true" />
|
||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Generate Tests" run_configuration_type="Application" />
|
||||
|
||||
@@ -1130,6 +1130,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>
|
||||
|
||||
@@ -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.*;
|
||||
@@ -197,7 +195,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
erasedInterfaceFunction.getValueParameters(), erasedInterfaceFunction.getReturnType(),
|
||||
Modality.OPEN, erasedInterfaceFunction.getVisibility());
|
||||
|
||||
descriptorForBridges.addOverriddenDescriptor(erasedInterfaceFunction);
|
||||
DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, erasedInterfaceFunction);
|
||||
functionCodegen.generateBridges(descriptorForBridges);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmOverloadsAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -134,6 +135,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
}
|
||||
|
||||
if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) {
|
||||
FunctionCodegen.generateLocalVariablesForParameters(mv, signature, null, Label(), Label(), remainingParameters, isStatic)
|
||||
mv.visitEnd()
|
||||
return
|
||||
}
|
||||
@@ -142,6 +144,9 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
val v = InstructionAdapter(mv)
|
||||
mv.visitCode()
|
||||
|
||||
val methodBegin = Label()
|
||||
mv.visitLabel(methodBegin)
|
||||
|
||||
val methodOwner = typeMapper.mapToCallableMethod(delegateFunctionDescriptor, false).owner
|
||||
if (!isStatic) {
|
||||
val thisIndex = frameMap.enterTemp(AsmTypes.OBJECT_TYPE)
|
||||
@@ -201,6 +206,13 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
|
||||
v.invokestatic(methodOwner.internalName, defaultMethod.name, defaultMethod.descriptor, false)
|
||||
}
|
||||
v.areturn(signature.returnType)
|
||||
|
||||
val methodEnd = Label()
|
||||
mv.visitLabel(methodEnd)
|
||||
|
||||
FunctionCodegen.generateLocalVariablesForParameters(mv, signature, null, methodBegin, methodEnd,
|
||||
remainingParameters, isStatic)
|
||||
|
||||
FunctionCodegen.endVisit(mv, null, methodElement)
|
||||
}
|
||||
|
||||
|
||||
@@ -1246,6 +1246,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
if (compileTimeValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (compileTimeValue.getUsesNonConstValAsConstant()) return null;
|
||||
|
||||
KotlinType expectedType = bindingContext.getType(expression);
|
||||
return compileTimeValue.toConstantValue(expectedType);
|
||||
}
|
||||
@@ -2119,7 +2122,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) {
|
||||
|
||||
@@ -400,11 +400,24 @@ public class FunctionCodegen {
|
||||
@NotNull Label methodEnd,
|
||||
@NotNull OwnerKind ownerKind
|
||||
) {
|
||||
Iterator<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator();
|
||||
generateLocalVariablesForParameters(mv, jvmMethodSignature, thisType, methodBegin, methodEnd,
|
||||
functionDescriptor.getValueParameters(),
|
||||
AsmUtil.isStaticMethod(ownerKind, functionDescriptor));
|
||||
}
|
||||
|
||||
public static void generateLocalVariablesForParameters(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||
@Nullable Type thisType,
|
||||
@NotNull Label methodBegin,
|
||||
@NotNull Label methodEnd,
|
||||
Collection<ValueParameterDescriptor> valueParameters,
|
||||
boolean isStatic
|
||||
) {
|
||||
Iterator<ValueParameterDescriptor> valueParameterIterator = valueParameters.iterator();
|
||||
List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
|
||||
int shift = 0;
|
||||
|
||||
boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
|
||||
if (!isStatic) {
|
||||
//add this
|
||||
if (thisType != null) {
|
||||
@@ -422,7 +435,7 @@ public class FunctionCodegen {
|
||||
String parameterName;
|
||||
|
||||
if (kind == JvmMethodParameterKind.VALUE) {
|
||||
ValueParameterDescriptor parameter = valueParameters.next();
|
||||
ValueParameterDescriptor parameter = valueParameterIterator.next();
|
||||
parameterName = parameter.getName().asString();
|
||||
}
|
||||
else {
|
||||
@@ -676,15 +689,6 @@ public class FunctionCodegen {
|
||||
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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,38 +771,6 @@ public class FunctionCodegen {
|
||||
iv.visitLabel(end);
|
||||
}
|
||||
|
||||
private void generateOldDefaultForFun(
|
||||
Method newDefaultMethod,
|
||||
JvmDeclarationOrigin origin,
|
||||
int flags,
|
||||
String[] exceptions,
|
||||
String owner
|
||||
) {
|
||||
if ("<init>".equals(newDefaultMethod.getName())) {
|
||||
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();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FrameMap createFrameMap(
|
||||
@NotNull GenerationState state,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -67,6 +68,9 @@ import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJ
|
||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PropertyCodegen {
|
||||
|
||||
private static Logger LOG = Logger.getInstance(PropertyCodegen.class);
|
||||
|
||||
private final GenerationState state;
|
||||
private final ClassBuilder v;
|
||||
private final FunctionCodegen functionCodegen;
|
||||
@@ -94,7 +98,11 @@ public class PropertyCodegen {
|
||||
|
||||
public void gen(@NotNull KtProperty property) {
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, property);
|
||||
assert variableDescriptor instanceof PropertyDescriptor : "Property " + property.getText() + " should have a property descriptor: " + variableDescriptor;
|
||||
if (!(variableDescriptor instanceof PropertyDescriptor)) {
|
||||
String problem = "Property " + property.getName() + " should have a property descriptor: " + variableDescriptor;
|
||||
LOG.error(problem, PsiUtilsKt.getElementTextWithContext(property));
|
||||
throw new AssertionError(problem);
|
||||
}
|
||||
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variableDescriptor;
|
||||
gen(property, propertyDescriptor, property.getGetter(), property.getSetter());
|
||||
@@ -114,7 +122,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 +136,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)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
@@ -39,7 +40,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 +96,6 @@ public class SamWrapperCodegen {
|
||||
);
|
||||
cv.visitSource(file.getName(), null);
|
||||
|
||||
writeKotlinSyntheticClassAnnotation(cv, state);
|
||||
|
||||
WriteAnnotationUtilKt.writeSyntheticClassMetadata(cv);
|
||||
|
||||
// e.g. ASM type for Function2
|
||||
@@ -166,7 +166,7 @@ public class SamWrapperCodegen {
|
||||
originalInterfaceErased.getValueParameters(), originalInterfaceErased.getReturnType(),
|
||||
Modality.OPEN, originalInterfaceErased.getVisibility());
|
||||
|
||||
descriptorForBridges.addOverriddenDescriptor(originalInterfaceErased);
|
||||
DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, originalInterfaceErased);
|
||||
codegen.generateBridges(descriptorForBridges);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
nodeAndSMAP = InlineCodegenUtil.getMethodNode(
|
||||
file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor(), containingClasses.getFacadeClassId()
|
||||
file.contentsToByteArray(), asmMethod.getName(), asmMethod.getDescriptor(), containerId
|
||||
);
|
||||
|
||||
if (nodeAndSMAP == null) {
|
||||
@@ -241,7 +241,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
SMAP smap;
|
||||
if (callDefault) {
|
||||
Type implementationOwner = typeMapper.mapOwner(functionDescriptor);
|
||||
Type implementationOwner = typeMapper.mapImplementationOwner(functionDescriptor);
|
||||
FakeMemberCodegen parentCodegen = new FakeMemberCodegen(codegen.getParentCodegen(), inliningFunction,
|
||||
(FieldOwnerContext) methodContext.getParentContext(),
|
||||
implementationOwner.getInternalName());
|
||||
@@ -366,7 +366,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
new FakeMemberCodegen(codegen.getParentCodegen(), expression,
|
||||
(FieldOwnerContext) context.getParentContext(),
|
||||
isLambda ? codegen.getParentCodegen().getClassName()
|
||||
: typeMapper.mapOwner(descriptor).getInternalName());
|
||||
: typeMapper.mapImplementationOwner(descriptor).getInternalName());
|
||||
|
||||
FunctionGenerationStrategy strategy =
|
||||
expression instanceof KtCallableReferenceExpression ?
|
||||
@@ -425,7 +425,7 @@ public class InlineCodegen extends CallGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,10 @@ package org.jetbrains.kotlin.codegen.inline;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class InvokeCall {
|
||||
private final int index;
|
||||
public final LambdaInfo lambdaInfo;
|
||||
public final int finallyDepthShift;
|
||||
|
||||
InvokeCall(int index, @Nullable LambdaInfo lambdaInfo, int finallyDepthShift) {
|
||||
this.index = index;
|
||||
InvokeCall(@Nullable LambdaInfo lambdaInfo, int finallyDepthShift) {
|
||||
this.lambdaInfo = lambdaInfo;
|
||||
this.finallyDepthShift = finallyDepthShift;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ public class LocalVarRemapper {
|
||||
|
||||
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index, MethodVisitor mv) {
|
||||
RemapInfo info = doRemap(index);
|
||||
//add entries only for shifted vars or remapped to locals
|
||||
if (SHIFT == info.status || REMAPPED == info.status && info.value instanceof StackValue.Local) {
|
||||
//add entries only for shifted vars
|
||||
if (SHIFT == info.status) {
|
||||
int newIndex = ((StackValue.Local) info.value).index;
|
||||
mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.utils.SmartSet;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
@@ -427,15 +428,15 @@ public class MethodInliner {
|
||||
catch (AnalyzerException e) {
|
||||
throw wrapException(e, node, "couldn't inline method call");
|
||||
}
|
||||
|
||||
AbstractInsnNode cur = node.instructions.getFirst();
|
||||
int index = 0;
|
||||
Set<AbstractInsnNode> toDelete = SmartSet.create();
|
||||
InsnList instructions = node.instructions;
|
||||
AbstractInsnNode cur = instructions.getFirst();
|
||||
|
||||
boolean awaitClassReification = false;
|
||||
int currentFinallyDeep = 0;
|
||||
|
||||
while (cur != null) {
|
||||
Frame<SourceValue> frame = sources[index];
|
||||
Frame<SourceValue> frame = sources[instructions.indexOf(cur)];
|
||||
|
||||
if (frame != null) {
|
||||
if (ReifiedTypeInliner.isNeedClassReificationMarker(cur)) {
|
||||
@@ -458,25 +459,11 @@ public class MethodInliner {
|
||||
if (isInvokeOnLambda(owner, name) /*&& methodInsnNode.owner.equals(INLINE_RUNTIME)*/) {
|
||||
SourceValue sourceValue = frame.getStack(firstParameterIndex);
|
||||
|
||||
LambdaInfo lambdaInfo = null;
|
||||
int varIndex = -1;
|
||||
LambdaInfo lambdaInfo = MethodInlinerUtilKt.getLambdaIfExistsAndMarkInstructions(
|
||||
this, MethodInlinerUtilKt.singleOrNullInsn(sourceValue), true, instructions, sources, toDelete
|
||||
);
|
||||
|
||||
if (sourceValue.insns.size() == 1) {
|
||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||
AbstractInsnNode processingInstruction = insnNode;
|
||||
|
||||
if (insnNode.getOpcode() == Opcodes.SWAP) {
|
||||
processingInstruction = InlineCodegenUtil.getPrevMeaningful(insnNode);
|
||||
}
|
||||
lambdaInfo = getLambdaIfExists(processingInstruction);
|
||||
if (lambdaInfo != null) {
|
||||
//remove inlinable access
|
||||
assert processingInstruction != null;
|
||||
InlineCodegenUtil.removeInterval(node, processingInstruction, insnNode);
|
||||
}
|
||||
}
|
||||
|
||||
invokeCalls.add(new InvokeCall(varIndex, lambdaInfo, currentFinallyDeep));
|
||||
invokeCalls.add(new InvokeCall(lambdaInfo, currentFinallyDeep));
|
||||
}
|
||||
else if (isAnonymousConstructorCall(owner, name)) {
|
||||
Map<Integer, LambdaInfo> lambdaMapping = new HashMap<Integer, LambdaInfo>();
|
||||
@@ -484,14 +471,13 @@ public class MethodInliner {
|
||||
int offset = 0;
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
SourceValue sourceValue = frame.getStack(firstParameterIndex + i);
|
||||
if (sourceValue.insns.size() == 1) {
|
||||
AbstractInsnNode insnNode = sourceValue.insns.iterator().next();
|
||||
LambdaInfo lambdaInfo = getLambdaIfExists(insnNode);
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo);
|
||||
node.instructions.remove(insnNode);
|
||||
}
|
||||
LambdaInfo lambdaInfo = MethodInlinerUtilKt.getLambdaIfExistsAndMarkInstructions(
|
||||
this, MethodInlinerUtilKt.singleOrNullInsn(sourceValue), false, instructions, sources, toDelete
|
||||
);
|
||||
if (lambdaInfo != null) {
|
||||
lambdaMapping.put(offset, lambdaInfo);
|
||||
}
|
||||
|
||||
offset += i == 0 ? 1 : argTypes[i - 1].getSize();
|
||||
}
|
||||
|
||||
@@ -518,7 +504,6 @@ public class MethodInliner {
|
||||
}
|
||||
AbstractInsnNode prevNode = cur;
|
||||
cur = cur.getNext();
|
||||
index++;
|
||||
|
||||
//given frame is <tt>null</tt> if and only if the corresponding instruction cannot be reached (dead code).
|
||||
if (frame == null) {
|
||||
@@ -528,11 +513,15 @@ public class MethodInliner {
|
||||
//it may occurs that interval for default handler starts before catch start label, so this label seems as dead,
|
||||
//but as result all this labels will be merged into one (see KT-5863)
|
||||
} else {
|
||||
node.instructions.remove(prevNode);
|
||||
toDelete.add(prevNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractInsnNode insnNode : toDelete) {
|
||||
instructions.remove(insnNode);
|
||||
}
|
||||
|
||||
//clean dead try/catch blocks
|
||||
List<TryCatchBlockNode> blocks = node.tryCatchBlocks;
|
||||
for (Iterator<TryCatchBlockNode> iterator = blocks.iterator(); iterator.hasNext(); ) {
|
||||
@@ -575,7 +564,7 @@ public class MethodInliner {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
LambdaInfo getLambdaIfExists(@Nullable AbstractInsnNode insnNode) {
|
||||
if (insnNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.codegen.optimization.common.InsnSequence
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
|
||||
|
||||
fun MethodInliner.getLambdaIfExistsAndMarkInstructions(
|
||||
insnNode: AbstractInsnNode?,
|
||||
processSwap: Boolean,
|
||||
insnList: InsnList,
|
||||
frames: Array<Frame<SourceValue>?>,
|
||||
toDelete: MutableSet<AbstractInsnNode>
|
||||
): LambdaInfo? {
|
||||
if (insnNode == null) return null
|
||||
|
||||
getLambdaIfExists(insnNode)?.let {
|
||||
//delete lambda aload instruction
|
||||
toDelete.add(insnNode)
|
||||
return it
|
||||
}
|
||||
|
||||
if (insnNode is VarInsnNode && insnNode.opcode == Opcodes.ALOAD) {
|
||||
val varIndex = insnNode.`var`
|
||||
val localFrame = frames[insnList.indexOf(insnNode)] ?: return null
|
||||
val storeIns = localFrame.getLocal(varIndex).singleOrNullInsn()
|
||||
if (storeIns is VarInsnNode && storeIns.getOpcode() == Opcodes.ASTORE) {
|
||||
val frame = frames[insnList.indexOf(storeIns)] ?: return null
|
||||
val topOfStack = frame.top()!!.singleOrNullInsn()
|
||||
getLambdaIfExistsAndMarkInstructions(topOfStack, processSwap, insnList, frames, toDelete)?.let {
|
||||
//remove intermediate lambda astore, aload instruction: see 'complexStack/simple.1.kt' test
|
||||
toDelete.add(storeIns)
|
||||
toDelete.add(insnNode)
|
||||
return it
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (processSwap && insnNode.opcode == Opcodes.SWAP) {
|
||||
val swapFrame = frames[insnList.indexOf(insnNode)] ?: return null
|
||||
val dispatchReceiver = swapFrame.top()!!.singleOrNullInsn()
|
||||
getLambdaIfExistsAndMarkInstructions(dispatchReceiver, false, insnList, frames, toDelete).let {
|
||||
//remove swap instruction (dispatch receiver would be deleted on recursion call): see 'complexStack/simpleExtension.1.kt' test
|
||||
toDelete.add(insnNode)
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun SourceValue.singleOrNullInsn() = insns.singleOrNull()
|
||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageFragment;
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaPackageScope;
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.TypeEnhancementKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass;
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement;
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement;
|
||||
@@ -159,7 +160,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 +182,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;
|
||||
@@ -504,7 +511,8 @@ public class JetTypeMapper {
|
||||
PrimitiveType primitiveType = KotlinBuiltIns.getPrimitiveTypeByFqName(fqName);
|
||||
if (primitiveType != null) {
|
||||
Type asmType = Type.getType(JvmPrimitiveType.get(primitiveType).getDesc());
|
||||
return TypeUtils.isNullableType(type) ? boxType(asmType) : asmType;
|
||||
boolean isNullableInJava = TypeUtils.isNullableType(type) || TypeEnhancementKt.hasEnhancedNullability(type);
|
||||
return isNullableInJava ? boxType(asmType) : asmType;
|
||||
}
|
||||
|
||||
PrimitiveType arrayElementType = KotlinBuiltIns.getPrimitiveTypeByArrayClassFqName(fqName);
|
||||
|
||||
@@ -77,7 +77,7 @@ fun getEffectiveVariance(parameterVariance: Variance, projectionKind: Variance):
|
||||
val CallableDescriptor?.isMethodWithDeclarationSiteWildcards: Boolean
|
||||
get() {
|
||||
if (this !is CallableMemberDescriptor) return false
|
||||
return firstOverridden {
|
||||
return original.firstOverridden(useOriginal = true) {
|
||||
METHODS_WITH_DECLARATION_SITE_WILDCARDS.contains(it.propertyIfAccessor.fqNameOrNull())
|
||||
} != null
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
@@ -130,16 +130,23 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
MessageCollector collector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose);
|
||||
|
||||
try {
|
||||
AnsiConsole.systemInstall();
|
||||
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
||||
AnsiConsole.systemInstall();
|
||||
}
|
||||
|
||||
errStream.print(messageRenderer.renderPreamble());
|
||||
return exec(collector, services, arguments);
|
||||
}
|
||||
finally {
|
||||
errStream.print(messageRenderer.renderConclusion());
|
||||
AnsiConsole.systemUninstall();
|
||||
|
||||
if (PlainTextMessageRenderer.COLOR_ENABLED) {
|
||||
AnsiConsole.systemUninstall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess") // Used in maven (see KotlinCompileMojoBase.java)
|
||||
@NotNull
|
||||
public ExitCode exec(@NotNull MessageCollector messageCollector, @NotNull Services services, @NotNull A arguments) {
|
||||
printVersionIfNeeded(messageCollector, arguments);
|
||||
@@ -213,7 +220,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
@NotNull Disposable rootDisposable
|
||||
);
|
||||
|
||||
protected void printVersionIfNeeded(@NotNull MessageCollector messageCollector, @NotNull A arguments) {
|
||||
private void printVersionIfNeeded(@NotNull MessageCollector messageCollector, @NotNull A arguments) {
|
||||
if (!arguments.version) return;
|
||||
|
||||
messageCollector.report(CompilerMessageSeverity.INFO,
|
||||
@@ -234,6 +241,7 @@ public abstract class CLICompiler<A extends CommonCompilerArguments> {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
@NotNull
|
||||
public static ExitCode doMainNoExit(@NotNull CLICompiler compiler, @NotNull String[] args) {
|
||||
try {
|
||||
|
||||
@@ -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.
|
||||
@@ -30,11 +30,14 @@ import java.util.Set;
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*;
|
||||
|
||||
public abstract class PlainTextMessageRenderer implements MessageRenderer {
|
||||
|
||||
private static final String KOTLIN_COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled";
|
||||
|
||||
// AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35).
|
||||
// TODO: investigate why ANSI escape codes on Windows only work in REPL for some reason
|
||||
private static final boolean COLOR_ENABLED =
|
||||
public static final boolean COLOR_ENABLED =
|
||||
!SystemInfo.isWindows &&
|
||||
!"false".equals(System.getProperty("kotlin.colors.enabled")) &&
|
||||
!"false".equals(System.getProperty(KOTLIN_COLORS_ENABLED_PROPERTY)) &&
|
||||
CLibrary.isatty(CLibrary.STDERR_FILENO) != 0;
|
||||
|
||||
private static final String LINE_SEPARATOR = LineSeparator.getSystemLineSeparator().getSeparatorString();
|
||||
|
||||
@@ -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.
|
||||
@@ -119,13 +119,13 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
|
||||
configuration.put(JVMConfigurationKeys.MODULE_NAME, arguments.moduleName ?: JvmAbi.DEFAULT_MODULE_NAME)
|
||||
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
|
||||
|
||||
if (arguments.module == null && arguments.freeArgs.isEmpty() && !arguments.version) {
|
||||
ReplFromTerminal.run(rootDisposable, configuration)
|
||||
return ExitCode.OK
|
||||
}
|
||||
|
||||
configuration.add(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY, StandardScriptDefinition)
|
||||
|
||||
if (arguments.skipMetadataVersionCheck) {
|
||||
JvmMetadataVersion.skipCheck = true
|
||||
}
|
||||
@@ -164,6 +164,8 @@ open class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val directory = File(arguments.module).absoluteFile.parentFile
|
||||
|
||||
val compilerConfiguration = KotlinToJVMBytecodeCompiler.createCompilerConfiguration(configuration, moduleScript.modules, directory)
|
||||
compilerConfiguration.put(JVMConfigurationKeys.MODULE_XML_FILE_PATH, arguments.module)
|
||||
|
||||
environment = createCoreEnvironment(rootDisposable, compilerConfiguration)
|
||||
|
||||
if (messageSeverityCollector.anyReported(CompilerMessageSeverity.ERROR)) return COMPILATION_ERROR
|
||||
|
||||
@@ -76,10 +76,6 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
||||
trace.setKotlinCodeAnalyzer(codeAnalyzer)
|
||||
}
|
||||
|
||||
override fun getContextForPackage(files: Collection<KtFile>): LightClassConstructionContext {
|
||||
return LightClassConstructionContext(bindingContext, module)
|
||||
}
|
||||
|
||||
override fun getContextForClassOrObject(classOrObject: KtClassOrObject): LightClassConstructionContext {
|
||||
//force resolve companion for light class generation
|
||||
bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
||||
|
||||
@@ -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.
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cli.jvm.compiler;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
@@ -37,7 +38,9 @@ import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleScriptData;
|
||||
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser;
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JVMConfigurationKeys;
|
||||
import org.jetbrains.kotlin.codegen.ClassFileFactory;
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration;
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -54,6 +57,7 @@ import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation.N
|
||||
import static org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR;
|
||||
|
||||
public class CompileEnvironmentUtil {
|
||||
private static Logger LOG = Logger.getInstance(CompileEnvironmentUtil.class);
|
||||
|
||||
@NotNull
|
||||
public static ModuleScriptData loadModuleDescriptions(String moduleDefinitionFile, MessageCollector messageCollector) {
|
||||
@@ -141,8 +145,9 @@ public class CompileEnvironmentUtil {
|
||||
public static List<KtFile> getKtFiles(
|
||||
@NotNull final Project project,
|
||||
@NotNull Collection<String> sourceRoots,
|
||||
@NotNull CompilerConfiguration configuration,
|
||||
@NotNull Function1<String, Unit> reportError
|
||||
) {
|
||||
) throws IOException {
|
||||
final VirtualFileSystem localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL);
|
||||
|
||||
final Set<VirtualFile> processedFiles = Sets.newHashSet();
|
||||
@@ -155,7 +160,17 @@ public class CompileEnvironmentUtil {
|
||||
|
||||
VirtualFile vFile = localFileSystem.findFileByPath(sourceRootPath);
|
||||
if (vFile == null) {
|
||||
reportError.invoke("Source file or directory not found: " + sourceRootPath);
|
||||
String message = "Source file or directory not found: " + sourceRootPath;
|
||||
|
||||
String moduleFilePath = configuration.get(JVMConfigurationKeys.MODULE_XML_FILE_PATH);
|
||||
if (moduleFilePath != null) {
|
||||
String moduleFileContent = FileUtil.loadFile(new File(moduleFilePath));
|
||||
LOG.warn(message +
|
||||
"\n\nmodule file path: " + moduleFilePath +
|
||||
"\ncontent:\n" + moduleFileContent);
|
||||
}
|
||||
|
||||
reportError.invoke(message);
|
||||
continue;
|
||||
}
|
||||
if (!vFile.isDirectory() && vFile.getFileType() != KotlinFileType.INSTANCE) {
|
||||
|
||||
@@ -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.
|
||||
@@ -131,7 +131,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
val index = JvmDependenciesIndex(javaRoots)
|
||||
(fileManager as KotlinCliJavaFileManagerImpl).initIndex(index)
|
||||
|
||||
sourceFiles.addAll(CompileEnvironmentUtil.getKtFiles(project, getSourceRootsCheckingForDuplicates(), {
|
||||
sourceFiles.addAll(CompileEnvironmentUtil.getKtFiles(project, getSourceRootsCheckingForDuplicates(), this.configuration, {
|
||||
message ->
|
||||
report(ERROR, message)
|
||||
}))
|
||||
|
||||
@@ -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.
|
||||
@@ -115,7 +115,7 @@ object KotlinToJVMBytecodeCompiler {
|
||||
for (module in chunk) {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
val ktFiles = CompileEnvironmentUtil.getKtFiles(
|
||||
environment.project, getAbsolutePaths(directory, module)) { s -> throw IllegalStateException("Should have been checked before: " + s) }
|
||||
environment.project, getAbsolutePaths(directory, module), configuration) { s -> throw IllegalStateException("Should have been checked before: " + s) }
|
||||
if (!checkKotlinPackageUsage(environment, ktFiles)) return false
|
||||
val moduleOutputDirectory = File(module.getOutputDirectory())
|
||||
val generationState = generate(environment, result, ktFiles, module, moduleOutputDirectory,
|
||||
|
||||
@@ -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.
|
||||
@@ -44,6 +44,8 @@ public class JVMConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<CompilerJarLocator> COMPILER_JAR_LOCATOR =
|
||||
CompilerConfigurationKey.create("Compiler jar locator");
|
||||
|
||||
public static final CompilerConfigurationKey<String> MODULE_XML_FILE_PATH = CompilerConfigurationKey.create("path to module.xml");
|
||||
|
||||
public static final CompilerConfigurationKey<List<Module>> MODULES =
|
||||
CompilerConfigurationKey.create("module data");
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.rubygrapefruit.platform.ProcessLauncher
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
@@ -61,9 +61,9 @@ object KotlinCompilerClient {
|
||||
|
||||
val flagFile = System.getProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY)
|
||||
?.let { it.trimQuotes() }
|
||||
?.satisfying { !it.isBlank() }
|
||||
?.check { !it.isBlank() }
|
||||
?.let { File(it) }
|
||||
?.satisfying { it.exists() }
|
||||
?.check { it.exists() }
|
||||
?: newFlagFile()
|
||||
return connectToCompileService(compilerId, flagFile, daemonJVMOptions, daemonOptions, reportingTargets, autostart)
|
||||
}
|
||||
@@ -262,7 +262,7 @@ object KotlinCompilerClient {
|
||||
.sortedWith(compareBy(DaemonJVMOptionsMemoryComparator().reversed(), { it.second.get() }))
|
||||
val optsCopy = daemonJVMOptions.copy()
|
||||
// if required options fit into fattest running daemon - return the daemon and required options with memory params set to actual ones in the daemon
|
||||
return aliveWithOpts.firstOrNull()?.satisfying { daemonJVMOptions memorywiseFitsInto it.second.get() }?.let {
|
||||
return aliveWithOpts.firstOrNull()?.check { daemonJVMOptions memorywiseFitsInto it.second.get() }?.let {
|
||||
Pair(it.first, optsCopy.updateMemoryUpperBounds(it.second.get()))
|
||||
}
|
||||
// else combine all options from running daemon to get fattest option for a new daemon to run
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.common.*
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
@@ -347,7 +347,7 @@ class CompileServiceImpl(
|
||||
if (fattestOpts memorywiseFitsInto daemonJVMOptions && !(daemonJVMOptions memorywiseFitsInto fattestOpts)) {
|
||||
// all others are smaller that me, take overs' clients and shut them down
|
||||
aliveWithOpts.forEach {
|
||||
it.first.getClients().satisfying { it.isGood }?.let {
|
||||
it.first.getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { registerClient(it) }
|
||||
}
|
||||
it.first.scheduleShutdown(true)
|
||||
@@ -357,7 +357,7 @@ class CompileServiceImpl(
|
||||
// there is at least one bigger, handover my clients to it and shutdown
|
||||
scheduleShutdown(true)
|
||||
aliveWithOpts.first().first.let { fattest ->
|
||||
getClients().satisfying { it.isGood }?.let {
|
||||
getClients().check { it.isGood }?.let {
|
||||
it.get().forEach { fattest.registerClient(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.jvm.bindingContextSlices.RUNTIME_ASSERTION_INFO
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
|
||||
@@ -74,9 +75,6 @@ class RuntimeAssertionInfo(val needNotNullAssertion: Boolean, val message: Strin
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
private fun KotlinType.hasEnhancedNullability()
|
||||
= annotations.findAnnotation(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION) != null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package org.jetbrains.kotlin.load.java.sam;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor;
|
||||
|
||||
@@ -31,6 +34,30 @@ import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor;
|
||||
setHasSynthesizedParameterNames(declaration.hasSynthesizedParameterNames());
|
||||
}
|
||||
|
||||
private SamAdapterConstructorDescriptor(
|
||||
@NotNull ClassDescriptor containingDeclaration,
|
||||
@Nullable JavaConstructorDescriptor original,
|
||||
@NotNull Annotations annotations,
|
||||
boolean isPrimary,
|
||||
@NotNull Kind kind,
|
||||
@NotNull SourceElement source,
|
||||
@NotNull JavaConstructorDescriptor declaration
|
||||
) {
|
||||
super(containingDeclaration, original, annotations, isPrimary, kind, source);
|
||||
this.declaration = declaration;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JavaConstructorDescriptor createDescriptor(
|
||||
@NotNull ClassDescriptor newOwner,
|
||||
@Nullable JavaConstructorDescriptor original,
|
||||
@NotNull Kind kind,
|
||||
@NotNull SourceElement sourceElement
|
||||
) {
|
||||
return new SamAdapterConstructorDescriptor(newOwner, original, getAnnotations(), isPrimary, kind, sourceElement, declaration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaConstructorDescriptor getOriginForSam() {
|
||||
|
||||
@@ -117,7 +117,7 @@ public class SamAdapterOverridabilityCondition implements ExternalOverridability
|
||||
return new SamAdapterInfo(samAdapter, ownerType);
|
||||
}
|
||||
|
||||
for (CallableMemberDescriptor overridden : samAdapter.getOverriddenDescriptors()) {
|
||||
for (CallableMemberDescriptor overridden : samAdapter.getOriginal().getOverriddenDescriptors()) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) overridden.getContainingDeclaration();
|
||||
|
||||
for (KotlinType immediateSupertype : TypeUtils.getImmediateSupertypes(ownerType)) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
// If type 'samType' contains no projection, then it's non-projection parametrization is 'samType' itself
|
||||
// Else each projection type argument 'out/in A_i' (but star projections) is replaced with it's bound 'A_i'
|
||||
@@ -43,7 +43,7 @@ internal fun nonProjectionParametrization(samType: KotlinType): KotlinType? {
|
||||
projection.projectionKind == Variance.INVARIANT -> projection
|
||||
|
||||
projection.isStarProjection ->
|
||||
parameter.upperBounds.first().satisfying {
|
||||
parameter.upperBounds.first().check {
|
||||
t -> !t.contains { it.constructor.declarationDescriptor in parametersSet }
|
||||
}?.asTypeProjection() ?: return@nonProjectionParametrization null
|
||||
|
||||
|
||||
@@ -49,10 +49,6 @@ object PackagePartClassUtils {
|
||||
else
|
||||
"_$str"
|
||||
|
||||
@TestOnly
|
||||
@JvmStatic fun getDefaultFileClassFqName(packageFqName: FqName, file: VirtualFile): FqName =
|
||||
getPackagePartFqName(packageFqName, file.name)
|
||||
|
||||
@TestOnly
|
||||
@JvmStatic fun getDefaultPartFqName(facadeClassFqName: FqName, file: VirtualFile): FqName =
|
||||
getPackagePartFqName(facadeClassFqName.parent(), file.name)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
|
||||
@@ -40,12 +41,14 @@ object JvmOverloadFilter : OverloadFilter {
|
||||
}
|
||||
|
||||
for (overload in overloads) {
|
||||
if (overload is ConstructorDescriptor) continue
|
||||
if (overload !is DeserializedCallableMemberDescriptor) continue
|
||||
|
||||
val containingDeclaration = overload.containingDeclaration
|
||||
if (containingDeclaration !is PackageFragmentDescriptor) {
|
||||
throw AssertionError("Package member expected; got $overload with containing declaration $containingDeclaration")
|
||||
}
|
||||
|
||||
val implClassName = JvmFileClassUtil.getImplClassName(overload) ?:
|
||||
throw AssertionError("No implClassName: $overload")
|
||||
val implClassFQN = containingDeclaration.fqName.child(implClassName)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.load.java.typeEnhancement.enhanceSignature
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||
@@ -47,9 +46,7 @@ class SamAdapterFunctionsScope(storageManager: StorageManager) : SyntheticScope
|
||||
if (!function.hasJavaOriginInHierarchy()) return null //TODO: should we go into base at all?
|
||||
if (!SingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
|
||||
if (function.returnType == null) return null
|
||||
//TODO: it's a temporary hack while original returns a function with platform types
|
||||
val enhancedFunction = function.enhanceSignature()
|
||||
return MyFunctionDescriptor.create(enhancedFunction)
|
||||
return MyFunctionDescriptor.create(function)
|
||||
}
|
||||
|
||||
override fun getSyntheticExtensionFunctions(receiverTypes: Collection<KotlinType>, name: Name, location: LookupLocation): Collection<FunctionDescriptor> {
|
||||
|
||||
@@ -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 modulesWhoseInternalsAreVisible(): 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.modulesWhoseInternalsAreVisible().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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -53,7 +52,6 @@ import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
@@ -65,14 +63,12 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.cfg.VariableUseState.*;
|
||||
import static org.jetbrains.kotlin.cfg.TailRecursionKind.*;
|
||||
import static org.jetbrains.kotlin.cfg.VariableUseState.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.UNREACHABLE_CODE;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
|
||||
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
||||
|
||||
public class ControlFlowInformationProvider {
|
||||
|
||||
@@ -360,6 +356,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 +374,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)) {
|
||||
@@ -684,15 +685,32 @@ public class ControlFlowInformationProvider {
|
||||
? ((InstructionWithValue) instruction).getOutputValue()
|
||||
: null;
|
||||
Pseudocode pseudocode = instruction.getOwner();
|
||||
boolean isUsedAsExpression = !pseudocode.getUsages(value).isEmpty();
|
||||
List<Instruction> usages = pseudocode.getUsages(value);
|
||||
boolean isUsedAsExpression = !usages.isEmpty();
|
||||
boolean isUsedAsResultOfLambda = isUsedAsResultOfLambda(usages);
|
||||
for (KtElement element : pseudocode.getValueElements(value)) {
|
||||
trace.record(BindingContext.USED_AS_EXPRESSION, element, isUsedAsExpression);
|
||||
trace.record(BindingContext.USED_AS_RESULT_OF_LAMBDA, element, isUsedAsResultOfLambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isUsedAsResultOfLambda(List<Instruction> usages) {
|
||||
for (Instruction usage : usages) {
|
||||
if (usage instanceof ReturnValueInstruction) {
|
||||
KtElement returnElement = ((ReturnValueInstruction) usage).getElement();
|
||||
PsiElement parentElement = returnElement.getParent();
|
||||
if (!(returnElement instanceof KtReturnExpression ||
|
||||
parentElement instanceof KtDeclaration && !(parentElement instanceof KtFunctionLiteral))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void checkIfExpressions() {
|
||||
PseudocodeTraverserKt.traverse(
|
||||
pseudocode, TraversalOrder.FORWARD, new ControlFlowInformationProvider.FunctionVoid1<Instruction>() {
|
||||
@@ -713,7 +731,7 @@ public class ControlFlowInformationProvider {
|
||||
trace.report(INVALID_IF_AS_EXPRESSION.on(ifExpression));
|
||||
}
|
||||
else {
|
||||
checkImplicitCastOnConditionalExpression(ifExpression, ImmutableList.of(thenExpression, elseExpression));
|
||||
checkImplicitCastOnConditionalExpression(ifExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -722,10 +740,41 @@ public class ControlFlowInformationProvider {
|
||||
);
|
||||
}
|
||||
|
||||
private void checkImplicitCastOnConditionalExpression(
|
||||
@NotNull KtExpression expression,
|
||||
@NotNull Collection<KtExpression> branchExpressions
|
||||
private static List<KtExpression> collectResultingExpressionsOfConditionalExpression(KtExpression expression) {
|
||||
List<KtExpression> leafBranches = new ArrayList<KtExpression>();
|
||||
collectResultingExpressionsOfConditionalExpressionRec(expression, leafBranches);
|
||||
return leafBranches;
|
||||
}
|
||||
|
||||
private static void collectResultingExpressionsOfConditionalExpressionRec(
|
||||
@Nullable KtExpression expression,
|
||||
@NotNull List<KtExpression> resultingExpressions
|
||||
) {
|
||||
if (expression instanceof KtIfExpression) {
|
||||
KtIfExpression ifExpression = (KtIfExpression) expression;
|
||||
collectResultingExpressionsOfConditionalExpressionRec(ifExpression.getThen(), resultingExpressions);
|
||||
collectResultingExpressionsOfConditionalExpressionRec(ifExpression.getElse(), resultingExpressions);
|
||||
}
|
||||
else if (expression instanceof KtWhenExpression) {
|
||||
KtWhenExpression whenExpression = (KtWhenExpression) expression;
|
||||
for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
|
||||
collectResultingExpressionsOfConditionalExpressionRec(whenEntry.getExpression(), resultingExpressions);
|
||||
}
|
||||
}
|
||||
else if (expression != null){
|
||||
KtExpression resultingExpression = getResultingExpression(expression);
|
||||
if (resultingExpression instanceof KtIfExpression || resultingExpression instanceof KtWhenExpression) {
|
||||
collectResultingExpressionsOfConditionalExpressionRec(resultingExpression, resultingExpressions);
|
||||
}
|
||||
else {
|
||||
resultingExpressions.add(resultingExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkImplicitCastOnConditionalExpression(@NotNull KtExpression expression) {
|
||||
Collection<KtExpression> branchExpressions = collectResultingExpressionsOfConditionalExpression(expression);
|
||||
|
||||
KotlinType expectedExpressionType = trace.get(EXPECTED_EXPRESSION_TYPE, expression);
|
||||
if (expectedExpressionType != null && expectedExpressionType != DONT_CARE) return;
|
||||
|
||||
@@ -734,10 +783,13 @@ public class ControlFlowInformationProvider {
|
||||
return;
|
||||
}
|
||||
if (KotlinBuiltIns.isAnyOrNullableAny(expressionType)) {
|
||||
boolean isUsedAsResultOfLambda = BindingContextUtilsKt.isUsedAsResultOfLambda(expression, trace.getBindingContext());
|
||||
for (KtExpression branchExpression : branchExpressions) {
|
||||
if (branchExpression == null) continue;
|
||||
KotlinType branchType = trace.getType(branchExpression);
|
||||
if (branchType == null || KotlinBuiltIns.isAnyOrNullableAny(branchType)) {
|
||||
if (branchType == null
|
||||
|| KotlinBuiltIns.isAnyOrNullableAny(branchType)
|
||||
|| (isUsedAsResultOfLambda && KotlinBuiltIns.isUnitOrNullableUnit(branchType))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -793,11 +845,7 @@ public class ControlFlowInformationProvider {
|
||||
KtWhenExpression whenExpression = (KtWhenExpression) element;
|
||||
|
||||
if (BindingContextUtilsKt.isUsedAsExpression(whenExpression, trace.getBindingContext())) {
|
||||
List<KtExpression> branchExpressions = new ArrayList<KtExpression>(whenExpression.getEntries().size());
|
||||
for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
|
||||
branchExpressions.add(whenEntry.getExpression());
|
||||
}
|
||||
checkImplicitCastOnConditionalExpression(whenExpression, branchExpressions);
|
||||
checkImplicitCastOnConditionalExpression(whenExpression);
|
||||
}
|
||||
|
||||
if (whenExpression.getElseExpression() != null) continue;
|
||||
|
||||
@@ -947,10 +947,19 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
mark(expression)
|
||||
val selectorExpression = expression.selectorExpression
|
||||
val receiverExpression = expression.receiverExpression
|
||||
val safe = expression is KtSafeQualifiedExpression
|
||||
|
||||
// todo: replace with selectorExpresion != null after parser is fixed
|
||||
if (selectorExpression is KtCallExpression || selectorExpression is KtSimpleNameExpression) {
|
||||
generateInstructions(selectorExpression)
|
||||
if (!safe) {
|
||||
generateInstructions(selectorExpression)
|
||||
}
|
||||
else {
|
||||
val resultLabel = builder.createUnboundLabel("result of call")
|
||||
builder.jumpOnFalse(resultLabel, expression, null)
|
||||
generateInstructions(selectorExpression)
|
||||
builder.bindLabel(resultLabel)
|
||||
}
|
||||
copyValue(selectorExpression, expression)
|
||||
}
|
||||
else {
|
||||
@@ -1001,6 +1010,8 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
val delegate = property.delegateExpression
|
||||
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)
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
package org.jetbrains.kotlin.cfg.pseudocodeTraverser
|
||||
|
||||
import org.jetbrains.kotlin.cfg.ControlFlowInfo
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.*
|
||||
import java.util.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder.FORWARD
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.SubroutineSinkInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.SubroutineEnterInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.SubroutineSinkInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder.FORWARD
|
||||
import java.util.*
|
||||
|
||||
fun Pseudocode.traverse(
|
||||
traversalOrder: TraversalOrder,
|
||||
@@ -109,26 +109,7 @@ private fun <I : ControlFlowInfo<*>> Pseudocode.collectDataFromSubgraph(
|
||||
if (!isLocal && isStart)
|
||||
continue
|
||||
|
||||
fun getPreviousIncludingSubGraphInstructions(): Collection<Instruction> {
|
||||
val previous = instruction.getPreviousInstructions(traversalOrder)
|
||||
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
||||
return previous
|
||||
}
|
||||
val result = ArrayList(previous)
|
||||
result.addAll(previousSubGraphInstructions)
|
||||
return result
|
||||
}
|
||||
val previousInstructions = getPreviousIncludingSubGraphInstructions()
|
||||
|
||||
fun updateEdgeDataForInstruction(
|
||||
previousValue: Edges<I>?,
|
||||
newValue: Edges<I>?
|
||||
) {
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
}
|
||||
val previousInstructions = getPreviousIncludingSubGraphInstructions(instruction, traversalOrder, startInstruction, previousSubGraphInstructions)
|
||||
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
val subroutinePseudocode = instruction.body
|
||||
@@ -146,7 +127,7 @@ private fun <I : ControlFlowInfo<*>> Pseudocode.collectDataFromSubgraph(
|
||||
else
|
||||
Edges(updateEdge(lastInstruction, instruction, newValue.incoming),
|
||||
updateEdge(lastInstruction, instruction, newValue.outgoing))
|
||||
updateEdgeDataForInstruction(previousValue, updatedValue)
|
||||
updateEdgeDataForInstruction(instruction, previousValue, updatedValue, edgesMap, changed)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -162,7 +143,30 @@ private fun <I : ControlFlowInfo<*>> Pseudocode.collectDataFromSubgraph(
|
||||
}
|
||||
}
|
||||
val mergedData = mergeEdges(instruction, incomingEdgesData)
|
||||
updateEdgeDataForInstruction(previousDataValue, mergedData)
|
||||
updateEdgeDataForInstruction(instruction, previousDataValue, mergedData, edgesMap, changed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPreviousIncludingSubGraphInstructions(
|
||||
instruction: Instruction,
|
||||
traversalOrder: TraversalOrder,
|
||||
startInstruction: Instruction,
|
||||
previousSubGraphInstructions: Collection<Instruction>
|
||||
): Collection<Instruction> {
|
||||
val previous = instruction.getPreviousInstructions(traversalOrder)
|
||||
if (instruction != startInstruction || previousSubGraphInstructions.isEmpty()) {
|
||||
return previous
|
||||
}
|
||||
val result = ArrayList(previous)
|
||||
result.addAll(previousSubGraphInstructions)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun <I : ControlFlowInfo<*>> updateEdgeDataForInstruction(
|
||||
instruction: Instruction, previousValue: Edges<I>?, newValue: Edges<I>?, edgesMap: MutableMap<Instruction, Edges<I>>, changed: BooleanArray) {
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -297,7 +296,7 @@ public interface Errors {
|
||||
|
||||
// Members
|
||||
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, String> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, DeclarationDescriptor> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
DiagnosticFactory0<KtNamedDeclaration> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory0.create(WARNING, modifierSetPosition(
|
||||
@@ -547,6 +546,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<KtDestructuringDeclaration> INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION = DiagnosticFactory0.create(ERROR, DEFAULT);
|
||||
DiagnosticFactory2<KtExpression, Name, KotlinType> COMPONENT_FUNCTION_MISSING = DiagnosticFactory2.create(ERROR, DEFAULT);
|
||||
DiagnosticFactory1<KtExpression, Name> COMPONENT_FUNCTION_ON_NULLABLE = DiagnosticFactory1.create(ERROR, DEFAULT);
|
||||
DiagnosticFactory2<KtExpression, Name, Collection<? extends ResolvedCall<?>>> COMPONENT_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR, DEFAULT);
|
||||
DiagnosticFactory3<KtExpression, Name, KotlinType, KotlinType> COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR, DEFAULT);
|
||||
|
||||
@@ -589,6 +589,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtExpression, KotlinType> NEXT_NONE_APPLICABLE = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtExpression> ITERATOR_MISSING = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtExpression> ITERATOR_ON_NULLABLE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, Collection<? extends ResolvedCall<?>>> ITERATOR_AMBIGUITY = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory2<KtExpression, String, KotlinType> DELEGATE_SPECIAL_FUNCTION_MISSING = DiagnosticFactory2.create(ERROR);
|
||||
@@ -771,7 +772,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);
|
||||
DiagnosticFactory1<KtElement, KtElement> NON_LOCAL_RETURN_NOT_ALLOWED = DiagnosticFactory1.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);
|
||||
@@ -787,7 +789,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);
|
||||
|
||||
@@ -61,7 +61,9 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
|
||||
is CallPosition.Unknown -> return false
|
||||
}
|
||||
|
||||
val receiverType = resolvedCall.dispatchReceiver?.type ?: return false
|
||||
val receiverType = resolvedCall.smartCastDispatchReceiverType
|
||||
?: (resolvedCall.dispatchReceiver ?: return false).type
|
||||
|
||||
val callableDescriptor = resolvedCall.resultingDescriptor.original
|
||||
|
||||
val substitutedDescriptor =
|
||||
|
||||
@@ -214,6 +214,7 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, "Initializer required for destructuring declaration");
|
||||
MAP.put(COMPONENT_FUNCTION_MISSING, "Destructuring declaration initializer of type {1} must have a ''{0}()'' function", TO_STRING, RENDER_TYPE);
|
||||
MAP.put(COMPONENT_FUNCTION_ON_NULLABLE, "Not nullable value required to call ''{0}()'' function of destructuring declaration initializer", TO_STRING);
|
||||
MAP.put(COMPONENT_FUNCTION_AMBIGUITY, "Function ''{0}()'' is ambiguous for this expression: {1}", TO_STRING, AMBIGUOUS_CALLS);
|
||||
MAP.put(COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, "''{0}()'' function returns ''{1}'', but ''{2}'' is expected",
|
||||
TO_STRING, RENDER_TYPE, RENDER_TYPE);
|
||||
@@ -368,6 +369,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(NEXT_NONE_APPLICABLE, "None of the next() functions is applicable for iterator() of type ''{0}''", RENDER_TYPE);
|
||||
|
||||
MAP.put(ITERATOR_MISSING, "For-loop range must have an iterator() method");
|
||||
MAP.put(ITERATOR_ON_NULLABLE, "Not nullable value required to call an iterator() method on for-loop range");
|
||||
MAP.put(ITERATOR_AMBIGUITY, "Method ''iterator()'' is ambiguous for this expression: {0}", AMBIGUOUS_CALLS);
|
||||
|
||||
MAP.put(DELEGATE_SPECIAL_FUNCTION_MISSING, "Missing ''{0}'' method on delegate of type ''{1}''", STRING, RENDER_TYPE);
|
||||
@@ -609,7 +611,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, "{0} must override {1} because it inherits multiple interface methods of it",
|
||||
RENDER_CLASS_OR_OBJECT, FQ_NAMES_IN_TYPES);
|
||||
|
||||
MAP.put(CONFLICTING_OVERLOADS, "''{0}'' is already defined in {1}", COMPACT_WITH_MODIFIERS, STRING);
|
||||
MAP.put(CONFLICTING_OVERLOADS, "''{0}'' conflicts with another declaration in {1}", COMPACT_WITH_MODIFIERS,
|
||||
DECLARATION_NAME_WITH_KIND);
|
||||
|
||||
MAP.put(FUNCTION_EXPECTED, "Expression ''{0}''{1} cannot be invoked as a function. " +
|
||||
"The function '" + OperatorNameConventions.INVOKE.asString() + "()' is not found",
|
||||
@@ -730,7 +733,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);
|
||||
|
||||
@@ -76,6 +76,19 @@ object Renderers {
|
||||
|
||||
@JvmField val NAME: Renderer<Named> = Renderer { it.name.asString() }
|
||||
|
||||
@JvmField val DECLARATION_NAME_WITH_KIND: Renderer<DeclarationDescriptor> = Renderer {
|
||||
val declarationKindWithSpace = when (it) {
|
||||
is PackageFragmentDescriptor -> "package "
|
||||
is ClassDescriptor -> "${it.renderKind()} "
|
||||
is ConstructorDescriptor -> "constructor "
|
||||
is PropertyGetterDescriptor -> "property getter "
|
||||
is PropertySetterDescriptor -> "property setter "
|
||||
is FunctionDescriptor -> "function "
|
||||
else -> throw AssertionError("Unexpected declaration kind: $it")
|
||||
}
|
||||
"$declarationKindWithSpace'${it.name.asString()}'"
|
||||
}
|
||||
|
||||
@JvmField val NAME_OF_PARENT_OR_FILE: Renderer<DeclarationDescriptor> = Renderer {
|
||||
if (DescriptorUtils.isTopLevelDeclaration(it) && it is DeclarationDescriptorWithVisibility && it.visibility == Visibilities.PRIVATE) {
|
||||
"file"
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.testFramework.LightVirtualFile
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
abstract class KtCodeFragment(
|
||||
@@ -146,7 +146,7 @@ abstract class KtCodeFragment(
|
||||
|
||||
private fun initImports(imports: String?) {
|
||||
if (imports != null && !imports.isEmpty()) {
|
||||
this.imports.addAll(imports.split(IMPORT_SEPARATOR).map { it.satisfying { it.startsWith("import ") } ?: "import $it" })
|
||||
this.imports.addAll(imports.split(IMPORT_SEPARATOR).map { it.check { it.startsWith("import ") } ?: "import $it" })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,23 @@ package org.jetbrains.kotlin.psi.codeFragmentUtil
|
||||
|
||||
import com.intellij.openapi.util.Key
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
val SUPPRESS_DIAGNOSTICS_IN_DEBUG_MODE: Key<Boolean> = Key.create<Boolean>("SUPPRESS_DIAGNOSTICS_IN_DEBUG_MODE")
|
||||
|
||||
fun KtElement.suppressDiagnosticsInDebugMode(): Boolean {
|
||||
return if (this is KtFile) {
|
||||
this.suppressDiagnosticsInDebugMode
|
||||
}
|
||||
else {
|
||||
val file = this.containingFile
|
||||
file is KtFile && file.suppressDiagnosticsInDebugMode
|
||||
}
|
||||
}
|
||||
|
||||
var KtFile.suppressDiagnosticsInDebugMode: Boolean
|
||||
get() = when (this) {
|
||||
is KtCodeFragment -> true
|
||||
|
||||
@@ -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}"; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +149,7 @@ public interface BindingContext {
|
||||
*/
|
||||
WritableSlice<KtExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice();
|
||||
WritableSlice<KtElement, Boolean> USED_AS_EXPRESSION = Slices.createSimpleSetSlice();
|
||||
WritableSlice<KtElement, Boolean> USED_AS_RESULT_OF_LAMBDA = Slices.createSimpleSetSlice();
|
||||
WritableSlice<KtElement, Boolean> UNREACHABLE_CODE = Slices.createSimpleSetSlice();
|
||||
|
||||
WritableSlice<VariableDescriptor, CaptureKind> CAPTURED_IN_CLOSURE = new BasicWritableSlice<VariableDescriptor, CaptureKind>(DO_NOTHING);
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.Severity;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
@@ -39,8 +38,6 @@ import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
||||
import org.jetbrains.kotlin.util.slicedMap.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.AMBIGUOUS_LABEL;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
@@ -223,7 +220,7 @@ public class BindingContextUtils {
|
||||
map.forEach(new Function3<WritableSlice, Object, Object, Void>() {
|
||||
@Override
|
||||
public Void invoke(WritableSlice slice, Object key, Object value) {
|
||||
if (filter == null || filter.accept(slice, null, key)) {
|
||||
if (filter == null || filter.accept(slice, key)) {
|
||||
trace.record(slice, key, value);
|
||||
}
|
||||
|
||||
@@ -234,7 +231,7 @@ public class BindingContextUtils {
|
||||
if (!commitDiagnostics) return;
|
||||
|
||||
for (Diagnostic diagnostic : diagnostics.getOwnDiagnostics()) {
|
||||
if (filter == null || filter.accept(null, diagnostic, diagnostic.getPsiElement())) {
|
||||
if (filter == null || filter.accept(null, diagnostic.getPsiElement())) {
|
||||
trace.report(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ fun KtReturnExpression.getTargetFunction(context: BindingContext): KtCallableDec
|
||||
}
|
||||
|
||||
fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean = context[BindingContext.USED_AS_EXPRESSION, this]!!
|
||||
fun KtExpression.isUsedAsResultOfLambda(context: BindingContext): Boolean = context[BindingContext.USED_AS_RESULT_OF_LAMBDA, this]!!
|
||||
fun KtExpression.isUsedAsStatement(context: BindingContext): Boolean = !isUsedAsExpression(context)
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
@@ -334,7 +333,7 @@ public class DelegatedPropertyResolver {
|
||||
dataFlowInfo, traceToResolveDelegatedProperty);
|
||||
traceToResolveDelegatedProperty.commit(new TraceEntryFilter() {
|
||||
@Override
|
||||
public boolean accept(@Nullable WritableSlice<?, ?> slice, @Nullable Diagnostic diagnostic, Object key) {
|
||||
public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
|
||||
return slice != CONSTRAINT_SYSTEM_COMPLETER;
|
||||
}
|
||||
}, true);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -28,11 +28,10 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
|
||||
|
||||
public class OverloadResolver {
|
||||
@NotNull private final BindingTrace trace;
|
||||
@NotNull private final OverloadFilter overloadFilter;
|
||||
@@ -50,72 +49,51 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
private void checkOverloads(@NotNull BodiesResolveContext c) {
|
||||
MultiMap<ClassDescriptor, ConstructorDescriptor> inClasses = MultiMap.create();
|
||||
MultiMap<FqNameUnsafe, ConstructorDescriptor> inPackages = MultiMap.create();
|
||||
fillGroupedConstructors(c, inClasses, inPackages);
|
||||
MultiMap<ClassDescriptor, ConstructorDescriptor> inClasses = findConstructorsInNestedClasses(c);
|
||||
|
||||
for (Map.Entry<KtClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
|
||||
checkOverloadsInAClass(entry.getValue(), entry.getKey(), inClasses.get(entry.getValue()));
|
||||
checkOverloadsInAClass(entry.getValue(), inClasses.get(entry.getValue()));
|
||||
}
|
||||
checkOverloadsInPackages(c, inPackages);
|
||||
checkOverloadsInPackages(c);
|
||||
}
|
||||
|
||||
private static void fillGroupedConstructors(
|
||||
@NotNull BodiesResolveContext c,
|
||||
@NotNull MultiMap<ClassDescriptor, ConstructorDescriptor> inClasses,
|
||||
@NotNull MultiMap<FqNameUnsafe, ConstructorDescriptor> inPackages
|
||||
) {
|
||||
private static MultiMap<ClassDescriptor, ConstructorDescriptor> findConstructorsInNestedClasses(@NotNull BodiesResolveContext c) {
|
||||
MultiMap<ClassDescriptor, ConstructorDescriptor> inClasses = MultiMap.create();
|
||||
|
||||
for (ClassDescriptorWithResolutionScopes klass : c.getDeclaredClasses().values()) {
|
||||
if (klass.getKind().isSingleton() || klass.getName().isSpecial()) {
|
||||
// Constructors of singletons or anonymous object aren't callable from the code, so they shouldn't participate in overload name checking
|
||||
continue;
|
||||
}
|
||||
DeclarationDescriptor containingDeclaration = klass.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
// TODO: check overload conflicts of functions with constructors in scripts
|
||||
}
|
||||
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
inClasses.putValues(classDescriptor, klass.getConstructors());
|
||||
}
|
||||
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
inPackages.putValues(getFqName(klass), klass.getConstructors());
|
||||
}
|
||||
else if (containingDeclaration instanceof ScriptDescriptor) {
|
||||
// TODO: check overload conflicts of functions with constructors in scripts
|
||||
}
|
||||
else if (!(containingDeclaration instanceof FunctionDescriptor || containingDeclaration instanceof PropertyDescriptor)) {
|
||||
else if (!(containingDeclaration instanceof FunctionDescriptor ||
|
||||
containingDeclaration instanceof PropertyDescriptor ||
|
||||
containingDeclaration instanceof PackageFragmentDescriptor)) {
|
||||
throw new IllegalStateException("Illegal class container: " + containingDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
return inClasses;
|
||||
}
|
||||
|
||||
private void checkOverloadsInPackages(
|
||||
@NotNull BodiesResolveContext c,
|
||||
@NotNull MultiMap<FqNameUnsafe, ConstructorDescriptor> inPackages
|
||||
) {
|
||||
private void checkOverloadsInPackages(@NotNull BodiesResolveContext c) {
|
||||
MultiMap<FqNameUnsafe, CallableMemberDescriptor> membersByName =
|
||||
OverloadUtil.groupModulePackageMembersByFqName(c, inPackages, overloadFilter);
|
||||
OverloadUtil.groupModulePackageMembersByFqName(c, overloadFilter);
|
||||
|
||||
for (Map.Entry<FqNameUnsafe, Collection<CallableMemberDescriptor>> e : membersByName.entrySet()) {
|
||||
FqNameUnsafe fqName = e.getKey().parent();
|
||||
checkOverloadsInPackage(e.getValue(), fqName);
|
||||
checkOverloadsInPackage(e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static String nameForErrorMessage(ClassDescriptor classDescriptor, KtClassOrObject jetClass) {
|
||||
String name = jetClass.getName();
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
if (jetClass instanceof KtObjectDeclaration) {
|
||||
// must be companion object
|
||||
name = classDescriptor.getContainingDeclaration().getName().asString();
|
||||
return "companion object " + name;
|
||||
}
|
||||
// safe
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
private void checkOverloadsInAClass(
|
||||
ClassDescriptorWithResolutionScopes classDescriptor, KtClassOrObject klass,
|
||||
ClassDescriptorWithResolutionScopes classDescriptor,
|
||||
Collection<ConstructorDescriptor> nestedClassConstructors
|
||||
) {
|
||||
MultiMap<Name, CallableMemberDescriptor> functionsByName = MultiMap.create();
|
||||
@@ -129,31 +107,24 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
for (Map.Entry<Name, Collection<CallableMemberDescriptor>> e : functionsByName.entrySet()) {
|
||||
checkOverloadsInClass(e.getValue(), classDescriptor, klass);
|
||||
checkOverloadsInClass(e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOverloadsInPackage(
|
||||
@NotNull Collection<CallableMemberDescriptor> members,
|
||||
@NotNull FqNameUnsafe packageFQN
|
||||
) {
|
||||
private void checkOverloadsInPackage(@NotNull Collection<CallableMemberDescriptor> members) {
|
||||
if (members.size() == 1) return;
|
||||
|
||||
for (Collection<? extends CallableMemberDescriptor> redeclarationGroup : OverloadUtil.getPossibleRedeclarationGroups(members)) {
|
||||
Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations = findRedeclarations(redeclarationGroup);
|
||||
// TODO: don't render FQ name here, extract this logic to somewhere
|
||||
reportRedeclarations(packageFQN.isRoot() ? "root package" : packageFQN.asString(), redeclarations);
|
||||
reportRedeclarations(redeclarations);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOverloadsInClass(
|
||||
@NotNull Collection<CallableMemberDescriptor> members,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull KtClassOrObject ktClass
|
||||
) {
|
||||
private void checkOverloadsInClass(@NotNull Collection<CallableMemberDescriptor> members) {
|
||||
if (members.size() == 1) return;
|
||||
|
||||
reportRedeclarations(nameForErrorMessage(classDescriptor, ktClass), findRedeclarations(members));
|
||||
reportRedeclarations(findRedeclarations(members));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -171,9 +142,7 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
KtDeclaration ktDeclaration = (KtDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(member);
|
||||
if (ktDeclaration != null) {
|
||||
redeclarations.add(Pair.create(ktDeclaration, member));
|
||||
}
|
||||
redeclarations.add(Pair.create(ktDeclaration, member));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,22 +172,38 @@ public class OverloadResolver {
|
||||
return file == null || file2 == null || file != file2;
|
||||
}
|
||||
|
||||
private void reportRedeclarations(@NotNull String functionContainer,
|
||||
@NotNull Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations) {
|
||||
private void reportRedeclarations(@NotNull Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations) {
|
||||
if (redeclarations.isEmpty()) return;
|
||||
|
||||
Iterator<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarationsIterator = redeclarations.iterator();
|
||||
CallableMemberDescriptor firstRedeclarationDescriptor = redeclarationsIterator.next().getSecond();
|
||||
CallableMemberDescriptor otherRedeclarationDescriptor = redeclarationsIterator.hasNext()
|
||||
? redeclarationsIterator.next().getSecond()
|
||||
: null;
|
||||
|
||||
for (Pair<KtDeclaration, CallableMemberDescriptor> redeclaration : redeclarations) {
|
||||
KtDeclaration ktDeclaration = redeclaration.getFirst();
|
||||
if (ktDeclaration == null) continue;
|
||||
|
||||
CallableMemberDescriptor memberDescriptor = redeclaration.getSecond();
|
||||
|
||||
KtDeclaration ktDeclaration = redeclaration.getFirst();
|
||||
CallableMemberDescriptor redeclarationDescriptor;
|
||||
if (otherRedeclarationDescriptor == null) {
|
||||
redeclarationDescriptor = firstRedeclarationDescriptor;
|
||||
}
|
||||
else if (firstRedeclarationDescriptor == memberDescriptor) {
|
||||
redeclarationDescriptor = otherRedeclarationDescriptor;
|
||||
}
|
||||
else {
|
||||
redeclarationDescriptor = firstRedeclarationDescriptor;
|
||||
}
|
||||
|
||||
if (memberDescriptor instanceof PropertyDescriptor) {
|
||||
trace.report(Errors.REDECLARATION.on(ktDeclaration, memberDescriptor.getName().asString()));
|
||||
}
|
||||
else {
|
||||
String containingClassName = ktDeclaration instanceof KtSecondaryConstructor ?
|
||||
((KtSecondaryConstructor) ktDeclaration).getContainingClassOrObject().getName() : null;
|
||||
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(
|
||||
ktDeclaration, memberDescriptor,
|
||||
containingClassName != null ? containingClassName : functionContainer));
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor,
|
||||
redeclarationDescriptor.getContainingDeclaration()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,14 +82,18 @@ object OverloadUtil {
|
||||
|
||||
@JvmStatic fun groupModulePackageMembersByFqName(
|
||||
c: BodiesResolveContext,
|
||||
constructorsInPackages: MultiMap<FqNameUnsafe, ConstructorDescriptor>,
|
||||
overloadFilter: OverloadFilter
|
||||
): MultiMap<FqNameUnsafe, CallableMemberDescriptor> {
|
||||
val packageMembersByName = MultiMap<FqNameUnsafe, CallableMemberDescriptor>()
|
||||
|
||||
collectModulePackageMembersWithSameName(packageMembersByName, c.functions.values, overloadFilter) {
|
||||
collectModulePackageMembersWithSameName(packageMembersByName, c.functions.values + c.declaredClasses.values, overloadFilter) {
|
||||
scope, name ->
|
||||
scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
|
||||
if (classifier is ClassDescriptor && !classifier.kind.isSingleton)
|
||||
functions + classifier.constructors
|
||||
else
|
||||
functions
|
||||
}
|
||||
|
||||
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
|
||||
@@ -97,15 +101,12 @@ object OverloadUtil {
|
||||
scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS).filterIsInstance<CallableMemberDescriptor>()
|
||||
}
|
||||
|
||||
// TODO handle constructor redeclarations in modules. See also: https://youtrack.jetbrains.com/issue/KT-3632
|
||||
packageMembersByName.putAllValues(constructorsInPackages)
|
||||
|
||||
return packageMembersByName
|
||||
}
|
||||
|
||||
private inline fun collectModulePackageMembersWithSameName(
|
||||
packageMembersByName: MultiMap<FqNameUnsafe, CallableMemberDescriptor>,
|
||||
interestingDescriptors: Collection<CallableMemberDescriptor>,
|
||||
interestingDescriptors: Collection<DeclarationDescriptor>,
|
||||
overloadFilter: OverloadFilter,
|
||||
getMembersByName: (MemberScope, Name) -> Collection<CallableMemberDescriptor>
|
||||
) {
|
||||
@@ -123,20 +124,25 @@ object OverloadUtil {
|
||||
}
|
||||
|
||||
private inline fun getModulePackageMembersWithSameName(
|
||||
packageMember: CallableMemberDescriptor,
|
||||
descriptor: DeclarationDescriptor,
|
||||
overloadFilter: OverloadFilter,
|
||||
getMembersByName: (MemberScope, Name) -> Collection<CallableMemberDescriptor>
|
||||
): Collection<CallableMemberDescriptor> {
|
||||
val containingPackage = packageMember.containingDeclaration
|
||||
val containingPackage = descriptor.containingDeclaration
|
||||
if (containingPackage !is PackageFragmentDescriptor) {
|
||||
throw AssertionError("$packageMember is not a top-level package member")
|
||||
throw AssertionError("$descriptor is not a top-level package member")
|
||||
}
|
||||
|
||||
val containingModule = DescriptorUtils.getContainingModuleOrNull(packageMember) ?: return listOf(packageMember)
|
||||
val containingModule = DescriptorUtils.getContainingModuleOrNull(descriptor) ?:
|
||||
return when (descriptor) {
|
||||
is CallableMemberDescriptor -> listOf(descriptor)
|
||||
is ClassDescriptor -> descriptor.constructors
|
||||
else -> throw AssertionError("Unexpected descriptor kind: $descriptor")
|
||||
}
|
||||
|
||||
val containingPackageScope = containingModule.getPackage(containingPackage.fqName).memberScope
|
||||
val possibleOverloads =
|
||||
getMembersByName(containingPackageScope, packageMember.name).filter {
|
||||
getMembersByName(containingPackageScope, descriptor.name).filter {
|
||||
// NB memberScope for PackageViewDescriptor includes module dependencies
|
||||
DescriptorUtils.getContainingModule(it) == containingModule
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator) {
|
||||
|
||||
@@ -90,7 +90,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
|
||||
val qualifier = resolveToPackageOrClass(
|
||||
qualifierPartList.subList(0, qualifierPartList.size - 1), module,
|
||||
trace, scope.ownerDescriptor, scope.satisfying { !userType.startWithPackage }, position = QualifierPosition.TYPE
|
||||
trace, scope.ownerDescriptor, scope.check { !userType.startWithPackage }, position = QualifierPosition.TYPE
|
||||
) ?: return TypeQualifierResolutionResult(qualifierPartList, null)
|
||||
|
||||
val lastPart = qualifierPartList.last()
|
||||
@@ -194,7 +194,7 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
}
|
||||
|
||||
val importedDescriptors = candidates.filter { isVisible(it, packageFragmentForVisibilityCheck, position = QualifierPosition.IMPORT) }.
|
||||
satisfying { it.isNotEmpty() } ?: candidates
|
||||
check { it.isNotEmpty() } ?: candidates
|
||||
|
||||
return SingleImportScope(aliasName, importedDescriptors)
|
||||
}
|
||||
@@ -410,14 +410,14 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
|
||||
val qualifierDescriptor = when {
|
||||
receiver is PackageQualifier -> {
|
||||
val childPackageFQN = receiver.packageView.fqName.child(name)
|
||||
receiver.packageView.module.getPackage(childPackageFQN).satisfying { !it.isEmpty() } ?:
|
||||
receiver.packageView.module.getPackage(childPackageFQN).check { !it.isEmpty() } ?:
|
||||
receiver.packageView.memberScope.getContributedClassifier(name, KotlinLookupLocation(expression))
|
||||
}
|
||||
receiver is ClassQualifier ->
|
||||
receiver.scope.getContributedClassifier(name, KotlinLookupLocation(expression))
|
||||
receiver == null ->
|
||||
context.scope.findClassifier(name, KotlinLookupLocation(expression)) ?:
|
||||
context.scope.ownerDescriptor.module.getPackage(FqName.ROOT.child(name)).satisfying { !it.isEmpty() }
|
||||
context.scope.ownerDescriptor.module.getPackage(FqName.ROOT.child(name)).check { !it.isEmpty() }
|
||||
receiver is ReceiverValue ->
|
||||
receiver.type.memberScope.memberScopeAsImportingScope().findClassifier(name, KotlinLookupLocation(expression))
|
||||
else -> null
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
package org.jetbrains.kotlin.resolve;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
||||
|
||||
public interface TraceEntryFilter {
|
||||
boolean accept(@Nullable WritableSlice<?, ?> slice, @Nullable Diagnostic diagnostic, Object key);
|
||||
boolean accept(@Nullable WritableSlice<?, ?> slice, Object key);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,9 @@ class CandidateResolver(
|
||||
return
|
||||
}
|
||||
|
||||
checkVisibility()
|
||||
if (!context.isDebuggerContext) {
|
||||
checkVisibility()
|
||||
}
|
||||
|
||||
when (checkArguments) {
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||
@@ -436,7 +438,7 @@ class CandidateResolver(
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> CallCandidateResolutionContext<D>.checkReceiver(
|
||||
candidateCall: ResolvedCall<D>,
|
||||
candidateCall: MutableResolvedCall<D>,
|
||||
receiverParameter: ReceiverParameterDescriptor?,
|
||||
receiverArgument: ReceiverValue?,
|
||||
isExplicitReceiver: Boolean,
|
||||
@@ -497,9 +499,12 @@ class CandidateResolver(
|
||||
if (smartCastResult == null) {
|
||||
reportUnsafeCall = true
|
||||
}
|
||||
else if (!smartCastResult.isCorrect) {
|
||||
// Error about unstable smart cast reported within checkAndRecordPossibleCast
|
||||
return OTHER_ERROR
|
||||
else {
|
||||
candidateCall.setSmartCastDispatchReceiverType(smartCastResult.resultType)
|
||||
if (!smartCastResult.isCorrect) {
|
||||
// Error about unstable smart cast reported within checkAndRecordPossibleCast
|
||||
return OTHER_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getExplicitReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.OTHER_ERROR
|
||||
@@ -154,28 +155,35 @@ class GenericCandidateResolver(private val argumentTypeResolver: ArgumentTypeRes
|
||||
val resolutionResults = getResolutionResultsCachedData(argumentExpression, context)?.resolutionResults
|
||||
if (resolutionResults == null || !resolutionResults.isSingleResult) return false
|
||||
|
||||
val resultingCall = resolutionResults.resultingCall
|
||||
if (resultingCall.isCompleted) return false
|
||||
val nestedCall = resolutionResults.resultingCall
|
||||
if (nestedCall.isCompleted) return false
|
||||
|
||||
val argumentConstraintSystem = resultingCall.constraintSystem ?: return false
|
||||
val nestedConstraintSystem = nestedCall.constraintSystem ?: return false
|
||||
|
||||
val candidateDescriptor = resultingCall.candidateDescriptor
|
||||
val candidateDescriptor = nestedCall.candidateDescriptor
|
||||
val returnType = candidateDescriptor.returnType ?: return false
|
||||
|
||||
val nestedTypeVariables = argumentConstraintSystem.getNestedTypeVariables(returnType)
|
||||
val nestedTypeVariables = nestedConstraintSystem.getNestedTypeVariables(returnType)
|
||||
|
||||
// we add an additional type variable only if no information is inferred for it.
|
||||
// otherwise we add currently inferred return type as before
|
||||
if (nestedTypeVariables.any { argumentConstraintSystem.getTypeBounds(it).bounds.isNotEmpty() }) return false
|
||||
if (nestedTypeVariables.any { nestedConstraintSystem.getTypeBounds(it).bounds.isNotEmpty() }) return false
|
||||
|
||||
val candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidateDescriptor)
|
||||
val conversion = candidateDescriptor.typeParameters.zip(candidateWithFreshVariables.typeParameters).toMap()
|
||||
|
||||
val freshVariables = returnType.getNestedTypeParameters().mapNotNull { conversion[it] }
|
||||
builder.registerTypeVariables(resultingCall.call.toHandle(), freshVariables, external = true)
|
||||
builder.registerTypeVariables(nestedCall.call.toHandle(), freshVariables, external = true)
|
||||
// Looks not too nice, but safe call result must be nullable if receiver is nullable
|
||||
val argumentExpressionType = candidateWithFreshVariables.returnType?.let {
|
||||
if (nestedCall.isSafeCall && nestedCall.getExplicitReceiverValue()?.type?.let {TypeUtils.isNullableType(it) } ?: true ) {
|
||||
TypeUtils.makeNullable(it)
|
||||
}
|
||||
else it
|
||||
}
|
||||
|
||||
builder.addSubtypeConstraint(
|
||||
candidateWithFreshVariables.returnType,
|
||||
argumentExpressionType,
|
||||
builder.compositeSubstitutor().substitute(effectiveExpectedType, Variance.INVARIANT),
|
||||
constraintPosition
|
||||
)
|
||||
|
||||
@@ -93,7 +93,7 @@ class InlineChecker implements CallChecker {
|
||||
}
|
||||
}
|
||||
|
||||
checkVisibility(targetDescriptor, expression, context);
|
||||
checkVisibilityAndAccess(targetDescriptor, expression, context);
|
||||
checkRecursion(context, targetDescriptor, expression);
|
||||
}
|
||||
|
||||
@@ -238,10 +238,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,12 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -63,7 +64,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
) {
|
||||
return new BasicCallResolutionContext(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
new ResolutionResultsCacheImpl(), null,
|
||||
callChecker, StatementFilter.NONE, isAnnotationContext, false,
|
||||
callChecker, StatementFilter.NONE, isAnnotationContext, false, false,
|
||||
CallPosition.Unknown.INSTANCE);
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
context.trace, context.scope, call, context.expectedType, context.dataFlowInfo, context.contextDependency, checkArguments,
|
||||
context.resolutionResultsCache, dataFlowInfoForArguments,
|
||||
context.callChecker,
|
||||
context.statementFilter, context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
context.statementFilter, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -100,14 +101,14 @@ public class BasicCallResolutionContext extends CallResolutionContext<BasicCallR
|
||||
) {
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BasicCallResolutionContext replaceCall(@NotNull Call newCall) {
|
||||
return new BasicCallResolutionContext(
|
||||
trace, scope, newCall, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
public void performContextDependentCallChecks(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
|
||||
@@ -58,11 +58,12 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
@Nullable Receiver explicitExtensionReceiverForInvoke,
|
||||
@NotNull CandidateResolveMode candidateResolveMode,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, isDebuggerContext,
|
||||
collectAllCandidates, callPosition);
|
||||
this.candidateCall = candidateCall;
|
||||
this.tracing = tracing;
|
||||
@@ -80,7 +81,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
context.dataFlowInfo, context.contextDependency, context.checkArguments,
|
||||
context.resolutionResultsCache, context.dataFlowInfoForArguments,
|
||||
context.callChecker, context.statementFilter, explicitExtensionReceiverForInvoke,
|
||||
candidateResolveMode, context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
candidateResolveMode, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -91,7 +92,7 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
candidateCall, tracing, context.trace, context.scope, context.call, context.expectedType,
|
||||
context.dataFlowInfo, context.contextDependency, context.checkArguments, context.resolutionResultsCache,
|
||||
context.dataFlowInfoForArguments, context.callChecker, context.statementFilter,
|
||||
null, CandidateResolveMode.FULLY, context.isAnnotationContext, context.collectAllCandidates,
|
||||
null, CandidateResolveMode.FULLY, context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition);
|
||||
}
|
||||
|
||||
@@ -110,6 +111,6 @@ public final class CallCandidateResolutionContext<D extends CallableDescriptor>
|
||||
return new CallCandidateResolutionContext<D>(
|
||||
candidateCall, tracing, trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments,
|
||||
resolutionResultsCache, dataFlowInfoForArguments, callChecker, statementFilter,
|
||||
explicitExtensionReceiverForInvoke, candidateResolveMode, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
explicitExtensionReceiverForInvoke, candidateResolveMode, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +50,12 @@ public abstract class CallResolutionContext<Context extends CallResolutionContex
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache, callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
this.call = call;
|
||||
this.checkArguments = checkArguments;
|
||||
if (dataFlowInfoForArguments != null) {
|
||||
|
||||
@@ -52,6 +52,8 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
|
||||
public final boolean isAnnotationContext;
|
||||
|
||||
public final boolean isDebuggerContext;
|
||||
|
||||
public final boolean collectAllCandidates;
|
||||
|
||||
@NotNull
|
||||
@@ -67,6 +69,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
@@ -79,6 +82,7 @@ public abstract class ResolutionContext<Context extends ResolutionContext<Contex
|
||||
this.callChecker = callChecker;
|
||||
this.statementFilter = statementFilter;
|
||||
this.isAnnotationContext = isAnnotationContext;
|
||||
this.isDebuggerContext = isDebuggerContext;
|
||||
this.collectAllCandidates = collectAllCandidates;
|
||||
this.callPosition = callPosition;
|
||||
}
|
||||
|
||||
@@ -87,12 +87,6 @@ public abstract class DelegatingResolvedCall<D extends CallableDescriptor> imple
|
||||
return resolvedCall.getValueArguments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<ValueParameterDescriptor, ResolvedValueArgument> getUnsubstitutedValueArguments() {
|
||||
return resolvedCall.getUnsubstitutedValueArguments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ArgumentMapping getArgumentMapping(@NotNull ValueArgument valueArgument) {
|
||||
@@ -121,4 +115,10 @@ public abstract class DelegatingResolvedCall<D extends CallableDescriptor> imple
|
||||
public boolean isSafeCall() {
|
||||
return resolvedCall.isSafeCall();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public KotlinType getSmartCastDispatchReceiverType() {
|
||||
return resolvedCall.getSmartCastDispatchReceiverType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.DelegatingBindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
|
||||
public interface MutableResolvedCall<D extends CallableDescriptor> extends ResolvedCall<D> {
|
||||
@@ -64,4 +65,6 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
|
||||
|
||||
//todo remove: use value to parameter map status
|
||||
boolean hasInferredReturnType();
|
||||
|
||||
void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType);
|
||||
}
|
||||
|
||||
@@ -64,10 +64,6 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
||||
@NotNull
|
||||
Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments();
|
||||
|
||||
/** Values (arguments) for value parameters, no type parameter substitution */
|
||||
@NotNull
|
||||
Map<ValueParameterDescriptor, ResolvedValueArgument> getUnsubstitutedValueArguments();
|
||||
|
||||
/** Values (arguments) for value parameters indexed by parameter index */
|
||||
@Nullable
|
||||
List<ResolvedValueArgument> getValueArgumentsByIndex();
|
||||
@@ -85,4 +81,7 @@ public interface ResolvedCall<D extends CallableDescriptor> {
|
||||
DataFlowInfoForArguments getDataFlowInfoForArguments();
|
||||
|
||||
boolean isSafeCall();
|
||||
|
||||
@Nullable
|
||||
KotlinType getSmartCastDispatchReceiverType();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.model;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||
@@ -40,9 +41,7 @@ import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE;
|
||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
|
||||
@@ -84,7 +83,6 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
|
||||
private final Map<TypeParameterDescriptor, KotlinType> typeArguments = Maps.newLinkedHashMap();
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newLinkedHashMap();
|
||||
private Map<ValueParameterDescriptor, ResolvedValueArgument> valueArgumentsBeforeSubstitution;
|
||||
private final MutableDataFlowInfoForArguments dataFlowInfoForArguments;
|
||||
private final Map<ValueArgument, ArgumentMatchImpl> argumentToParameterMap = Maps.newHashMap();
|
||||
|
||||
@@ -94,6 +92,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
private ConstraintSystem constraintSystem = null;
|
||||
private Boolean hasInferredReturnType = null;
|
||||
private boolean completed = false;
|
||||
private KotlinType smartCastDispatchReceiverType = null;
|
||||
|
||||
private ResolvedCallImpl(
|
||||
@NotNull ResolutionCandidate<D> candidate,
|
||||
@@ -195,25 +194,27 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
}
|
||||
}
|
||||
|
||||
Map<ValueParameterDescriptor, ValueParameterDescriptor> substitutedParametersMap = Maps.newHashMap();
|
||||
for (ValueParameterDescriptor valueParameterDescriptor : resultingDescriptor.getValueParameters()) {
|
||||
substitutedParametersMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
|
||||
}
|
||||
List<ValueParameterDescriptor> substitutedParameters = resultingDescriptor.getValueParameters();
|
||||
|
||||
Collection<Map.Entry<ValueParameterDescriptor, ResolvedValueArgument>> valueArgumentsBeforeSubstitution =
|
||||
new SmartList<Map.Entry<ValueParameterDescriptor, ResolvedValueArgument>>(valueArguments.entrySet());
|
||||
|
||||
valueArgumentsBeforeSubstitution = Maps.newLinkedHashMap(valueArguments);
|
||||
valueArguments.clear();
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : valueArgumentsBeforeSubstitution.entrySet()) {
|
||||
ValueParameterDescriptor substitutedVersion = substitutedParametersMap.get(entry.getKey().getOriginal());
|
||||
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : valueArgumentsBeforeSubstitution) {
|
||||
ValueParameterDescriptor substitutedVersion = substitutedParameters.get(entry.getKey().getIndex());
|
||||
assert substitutedVersion != null : entry.getKey();
|
||||
valueArguments.put(substitutedVersion, entry.getValue());
|
||||
}
|
||||
|
||||
Map<ValueArgument, ArgumentMatchImpl> originalArgumentToParameterMap = Maps.newLinkedHashMap(argumentToParameterMap);
|
||||
Collection<Map.Entry<ValueArgument, ArgumentMatchImpl>> unsubstitutedArgumentMappings =
|
||||
new SmartList<Map.Entry<ValueArgument, ArgumentMatchImpl>>(argumentToParameterMap.entrySet());
|
||||
|
||||
argumentToParameterMap.clear();
|
||||
for (Map.Entry<ValueArgument, ArgumentMatchImpl> entry : originalArgumentToParameterMap.entrySet()) {
|
||||
for (Map.Entry<ValueArgument, ArgumentMatchImpl> entry : unsubstitutedArgumentMappings) {
|
||||
ArgumentMatchImpl argumentMatch = entry.getValue();
|
||||
ValueParameterDescriptor valueParameterDescriptor = argumentMatch.getValueParameter();
|
||||
ValueParameterDescriptor substitutedVersion = substitutedParametersMap.get(valueParameterDescriptor.getOriginal());
|
||||
ValueParameterDescriptor substitutedVersion = substitutedParameters.get(valueParameterDescriptor.getIndex());
|
||||
assert substitutedVersion != null : valueParameterDescriptor;
|
||||
argumentToParameterMap.put(entry.getKey(), argumentMatch.replaceValueParameter(substitutedVersion));
|
||||
}
|
||||
@@ -264,14 +265,6 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
return valueArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Map<ValueParameterDescriptor, ResolvedValueArgument> getUnsubstitutedValueArguments() {
|
||||
// TODO We need unsubstituted value arguments to compare signatures for specificity when explicit type arguments are provided.
|
||||
// Current implementation is questionable (mostly due to lack of well-defined contract for MutableResolvedCall).
|
||||
return valueArgumentsBeforeSubstitution != null ? valueArgumentsBeforeSubstitution : valueArguments;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<ResolvedValueArgument> getValueArgumentsByIndex() {
|
||||
@@ -370,4 +363,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
public TypeSubstitutor getKnownTypeParametersSubstitutor() {
|
||||
return knownTypeParametersSubstitutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSmartCastDispatchReceiverType(@NotNull KotlinType smartCastDispatchReceiverType) {
|
||||
this.smartCastDispatchReceiverType = smartCastDispatchReceiverType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public KotlinType getSmartCastDispatchReceiverType() {
|
||||
return smartCastDispatchReceiverType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,14 +69,18 @@ class CandidateCallWithArgumentMapping<D : CallableDescriptor, K> private constr
|
||||
val argumentsToParameters = hashMapOf<K, ValueParameterDescriptor>()
|
||||
var parametersWithDefaultValuesCount = 0
|
||||
|
||||
for ((valueParameterDescriptor, resolvedValueArgument) in call.unsubstitutedValueArguments.entries) {
|
||||
val unsubstitutedValueParameters = call.candidateDescriptor.original.valueParameters
|
||||
for ((valueParameterDescriptor, resolvedValueArgument) in call.valueArguments.entries) {
|
||||
if (resolvedValueArgument is DefaultValueArgument) {
|
||||
parametersWithDefaultValuesCount++
|
||||
}
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,15 +19,13 @@ package org.jetbrains.kotlin.resolve.calls.results
|
||||
import gnu.trove.THashSet
|
||||
import gnu.trove.TObjectHashingStrategy
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilderImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.toHandle
|
||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -35,14 +33,15 @@ import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionMutableResolve
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
|
||||
fun <D : CallableDescriptor> findMaximallySpecific(
|
||||
candidates: Set<MutableResolvedCall<D>>,
|
||||
checkArgumentsMode: CheckArgumentTypesMode,
|
||||
discriminateGenerics: Boolean
|
||||
discriminateGenerics: Boolean,
|
||||
isDebuggerContext: Boolean
|
||||
): MutableResolvedCall<D>? =
|
||||
if (candidates.size <= 1)
|
||||
candidates.firstOrNull()
|
||||
@@ -56,7 +55,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
}.singleOrNull()
|
||||
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||
findMaximallySpecificCall(candidates, discriminateGenerics)
|
||||
findMaximallySpecificCall(candidates, discriminateGenerics, isDebuggerContext)
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> findMaximallySpecificVariableAsFunctionCalls(candidates: Set<MutableResolvedCall<D>>): Set<MutableResolvedCall<D>> {
|
||||
@@ -67,7 +66,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
throw AssertionError("Regular call among variable-as-function calls: $it")
|
||||
}
|
||||
|
||||
val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false) ?: return emptySet()
|
||||
val maxSpecificVariableCall = findMaximallySpecificCall(variableCalls, false, false) ?: return emptySet()
|
||||
|
||||
return candidates.filterTo(newResolvedCallSet<MutableResolvedCall<D>>(2)) {
|
||||
it.resultingVariableDescriptor == maxSpecificVariableCall.resultingDescriptor
|
||||
@@ -76,7 +75,8 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
|
||||
private fun <D : CallableDescriptor> findMaximallySpecificCall(
|
||||
candidates: Set<MutableResolvedCall<D>>,
|
||||
discriminateGenerics: Boolean
|
||||
discriminateGenerics: Boolean,
|
||||
isDebuggerContext: Boolean
|
||||
): MutableResolvedCall<D>? {
|
||||
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
||||
|
||||
@@ -89,7 +89,7 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
|
||||
val bestCandidatesByParameterTypes = conflictingCandidates.mapNotNull {
|
||||
candidate ->
|
||||
candidate.satisfying {
|
||||
candidate.check {
|
||||
isMostSpecific(candidate, conflictingCandidates) {
|
||||
call1, call2 ->
|
||||
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
|
||||
@@ -97,7 +97,10 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
}
|
||||
}
|
||||
|
||||
return bestCandidatesByParameterTypes.exactMaxWith { call1, call2 -> isOfNotLessSpecificShape(call1, call2) }?.resolvedCall
|
||||
return bestCandidatesByParameterTypes.exactMaxWith {
|
||||
call1, call2 ->
|
||||
isOfNotLessSpecificShape(call1, call2) && isOfNotLessSpecificVisibilityForDebugger(call1, call2, isDebuggerContext)
|
||||
}?.resolvedCall
|
||||
}
|
||||
|
||||
private inline fun <C : Any> Collection<C>.exactMaxWith(isNotWorse: (C, C) -> Boolean): C? {
|
||||
@@ -231,6 +234,22 @@ class OverloadingConflictResolver(private val builtIns: KotlinBuiltIns) {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun <D: CallableDescriptor, K> isOfNotLessSpecificVisibilityForDebugger(
|
||||
call1: CandidateCallWithArgumentMapping<D, K>,
|
||||
call2: CandidateCallWithArgumentMapping<D, K>,
|
||||
isDebuggerContext: Boolean
|
||||
): Boolean {
|
||||
if (isDebuggerContext) {
|
||||
val isMoreVisible1 = Visibilities.compare(
|
||||
call1.resolvedCall.resultingDescriptor.visibility,
|
||||
call2.resolvedCall.resultingDescriptor.visibility
|
||||
)
|
||||
if (isMoreVisible1 != null && isMoreVisible1 < 0) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if `d1` is definitely not less specific than `d2`,
|
||||
* `false` if `d1` is definitely less specific than `d2`,
|
||||
@@ -307,9 +326,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)
|
||||
|
||||
|
||||
@@ -96,7 +96,8 @@ public class ResolutionResultsHandler {
|
||||
Set<MutableResolvedCall<D>> successfulAndIncomplete = Sets.newLinkedHashSet();
|
||||
successfulAndIncomplete.addAll(successfulCandidates);
|
||||
successfulAndIncomplete.addAll(incompleteCandidates);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(successfulAndIncomplete, true, checkArgumentsMode);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(
|
||||
successfulAndIncomplete, true, context.isDebuggerContext, checkArgumentsMode);
|
||||
if (results.isSingleResult()) {
|
||||
MutableResolvedCall<D> resultingCall = results.getResultingCall();
|
||||
resultingCall.getTrace().moveAllMyDataTo(context.trace);
|
||||
@@ -147,7 +148,7 @@ public class ResolutionResultsHandler {
|
||||
if (severityLevel.contains(ARGUMENTS_MAPPING_ERROR)) {
|
||||
return recordFailedInfo(tracing, trace, thisLevel);
|
||||
}
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false, checkArgumentsMode);
|
||||
OverloadResolutionResultsImpl<D> results = chooseAndReportMaximallySpecific(thisLevel, false, false, checkArgumentsMode);
|
||||
return recordFailedInfo(tracing, trace, results.getResultingCalls());
|
||||
}
|
||||
}
|
||||
@@ -188,6 +189,7 @@ public class ResolutionResultsHandler {
|
||||
public <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> chooseAndReportMaximallySpecific(
|
||||
@NotNull Set<MutableResolvedCall<D>> candidates,
|
||||
boolean discriminateGenerics,
|
||||
boolean isDebuggerContext,
|
||||
@NotNull CheckArgumentTypesMode checkArgumentsMode
|
||||
) {
|
||||
if (candidates.size() == 1) {
|
||||
@@ -203,14 +205,14 @@ public class ResolutionResultsHandler {
|
||||
return OverloadResolutionResultsImpl.success(noOverrides.iterator().next());
|
||||
}
|
||||
|
||||
MutableResolvedCall<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, checkArgumentsMode, false);
|
||||
MutableResolvedCall<D> maximallySpecific = overloadingConflictResolver.findMaximallySpecific(noOverrides, checkArgumentsMode, false, isDebuggerContext);
|
||||
if (maximallySpecific != null) {
|
||||
return OverloadResolutionResultsImpl.success(maximallySpecific);
|
||||
}
|
||||
|
||||
if (discriminateGenerics) {
|
||||
MutableResolvedCall<D> maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(
|
||||
noOverrides, checkArgumentsMode, true);
|
||||
noOverrides, checkArgumentsMode, true, isDebuggerContext);
|
||||
if (maximallySpecificGenericsDiscriminated != null) {
|
||||
return OverloadResolutionResultsImpl.success(maximallySpecificGenericsDiscriminated);
|
||||
}
|
||||
|
||||
@@ -58,11 +58,12 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
@NotNull StatementFilter statementFilter,
|
||||
@NotNull Collection<MutableResolvedCall<F>> resolvedCalls,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, call, expectedType, dataFlowInfo, contextDependency, checkArguments, resolutionResultsCache,
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
dataFlowInfoForArguments, callChecker, statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
this.lazyCandidates = lazyCandidates;
|
||||
this.resolvedCalls = resolvedCalls;
|
||||
this.tracing = tracing;
|
||||
@@ -79,7 +80,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
context.resolutionResultsCache, context.dataFlowInfoForArguments,
|
||||
context.callChecker,
|
||||
context.statementFilter, new SmartList<MutableResolvedCall<F>>(),
|
||||
context.isAnnotationContext, context.collectAllCandidates, context.callPosition);
|
||||
context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates, context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -113,7 +114,7 @@ public class ResolutionTask<D extends CallableDescriptor, F extends D> extends C
|
||||
resolutionResultsCache, dataFlowInfoForArguments,
|
||||
callChecker,
|
||||
statementFilter, resolvedCalls,
|
||||
isAnnotationContext, collectAllCandidates, callPosition);
|
||||
isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
@@ -46,9 +47,9 @@ fun createSynthesizedInvokes(functions: Collection<FunctionDescriptor>): Collect
|
||||
synthesizedSuperFun.modality,
|
||||
synthesizedSuperFun.visibility,
|
||||
CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
|
||||
true
|
||||
/* copyOverrides = */ false
|
||||
)
|
||||
fakeOverride.addOverriddenDescriptor(synthesizedSuperFun)
|
||||
fakeOverride.setSingleOverridden(synthesizedSuperFun)
|
||||
fakeOverride
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.types.DeferredType
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
class NewResolveOldInference(
|
||||
@@ -290,7 +290,7 @@ class NewResolveOldInference(
|
||||
tracing.bindReference(variable.resolvedCall.trace, variable.resolvedCall)
|
||||
// todo hacks
|
||||
val functionCall = CallTransformer.CallForImplicitInvoke(
|
||||
basicCallContext.call.explicitReceiver?.satisfying { useExplicitReceiver },
|
||||
basicCallContext.call.explicitReceiver?.check { useExplicitReceiver },
|
||||
variableReceiver, basicCallContext.call)
|
||||
val tracingForInvoke = TracingStrategyForInvoke(calleeExpression, functionCall, variableReceiver.type)
|
||||
val basicCallResolutionContext = basicCallContext.replaceBindingTrace(variable.resolvedCall.trace)
|
||||
|
||||
@@ -21,16 +21,14 @@ import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.containsError
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
|
||||
@@ -50,7 +48,9 @@ internal class ScopeTowerImpl(
|
||||
override val lexicalScope: LexicalScope = resolutionContext.scope
|
||||
|
||||
override val implicitReceivers = resolutionContext.scope.getImplicitReceiversHierarchy().
|
||||
mapNotNull { it.value.satisfying { !it.type.containsError() } }
|
||||
mapNotNull { it.value.check { !it.type.containsError() } }
|
||||
|
||||
val isDebuggerContext = resolutionContext.isDebuggerContext
|
||||
}
|
||||
|
||||
private class DataFlowDecoratorImpl(private val resolutionContext: ResolutionContext<*>): DataFlowDecorator {
|
||||
|
||||
@@ -22,14 +22,14 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ClassQualifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
|
||||
internal class KnownResultProcessor<C>(
|
||||
val result: Collection<C>
|
||||
): ScopeTowerProcessor<C> {
|
||||
override fun process(data: TowerData)
|
||||
= if (data == TowerData.Empty) listOfNotNull(result.satisfying { it.isNotEmpty() }) else emptyList()
|
||||
= if (data == TowerData.Empty) listOfNotNull(result.check { it.isNotEmpty() }) else emptyList()
|
||||
}
|
||||
|
||||
internal class CompositeScopeTowerProcessor<C>(
|
||||
@@ -45,7 +45,7 @@ internal abstract class AbstractSimpleScopeTowerProcessor<C>(
|
||||
|
||||
protected abstract fun simpleProcess(data: TowerData): Collection<C>
|
||||
|
||||
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).satisfying { it.isNotEmpty() })
|
||||
override fun process(data: TowerData): List<Collection<C>> = listOfNotNull(simpleProcess(data).check { it.isNotEmpty() })
|
||||
}
|
||||
|
||||
internal class ExplicitReceiverScopeTowerProcessor<C>(
|
||||
|
||||
@@ -62,10 +62,13 @@ internal abstract class AbstractScopeTowerLevel(
|
||||
if (descriptor.isSynthesized) diagnostics.add(SynthesizedDescriptorDiagnostic)
|
||||
if (dispatchReceiverSmartCastType != null) diagnostics.add(UsedSmartCastForDispatchReceiver(dispatchReceiverSmartCastType))
|
||||
|
||||
Visibilities.findInvisibleMember(
|
||||
dispatchReceiver, descriptor,
|
||||
scopeTower.lexicalScope.ownerDescriptor
|
||||
)?.let { diagnostics.add(VisibilityError(it)) }
|
||||
val shouldSkipVisibilityCheck = scopeTower is ScopeTowerImpl && scopeTower.isDebuggerContext
|
||||
if (!shouldSkipVisibilityCheck) {
|
||||
Visibilities.findInvisibleMember(
|
||||
dispatchReceiver, descriptor,
|
||||
scopeTower.lexicalScope.ownerDescriptor
|
||||
)?.let { diagnostics.add(VisibilityError(it)) }
|
||||
}
|
||||
}
|
||||
return CandidateWithBoundDispatchReceiverImpl(dispatchReceiver, descriptor, diagnostics)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import java.util.*
|
||||
|
||||
interface TowerContext<C> {
|
||||
@@ -221,13 +221,13 @@ class TowerResolver {
|
||||
|
||||
override fun getSuccessfulCandidates(): Collection<C>? = getResolved() ?: getResolvedSynthetic()
|
||||
|
||||
fun getResolved() = currentCandidates.satisfying { currentLevel == ResolutionCandidateApplicability.RESOLVED }
|
||||
fun getResolved() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED }
|
||||
|
||||
fun getResolvedSynthetic() = currentCandidates.satisfying { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
|
||||
fun getResolvedSynthetic() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_SYNTHESIZED }
|
||||
|
||||
fun getResolvedLowPriority() = currentCandidates.satisfying { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY }
|
||||
fun getResolvedLowPriority() = currentCandidates.check { currentLevel == ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY }
|
||||
|
||||
fun getErrors() = currentCandidates.satisfying {
|
||||
fun getErrors() = currentCandidates.check {
|
||||
currentLevel == null || currentLevel!! > ResolutionCandidateApplicability.RESOLVED_LOW_PRIORITY
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ private fun deprecationByOverridden(root: CallableMemberDescriptor): Deprecation
|
||||
visited.add(node)
|
||||
|
||||
val deprecatedAnnotation = node.getDeprecationByAnnotation()
|
||||
val overriddenDescriptors = node.overriddenDescriptors
|
||||
val overriddenDescriptors = node.original.overriddenDescriptors
|
||||
when {
|
||||
deprecatedAnnotation != null -> {
|
||||
deprecations.add(deprecatedAnnotation)
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.satisfying
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
open class FileScopeProviderImpl(
|
||||
private val topLevelDescriptorProvider: TopLevelDescriptorProvider,
|
||||
@@ -159,7 +159,7 @@ open class FileScopeProviderImpl(
|
||||
if (name in excludedNames) return null
|
||||
val classifier = scope.getContributedClassifier(name, location) ?: return null
|
||||
val visible = Visibilities.isVisibleWithIrrelevantReceiver(classifier as ClassDescriptor, fromDescriptor)
|
||||
return classifier.satisfying { filteringKind == if (visible) FilteringKind.VISIBLE_CLASSES else FilteringKind.INVISIBLE_CLASSES }
|
||||
return classifier.check { filteringKind == if (visible) FilteringKind.VISIBLE_CLASSES else FilteringKind.INVISIBLE_CLASSES }
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> {
|
||||
|
||||
@@ -262,6 +262,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
}
|
||||
|
||||
List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
|
||||
if (typeParameters.isEmpty()) return Collections.emptyList();
|
||||
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ open class LazyClassMemberScope(
|
||||
|
||||
override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
||||
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent) as? KtDeclaration ?: error("fromCurrent can not be a fake override")
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()))
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromSuper.containingDeclaration))
|
||||
}
|
||||
})
|
||||
OverrideResolver.resolveUnknownVisibilities(result, trace)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
@@ -32,7 +31,6 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtKeywordToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
@@ -1181,7 +1179,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() {
|
||||
@Override
|
||||
public boolean accept(@Nullable WritableSlice<?, ?> slice, @Nullable Diagnostic diagnostic, Object key) {
|
||||
public boolean accept(@Nullable WritableSlice<?, ?> slice, Object key) {
|
||||
// the type of the right (and sometimes left) expression isn't 'Any?' actually
|
||||
if ((key == right || key == left) && slice == EXPRESSION_TYPE_INFO) return false;
|
||||
|
||||
|
||||
@@ -571,8 +571,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();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
@@ -41,38 +42,14 @@ class DestructuringDeclarationResolver(
|
||||
fun defineLocalVariablesFromMultiDeclaration(
|
||||
writableScope: LexicalWritableScope,
|
||||
destructuringDeclaration: KtDestructuringDeclaration,
|
||||
receiver: ReceiverValue,
|
||||
reportErrorsOn: KtExpression,
|
||||
receiver: ReceiverValue?,
|
||||
initializer: KtExpression?,
|
||||
context: ExpressionTypingContext
|
||||
) {
|
||||
for ((componentIndex, entry) in destructuringDeclaration.entries.withIndex()) {
|
||||
val componentName = createComponentName(componentIndex + 1)
|
||||
|
||||
val expectedType = getExpectedTypeForComponent(context, entry)
|
||||
val results = fakeCallResolver.resolveFakeCall(context.replaceExpectedType(expectedType), receiver, componentName,
|
||||
entry, reportErrorsOn, FakeCallKind.COMPONENT)
|
||||
|
||||
var componentType: KotlinType? = null
|
||||
if (results.isSuccess) {
|
||||
context.trace.record(BindingContext.COMPONENT_RESOLVED_CALL, entry, results.resultingCall)
|
||||
|
||||
val functionDescriptor = results.resultingDescriptor
|
||||
symbolUsageValidator.validateCall(null, functionDescriptor, context.trace, entry)
|
||||
|
||||
componentType = functionDescriptor.returnType
|
||||
if (componentType != null && !TypeUtils.noExpectedType(expectedType) && !KotlinTypeChecker.DEFAULT.isSubtypeOf(componentType, expectedType)) {
|
||||
context.trace.report(Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(reportErrorsOn, componentName, componentType, expectedType))
|
||||
}
|
||||
}
|
||||
else if (results.isAmbiguity) {
|
||||
context.trace.report(Errors.COMPONENT_FUNCTION_AMBIGUITY.on(reportErrorsOn, componentName, results.getResultingCalls()))
|
||||
}
|
||||
else {
|
||||
context.trace.report(Errors.COMPONENT_FUNCTION_MISSING.on(reportErrorsOn, componentName, receiver.getType()))
|
||||
}
|
||||
if (componentType == null) {
|
||||
componentType = ErrorUtils.createErrorType("$componentName() return type")
|
||||
}
|
||||
val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer)
|
||||
val variableDescriptor = localVariableResolver.resolveLocalVariableDescriptorWithType(writableScope, entry, componentType, context.trace)
|
||||
|
||||
ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, variableDescriptor)
|
||||
@@ -81,6 +58,40 @@ class DestructuringDeclarationResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveComponentFunctionAndGetType(
|
||||
componentName: Name,
|
||||
context: ExpressionTypingContext,
|
||||
entry: KtDestructuringDeclarationEntry,
|
||||
receiver: ReceiverValue?,
|
||||
initializer: KtExpression?
|
||||
): KotlinType {
|
||||
fun errorType() = ErrorUtils.createErrorType("$componentName() return type")
|
||||
|
||||
if (receiver == null || initializer == null) return errorType()
|
||||
|
||||
val expectedType = getExpectedTypeForComponent(context, entry)
|
||||
val results = fakeCallResolver.resolveFakeCall(
|
||||
context.replaceExpectedType(expectedType), receiver, componentName,
|
||||
entry, initializer, FakeCallKind.COMPONENT
|
||||
)
|
||||
|
||||
if (!results.isSuccess) {
|
||||
return errorType()
|
||||
}
|
||||
|
||||
context.trace.record(BindingContext.COMPONENT_RESOLVED_CALL, entry, results.resultingCall)
|
||||
|
||||
val functionDescriptor = results.resultingDescriptor
|
||||
symbolUsageValidator.validateCall(null, functionDescriptor, context.trace, entry)
|
||||
|
||||
val functionReturnType = functionDescriptor.returnType
|
||||
if (functionReturnType != null && !TypeUtils.noExpectedType(expectedType)
|
||||
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(functionReturnType, expectedType) ) {
|
||||
context.trace.report(Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(initializer, componentName, functionReturnType, expectedType))
|
||||
}
|
||||
return functionReturnType ?: errorType()
|
||||
}
|
||||
|
||||
private fun getExpectedTypeForComponent(context: ExpressionTypingContext, entry: KtDestructuringDeclarationEntry): KotlinType {
|
||||
val entryTypeRef = entry.typeReference ?: return TypeUtils.NO_EXPECTED_TYPE
|
||||
return typeResolver.resolveType(context.scope, entryTypeRef, context.trace, true)
|
||||
|
||||
@@ -58,7 +58,18 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
context.contextDependency, context.resolutionResultsCache,
|
||||
context.callChecker,
|
||||
context.statementFilter,
|
||||
context.isAnnotationContext, context.collectAllCandidates,
|
||||
context.isAnnotationContext, context.isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpressionTypingContext newContext(@NotNull ResolutionContext context, boolean isDebuggerContext) {
|
||||
return new ExpressionTypingContext(
|
||||
context.trace, context.scope, context.dataFlowInfo, context.expectedType,
|
||||
context.contextDependency, context.resolutionResultsCache,
|
||||
context.callChecker,
|
||||
context.statementFilter,
|
||||
context.isAnnotationContext, isDebuggerContext, context.collectAllCandidates,
|
||||
context.callPosition);
|
||||
}
|
||||
|
||||
@@ -76,7 +87,7 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
) {
|
||||
return new ExpressionTypingContext(
|
||||
trace, scope, dataFlowInfo, expectedType, contextDependency, resolutionResultsCache, callChecker,
|
||||
statementFilter, isAnnotationContext, false, CallPosition.Unknown.INSTANCE);
|
||||
statementFilter, isAnnotationContext, false, false, CallPosition.Unknown.INSTANCE);
|
||||
}
|
||||
|
||||
private ExpressionTypingContext(
|
||||
@@ -89,12 +100,13 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
@NotNull CallChecker callChecker,
|
||||
@NotNull StatementFilter statementFilter,
|
||||
boolean isAnnotationContext,
|
||||
boolean isDebuggerContext,
|
||||
boolean collectAllCandidates,
|
||||
@NotNull CallPosition callPosition
|
||||
) {
|
||||
super(trace, scope, expectedType, dataFlowInfo, contextDependency, resolutionResultsCache,
|
||||
callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,6 +124,6 @@ public class ExpressionTypingContext extends ResolutionContext<ExpressionTypingC
|
||||
return new ExpressionTypingContext(trace, scope, dataFlowInfo,
|
||||
expectedType, contextDependency, resolutionResultsCache,
|
||||
callChecker,
|
||||
statementFilter, isAnnotationContext, collectAllCandidates, callPosition);
|
||||
statementFilter, isAnnotationContext, isDebuggerContext, collectAllCandidates, callPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.*;
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
||||
import org.jetbrains.kotlin.resolve.DeclarationsCheckerBuilder;
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
|
||||
@@ -144,8 +148,12 @@ public abstract class ExpressionTypingVisitorDispatcher extends KtVisitor<Kotlin
|
||||
@Override
|
||||
@NotNull
|
||||
public final KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||
if (!isStatement) return getTypeInfo(expression, context);
|
||||
return getTypeInfo(expression, context, getStatementVisitor(context));
|
||||
ExpressionTypingContext newContext = context;
|
||||
if (CodeFragmentUtilKt.suppressDiagnosticsInDebugMode(expression)) {
|
||||
newContext = ExpressionTypingContext.newContext(context, true);
|
||||
}
|
||||
if (!isStatement) return getTypeInfo(expression, newContext);
|
||||
return getTypeInfo(expression, newContext, getStatementVisitor(newContext));
|
||||
}
|
||||
|
||||
protected ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user