diff --git a/.idea/runConfigurations/All_Tests.xml b/.idea/runConfigurations/All_Tests.xml
index 377a192e945..bf876130bd6 100644
--- a/.idea/runConfigurations/All_Tests.xml
+++ b/.idea/runConfigurations/All_Tests.xml
@@ -22,6 +22,7 @@
+
diff --git a/annotations/com/intellij/codeInsight/annotations.xml b/annotations/com/intellij/codeInsight/annotations.xml
new file mode 100644
index 00000000000..0ef0480992d
--- /dev/null
+++ b/annotations/com/intellij/codeInsight/annotations.xml
@@ -0,0 +1,5 @@
+
+ -
+
+
+
\ No newline at end of file
diff --git a/annotations/com/intellij/lang/annotations.xml b/annotations/com/intellij/lang/annotations.xml
index f603cab30a6..ebed995bb20 100644
--- a/annotations/com/intellij/lang/annotations.xml
+++ b/annotations/com/intellij/lang/annotations.xml
@@ -2,4 +2,8 @@
-
+ -
+
+
\ No newline at end of file
diff --git a/build.xml b/build.xml
index 1862125cb6e..5ae5de6105d 100644
--- a/build.xml
+++ b/build.xml
@@ -474,6 +474,16 @@
void stop();
void dispose();
}
+
+ -keepclassmembers class org.jetbrains.org.objectweb.asm.Opcodes {
+ *** ASM5;
+ }
+
+ -keepclassmembers class org.jetbrains.org.objectweb.asm.ClassReader {
+ *** SKIP_CODE;
+ *** SKIP_DEBUG;
+ *** SKIP_FRAMES;
+ }
]]>
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java
index cb573329da2..df2af34a135 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java
@@ -85,7 +85,10 @@ public abstract class AnnotationCodegen {
bindingContext = typeMapper.getBindingContext();
}
- public void genAnnotations(Annotated annotated) {
+ /**
+ * @param returnType can be null if not applicable (e.g. {@code annotated} is a class)
+ */
+ public void genAnnotations(@Nullable Annotated annotated, @Nullable Type returnType) {
if (annotated == null) {
return;
}
@@ -111,7 +114,7 @@ public abstract class AnnotationCodegen {
}
if (modifierList == null) {
- generateAdditionalAnnotations(annotated, Collections.emptySet());
+ generateAdditionalAnnotations(annotated, returnType, Collections.emptySet());
return;
}
@@ -131,10 +134,14 @@ public abstract class AnnotationCodegen {
}
}
- generateAdditionalAnnotations(annotated, annotationDescriptorsAlreadyPresent);
+ generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent);
}
- private void generateAdditionalAnnotations(@NotNull Annotated annotated, @NotNull Set annotationDescriptorsAlreadyPresent) {
+ private void generateAdditionalAnnotations(
+ @NotNull Annotated annotated,
+ @Nullable Type returnType,
+ @NotNull Set annotationDescriptorsAlreadyPresent
+ ) {
if (annotated instanceof CallableDescriptor) {
CallableDescriptor descriptor = (CallableDescriptor) annotated;
@@ -142,7 +149,9 @@ public abstract class AnnotationCodegen {
if (isInvisibleFromTheOutside(descriptor)) return;
if (descriptor instanceof ValueParameterDescriptor && isInvisibleFromTheOutside(descriptor.getContainingDeclaration())) return;
- generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
+ if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
+ generateNullabilityAnnotation(descriptor.getReturnType(), annotationDescriptorsAlreadyPresent);
+ }
}
}
@@ -166,7 +175,6 @@ public abstract class AnnotationCodegen {
}
boolean isNullableType = JvmCodegenUtil.isNullableType(type);
- if (!isNullableType && KotlinBuiltIns.getInstance().isPrimitiveType(type)) return;
Class> annotationClass = isNullableType ? Nullable.class : NotNull.class;
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
index b92daaf9f44..60cbe9f7dcc 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java
@@ -722,7 +722,7 @@ public class ExpressionCodegen extends JetVisitor implem
invokeFunction(fakeCall, StackValue.local(iteratorVarIndex, asmTypeForIterator), hasNextCall);
JetType type = hasNextCall.getResultingDescriptor().getReturnType();
- assert type != null && JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
+ assert type != null && JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
Type asmType = asmType(type);
StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v);
@@ -3413,6 +3413,11 @@ The "returned" value of try expression with no finally is either the last expres
myFrameMap.leave(descriptor);
+ Label clauseEnd = new Label();
+ v.mark(clauseEnd);
+
+ v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, index);
+
genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null);
generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName());
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
index c2dbc72820a..6d859f6d627 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java
@@ -143,7 +143,7 @@ public class FunctionCodegen extends ParentCodegenAware {
v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
}
- AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor);
+ AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, asmMethod.getReturnType());
generateParameterAnnotations(functionDescriptor, mv, jvmSignature);
@@ -180,7 +180,8 @@ public class FunctionCodegen extends ParentCodegenAware {
List kotlinParameterTypes = jvmSignature.getValueParameters();
for (int i = 0; i < kotlinParameterTypes.size(); i++) {
- JvmMethodParameterKind kind = kotlinParameterTypes.get(i).getKind();
+ JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
+ JvmMethodParameterKind kind = parameterSignature.getKind();
if (kind.isSkippedInGenericSignature()) {
markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
continue;
@@ -189,7 +190,7 @@ public class FunctionCodegen extends ParentCodegenAware {
if (kind == JvmMethodParameterKind.VALUE) {
ValueParameterDescriptor parameter = iterator.next();
v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
- AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter);
+ AnnotationCodegen.forParameter(i, mv, typeMapper).genAnnotations(parameter, parameterSignature.getAsmType());
}
}
}
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
index df1b6cc5342..15ef11f2960 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java
@@ -54,7 +54,6 @@ import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature;
-import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -67,10 +66,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method;
import java.util.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
-import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
@@ -78,6 +74,9 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.DelegationToTraitImpl;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.OtherOrigin;
+import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
@@ -208,7 +207,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
writeInnerClasses();
- AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
+ AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null);
}
@Override
@@ -485,7 +484,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetType returnType = function.getReturnType();
assert returnType != null : function.toString();
JetType paramType = function.getValueParameters().get(0).getType();
- if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) {
+ if (JetTypeChecker.DEFAULT.equalTypes(arrayType, returnType) && JetTypeChecker.DEFAULT.equalTypes(arrayType, paramType)) {
return true;
}
}
@@ -1083,11 +1082,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) {
PropertyDescriptor property = info.descriptor;
+ Type type = typeMapper.mapType(property);
FieldVisitor fv = v.newField(OtherOrigin(property), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false),
- typeMapper.mapType(property).getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
+ type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()),
info.defaultValue);
- AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property);
+ AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type);
//This field are always static and final so if it has constant initializer don't do anything in clinit,
//field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
index 1dc03a34674..714fe0463ab 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java
@@ -145,18 +145,15 @@ public class PropertyCodegen {
return false;
}
- FieldVisitor fv;
if (Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor))) {
- fv = generateBackingFieldAccess(p, descriptor);
+ generateBackingFieldAccess(p, descriptor);
}
else if (p instanceof JetProperty && ((JetProperty) p).hasDelegate()) {
- fv = generatePropertyDelegateAccess((JetProperty) p, descriptor);
+ generatePropertyDelegateAccess((JetProperty) p, descriptor);
}
else {
return false;
}
-
- AnnotationCodegen.forField(fv, typeMapper).genAnnotations(descriptor);
return true;
}
@@ -172,7 +169,7 @@ public class PropertyCodegen {
if (!isTrait(context.getContextDescriptor()) || kind == OwnerKind.TRAIT_IMPL) {
int flags = ACC_DEPRECATED | ACC_FINAL | ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC;
MethodVisitor mv = v.newMethod(OtherOrigin(descriptor), flags, name, desc, null, null);
- AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor);
+ AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(descriptor, Type.VOID_TYPE);
mv.visitCode();
mv.visitInsn(Opcodes.RETURN);
mv.visitEnd();
@@ -187,7 +184,7 @@ public class PropertyCodegen {
}
}
- private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
+ private void generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.FIELD_FLAGS) {
@@ -230,21 +227,22 @@ public class PropertyCodegen {
v.getSerializationBindings().put(FIELD_FOR_PROPERTY, propertyDescriptor, Pair.create(type, name));
- return builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
- typeMapper.mapFieldSignature(jetType), defaultValue);
+ FieldVisitor fv = builder.newField(OtherOrigin(element, propertyDescriptor), modifiers, name, type.getDescriptor(),
+ typeMapper.mapFieldSignature(jetType), defaultValue);
+ AnnotationCodegen.forField(fv, typeMapper).genAnnotations(propertyDescriptor, type);
}
- private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
+ private void generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
if (delegateType == null) {
// If delegate expression is unresolved reference
delegateType = ErrorUtils.createErrorType("Delegate type");
}
- return generateBackingField(p, propertyDescriptor, true, delegateType, null);
+ generateBackingField(p, propertyDescriptor, true, delegateType, null);
}
- private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
+ private void generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
Object value = null;
if (shouldWriteFieldInitializer(propertyDescriptor)) {
@@ -254,7 +252,7 @@ public class PropertyCodegen {
}
}
- return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
+ generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
}
private boolean shouldWriteFieldInitializer(@NotNull PropertyDescriptor descriptor) {
diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java
index 38849663539..6dee5371442 100644
--- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java
+++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java
@@ -446,8 +446,7 @@ public class JetTypeMapper {
invokeOpcode = INVOKEINTERFACE;
}
else {
- boolean isPrivateFunInvocation = isCallInsideSameClassAsDeclared(functionDescriptor, context) &&
- functionDescriptor.getVisibility() == Visibilities.PRIVATE;
+ boolean isPrivateFunInvocation = functionDescriptor.getVisibility() == Visibilities.PRIVATE;
invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java
index 924c8f87f20..81f2e67463f 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/AlternativeMethodSignatureData.java
@@ -139,7 +139,7 @@ public class AlternativeMethodSignatureData extends ElementAlternativeSignatureD
JetType substitutedReturnType = substitutor.substitute(returnType, Variance.INVARIANT);
assert substitutedReturnType != null;
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(altReturnType, substitutedReturnType)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(altReturnType, substitutedReturnType)) {
throw new AlternativeSignatureMismatchException(
"Return type is changed to not subtype for method which overrides another: " + altReturnType + ", was: " + returnType);
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java
index f8ba53037cc..b8a0da70239 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java
@@ -59,8 +59,8 @@ class PropagationHeuristics {
JetType elementTypeInSuper = arrayTypeFromSuper.getArguments().get(0).getType();
JetType elementType = type.getArguments().get(0).getType();
- if (JetTypeChecker.INSTANCE.isSubtypeOf(elementType, elementTypeInSuper)
- && !JetTypeChecker.INSTANCE.equalTypes(elementType, elementTypeInSuper)) {
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(elementType, elementTypeInSuper)
+ && !JetTypeChecker.DEFAULT.equalTypes(elementType, elementTypeInSuper)) {
JetTypeImpl betterTypeInSuper = new JetTypeImpl(
arrayTypeFromSuper.getAnnotations(),
arrayTypeFromSuper.getConstructor(),
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java
index 39050e233d4..9bd7d799793 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassImpl.java
@@ -16,10 +16,8 @@
package org.jetbrains.jet.lang.resolve.java.structure.impl;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiCompiledElement;
-import com.intellij.psi.PsiTypeParameter;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,7 +28,9 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*;
@@ -181,4 +181,27 @@ public class JavaClassImpl extends JavaClassifierImpl implements JavaC
return OriginKind.SOURCE;
}
}
+
+ @NotNull
+ @Override
+ public JavaType createImmediateType(@NotNull JavaTypeSubstitutor substitutor) {
+ return new JavaClassifierTypeImpl(
+ JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutor)));
+ }
+
+ @NotNull
+ private static PsiSubstitutor createPsiSubstitutor(@NotNull JavaTypeSubstitutor substitutor) {
+ Map substMap = new HashMap();
+ for (Map.Entry entry : substitutor.getSubstitutionMap().entrySet()) {
+ PsiTypeParameter key = ((JavaTypeParameterImpl) entry.getKey()).getPsi();
+ if (entry.getValue() == null) {
+ substMap.put(key, null);
+ }
+ else {
+ substMap.put(key, ((JavaTypeImpl) entry.getValue()).getPsi());
+ }
+ }
+
+ return PsiSubstitutorImpl.createSubstitutor(substMap);
+ }
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java
index 13493d162c6..d91be1c9ca7 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaClassifierTypeImpl.java
@@ -16,20 +16,12 @@
package org.jetbrains.jet.lang.resolve.java.structure.impl;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiClassType;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifierType;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor;
+import org.jetbrains.jet.lang.resolve.java.structure.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import static org.jetbrains.jet.lang.resolve.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.types;
@@ -68,13 +60,25 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl implement
if (resolutionResult == null) {
PsiClassType.ClassResolveResult result = getPsi().resolveGenerics();
PsiClass psiClass = result.getElement();
+ PsiSubstitutor substitutor = result.getSubstitutor();
resolutionResult = new ResolutionResult(
psiClass == null ? null : JavaClassifierImpl.create(psiClass),
- new JavaTypeSubstitutorImpl(result.getSubstitutor())
+ new JavaTypeSubstitutorImpl(convertSubstitutionMap(substitutor.getSubstitutionMap()))
);
}
}
+ @NotNull
+ private Map convertSubstitutionMap(@NotNull Map psiMap) {
+ Map substitutionMap = new HashMap();
+ for (Map.Entry entry : psiMap.entrySet()) {
+ PsiType value = entry.getValue();
+ substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value));
+ }
+
+ return substitutionMap;
+ }
+
@Override
@NotNull
public Collection getSupertypes() {
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java
index 680d5c53cdb..d859abdba9c 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeImpl.java
@@ -39,31 +39,31 @@ public abstract class JavaTypeImpl implements JavaType {
return psiType.accept(new PsiTypeVisitor>() {
@Nullable
@Override
- public JavaTypeImpl> visitType(PsiType type) {
+ public JavaTypeImpl> visitType(@NotNull PsiType type) {
throw new UnsupportedOperationException("Unsupported PsiType: " + type);
}
@Nullable
@Override
- public JavaTypeImpl> visitPrimitiveType(PsiPrimitiveType primitiveType) {
+ public JavaTypeImpl> visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) {
return new JavaPrimitiveTypeImpl(primitiveType);
}
@Nullable
@Override
- public JavaTypeImpl> visitArrayType(PsiArrayType arrayType) {
+ public JavaTypeImpl> visitArrayType(@NotNull PsiArrayType arrayType) {
return new JavaArrayTypeImpl(arrayType);
}
@Nullable
@Override
- public JavaTypeImpl> visitClassType(PsiClassType classType) {
+ public JavaTypeImpl> visitClassType(@NotNull PsiClassType classType) {
return new JavaClassifierTypeImpl(classType);
}
@Nullable
@Override
- public JavaTypeImpl> visitWildcardType(PsiWildcardType wildcardType) {
+ public JavaTypeImpl> visitWildcardType(@NotNull PsiWildcardType wildcardType) {
return new JavaWildcardTypeImpl(wildcardType);
}
});
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java
index 45ad66eaf8a..6c45f61f0ad 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeProviderImpl.java
@@ -18,10 +18,12 @@ package org.jetbrains.jet.lang.resolve.java.structure.impl;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiType;
+import com.intellij.psi.PsiWildcardType;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeProvider;
+import org.jetbrains.jet.lang.resolve.java.structure.JavaWildcardType;
public class JavaTypeProviderImpl implements JavaTypeProvider {
private final PsiManager manager;
@@ -35,4 +37,22 @@ public class JavaTypeProviderImpl implements JavaTypeProvider {
public JavaType createJavaLangObjectType() {
return JavaTypeImpl.create(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject())));
}
+
+ @NotNull
+ @Override
+ public JavaWildcardType createUpperBoundWildcard(@NotNull JavaType bound) {
+ return new JavaWildcardTypeImpl(PsiWildcardType.createExtends(manager, ((JavaTypeImpl) bound).getPsi()));
+ }
+
+ @NotNull
+ @Override
+ public JavaWildcardType createLowerBoundWildcard(@NotNull JavaType bound) {
+ return new JavaWildcardTypeImpl(PsiWildcardType.createSuper(manager, ((JavaTypeImpl) bound).getPsi()));
+ }
+
+ @NotNull
+ @Override
+ public JavaWildcardType createUnboundedWildcard() {
+ return new JavaWildcardTypeImpl(PsiWildcardType.createUnbounded(manager));
+ }
}
diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java
index 9983a52bcf3..146d79a5e86 100644
--- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java
+++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaTypeSubstitutorImpl.java
@@ -16,83 +16,170 @@
package org.jetbrains.jet.lang.resolve.java.structure.impl;
-import com.intellij.psi.PsiSubstitutor;
-import com.intellij.psi.PsiType;
-import com.intellij.psi.PsiTypeParameter;
-import com.intellij.psi.impl.PsiSubstitutorImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeParameter;
-import org.jetbrains.jet.lang.resolve.java.structure.JavaTypeSubstitutor;
+import org.jetbrains.jet.lang.resolve.java.structure.*;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class JavaTypeSubstitutorImpl implements JavaTypeSubstitutor {
- private final PsiSubstitutor psiSubstitutor;
- private Map substitutionMap;
+ private final Map substitutionMap;
- public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor) {
- this.psiSubstitutor = psiSubstitutor;
- }
-
- public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor, @NotNull Map substitutionMap) {
- this(psiSubstitutor);
+ public JavaTypeSubstitutorImpl(@NotNull Map substitutionMap) {
this.substitutionMap = substitutionMap;
}
@NotNull
- public static JavaTypeSubstitutor create(@NotNull Map substitutionMap) {
- Map psiMap = new HashMap();
- for (Map.Entry entry : substitutionMap.entrySet()) {
- JavaTypeImpl value = ((JavaTypeImpl) entry.getValue());
- psiMap.put(((JavaTypeParameterImpl) entry.getKey()).getPsi(), value == null ? null : value.getPsi());
- }
- PsiSubstitutor psiSubstitutor = PsiSubstitutorImpl.createSubstitutor(psiMap);
- return new JavaTypeSubstitutorImpl(psiSubstitutor, substitutionMap);
+ @Override
+ public JavaType substitute(@NotNull JavaType type) {
+ JavaType substitutedType = substituteInternal(type);
+ return substitutedType != null ? substitutedType : correctSubstitutionForRawType(type);
}
- @Override
@NotNull
- public JavaType substitute(@NotNull JavaType type) {
- return JavaTypeImpl.create(psiSubstitutor.substitute(((JavaTypeImpl) type).getPsi()));
+ // In case of raw type we get substition map like T -> null,
+ // in this case we should substitute upper bound of T or,
+ // if it does not exist, return java.lang.Object
+ private JavaType correctSubstitutionForRawType(@NotNull JavaType original) {
+ if (original instanceof JavaClassifierType) {
+ JavaClassifier classifier = ((JavaClassifierType) original).getClassifier();
+ if (classifier instanceof JavaTypeParameter) {
+ return rawTypeForTypeParameter((JavaTypeParameter) classifier);
+ }
+ }
+
+ return original;
+ }
+
+ @Nullable
+ private JavaType substituteInternal(@NotNull JavaType type) {
+ if (type instanceof JavaClassifierType) {
+ JavaClassifierType classifierType = (JavaClassifierType) type;
+ JavaClassifier classifier = classifierType.getClassifier();
+
+ if (classifier instanceof JavaTypeParameter) {
+ return substitute((JavaTypeParameter) classifier);
+ }
+ else if (classifier instanceof JavaClass) {
+ JavaClass javaClass = (JavaClass) classifier;
+ Map substMap = new HashMap();
+ processClass(javaClass, classifierType.getSubstitutor(), substMap);
+
+ return javaClass.createImmediateType(new JavaTypeSubstitutorImpl(substMap));
+ }
+
+ return type;
+ }
+ else if (type instanceof JavaPrimitiveType) {
+ return type;
+ }
+ else if (type instanceof JavaArrayType) {
+ JavaType componentType = ((JavaArrayType) type).getComponentType();
+ JavaType substitutedComponentType = substitute(componentType);
+ if (substitutedComponentType == componentType) return type;
+
+ return substitutedComponentType.createArrayType();
+ }
+ else if (type instanceof JavaWildcardType) {
+ return substituteWildcardType((JavaWildcardType) type);
+ }
+
+ return type;
+ }
+
+ private void processClass(@NotNull JavaClass javaClass, @NotNull JavaTypeSubstitutor substitutor, @NotNull Map substMap) {
+ List typeParameters = javaClass.getTypeParameters();
+ for (JavaTypeParameter typeParameter : typeParameters) {
+ JavaType substitutedParam = substitutor.substitute(typeParameter);
+ if (substitutedParam == null) {
+ substMap.put(typeParameter, null);
+ }
+ else {
+ substMap.put(typeParameter, substituteInternal(substitutedParam));
+ }
+ }
+
+ if (javaClass.isStatic()) {
+ return;
+ }
+
+ JavaClass outerClass = javaClass.getOuterClass();
+ if (outerClass != null) {
+ processClass(outerClass, substitutor, substMap);
+ }
+ }
+
+ @Nullable
+ private JavaType substituteWildcardType(@NotNull JavaWildcardType wildcardType) {
+ JavaType bound = wildcardType.getBound();
+ if (bound == null) {
+ return wildcardType;
+ }
+
+ JavaType newBound = substituteInternal(bound);
+ if (newBound == null) {
+ // This can be in case of substitution wildcard to raw type
+ return null;
+ }
+
+ return rebound(wildcardType, newBound);
+ }
+
+ @NotNull
+ private static JavaWildcardType rebound(@NotNull JavaWildcardType type, @NotNull JavaType newBound) {
+ if (type.getTypeProvider().createJavaLangObjectType().equals(newBound)) {
+ return type.getTypeProvider().createUnboundedWildcard();
+ }
+
+ if (type.isExtends()) {
+ return type.getTypeProvider().createUpperBoundWildcard(newBound);
+ }
+ else {
+ return type.getTypeProvider().createLowerBoundWildcard(newBound);
+ }
+ }
+
+ @NotNull
+ private JavaType rawTypeForTypeParameter(@NotNull JavaTypeParameter typeParameter) {
+ Collection bounds = typeParameter.getUpperBounds();
+ if (!bounds.isEmpty()) {
+ return substitute(bounds.iterator().next());
+ }
+
+ return typeParameter.getTypeProvider().createJavaLangObjectType();
}
@Override
@Nullable
public JavaType substitute(@NotNull JavaTypeParameter typeParameter) {
- PsiType psiType = psiSubstitutor.substitute(((JavaTypeParameterImpl) typeParameter).getPsi());
- return psiType == null ? null : JavaTypeImpl.create(psiType);
+ if (substitutionMap.containsKey(typeParameter)) {
+ return substitutionMap.get(typeParameter);
+ }
+
+ return typeParameter.getType();
}
@Override
@NotNull
public Map getSubstitutionMap() {
- if (substitutionMap == null) {
- Map psiMap = psiSubstitutor.getSubstitutionMap();
- substitutionMap = new HashMap();
- for (Map.Entry entry : psiMap.entrySet()) {
- PsiType value = entry.getValue();
- substitutionMap.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value));
- }
- }
-
return substitutionMap;
}
@Override
public int hashCode() {
- return psiSubstitutor.hashCode();
+ return substitutionMap.hashCode();
}
@Override
public boolean equals(Object obj) {
- return obj instanceof JavaTypeSubstitutorImpl && psiSubstitutor.equals(((JavaTypeSubstitutorImpl) obj).psiSubstitutor);
+ return obj instanceof JavaTypeSubstitutorImpl && substitutionMap.equals(((JavaTypeSubstitutorImpl) obj).substitutionMap);
}
@Override
public String toString() {
- return getClass().getSimpleName() + ": " + psiSubstitutor;
+ return getClass().getSimpleName() + ": " + substitutionMap;
}
-}
+}
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java
index 79db9004292..957f86ec3c7 100644
--- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java
+++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java
@@ -44,8 +44,8 @@ public class CheckerTestUtil {
public int compare(@NotNull Diagnostic o1, @NotNull Diagnostic o2) {
List ranges1 = o1.getTextRanges();
List ranges2 = o2.getTextRanges();
- if (ranges1.size() != ranges2.size()) return ranges1.size() - ranges2.size();
- for (int i = 0; i < ranges1.size(); i++) {
+ int minNumberOfRanges = ranges1.size() < ranges2.size() ? ranges1.size() : ranges2.size();
+ for (int i = 0; i < minNumberOfRanges; i++) {
TextRange range1 = ranges1.get(i);
TextRange range2 = ranges2.get(i);
int startOffset1 = range1.getStartOffset();
@@ -61,7 +61,7 @@ public class CheckerTestUtil {
return endOffset2 - endOffset1;
}
}
- return 0;
+ return ranges1.size() - ranges2.size();
}
};
private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()");
@@ -439,41 +439,39 @@ public class CheckerTestUtil {
}
}
- private static List getSortedDiagnosticDescriptors(Collection diagnostics) {
- List list = Lists.newArrayList(diagnostics);
- Collections.sort(list, DIAGNOSTIC_COMPARATOR);
-
- List diagnosticDescriptors = Lists.newArrayList();
- DiagnosticDescriptor currentDiagnosticDescriptor = null;
- for (Diagnostic diagnostic : list) {
- List textRanges = diagnostic.getTextRanges();
+ @NotNull
+ private static List getSortedDiagnosticDescriptors(@NotNull Collection diagnostics) {
+ LinkedListMultimap diagnosticsGroupedByRanges = LinkedListMultimap.create();
+ for (Diagnostic diagnostic : diagnostics) {
if (!diagnostic.isValid()) continue;
-
- TextRange textRange = textRanges.get(0);
- if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) {
- currentDiagnosticDescriptor.diagnostics.add(diagnostic);
- }
- else {
- currentDiagnosticDescriptor = new DiagnosticDescriptor(textRange.getStartOffset(), textRange.getEndOffset(), diagnostic);
- diagnosticDescriptors.add(currentDiagnosticDescriptor);
+ for (TextRange textRange : diagnostic.getTextRanges()) {
+ diagnosticsGroupedByRanges.put(textRange, diagnostic);
}
}
+ List diagnosticDescriptors = Lists.newArrayList();
+ for (TextRange range : diagnosticsGroupedByRanges.keySet()) {
+ diagnosticDescriptors.add(
+ new DiagnosticDescriptor(range.getStartOffset(), range.getEndOffset(), diagnosticsGroupedByRanges.get(range)));
+ }
+ Collections.sort(diagnosticDescriptors, new Comparator() {
+ @Override
+ public int compare(DiagnosticDescriptor d1, DiagnosticDescriptor d2) {
+ // Start early -- go first; start at the same offset, the one who end later is the outer, i.e. goes first
+ return (d1.start != d2.start) ? d1.start - d2.start : d2.end - d1.end;
+ }
+ });
return diagnosticDescriptors;
}
private static class DiagnosticDescriptor {
private final int start;
private final int end;
- private final List diagnostics = Lists.newArrayList();
+ private final List diagnostics;
- DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) {
+ DiagnosticDescriptor(int start, int end, List diagnostics) {
this.start = start;
this.end = end;
- this.diagnostics.add(diagnostic);
- }
-
- public boolean equalRange(TextRange textRange) {
- return start == textRange.getStartOffset() && end == textRange.getEndOffset();
+ this.diagnostics = diagnostics;
}
public Multiset getDiagnosticTypeStrings() {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
index 7379e15f149..5abdb9058f1 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
@@ -16,7 +16,6 @@
package org.jetbrains.jet.lang.cfg;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
@@ -53,8 +52,6 @@ import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*;
-import static org.jetbrains.jet.lang.cfg.JetControlFlowProcessor.CFPContext.IN_CONDITION;
-import static org.jetbrains.jet.lang.cfg.JetControlFlowProcessor.CFPContext.NOT_IN_CONDITION;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lexer.JetTokens.*;
@@ -83,14 +80,14 @@ public class JetControlFlowProcessor {
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
List valueParameters = declarationWithBody.getValueParameters();
for (JetParameter valueParameter : valueParameters) {
- cfpVisitor.generateInstructions(valueParameter, NOT_IN_CONDITION);
+ cfpVisitor.generateInstructions(valueParameter);
}
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (bodyExpression != null) {
- cfpVisitor.generateInstructions(bodyExpression, NOT_IN_CONDITION);
+ cfpVisitor.generateInstructions(bodyExpression);
}
} else {
- cfpVisitor.generateInstructions(subroutine, NOT_IN_CONDITION);
+ cfpVisitor.generateInstructions(subroutine);
}
return builder.exitSubroutine(subroutine);
}
@@ -106,48 +103,33 @@ public class JetControlFlowProcessor {
builder.bindLabel(afterDeclaration);
}
- /*package*/ enum CFPContext {
- IN_CONDITION(true),
- NOT_IN_CONDITION(false);
-
- private final boolean inCondition;
-
- private CFPContext(boolean inCondition) {
- this.inCondition = inCondition;
- }
-
- public boolean inCondition() {
- return inCondition;
- }
- }
-
- private class CFPVisitor extends JetVisitorVoidWithParameter {
+ private class CFPVisitor extends JetVisitorVoid {
private final JetControlFlowBuilder builder;
- private final JetVisitorVoidWithParameter conditionVisitor = new JetVisitorVoidWithParameter() {
+ private final JetVisitorVoid conditionVisitor = new JetVisitorVoid() {
@Override
- public void visitWhenConditionInRangeVoid(@NotNull JetWhenConditionInRange condition, CFPContext context) {
- generateInstructions(condition.getRangeExpression(), context);
- generateInstructions(condition.getOperationReference(), context);
+ public void visitWhenConditionInRange(@NotNull JetWhenConditionInRange condition) {
+ generateInstructions(condition.getRangeExpression());
+ generateInstructions(condition.getOperationReference());
// TODO : read the call to contains()...
createNonSyntheticValue(condition, condition.getRangeExpression(), condition.getOperationReference());
}
@Override
- public void visitWhenConditionIsPatternVoid(@NotNull JetWhenConditionIsPattern condition, CFPContext context) {
+ public void visitWhenConditionIsPattern(@NotNull JetWhenConditionIsPattern condition) {
// TODO: types in CF?
}
@Override
- public void visitWhenConditionWithExpressionVoid(@NotNull JetWhenConditionWithExpression condition, CFPContext context) {
- generateInstructions(condition.getExpression(), context);
+ public void visitWhenConditionWithExpression(@NotNull JetWhenConditionWithExpression condition) {
+ generateInstructions(condition.getExpression());
copyValue(condition.getExpression(), condition);
}
@Override
- public void visitJetElementVoid(@NotNull JetElement element, CFPContext context) {
+ public void visitJetElement(@NotNull JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
}
};
@@ -160,9 +142,9 @@ public class JetControlFlowProcessor {
builder.mark(element);
}
- public void generateInstructions(@Nullable JetElement element, CFPContext context) {
+ public void generateInstructions(@Nullable JetElement element) {
if (element == null) return;
- element.accept(this, context);
+ element.accept(this);
checkNothingType(element);
}
@@ -266,26 +248,26 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitParenthesizedExpressionVoid(@NotNull JetParenthesizedExpression expression, CFPContext context) {
+ public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
mark(expression);
JetExpression innerExpression = expression.getExpression();
if (innerExpression != null) {
- generateInstructions(innerExpression, context);
+ generateInstructions(innerExpression);
copyValue(innerExpression, expression);
}
}
@Override
- public void visitAnnotatedExpressionVoid(@NotNull JetAnnotatedExpression expression, CFPContext context) {
+ public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) {
JetExpression baseExpression = expression.getBaseExpression();
if (baseExpression != null) {
- generateInstructions(baseExpression, context);
+ generateInstructions(baseExpression);
copyValue(baseExpression, expression);
}
}
@Override
- public void visitThisExpressionVoid(@NotNull JetThisExpression expression, CFPContext context) {
+ public void visitThisExpression(@NotNull JetThisExpression expression) {
ResolvedCall> resolvedCall = getResolvedCall(expression);
if (resolvedCall == null) {
createNonSyntheticValue(expression);
@@ -294,74 +276,50 @@ public class JetControlFlowProcessor {
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
- builder.readVariable(expression, expression, resolvedCall, getReceiverValues(expression, resolvedCall, true));
+ builder.readVariable(expression, expression, resolvedCall, getReceiverValues(resolvedCall, true));
}
copyValue(expression, expression.getInstanceReference());
}
@Override
- public void visitConstantExpressionVoid(@NotNull JetConstantExpression expression, CFPContext context) {
+ public void visitConstantExpression(@NotNull JetConstantExpression expression) {
CompileTimeConstant> constant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
builder.loadConstant(expression, constant);
}
@Override
- public void visitSimpleNameExpressionVoid(@NotNull JetSimpleNameExpression expression, CFPContext context) {
+ public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
ResolvedCall> resolvedCall = getResolvedCall(expression);
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
- generateCall(expression, expression, variableAsFunctionResolvedCall.getVariableCall());
+ generateCall(expression, variableAsFunctionResolvedCall.getVariableCall());
}
- else if (!generateCall(expression, expression) && !(expression.getParent() instanceof JetCallExpression)) {
+ else if (!generateCall(expression, true) && !(expression.getParent() instanceof JetCallExpression)) {
createNonSyntheticValue(expression, generateAndGetReceiverIfAny(expression));
}
}
@Override
- public void visitLabeledExpressionVoid(@NotNull JetLabeledExpression expression, CFPContext context) {
+ public void visitLabeledExpression(@NotNull JetLabeledExpression expression) {
mark(expression);
JetExpression baseExpression = expression.getBaseExpression();
if (baseExpression != null) {
- generateInstructions(baseExpression, context);
+ generateInstructions(baseExpression);
copyValue(baseExpression, expression);
}
}
@SuppressWarnings("SuspiciousMethodCalls")
@Override
- public void visitBinaryExpressionVoid(@NotNull JetBinaryExpression expression, CFPContext context) {
+ public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
JetSimpleNameExpression operationReference = expression.getOperationReference();
IElementType operationType = operationReference.getReferencedNameElementType();
- if (!ImmutableSet.of(ANDAND, OROR, EQ, ELVIS).contains(operationType)) {
- mark(expression);
- }
JetExpression left = expression.getLeft();
JetExpression right = expression.getRight();
- if (operationType == ANDAND) {
- generateInstructions(left, IN_CONDITION);
- Label resultLabel = builder.createUnboundLabel();
- builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left));
- if (right != null) {
- generateInstructions(right, IN_CONDITION);
- }
- builder.bindLabel(resultLabel);
- if (!context.inCondition()) {
- predefinedOperation(expression, AND);
- }
- }
- else if (operationType == OROR) {
- generateInstructions(left, IN_CONDITION);
- Label resultLabel = builder.createUnboundLabel();
- builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left));
- if (right != null) {
- generateInstructions(right, IN_CONDITION);
- }
- builder.bindLabel(resultLabel);
- if (!context.inCondition()) {
- predefinedOperation(expression, OR);
- }
+ if (operationType == ANDAND || operationType == OROR) {
+ generateBooleanOperation(expression);
}
else if (operationType == EQ) {
visitAssignment(left, getDeferredValue(right), expression);
@@ -369,42 +327,59 @@ public class JetControlFlowProcessor {
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
ResolvedCall> resolvedCall = getResolvedCall(operationReference);
if (resolvedCall != null) {
- CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
+ PseudoValue rhsValue = generateCall(operationReference, resolvedCall).getOutputValue();
Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
- if (descriptor.getName().equals(assignMethodName)) {
- generateCall(expression, operationReference, resolvedCall);
- }
- else {
+ if (!resolvedCall.getResultingDescriptor().getName().equals(assignMethodName)) {
/* At this point assignment of the form a += b actually means a = a + b
* So we first generate call of "+" operation and then use its output pseudo-value
* as a right-hand side when generating assignment call
*/
- Function0 rhsDeferredValue =
- getValueAsFunction(generateCall(null, operationReference, resolvedCall).getOutputValue());
- visitAssignment(left, rhsDeferredValue, expression);
+ visitAssignment(left, getValueAsFunction(rhsValue), expression);
}
}
else {
- generateBothArguments(expression);
+ generateBothArgumentsAndMark(expression);
}
}
else if (operationType == ELVIS) {
- generateInstructions(left, NOT_IN_CONDITION);
+ generateInstructions(left);
+ mark(expression);
Label afterElvis = builder.createUnboundLabel();
builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left));
if (right != null) {
- generateInstructions(right, NOT_IN_CONDITION);
+ generateInstructions(right);
}
builder.bindLabel(afterElvis);
mergeValues(Arrays.asList(left, right), expression);
}
else {
- if (!generateCall(expression, operationReference)) {
- generateBothArguments(expression);
+ if (!generateCall(operationReference, true)) {
+ generateBothArgumentsAndMark(expression);
}
}
}
+ private void generateBooleanOperation(JetBinaryExpression expression) {
+ IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
+ JetExpression left = expression.getLeft();
+ JetExpression right = expression.getRight();
+
+ Label resultLabel = builder.createUnboundLabel();
+ generateInstructions(left);
+ if (operationType == ANDAND) {
+ builder.jumpOnFalse(resultLabel, expression, builder.getBoundValue(left));
+ }
+ else {
+ builder.jumpOnTrue(resultLabel, expression, builder.getBoundValue(left));
+ }
+ if (right != null) {
+ generateInstructions(right);
+ }
+ builder.bindLabel(resultLabel);
+ JetControlFlowBuilder.PredefinedOperation operation = operationType == ANDAND ? AND : OR;
+ builder.predefinedOperation(expression, operation, elementsToValues(Arrays.asList(left, right)));
+ }
+
private Function0 getValueAsFunction(final PseudoValue value) {
return new Function0() {
@Override
@@ -418,29 +393,23 @@ public class JetControlFlowProcessor {
return new Function0() {
@Override
public PseudoValue invoke() {
- generateInstructions(expression, NOT_IN_CONDITION);
+ generateInstructions(expression);
return builder.getBoundValue(expression);
}
};
}
- private void predefinedOperation(JetBinaryExpression expression, JetControlFlowBuilder.PredefinedOperation operation) {
- builder.predefinedOperation(
- expression, operation, elementsToValues(Arrays.asList(expression.getLeft(), expression.getRight()))
- );
- }
-
- private void generateBothArguments(JetBinaryExpression expression) {
+ private void generateBothArgumentsAndMark(JetBinaryExpression expression) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left != null) {
- generateInstructions(left, NOT_IN_CONDITION);
+ generateInstructions(left);
}
JetExpression right = expression.getRight();
if (right != null) {
- generateInstructions(right, NOT_IN_CONDITION);
+ generateInstructions(right);
}
-
createNonSyntheticValue(expression, left, right);
+ mark(expression);
}
private void visitAssignment(JetExpression lhs, @NotNull Function0 rhsDeferredValue, JetExpression parentExpression) {
@@ -461,7 +430,7 @@ public class JetControlFlowProcessor {
if (left instanceof JetSimpleNameExpression || left instanceof JetQualifiedExpression) {
accessTarget = getResolvedCallAccessTarget(PsiUtilPackage.getQualifiedElementSelector(left));
if (accessTarget instanceof AccessTarget.Call) {
- receiverValues = getReceiverValues(lhs, ((AccessTarget.Call) accessTarget).getResolvedCall(), true);
+ receiverValues = getReceiverValues(((AccessTarget.Call) accessTarget).getResolvedCall(), true);
}
}
else if (left instanceof JetProperty) {
@@ -497,9 +466,9 @@ public class JetControlFlowProcessor {
mark(lhs);
}
- generateInstructions(lhs.getArrayExpression(), NOT_IN_CONDITION);
+ generateInstructions(lhs.getArrayExpression());
- Map receiverValues = getReceiverValues(lhs, setResolvedCall, false);
+ Map receiverValues = getReceiverValues(setResolvedCall, false);
SmartFMap argumentValues =
getArraySetterArguments(rhsDeferredValue, setResolvedCall);
@@ -566,7 +535,7 @@ public class JetControlFlowProcessor {
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression, @Nullable ResolvedCall> resolvedCall) {
mark(arrayAccessExpression);
- if (!checkAndGenerateCall(arrayAccessExpression, arrayAccessExpression, resolvedCall)) {
+ if (!checkAndGenerateCall(arrayAccessExpression, resolvedCall, true)) {
generateArrayAccessWithoutCall(arrayAccessExpression);
}
}
@@ -580,10 +549,10 @@ public class JetControlFlowProcessor {
JetExpression arrayExpression = arrayAccessExpression.getArrayExpression();
inputExpressions.add(arrayExpression);
- generateInstructions(arrayExpression, NOT_IN_CONDITION);
+ generateInstructions(arrayExpression);
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
- generateInstructions(index, NOT_IN_CONDITION);
+ generateInstructions(index);
inputExpressions.add(index);
}
@@ -591,14 +560,13 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitUnaryExpressionVoid(@NotNull JetUnaryExpression expression, CFPContext context) {
- mark(expression);
+ public void visitUnaryExpression(@NotNull JetUnaryExpression expression) {
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
JetExpression baseExpression = expression.getBaseExpression();
if (baseExpression == null) return;
if (JetTokens.EXCLEXCL == operationType) {
- generateInstructions(baseExpression, NOT_IN_CONDITION);
+ generateInstructions(baseExpression);
builder.predefinedOperation(expression, NOT_NULL_ASSERTION, elementsToValues(Collections.singletonList(baseExpression)));
return;
}
@@ -608,15 +576,18 @@ public class JetControlFlowProcessor {
PseudoValue rhsValue;
if (resolvedCall != null) {
- rhsValue = generateCall(incrementOrDecrement ? null : expression, operationSign, resolvedCall).getOutputValue();
+ rhsValue = generateCall(operationSign, resolvedCall).getOutputValue();
}
else {
- generateInstructions(baseExpression, NOT_IN_CONDITION);
+ generateInstructions(baseExpression);
rhsValue = createNonSyntheticValue(expression, baseExpression);
}
if (incrementOrDecrement) {
visitAssignment(baseExpression, getValueAsFunction(rhsValue), expression);
+ if (expression instanceof JetPostfixExpression) {
+ copyValue(baseExpression, expression);
+ }
}
}
@@ -625,19 +596,19 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitIfExpressionVoid(@NotNull JetIfExpression expression, CFPContext context) {
+ public void visitIfExpression(@NotNull JetIfExpression expression) {
mark(expression);
List branches = new ArrayList(2);
JetExpression condition = expression.getCondition();
if (condition != null) {
- generateInstructions(condition, IN_CONDITION);
+ generateInstructions(condition);
}
Label elseLabel = builder.createUnboundLabel();
builder.jumpOnFalse(elseLabel, expression, builder.getBoundValue(condition));
JetExpression thenBranch = expression.getThen();
if (thenBranch != null) {
branches.add(thenBranch);
- generateInstructions(thenBranch, context);
+ generateInstructions(thenBranch);
}
else {
builder.loadUnit(expression);
@@ -648,7 +619,7 @@ public class JetControlFlowProcessor {
JetExpression elseBranch = expression.getElse();
if (elseBranch != null) {
branches.add(elseBranch);
- generateInstructions(elseBranch, context);
+ generateInstructions(elseBranch);
}
else {
builder.loadUnit(expression);
@@ -659,13 +630,11 @@ public class JetControlFlowProcessor {
private class FinallyBlockGenerator {
private final JetFinallySection finallyBlock;
- private final CFPContext context;
private Label startFinally = null;
private Label finishFinally = null;
- private FinallyBlockGenerator(JetFinallySection block, CFPContext context) {
+ private FinallyBlockGenerator(JetFinallySection block) {
finallyBlock = block;
- this.context = context;
}
public void generate() {
@@ -678,18 +647,18 @@ public class JetControlFlowProcessor {
}
startFinally = builder.createUnboundLabel("start finally");
builder.bindLabel(startFinally);
- generateInstructions(finalExpression, context);
+ generateInstructions(finalExpression);
finishFinally = builder.createUnboundLabel("finish finally");
builder.bindLabel(finishFinally);
}
}
@Override
- public void visitTryExpressionVoid(@NotNull JetTryExpression expression, CFPContext context) {
+ public void visitTryExpression(@NotNull JetTryExpression expression) {
mark(expression);
JetFinallySection finallyBlock = expression.getFinallyBlock();
- final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock, context);
+ final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
boolean hasFinally = finallyBlock != null;
if (hasFinally) {
builder.enterTryFinally(new GenerationTrigger() {
@@ -706,7 +675,7 @@ public class JetControlFlowProcessor {
});
}
- Label onExceptionToFinallyBlock = generateTryAndCatches(expression, context);
+ Label onExceptionToFinallyBlock = generateTryAndCatches(expression);
if (hasFinally) {
assert onExceptionToFinallyBlock != null : "No finally lable generated: " + expression.getText();
@@ -733,7 +702,7 @@ public class JetControlFlowProcessor {
// Returns label for 'finally' block
@Nullable
- private Label generateTryAndCatches(@NotNull JetTryExpression expression, CFPContext context) {
+ private Label generateTryAndCatches(@NotNull JetTryExpression expression) {
List catchClauses = expression.getCatchClauses();
boolean hasCatches = !catchClauses.isEmpty();
@@ -750,7 +719,7 @@ public class JetControlFlowProcessor {
}
JetBlockExpression tryBlock = expression.getTryBlock();
- generateInstructions(tryBlock, context);
+ generateInstructions(tryBlock);
if (hasCatches) {
Label afterCatches = builder.createUnboundLabel("afterCatches");
@@ -781,7 +750,7 @@ public class JetControlFlowProcessor {
}
JetExpression catchBody = catchClause.getCatchBody();
if (catchBody != null) {
- generateInstructions(catchBody, NOT_IN_CONDITION);
+ generateInstructions(catchBody);
}
builder.jump(afterCatches, expression);
builder.exitLexicalScope(catchClause);
@@ -794,15 +763,15 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitWhileExpressionVoid(@NotNull JetWhileExpression expression, CFPContext context) {
- mark(expression);
+ public void visitWhileExpression(@NotNull JetWhileExpression expression) {
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition();
if (condition != null) {
- generateInstructions(condition, IN_CONDITION);
+ generateInstructions(condition);
}
+ mark(expression);
boolean conditionIsTrueConstant = CompileTimeConstantUtils.canBeReducedToBooleanConstant(condition, trace, true);
if (!conditionIsTrueConstant) {
builder.jumpOnFalse(loopInfo.getExitPoint(), expression, builder.getBoundValue(condition));
@@ -811,7 +780,7 @@ public class JetControlFlowProcessor {
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody();
if (body != null) {
- generateInstructions(body, NOT_IN_CONDITION);
+ generateInstructions(body);
}
builder.jump(loopInfo.getEntryPoint(), expression);
builder.exitLoop(expression);
@@ -819,7 +788,7 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitDoWhileExpressionVoid(@NotNull JetDoWhileExpression expression, CFPContext context) {
+ public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
builder.enterLexicalScope(expression);
mark(expression);
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
@@ -827,12 +796,12 @@ public class JetControlFlowProcessor {
builder.bindLabel(loopInfo.getBodyEntryPoint());
JetExpression body = expression.getBody();
if (body != null) {
- generateInstructions(body, NOT_IN_CONDITION);
+ generateInstructions(body);
}
builder.bindLabel(loopInfo.getConditionEntryPoint());
JetExpression condition = expression.getCondition();
if (condition != null) {
- generateInstructions(condition, IN_CONDITION);
+ generateInstructions(condition);
}
builder.jumpOnTrue(loopInfo.getEntryPoint(), expression, builder.getBoundValue(condition));
builder.exitLoop(expression);
@@ -841,13 +810,12 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitForExpressionVoid(@NotNull JetForExpression expression, CFPContext context) {
+ public void visitForExpression(@NotNull JetForExpression expression) {
builder.enterLexicalScope(expression);
- mark(expression);
JetExpression loopRange = expression.getLoopRange();
if (loopRange != null) {
- generateInstructions(loopRange, NOT_IN_CONDITION);
+ generateInstructions(loopRange);
}
declareLoopParameter(expression);
@@ -863,9 +831,10 @@ public class JetControlFlowProcessor {
builder.bindLabel(loopInfo.getBodyEntryPoint());
writeLoopParameterAssignment(expression);
+ mark(expression);
JetExpression body = expression.getBody();
if (body != null) {
- generateInstructions(body, NOT_IN_CONDITION);
+ generateInstructions(body);
}
builder.nondeterministicJump(loopInfo.getEntryPoint(), expression, null);
@@ -891,15 +860,21 @@ public class JetControlFlowProcessor {
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
JetExpression loopRange = expression.getLoopRange();
- JetType loopRangeType = trace.get(BindingContext.EXPRESSION_TYPE, loopRange);
- TypePredicate loopRangeTypeSet = loopRangeType != null ? new SingleType(loopRangeType) : AllTypes.instance$;
- PseudoValue loopRangeValue = builder.getBoundValue(loopRange);
+ TypePredicate loopRangeTypePredicate = AllTypes.instance$;
+ ResolvedCall> iteratorResolvedCall = trace.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange);
+ if (iteratorResolvedCall != null) {
+ ReceiverValue iteratorReceiver = getExplicitReceiverValue(iteratorResolvedCall);
+ if (iteratorReceiver.exists()) {
+ loopRangeTypePredicate = PseudocodePackage.getReceiverTypePredicate(iteratorResolvedCall, iteratorReceiver);
+ }
+ }
+ PseudoValue loopRangeValue = builder.getBoundValue(loopRange);
PseudoValue value = builder.magic(
loopRange != null ? loopRange : expression,
null,
Collections.singletonList(loopRangeValue),
- Collections.singletonMap(loopRangeValue, loopRangeTypeSet),
+ Collections.singletonMap(loopRangeValue, loopRangeTypePredicate),
true
).getOutputValue();
@@ -913,8 +888,19 @@ public class JetControlFlowProcessor {
}
}
+ private ReceiverValue getExplicitReceiverValue(ResolvedCall> resolvedCall) {
+ switch(resolvedCall.getExplicitReceiverKind()) {
+ case THIS_OBJECT:
+ return resolvedCall.getThisObject();
+ case RECEIVER_ARGUMENT:
+ return resolvedCall.getReceiverArgument();
+ default:
+ return ReceiverValue.NO_RECEIVER;
+ }
+ }
+
@Override
- public void visitBreakExpressionVoid(@NotNull JetBreakExpression expression, CFPContext context) {
+ public void visitBreakExpression(@NotNull JetBreakExpression expression) {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
@@ -923,7 +909,7 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitContinueExpressionVoid(@NotNull JetContinueExpression expression, CFPContext context) {
+ public void visitContinueExpression(@NotNull JetContinueExpression expression) {
JetElement loop = getCorrespondingLoop(expression);
if (loop != null) {
checkJumpDoesNotCrossFunctionBoundary(expression, loop);
@@ -966,10 +952,10 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitReturnExpressionVoid(@NotNull JetReturnExpression expression, CFPContext context) {
+ public void visitReturnExpression(@NotNull JetReturnExpression expression) {
JetExpression returnedExpression = expression.getReturnedExpression();
if (returnedExpression != null) {
- generateInstructions(returnedExpression, NOT_IN_CONDITION);
+ generateInstructions(returnedExpression);
}
JetSimpleNameExpression labelElement = expression.getTargetLabel();
JetElement subroutine;
@@ -1001,17 +987,30 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitParameterVoid(@NotNull JetParameter parameter, CFPContext context) {
+ public void visitParameter(@NotNull JetParameter parameter) {
builder.declareParameter(parameter);
JetExpression defaultValue = parameter.getDefaultValue();
if (defaultValue != null) {
- generateInstructions(defaultValue, context);
+ Label skipDefaultValue = builder.createUnboundLabel("after default value for parameter " + parameter.getName());
+ builder.nondeterministicJump(skipDefaultValue, defaultValue, null);
+ generateInstructions(defaultValue);
+ builder.bindLabel(skipDefaultValue);
}
- generateInitializer(parameter, createSyntheticValue(parameter));
+ generateInitializer(parameter, computePseudoValueForParameter(parameter));
+ }
+
+ @NotNull
+ private PseudoValue computePseudoValueForParameter(@NotNull JetParameter parameter) {
+ PseudoValue syntheticValue = createSyntheticValue(parameter);
+ PseudoValue defaultValue = builder.getBoundValue(parameter.getDefaultValue());
+ if (defaultValue == null) {
+ return syntheticValue;
+ }
+ return builder.merge(parameter, Lists.newArrayList(defaultValue, syntheticValue)).getOutputValue();
}
@Override
- public void visitBlockExpressionVoid(@NotNull JetBlockExpression expression, CFPContext context) {
+ public void visitBlockExpression(@NotNull JetBlockExpression expression) {
boolean declareLexicalScope = !isBlockInDoWhile(expression);
if (declareLexicalScope) {
builder.enterLexicalScope(expression);
@@ -1019,7 +1018,7 @@ public class JetControlFlowProcessor {
mark(expression);
List statements = expression.getStatements();
for (JetElement statement : statements) {
- generateInstructions(statement, NOT_IN_CONDITION);
+ generateInstructions(statement);
}
if (statements.isEmpty()) {
builder.loadUnit(expression);
@@ -1039,12 +1038,12 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitNamedFunctionVoid(@NotNull JetNamedFunction function, CFPContext context) {
+ public void visitNamedFunction(@NotNull JetNamedFunction function) {
processLocalDeclaration(function);
}
@Override
- public void visitFunctionLiteralExpressionVoid(@NotNull JetFunctionLiteralExpression expression, CFPContext context) {
+ public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
mark(expression);
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
processLocalDeclaration(functionLiteral);
@@ -1052,44 +1051,43 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitQualifiedExpressionVoid(@NotNull JetQualifiedExpression expression, CFPContext context) {
+ public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
mark(expression);
JetExpression selectorExpression = expression.getSelectorExpression();
JetExpression receiverExpression = expression.getReceiverExpression();
// todo: replace with selectorExpresion != null after parser is fixed
if (selectorExpression instanceof JetCallExpression || selectorExpression instanceof JetSimpleNameExpression) {
- generateInstructions(selectorExpression, NOT_IN_CONDITION);
+ generateInstructions(selectorExpression);
copyValue(selectorExpression, expression);
}
else {
- generateInstructions(receiverExpression, NOT_IN_CONDITION);
+ generateInstructions(receiverExpression);
createNonSyntheticValue(expression, receiverExpression);
}
}
@Override
- public void visitCallExpressionVoid(@NotNull JetCallExpression expression, CFPContext context) {
- mark(expression);
-
+ public void visitCallExpression(@NotNull JetCallExpression expression) {
JetExpression calleeExpression = expression.getCalleeExpression();
- if (!generateCall(expression, calleeExpression)) {
+ if (!generateCall(calleeExpression, true)) {
List inputExpressions = new ArrayList();
for (ValueArgument argument : expression.getValueArguments()) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
- generateInstructions(argumentExpression, NOT_IN_CONDITION);
+ generateInstructions(argumentExpression);
inputExpressions.add(argumentExpression);
}
}
for (JetExpression functionLiteral : expression.getFunctionLiteralArguments()) {
- generateInstructions(functionLiteral, NOT_IN_CONDITION);
+ generateInstructions(functionLiteral);
inputExpressions.add(functionLiteral);
}
- generateInstructions(calleeExpression, NOT_IN_CONDITION);
+ generateInstructions(calleeExpression);
inputExpressions.add(calleeExpression);
inputExpressions.add(generateAndGetReceiverIfAny(expression));
+ mark(expression);
createNonSyntheticValue(expression, inputExpressions);
}
}
@@ -1103,13 +1101,13 @@ public class JetControlFlowProcessor {
if (qualifiedExpression.getSelectorExpression() != expression) return null;
JetExpression receiverExpression = qualifiedExpression.getReceiverExpression();
- generateInstructions(receiverExpression, NOT_IN_CONDITION);
+ generateInstructions(receiverExpression);
return receiverExpression;
}
@Override
- public void visitPropertyVoid(@NotNull JetProperty property, CFPContext context) {
+ public void visitProperty(@NotNull JetProperty property) {
builder.declareVariable(property);
JetExpression initializer = property.getInitializer();
if (initializer != null) {
@@ -1117,23 +1115,23 @@ public class JetControlFlowProcessor {
}
JetExpression delegate = property.getDelegateExpression();
if (delegate != null) {
- generateInstructions(delegate, NOT_IN_CONDITION);
+ generateInstructions(delegate);
}
if (JetPsiUtil.isLocal(property)) {
for (JetPropertyAccessor accessor : property.getAccessors()) {
- generateInstructions(accessor, NOT_IN_CONDITION);
+ generateInstructions(accessor);
}
}
}
@Override
- public void visitMultiDeclarationVoid(@NotNull JetMultiDeclaration declaration, CFPContext context) {
+ public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) {
visitMultiDeclaration(declaration, true);
}
private void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration, boolean generateWriteForEntries) {
JetExpression initializer = declaration.getInitializer();
- generateInstructions(initializer, NOT_IN_CONDITION);
+ generateInstructions(initializer);
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
builder.declareVariable(entry);
@@ -1145,7 +1143,7 @@ public class JetControlFlowProcessor {
entry,
entry,
resolvedCall,
- getReceiverValues(initializer, resolvedCall, false),
+ getReceiverValues(resolvedCall, false),
Collections.emptyMap()
).getOutputValue();
}
@@ -1160,34 +1158,34 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitPropertyAccessorVoid(@NotNull JetPropertyAccessor accessor, CFPContext context) {
+ public void visitPropertyAccessor(@NotNull JetPropertyAccessor accessor) {
processLocalDeclaration(accessor);
}
@Override
- public void visitBinaryWithTypeRHSExpressionVoid(@NotNull JetBinaryExpressionWithTypeRHS expression, CFPContext context) {
+ public void visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression) {
mark(expression);
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
JetExpression left = expression.getLeft();
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
- generateInstructions(left, NOT_IN_CONDITION);
+ generateInstructions(left);
copyValue(left, expression);
}
else {
- visitJetElementVoid(expression, context);
+ visitJetElement(expression);
createNonSyntheticValue(expression, left);
}
}
@Override
- public void visitThrowExpressionVoid(@NotNull JetThrowExpression expression, CFPContext context) {
+ public void visitThrowExpression(@NotNull JetThrowExpression expression) {
mark(expression);
JetExpression thrownExpression = expression.getThrownExpression();
if (thrownExpression == null) return;
- generateInstructions(thrownExpression, NOT_IN_CONDITION);
+ generateInstructions(thrownExpression);
PseudoValue thrownValue = builder.getBoundValue(thrownExpression);
if (thrownValue == null) return;
@@ -1196,29 +1194,29 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitArrayAccessExpressionVoid(@NotNull JetArrayAccessExpression expression, CFPContext context) {
+ public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
mark(expression);
ResolvedCall getMethodResolvedCall = trace.get(BindingContext.INDEXED_LVALUE_GET, expression);
- if (!checkAndGenerateCall(expression, expression, getMethodResolvedCall)) {
+ if (!checkAndGenerateCall(expression, getMethodResolvedCall, true)) {
generateArrayAccess(expression, getMethodResolvedCall);
}
}
@Override
- public void visitIsExpressionVoid(@NotNull JetIsExpression expression, CFPContext context) {
+ public void visitIsExpression(@NotNull JetIsExpression expression) {
mark(expression);
JetExpression left = expression.getLeftHandSide();
- generateInstructions(left, context);
+ generateInstructions(left);
createNonSyntheticValue(expression, left);
}
@Override
- public void visitWhenExpressionVoid(@NotNull JetWhenExpression expression, CFPContext context) {
+ public void visitWhenExpression(@NotNull JetWhenExpression expression) {
mark(expression);
JetExpression subjectExpression = expression.getSubjectExpression();
if (subjectExpression != null) {
- generateInstructions(subjectExpression, context);
+ generateInstructions(subjectExpression);
}
boolean hasElse = false;
@@ -1244,7 +1242,7 @@ public class JetControlFlowProcessor {
JetWhenCondition[] conditions = whenEntry.getConditions();
for (int i = 0; i < conditions.length; i++) {
JetWhenCondition condition = conditions[i];
- condition.accept(conditionVisitor, context);
+ condition.accept(conditionVisitor);
if (i + 1 < conditions.length) {
PseudoValue conditionValue = createSyntheticValue(condition, subjectExpression, condition);
builder.nondeterministicJump(bodyLabel, expression, conditionValue);
@@ -1264,7 +1262,7 @@ public class JetControlFlowProcessor {
builder.bindLabel(bodyLabel);
JetExpression whenEntryExpression = whenEntry.getExpression();
if (whenEntryExpression != null) {
- generateInstructions(whenEntryExpression, context);
+ generateInstructions(whenEntryExpression);
branches.add(whenEntryExpression);
}
builder.jump(doneLabel, expression);
@@ -1282,28 +1280,28 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitObjectLiteralExpressionVoid(@NotNull JetObjectLiteralExpression expression, CFPContext context) {
+ public void visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression) {
mark(expression);
JetObjectDeclaration declaration = expression.getObjectDeclaration();
- generateInstructions(declaration, context);
+ generateInstructions(declaration);
builder.createAnonymousObject(expression);
}
@Override
- public void visitObjectDeclarationVoid(@NotNull JetObjectDeclaration objectDeclaration, CFPContext context) {
- visitClassOrObject(objectDeclaration, context);
+ public void visitObjectDeclaration(@NotNull JetObjectDeclaration objectDeclaration) {
+ visitClassOrObject(objectDeclaration);
}
@Override
- public void visitStringTemplateExpressionVoid(@NotNull JetStringTemplateExpression expression, CFPContext context) {
+ public void visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression) {
mark(expression);
List inputExpressions = new ArrayList();
for (JetStringTemplateEntry entry : expression.getEntries()) {
if (entry instanceof JetStringTemplateEntryWithExpression) {
JetExpression entryExpression = entry.getExpression();
- generateInstructions(entryExpression, NOT_IN_CONDITION);
+ generateInstructions(entryExpression);
inputExpressions.add(entryExpression);
}
}
@@ -1311,67 +1309,67 @@ public class JetControlFlowProcessor {
}
@Override
- public void visitTypeProjectionVoid(@NotNull JetTypeProjection typeProjection, CFPContext context) {
+ public void visitTypeProjection(@NotNull JetTypeProjection typeProjection) {
// TODO : Support Type Arguments. Class object may be initialized at this point");
}
@Override
- public void visitAnonymousInitializerVoid(@NotNull JetClassInitializer classInitializer, CFPContext context) {
- generateInstructions(classInitializer.getBody(), context);
+ public void visitAnonymousInitializer(@NotNull JetClassInitializer classInitializer) {
+ generateInstructions(classInitializer.getBody());
}
- private void visitClassOrObject(JetClassOrObject classOrObject, CFPContext context) {
+ private void visitClassOrObject(JetClassOrObject classOrObject) {
for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) {
- generateInstructions(specifier, context);
+ generateInstructions(specifier);
}
List declarations = classOrObject.getDeclarations();
if (classOrObject.isLocal()) {
for (JetDeclaration declaration : declarations) {
- generateInstructions(declaration, context);
+ generateInstructions(declaration);
}
return;
}
//For top-level and inner classes and objects functions are collected and checked separately.
for (JetDeclaration declaration : declarations) {
if (declaration instanceof JetProperty || declaration instanceof JetClassInitializer) {
- generateInstructions(declaration, context);
+ generateInstructions(declaration);
}
}
}
@Override
- public void visitClassVoid(@NotNull JetClass klass, CFPContext context) {
+ public void visitClass(@NotNull JetClass klass) {
List parameters = klass.getPrimaryConstructorParameters();
for (JetParameter parameter : parameters) {
- generateInstructions(parameter, context);
+ generateInstructions(parameter);
}
- visitClassOrObject(klass, context);
+ visitClassOrObject(klass);
}
@Override
- public void visitDelegationToSuperCallSpecifierVoid(@NotNull JetDelegatorToSuperCall call, CFPContext context) {
+ public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
List extends ValueArgument> valueArguments = call.getValueArguments();
for (ValueArgument valueArgument : valueArguments) {
- generateInstructions(valueArgument.getArgumentExpression(), context);
+ generateInstructions(valueArgument.getArgumentExpression());
}
}
@Override
- public void visitDelegationByExpressionSpecifierVoid(@NotNull JetDelegatorByExpressionSpecifier specifier, CFPContext context) {
- generateInstructions(specifier.getDelegateExpression(), context);
+ public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) {
+ generateInstructions(specifier.getDelegateExpression());
}
@Override
- public void visitJetFileVoid(@NotNull JetFile file, CFPContext context) {
+ public void visitJetFile(@NotNull JetFile file) {
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) {
- generateInstructions(declaration, context);
+ generateInstructions(declaration);
}
}
}
@Override
- public void visitJetElementVoid(@NotNull JetElement element, CFPContext context) {
+ public void visitJetElement(@NotNull JetElement element) {
builder.unsupported(element);
}
@@ -1380,29 +1378,32 @@ public class JetControlFlowProcessor {
return trace.get(BindingContext.RESOLVED_CALL, expression);
}
- private boolean generateCall(JetExpression callExpression, @Nullable JetExpression calleeExpression) {
+ private boolean generateCall(@Nullable JetExpression calleeExpression, boolean bindResultValue) {
if (calleeExpression == null) return false;
- return checkAndGenerateCall(callExpression, calleeExpression, getResolvedCall(calleeExpression));
+ return checkAndGenerateCall(calleeExpression, getResolvedCall(calleeExpression), bindResultValue);
}
- private boolean checkAndGenerateCall(JetExpression callExpression, JetExpression calleeExpression, @Nullable ResolvedCall> resolvedCall) {
+ private boolean checkAndGenerateCall(JetExpression calleeExpression, @Nullable ResolvedCall> resolvedCall, boolean bindResultValue) {
if (resolvedCall == null) {
builder.compilationError(calleeExpression, "No resolved call");
return false;
}
- generateCall(callExpression, calleeExpression, resolvedCall);
+ generateCall(calleeExpression, resolvedCall);
return true;
}
@NotNull
- private InstructionWithValue generateCall(JetExpression callExpression, JetExpression calleeExpression, ResolvedCall> resolvedCall) {
+ private InstructionWithValue generateCall(JetExpression calleeExpression, ResolvedCall> resolvedCall) {
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
- return generateCall(callExpression, calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
+ return generateCall(calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
}
+ JetElement callElement = resolvedCall.getCall().getCallElement();
+ JetExpression callExpression = callElement instanceof JetExpression ? (JetExpression) callElement : null;
+
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
- Map receivers = getReceiverValues(callExpression, resolvedCall, true);
+ Map receivers = getReceiverValues(resolvedCall, true);
SmartFMap parameterValues = SmartFMap.emptyMap();
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
@@ -1412,27 +1413,30 @@ public class JetControlFlowProcessor {
}
if (resultingDescriptor instanceof VariableDescriptor) {
+ assert callExpression != null
+ : "Variable-based call without call expression: " + callElement.getText();
assert parameterValues.isEmpty()
- : "Variable-based call with non-empty argument list: " + resolvedCall.getCall().getCallElement().getText();
+ : "Variable-based call with non-empty argument list: " + callElement.getText();
return builder.readVariable(calleeExpression, callExpression, resolvedCall, receivers);
}
+ mark(resolvedCall.getCall().getCallElement());
return builder.call(calleeExpression, callExpression, resolvedCall, receivers, parameterValues);
}
@NotNull
private Map getReceiverValues(
- JetExpression callExpression,
ResolvedCall> resolvedCall,
boolean generateInstructions) {
SmartFMap receiverValues = SmartFMap.emptyMap();
- receiverValues = getReceiverValues(callExpression, resolvedCall.getThisObject(), generateInstructions, receiverValues);
- receiverValues = getReceiverValues(callExpression, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues);
+ JetElement callElement = resolvedCall.getCall().getCallElement();
+ receiverValues = getReceiverValues(callElement, resolvedCall.getThisObject(), generateInstructions, receiverValues);
+ receiverValues = getReceiverValues(callElement, resolvedCall.getReceiverArgument(), generateInstructions, receiverValues);
return receiverValues;
}
@NotNull
private SmartFMap getReceiverValues(
- JetExpression callExpression,
+ JetElement callElement,
ReceiverValue receiver,
boolean generateInstructions,
SmartFMap receiverValues
@@ -1441,13 +1445,13 @@ public class JetControlFlowProcessor {
if (receiver instanceof ThisReceiver) {
if (generateInstructions) {
- receiverValues = receiverValues.plus(createSyntheticValue(callExpression), receiver);
+ receiverValues = receiverValues.plus(createSyntheticValue(callElement), receiver);
}
}
else if (receiver instanceof ExpressionReceiver) {
JetExpression expression = ((ExpressionReceiver) receiver).getExpression();
if (generateInstructions) {
- generateInstructions(expression, NOT_IN_CONDITION);
+ generateInstructions(expression);
}
PseudoValue receiverPseudoValue = builder.getBoundValue(expression);
@@ -1485,7 +1489,7 @@ public class JetControlFlowProcessor {
SmartFMap parameterValues) {
JetExpression expression = valueArgument.getArgumentExpression();
if (expression != null) {
- generateInstructions(expression, NOT_IN_CONDITION);
+ generateInstructions(expression);
PseudoValue argValue = builder.getBoundValue(expression);
if (argValue != null) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java
index 26944142c2c..8bafae1e6a1 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java
@@ -124,8 +124,12 @@ public class JetFlowInformationProvider {
}
public void checkFunction(@Nullable JetType expectedReturnType) {
+ UnreachableCode unreachableCode = collectUnreachableCode();
+ reportUnreachableCode(unreachableCode);
- checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE);
+ if (subroutine instanceof JetFunctionLiteral) return;
+
+ checkDefiniteReturn(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, unreachableCode);
markTailCalls();
}
@@ -195,7 +199,7 @@ public class JetFlowInformationProvider {
JetElement element = localDeclarationInstruction.getElement();
if (element instanceof JetDeclarationWithBody) {
JetDeclarationWithBody localDeclaration = (JetDeclarationWithBody) element;
- if (localDeclaration instanceof JetFunctionLiteral) continue;
+
CallableDescriptor functionDescriptor =
(CallableDescriptor) trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, localDeclaration);
JetType expectedType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
@@ -208,7 +212,7 @@ public class JetFlowInformationProvider {
}
}
- public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) {
+ public void checkDefiniteReturn(final @NotNull JetType expectedReturnType, @NotNull final UnreachableCode unreachableCode) {
assert subroutine instanceof JetDeclarationWithBody;
JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine;
@@ -219,11 +223,6 @@ public class JetFlowInformationProvider {
final boolean blockBody = function.hasBlockBody();
- final Set rootUnreachableElements = collectUnreachableCode();
- for (JetElement element : rootUnreachableElements) {
- trace.report(UNREACHABLE_CODE.on(element));
- }
-
final boolean[] noReturnError = new boolean[] { false };
for (JetElement returnedExpression : returnedExpressions) {
returnedExpression.accept(new JetVisitorVoid() {
@@ -240,7 +239,7 @@ public class JetFlowInformationProvider {
if (blockBody && !noExpectedType(expectedReturnType)
&& !KotlinBuiltIns.getInstance().isUnit(expectedReturnType)
- && !rootUnreachableElements.contains(element)) {
+ && !unreachableCode.getElements().contains(element)) {
noReturnError[0] = true;
}
}
@@ -251,17 +250,25 @@ public class JetFlowInformationProvider {
}
}
- private Set collectUnreachableCode() {
- Collection unreachableElements = Lists.newArrayList();
- for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
- if (!(deadInstruction instanceof JetElementInstruction)
- || deadInstruction instanceof LoadUnitValueInstruction
- || deadInstruction instanceof MergeInstruction
- || (deadInstruction instanceof MagicInstruction && ((MagicInstruction) deadInstruction).getSynthetic())) continue;
+ private void reportUnreachableCode(@NotNull UnreachableCode unreachableCode) {
+ for (JetElement element : unreachableCode.getElements()) {
+ trace.report(UNREACHABLE_CODE.on(element, unreachableCode.getUnreachableTextRanges(element)));
+ }
+ }
- JetElement element = ((JetElementInstruction) deadInstruction).getElement();
+ @NotNull
+ private UnreachableCode collectUnreachableCode() {
+ Set reachableElements = Sets.newHashSet();
+ Set unreachableElements = Sets.newHashSet();
+ for (Instruction instruction : pseudocode.getInstructionsIncludingDeadCode()) {
+ if (!(instruction instanceof JetElementInstruction)
+ || instruction instanceof LoadUnitValueInstruction
+ || instruction instanceof MergeInstruction
+ || (instruction instanceof MagicInstruction && ((MagicInstruction) instruction).getSynthetic())) continue;
- if (deadInstruction instanceof JumpInstruction) {
+ JetElement element = ((JetElementInstruction) instruction).getElement();
+
+ if (instruction instanceof JumpInstruction) {
boolean isJumpElement = element instanceof JetBreakExpression
|| element instanceof JetContinueExpression
|| element instanceof JetReturnExpression
@@ -269,10 +276,14 @@ public class JetFlowInformationProvider {
if (!isJumpElement) continue;
}
- unreachableElements.add(element);
+ if (instruction.getDead()) {
+ unreachableElements.add(element);
+ }
+ else {
+ reachableElements.add(element);
+ }
}
- // This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
- return JetPsiUtil.findRootExpressions(unreachableElements);
+ return new UnreachableCodeImpl(reachableElements, unreachableElements);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt
index 892aea97202..d6a40033efa 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.kt
@@ -181,18 +181,10 @@ fun traverseFollowingInstructions(
while (!stack.isEmpty()) {
val instruction = stack.pop()
- visited.add(instruction)
+ if (!visited.add(instruction)) continue
+ if (handler != null && !handler(instruction)) return false
- val followingInstructions = instruction.getNextInstructions(order)
-
- for (followingInstruction in followingInstructions) {
- if (!visited.contains(followingInstruction)) {
- if (handler != null && !handler(instruction)) {
- return false
- }
- stack.push(followingInstruction)
- }
- }
+ instruction.getNextInstructions(order).forEach { stack.push(it) }
}
return true
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt
new file mode 100644
index 00000000000..b1597d88feb
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/UnreachableCode.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010-2014 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.jet.lang.cfg
+
+import org.jetbrains.jet.lang.psi.JetElement
+import com.intellij.openapi.util.TextRange
+import java.util.HashSet
+import org.jetbrains.jet.lang.psi.JetPsiUtil
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
+import com.intellij.psi.PsiWhiteSpace
+import java.util.ArrayList
+import org.jetbrains.jet.lexer.JetTokens
+import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.psi.PsiComment
+
+trait UnreachableCode {
+ val elements: Set
+ fun getUnreachableTextRanges(element: JetElement): List
+}
+
+class UnreachableCodeImpl(
+ private val reachableElements: Set,
+ private val unreachableElements: Set
+) : UnreachableCode {
+
+ // This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
+ override val elements = JetPsiUtil.findRootExpressions(unreachableElements)
+
+ override fun getUnreachableTextRanges(element: JetElement): List {
+ return if (element.hasChildrenInSet(reachableElements)) {
+ element.getLeavesOrReachableChildren().removeReachableElementsWithMeaninglessSiblings().mergeAdjacentTextRanges()
+ }
+ else {
+ listOf(element.getTextRange()!!)
+ }
+ }
+
+ private fun JetElement.hasChildrenInSet(set: Set): Boolean {
+ return PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
+ }
+
+ private fun JetElement.getLeavesOrReachableChildren(): List {
+ val children = ArrayList()
+ acceptChildren(object : PsiElementVisitor() {
+ override fun visitElement(element: PsiElement) {
+ val isReachable = element is JetElement && reachableElements.contains(element) && !element.hasChildrenInSet(unreachableElements)
+ if (isReachable || element.getChildren().size == 0) {
+ children.add(element)
+ }
+ else {
+ element.acceptChildren(this)
+ }
+ }
+ })
+ return children
+ }
+
+ fun List.removeReachableElementsWithMeaninglessSiblings(): List {
+ fun PsiElement.isMeaningless() = this is PsiWhiteSpace
+ || this.getNode()?.getElementType() == JetTokens.COMMA
+ || this is PsiComment
+
+ val childrenToRemove = HashSet()
+ fun collectSiblingsIfMeaningless(elementIndex: Int, direction: Int) {
+ val index = elementIndex + direction
+ if (index !in 0..(size() - 1)) return
+
+ val element = this[index]
+ if (element.isMeaningless()) {
+ childrenToRemove.add(element)
+ collectSiblingsIfMeaningless(index, direction)
+ }
+ }
+ for ((index, element) in this.withIndices()) {
+ if (reachableElements.contains(element)) {
+ childrenToRemove.add(element)
+ collectSiblingsIfMeaningless(index, -1)
+ collectSiblingsIfMeaningless(index, 1)
+ }
+ }
+ return this.filter { it !in childrenToRemove }
+ }
+
+
+ private fun List.mergeAdjacentTextRanges(): List {
+ val result = ArrayList()
+ val lastRange = fold(null: TextRange?) {
+ currentTextRange, element ->
+
+ val elementRange = element.getTextRange()!!
+ if (currentTextRange == null) {
+ elementRange
+ }
+ else if (currentTextRange.getEndOffset() == elementRange.getStartOffset()) {
+ currentTextRange.union(elementRange)
+ }
+ else {
+ result.add(currentTextRange)
+ elementRange
+ }
+ }
+ if (lastRange != null) {
+ result.add(lastRange)
+ }
+ return result
+ }
+}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java
index e86b008fd7d..91044d06959 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/Pseudocode.java
@@ -45,7 +45,7 @@ public interface Pseudocode {
List getReversedInstructions();
@NotNull
- List getDeadInstructions();
+ List getInstructionsIncludingDeadCode();
@NotNull
SubroutineExitInstruction getExitInstruction();
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java
index 650d9123af3..7452157936e 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/PseudocodeImpl.java
@@ -183,30 +183,10 @@ public class PseudocodeImpl implements Pseudocode {
return Lists.newArrayList(traversedInstructions);
}
- //for tests only
- @NotNull
- public List getAllInstructions() {
- return mutableInstructionList;
- }
-
@Override
@NotNull
- public List getDeadInstructions() {
- List deadInstructions = Lists.newArrayList();
- for (Instruction instruction : mutableInstructionList) {
- if (isDead(instruction)) {
- deadInstructions.add(instruction);
- }
- }
- return deadInstructions;
- }
-
- private static boolean isDead(@NotNull Instruction instruction) {
- if (!((InstructionImpl)instruction).getDead()) return false;
- for (Instruction copy : instruction.getCopies()) {
- if (!((InstructionImpl)copy).getDead()) return false;
- }
- return true;
+ public List getInstructionsIncludingDeadCode() {
+ return mutableInstructionList;
}
//for tests only
@@ -390,7 +370,7 @@ public class PseudocodeImpl implements Pseudocode {
Set instructionSet = Sets.newHashSet(instructions);
for (Instruction instruction : mutableInstructionList) {
if (!instructionSet.contains(instruction)) {
- ((InstructionImpl)instruction).die();
+ ((InstructionImpl)instruction).setMarkedAsDead(true);
for (Instruction nextInstruction : instruction.getNextInstructions()) {
nextInstruction.getPreviousInstructions().remove(instruction);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt
index ac4bd2030cb..04b8eb99a64 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt
@@ -28,16 +28,52 @@ public trait TypePredicate: (JetType) -> Boolean {
}
public data class SingleType(val targetType: JetType): TypePredicate {
- override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.INSTANCE.equalTypes(typeToCheck, targetType)
+ override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.equalTypes(typeToCheck, targetType)
override fun toString(): String = targetType.render()
}
+public data class AllSubtypes(val upperBound: JetType): TypePredicate {
+ override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.DEFAULT.isSubtypeOf(typeToCheck, upperBound)
+
+ override fun toString(): String = "{<: ${upperBound.render()}}"
+}
+
+public data class ForAllTypes(val typeSets: List): TypePredicate {
+ override fun invoke(typeToCheck: JetType): Boolean = typeSets.all { it(typeToCheck) }
+
+ override fun toString(): String = "AND{${typeSets.makeString(", ")}}"
+}
+
+public data class ForSomeType(val typeSets: List): TypePredicate {
+ override fun invoke(typeToCheck: JetType): Boolean = typeSets.any { it(typeToCheck) }
+
+ override fun toString(): String = "OR{${typeSets.makeString(", ")}}"
+}
+
public object AllTypes : TypePredicate {
override fun invoke(typeToCheck: JetType): Boolean = true
- override fun toString(): String = ""
+ override fun toString(): String = "*"
}
+// todo: simplify computed type predicate when possible
+fun and(predicates: Collection): TypePredicate =
+ when (predicates.size) {
+ 0 -> AllTypes
+ 1 -> predicates.first()
+ else -> ForAllTypes(predicates.toList())
+ }
+
+fun or(predicates: Collection): TypePredicate? =
+ when (predicates.size) {
+ 0 -> null
+ 1 -> predicates.first()
+ else -> ForSomeType(predicates.toList())
+ }
+
+fun JetType.getSubtypesPredicate(): TypePredicate? =
+ if (TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, this)) AllSubtypes(this) else SingleType(this)
+
private fun JetType.render(): String = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(this)
public fun TypePredicate.expectedTypeFor(keys: Iterable): Map =
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt
index 17fbcaaeffe..ea2df5fbe4e 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/Instruction.kt
@@ -23,14 +23,16 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
public trait Instruction {
public var owner: Pseudocode
- public val previousInstructions: MutableCollection
+ public val previousInstructions: Collection
public val nextInstructions: Collection
+ public val dead: Boolean
+
public val lexicalScope: LexicalScope
public val inputValues: List
- public fun getCopies(): Collection
+ public val copies: Collection
public fun accept(visitor: InstructionVisitor)
public fun accept(visitor: InstructionVisitorWithResult): R
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt
index bb367a57f1b..3318a932b83 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/InstructionImpl.kt
@@ -25,39 +25,6 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
public abstract class InstructionImpl(public override val lexicalScope: LexicalScope): Instruction {
private var _owner: Pseudocode? = null
- private val _copies = HashSet()
- private var original: Instruction? = null
- protected var _dead: Boolean = false
-
- private fun setOriginalInstruction(value: Instruction?) {
- assert(original == null) { "Instruction can't have two originals: this.original = ${original}; new original = $this" }
- original = value
- }
-
- protected fun outgoingEdgeTo(target: Instruction?): Instruction? {
- if (target != null) {
- target.previousInstructions.add(this)
- }
- return target
- }
-
- protected fun updateCopyInfo(instruction: InstructionImpl): Instruction {
- _copies.add(instruction)
- instruction.setOriginalInstruction(this)
- return instruction
- }
-
- protected abstract fun createCopy(): InstructionImpl
-
- public fun die() {
- _dead = true
- }
-
- public val dead: Boolean get() = _dead
-
- public fun copy(): Instruction {
- return updateCopyInfo(createCopy())
- }
override var owner: Pseudocode
get() = _owner!!
@@ -66,16 +33,34 @@ public abstract class InstructionImpl(public override val lexicalScope: LexicalS
_owner = value
}
+ private var allCopies: MutableSet? = null
+
+ override val copies: Collection
+ get() = allCopies?.filter { it != this } ?: Collections.emptyList()
+
+ fun copy(): Instruction = updateCopyInfo(createCopy())
+
+ protected abstract fun createCopy(): InstructionImpl
+
+ protected fun updateCopyInfo(instruction: InstructionImpl): Instruction {
+ if (allCopies == null) {
+ allCopies = hashSetOf(this)
+ }
+ instruction.allCopies = allCopies
+ allCopies!!.add(instruction)
+ return instruction
+ }
+
+ public var markedAsDead: Boolean = false
+
+ override val dead: Boolean get() = allCopies?.all { it.markedAsDead } ?: markedAsDead
+
override val previousInstructions: MutableCollection = LinkedHashSet()
- override val inputValues: List = Collections.emptyList()
-
- override fun getCopies(): Collection {
- return original?.let { original ->
- val originalCopies = Sets.newHashSet(original.getCopies())
- originalCopies.remove(this)
- originalCopies.add(original)
- originalCopies
- } ?: _copies
+ protected fun outgoingEdgeTo(target: Instruction?): Instruction? {
+ (target as InstructionImpl?)?.previousInstructions?.add(this)
+ return target
}
+
+ override val inputValues: List = Collections.emptyList()
}
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt
index 01871a57938..41e3886f47b 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/pseudocodeUtil.kt
@@ -16,13 +16,21 @@
package org.jetbrains.jet.lang.cfg.pseudocode
-import org.jetbrains.jet.lang.psi.JetExpression
-import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.traverseFollowingInstructions
-import java.util.HashSet
-import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.TraversalOrder
-import org.jetbrains.jet.lang.psi.JetFunction
-import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
-import org.jetbrains.jet.lang.psi.JetFunctionLiteral
+import org.jetbrains.jet.lang.cfg.pseudocodeTraverser.*
+import org.jetbrains.jet.lang.cfg.pseudocode.instructions.*
+import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.*
+import org.jetbrains.jet.lang.cfg.pseudocode.instructions.jumps.*
+import org.jetbrains.jet.lang.psi.*
+import org.jetbrains.jet.lang.descriptors.*
+import org.jetbrains.jet.lang.resolve.bindingContextUtil.*
+import org.jetbrains.jet.lang.resolve.calls.model.*
+import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
+import org.jetbrains.jet.lang.resolve.BindingContext
+import java.util.*
+import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
+import org.jetbrains.jet.lang.resolve.OverridingUtil
+import org.jetbrains.jet.lang.types.TypeUtils
+import org.jetbrains.jet.lang.types.JetType
fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
val value = pseudocode.getElementValue(this);
@@ -32,7 +40,7 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
return when {
(getParent() as? JetFunction)?.getBodyExpression() == this ->
true
- pseudocode.getElementValue(getParentByType(javaClass())?.getBodyExpression()) == value ->
+ value.implicitReturnValue ->
true
else ->
false
@@ -42,4 +50,127 @@ fun JetExpression.isStatement(pseudocode: Pseudocode): Boolean {
val instruction = value.createdAt
if (considerUsedIfCreatedBeforeExit() && instruction.nextInstructions.any { it == pseudocode.getExitInstruction() }) return false
return traverseFollowingInstructions(instruction, HashSet(), TraversalOrder.FORWARD) { value !in it.inputValues }
+}
+
+val PseudoValue.implicitReturnValue: Boolean
+ get() {
+ val pseudocode = createdAt.owner
+
+ val function = pseudocode.getCorrespondingElement() as? JetDeclarationWithBody
+
+ if (function is JetFunctionLiteral || (function != null && !function.hasBlockBody())) {
+ return pseudocode.getElementValue(function.getBodyExpression()) == this
+ }
+ return false
+ }
+
+fun Pseudocode.collectValueUsages(): Map> {
+ val map = HashMap>()
+ traverseFollowingInstructions(getEnterInstruction(), HashSet(), TraversalOrder.FORWARD) {
+ for (value in it.inputValues) {
+ map.getOrPut(value){ ArrayList() }.add(it)
+ }
+ true
+ }
+
+ return map
+}
+
+fun getReceiverTypePredicate(resolvedCall: ResolvedCall<*>, receiverValue: ReceiverValue): TypePredicate? {
+ val callableDescriptor = resolvedCall.getResultingDescriptor()
+ if (callableDescriptor == null) return null
+
+ when (receiverValue) {
+ resolvedCall.getReceiverArgument() -> {
+ val receiverParameter = callableDescriptor.getReceiverParameter()
+ if (receiverParameter != null) return receiverParameter.getType().getSubtypesPredicate()
+ }
+ resolvedCall.getThisObject() -> {
+ val rootCallableDescriptors = OverridingUtil.getTopmostOverridenDescriptors(callableDescriptor)
+ return or(rootCallableDescriptors.map {
+ it.getExpectedThisObject()?.getType()?.let { TypeUtils.makeNullableIfNeeded(it, resolvedCall.isSafeCall()) }?.getSubtypesPredicate()
+ }.filterNotNull())
+ }
+ }
+
+ return null
+}
+
+fun getExpectedTypePredicate(
+ value: PseudoValue,
+ valueUsageMap: Map>,
+ bindingContext: BindingContext
+): TypePredicate {
+ val typePredicates = HashSet()
+
+ fun addSubtypesOf(jetType: JetType?) = typePredicates.add(jetType?.getSubtypesPredicate())
+
+ fun addTypePredicates(value: PseudoValue) {
+ if (value.implicitReturnValue) {
+ val function = value.createdAt.owner.getCorrespondingElement() as? JetDeclarationWithBody
+ val functionDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor
+ addSubtypesOf(functionDescriptor?.getReturnType())
+ }
+
+ valueUsageMap[value]?.forEach {
+ when (it) {
+ is ReturnValueInstruction -> {
+ val functionDescriptor = (it.element as JetReturnExpression).getTargetFunctionDescriptor(bindingContext)
+ addSubtypesOf(functionDescriptor?.getReturnType())
+ }
+
+ is ConditionalJumpInstruction ->
+ addSubtypesOf(KotlinBuiltIns.getInstance().getBooleanType())
+
+ is ThrowExceptionInstruction ->
+ addSubtypesOf(KotlinBuiltIns.getInstance().getThrowable().getDefaultType())
+
+ is MergeInstruction ->
+ addTypePredicates(it.outputValue)
+
+ is AccessValueInstruction -> {
+ val accessTarget = it.target
+ val receiverValue = it.receiverValues[value]
+ if (receiverValue != null) {
+ typePredicates.add(getReceiverTypePredicate((accessTarget as AccessTarget.Call).resolvedCall, receiverValue))
+ }
+ else {
+ val expectedType = when (accessTarget) {
+ is AccessTarget.Call ->
+ (accessTarget.resolvedCall.getResultingDescriptor() as? VariableDescriptor)?.getType()
+ is AccessTarget.Declaration ->
+ accessTarget.descriptor.getType()
+ else ->
+ null
+ }
+ addSubtypesOf(expectedType)
+ }
+ }
+
+ is CallInstruction -> {
+ val receiverValue = it.receiverValues[value]
+ if (receiverValue != null) {
+ typePredicates.add(getReceiverTypePredicate(it.resolvedCall, receiverValue))
+ }
+ else {
+ it.arguments[value]?.let { parameter ->
+ val expectedType = when (it.resolvedCall.getValueArguments()[parameter]) {
+ is VarargValueArgument ->
+ parameter.getVarargElementType()
+ else ->
+ parameter.getType()
+ }
+ addSubtypesOf(expectedType)
+ }
+ }
+ }
+
+ is MagicInstruction ->
+ typePredicates.add(it.expectedTypes[value])
+ }
+ }
+ }
+
+ addTypePredicates(value)
+ return and(typePredicates.filterNotNull())
}
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java
index 598049b6c5a..8616757045f 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java
@@ -27,6 +27,7 @@ public abstract class AbstractDiagnostic implements Parame
private final E psiElement;
private final DiagnosticFactoryWithPsiElement factory;
private final Severity severity;
+ private List textRanges;
public AbstractDiagnostic(@NotNull E psiElement,
@NotNull DiagnosticFactoryWithPsiElement factory,
@@ -63,6 +64,9 @@ public abstract class AbstractDiagnostic implements Parame
@Override
@NotNull
public List getTextRanges() {
+ if (textRanges != null) {
+ return textRanges;
+ }
return getFactory().getTextRanges(this);
}
@@ -71,4 +75,10 @@ public abstract class AbstractDiagnostic implements Parame
if (!getFactory().isValid(this)) return false;
return true;
}
+
+ @NotNull
+ public Diagnostic setTextRanges(@NotNull List textRanges) {
+ this.textRanges = textRanges;
+ return this;
+ }
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java
index 5a01175740d..a015899f523 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java
@@ -30,7 +30,7 @@ public abstract class DiagnosticFactoryWithPsiElement getTextRanges(ParametrizedDiagnostic diagnostic) {
- return positioningStrategy.mark(diagnostic.getPsiElement());
+ return positioningStrategy.markDiagnostic(diagnostic);
}
protected boolean isValid(ParametrizedDiagnostic diagnostic) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java
index 3d0df53cdf9..1620da3f528 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java
@@ -17,9 +17,11 @@
package org.jetbrains.jet.lang.diagnostics;
import com.google.common.collect.ImmutableSet;
+import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
@@ -446,7 +448,13 @@ public interface Errors {
// Control flow / Data flow
- DiagnosticFactory0 UNREACHABLE_CODE = DiagnosticFactory0.create(WARNING);
+ DiagnosticFactory1> UNREACHABLE_CODE = DiagnosticFactory1.create(
+ WARNING, PositioningStrategies.markTextRangesFromDiagnostic(new Function1>() {
+ @Override
+ public List invoke(Diagnostic diagnostic) {
+ return UNREACHABLE_CODE.cast(diagnostic).getA();
+ }
+ }));
DiagnosticFactory0 VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, NAME_IDENTIFIER);
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java
index b472dd4169c..a0e5d07199c 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java
@@ -23,6 +23,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
+import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.*;
@@ -527,6 +528,18 @@ public class PositioningStrategies {
}
};
+ public static PositioningStrategy markTextRangesFromDiagnostic(
+ @NotNull final Function1> getTextRanges
+ ) {
+ return new PositioningStrategy() {
+ @NotNull
+ @Override
+ public List markDiagnostic(@NotNull ParametrizedDiagnostic extends PsiElement> diagnostic) {
+ return getTextRanges.invoke(diagnostic);
+ }
+ };
+ }
+
private PositioningStrategies() {
}
}
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java
index a149ef32b69..16486f78e7a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java
@@ -27,7 +27,12 @@ import java.util.List;
public class PositioningStrategy {
@NotNull
- public List mark(@NotNull E element) {
+ public List markDiagnostic(@NotNull ParametrizedDiagnostic extends E> diagnostic) {
+ return mark(diagnostic.getPsiElement());
+ }
+
+ @NotNull
+ protected List mark(@NotNull E element) {
return markElement(element);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java
index deace52941b..bb804680559 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java
@@ -212,7 +212,7 @@ public class DefaultErrorMessages {
MAP.put(INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER,
"Setter of this property can be overridden, so initialization using backing field required", NAME);
- MAP.put(UNREACHABLE_CODE, "Unreachable code");
+ MAP.put(UNREACHABLE_CODE, "Unreachable code", TO_STRING);
MAP.put(MANY_CLASS_OBJECTS, "Only one class object is allowed per class");
MAP.put(CLASS_OBJECT_NOT_ALLOWED, "A class object is not allowed here");
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java
index 0bf808a306e..72d3d2b52da 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java
@@ -229,13 +229,13 @@ public class Renderers {
parameterTypes.add(valueParameterDescriptor.getType());
if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue;
JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex());
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(actualType, valueParameterDescriptor.getType())) {
errorPositions.add(ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
}
}
if (receiverType != null && inferenceErrorData.receiverArgumentType != null &&
- !JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) {
+ !JetTypeChecker.DEFAULT.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) {
errorPositions.add(ConstraintPosition.RECEIVER_POSITION);
}
@@ -333,7 +333,7 @@ public class Renderers {
JetType upperBoundWithSubstitutedInferredTypes =
systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
if (upperBoundWithSubstitutedInferredTypes != null &&
- !JetTypeChecker.INSTANCE.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
+ !JetTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) {
violatedUpperBound = upperBoundWithSubstitutedInferredTypes;
break;
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
index 9e81e05b271..1c6dbfb32d7 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java
@@ -780,13 +780,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
// Parse when block
myBuilder.enableNewlines();
- expect(LBRACE, "Expecting '{'");
+ if (expect(LBRACE, "Expecting '{'")) {
+ while (!eof() && !at(RBRACE)) {
+ parseWhenEntry();
+ }
- while (!eof() && !at(RBRACE)) {
- parseWhenEntry();
+ expect(RBRACE, "Expecting '}'");
}
-
- expect(RBRACE, "Expecting '}'");
myBuilder.restoreNewlinesState();
when.done(WHEN);
@@ -1370,35 +1370,40 @@ public class JetExpressionParsing extends AbstractJetParsing {
advance(); // FOR_KEYWORD
- myBuilder.disableNewlines();
- expect(LPAR, "Expecting '(' to open a loop range", TokenSet.create(RPAR, VAL_KEYWORD, VAR_KEYWORD, IDENTIFIER));
+ if (expect(LPAR, "Expecting '(' to open a loop range", EXPRESSION_FIRST)) {
+ myBuilder.disableNewlines();
- PsiBuilder.Marker parameter = mark();
- if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
- if (at(LPAR)) {
- myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
+ if (!at(RPAR)) {
+ PsiBuilder.Marker parameter = mark();
+ if (at(VAL_KEYWORD) || at(VAR_KEYWORD)) advance(); // VAL_KEYWORD or VAR_KEYWORD
+ if (at(LPAR)) {
+ myJetParsing.parseMultiDeclarationName(TokenSet.create(IN_KEYWORD, LBRACE));
+ parameter.done(MULTI_VARIABLE_DECLARATION);
+ }
+ else {
+ expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON, IN_KEYWORD));
- parameter.done(MULTI_VARIABLE_DECLARATION);
- }
- else {
- expect(IDENTIFIER, "Expecting a variable name", TokenSet.create(COLON));
+ if (at(COLON)) {
+ advance(); // COLON
+ myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
+ }
+ parameter.done(VALUE_PARAMETER);
+ }
- if (at(COLON)) {
- advance(); // COLON
- myJetParsing.parseTypeRef(TokenSet.create(IN_KEYWORD));
+ if (expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE, RPAR))) {
+ PsiBuilder.Marker range = mark();
+ parseExpression();
+ range.done(LOOP_RANGE);
+ }
}
- parameter.done(VALUE_PARAMETER);
+ else {
+ error("Expecting a variable name");
+ }
+
+ expectNoAdvance(RPAR, "Expecting ')'");
+ myBuilder.restoreNewlinesState();
}
- expect(IN_KEYWORD, "Expecting 'in'", TokenSet.create(LPAR, LBRACE));
-
- PsiBuilder.Marker range = mark();
- parseExpression();
- range.done(LOOP_RANGE);
-
- expectNoAdvance(RPAR, "Expecting ')'");
- myBuilder.restoreNewlinesState();
-
parseControlStructureBody();
loop.done(FOR);
@@ -1548,13 +1553,14 @@ public class JetExpressionParsing extends AbstractJetParsing {
*/
private void parseCondition() {
myBuilder.disableNewlines();
- expect(LPAR, "Expecting a condition in parentheses '(...)'");
- PsiBuilder.Marker condition = mark();
- parseExpression();
- condition.done(CONDITION);
+ if (expect(LPAR, "Expecting a condition in parentheses '(...)'", EXPRESSION_FIRST)) {
+ PsiBuilder.Marker condition = mark();
+ parseExpression();
+ condition.done(CONDITION);
+ expect(RPAR, "Expecting ')");
+ }
- expect(RPAR, "Expecting ')");
myBuilder.restoreNewlinesState();
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java
index bbd431f232c..9c40ea72366 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2013 JetBrains s.r.o.
+ * Copyright 2010-2014 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.
@@ -17,7 +17,10 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.lexer.JetTokens;
public class JetDoWhileExpression extends JetWhileExpressionBase {
public JetDoWhileExpression(@NotNull ASTNode node) {
@@ -28,4 +31,11 @@ public class JetDoWhileExpression extends JetWhileExpressionBase {
public R accept(@NotNull JetVisitor visitor, D data) {
return visitor.visitDoWhileExpression(this, data);
}
+
+ @Nullable
+ @IfNotParsed
+ public PsiElement getWhileKeywordElement() {
+ //noinspection ConstantConditions
+ return findChildByType(JetTokens.WHILE_KEYWORD);
+ }
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java
index ca97a616510..d166b46d261 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetIfExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2013 JetBrains s.r.o.
+ * Copyright 2010-2014 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.
@@ -17,9 +17,11 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
+import org.jetbrains.jet.lexer.JetTokens;
public class JetIfExpression extends JetExpressionImpl {
public JetIfExpression(@NotNull ASTNode node) {
@@ -36,6 +38,16 @@ public class JetIfExpression extends JetExpressionImpl {
return findExpressionUnder(JetNodeTypes.CONDITION);
}
+ @Nullable @IfNotParsed
+ public PsiElement getLeftParenthesis() {
+ return findChildByType(JetTokens.LPAR);
+ }
+
+ @Nullable @IfNotParsed
+ public PsiElement getRightParenthesis() {
+ return findChildByType(JetTokens.RPAR);
+ }
+
@Nullable
public JetExpression getThen() {
return findExpressionUnder(JetNodeTypes.THEN);
@@ -45,4 +57,9 @@ public class JetIfExpression extends JetExpressionImpl {
public JetExpression getElse() {
return findExpressionUnder(JetNodeTypes.ELSE);
}
+
+ @Nullable
+ public PsiElement getElseKeyword() {
+ return findChildByType(JetTokens.ELSE_KEYWORD);
+ }
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java
index 0f86e062358..9cab172d203 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetLoopExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2013 JetBrains s.r.o.
+ * Copyright 2010-2014 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.
@@ -17,9 +17,11 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
+import org.jetbrains.jet.lexer.JetTokens;
public abstract class JetLoopExpression extends JetExpressionImpl implements JetStatementExpression {
public JetLoopExpression(@NotNull ASTNode node) {
@@ -30,4 +32,15 @@ public abstract class JetLoopExpression extends JetExpressionImpl implements Jet
public JetExpression getBody() {
return findExpressionUnder(JetNodeTypes.BODY);
}
+
+ @Nullable
+ @IfNotParsed
+ public PsiElement getLeftParenthesis() {
+ return findChildByType(JetTokens.LPAR);
+ }
+
+ @Nullable @IfNotParsed
+ public PsiElement getRightParenthesis() {
+ return findChildByType(JetTokens.RPAR);
+ }
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
index 59d6e08d1b4..74de6355425 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2013 JetBrains s.r.o.
+ * Copyright 2010-2014 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.
@@ -47,13 +47,28 @@ public class JetWhenExpression extends JetExpressionImpl {
@NotNull
public PsiElement getWhenKeywordElement() {
+ //noinspection ConstantConditions
return findChildByType(JetTokens.WHEN_KEYWORD);
}
@Nullable
- public PsiElement getCloseBraceNode() {
- ASTNode openBraceNode = getNode().findChildByType(JetTokens.RBRACE);
- return openBraceNode != null ? openBraceNode.getPsi() : null;
+ public PsiElement getCloseBrace() {
+ return findChildByType(JetTokens.RBRACE);
+ }
+
+ @Nullable
+ public PsiElement getOpenBrace() {
+ return findChildByType(JetTokens.LBRACE);
+ }
+
+ @Nullable
+ public PsiElement getLeftParenthesis() {
+ return findChildByType(JetTokens.LPAR);
+ }
+
+ @Nullable
+ public PsiElement getRightParenthesis() {
+ return findChildByType(JetTokens.RPAR);
}
@Nullable
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java
index 8f9218064a6..c8fa88df31a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2013 JetBrains s.r.o.
+ * Copyright 2010-2014 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.
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java
index 602fc439e60..6addb68814f 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileElementType.java
@@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
import java.io.IOException;
public class JetFileElementType extends IStubFileElementType {
- public static final int STUB_VERSION = 28;
+ public static final int STUB_VERSION = 29;
public JetFileElementType() {
super("jet.FILE", JetLanguage.INSTANCE);
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java
index cac012ab8a3..fea9bfacc72 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementType.java
@@ -23,13 +23,14 @@ import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IStubFileElementType;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayFactory;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.lang.psi.*;
+import org.jetbrains.jet.lang.psi.JetClassOrObject;
+import org.jetbrains.jet.lang.psi.JetElementImplStub;
+import org.jetbrains.jet.lang.psi.JetFunction;
+import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.plugin.JetLanguage;
import java.lang.reflect.Array;
@@ -37,9 +38,6 @@ import java.lang.reflect.Constructor;
public abstract class JetStubElementType> extends IStubElementType {
- @SuppressWarnings("unchecked")
- private static final Class extends PsiElement>[] ALWAYS_CREATE_STUB_FOR = new Class[] { JetClass.class, JetObjectDeclaration.class };
-
@NotNull
private final Constructor byNodeConstructor;
@NotNull
@@ -93,11 +91,14 @@ public abstract class JetStubElementType[] stopAt = ArrayUtil.append(ALWAYS_CREATE_STUB_FOR, JetBlockExpression.class);
- @SuppressWarnings("unchecked") JetWithExpressionInitializer withInitializer =
- PsiTreeUtil.getParentOfType(declaration, JetWithExpressionInitializer.class, true, stopAt);
- if (withInitializer != null) {
- JetExpression initializer = withInitializer.getInitializer();
- if (PsiTreeUtil.isAncestor(initializer, declaration, true)) {
- return false;
- }
- }
-
- // Don't create stubs if declaration is inside property delegate
- @SuppressWarnings("unchecked") JetPropertyDelegate delegate = PsiTreeUtil.getParentOfType(declaration, JetPropertyDelegate.class, true, stopAt);
- if (delegate != null) {
- JetExpression delegateExpression = delegate.getExpression();
- if (PsiTreeUtil.isAncestor(delegateExpression, declaration, true)) {
- return false;
- }
- }
-
- return true;
- }
-
@Override
public void indexStub(@NotNull StubT stub, @NotNull IndexSink sink) {
// do not force inheritors to implement this method
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
index 2ab6943670f..1841ed6dfd7 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.kt
@@ -21,14 +21,18 @@ import org.jetbrains.jet.lang.psi.Call
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
-import org.jetbrains.jet.lang.psi.JetBinaryExpression
-import org.jetbrains.jet.lang.psi.JetUnaryExpression
-import org.jetbrains.jet.lang.psi.JetArrayAccessExpression
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetOperationExpression
import org.jetbrains.jet.lang.resolve.BindingContext.CALL
-import com.intellij.psi.util.PsiTreeUtil
-import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
+import org.jetbrains.jet.lang.psi.JetReturnExpression
+import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
+import org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET
+import org.jetbrains.jet.lang.resolve.BindingContext.FUNCTION
+import org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR
+import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
+import org.jetbrains.jet.lang.psi.JetDeclarationWithBody
+import org.jetbrains.jet.lang.resolve.DescriptorUtils
+import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor
/**
* For expressions like a(), a[i], a.b.c(), +a, a + b, (a()), a(): Int, @label a()
@@ -51,3 +55,16 @@ fun JetExpression.getCorrespondingCall(bindingContext: BindingContext): Call? {
}
return bindingContext[CALL, reference]
}
+
+public fun JetReturnExpression.getTargetFunctionDescriptor(bindingContext: BindingContext): FunctionDescriptor? {
+ val targetLabel = getTargetLabel()
+ if (targetLabel != null) return bindingContext[LABEL_TARGET, targetLabel]?.let { bindingContext[FUNCTION, it] }
+
+ val declarationDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, getParentByType(javaClass())]
+ val containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, javaClass(), false)
+ if (containingFunctionDescriptor == null) return null
+
+ return stream(containingFunctionDescriptor) { DescriptorUtils.getParentOfType(it, javaClass()) }
+ .dropWhile { it is AnonymousFunctionDescriptor }
+ .firstOrNull()
+}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java
index a07420658a7..8c4c3bd712c 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java
@@ -220,13 +220,13 @@ public class DeclarationsChecker {
REMOVE_IF_SUBTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
- return JetTypeChecker.INSTANCE.isSubtypeOf(other, subject);
+ return JetTypeChecker.DEFAULT.isSubtypeOf(other, subject);
}
},
REMOVE_IF_SUPERTYPE_IN_THE_SET {
@Override
public boolean removeNeeded(JetType subject, JetType other) {
- return JetTypeChecker.INSTANCE.isSubtypeOf(subject, other);
+ return JetTypeChecker.DEFAULT.isSubtypeOf(subject, other);
}
};
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java
index 3cc288d0deb..327a1c81b5d 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegatedPropertyResolver.java
@@ -98,7 +98,7 @@ public class DelegatedPropertyResolver {
JetType propertyType = propertyDescriptor.getType();
/* Do not check return type of get() method of delegate for properties with DeferredType because property type is taken from it */
- if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.INSTANCE.isSubtypeOf(returnType, propertyType)) {
+ if (!(propertyType instanceof DeferredType) && returnType != null && !JetTypeChecker.DEFAULT.isSubtypeOf(returnType, propertyType)) {
Call call = trace.getBindingContext().get(DELEGATED_PROPERTY_CALL, propertyDescriptor.getGetter());
assert call != null : "Call should exists for " + propertyDescriptor.getGetter();
trace.report(DELEGATE_SPECIAL_FUNCTION_RETURN_TYPE_MISMATCH
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
index c5f96ec1e87..9afc4b1a47a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java
@@ -760,7 +760,7 @@ public class DescriptorResolver {
boolean isClassObjectConstraint,
BindingTrace trace
) {
- if (!TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, upperBoundType)) {
+ if (!TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, upperBoundType)) {
if (isClassObjectConstraint) {
trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, upperBoundType));
}
@@ -1360,7 +1360,7 @@ public class DescriptorResolver {
) {
for (JetType bound : typeParameterDescriptor.getUpperBounds()) {
JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(typeArgument, substitutedBound)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) {
trace.report(UPPER_BOUND_VIOLATED.on(jetTypeArgument, substitutedBound, typeArgument));
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java
index 6eccea98512..8bf3e2fc931 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadUtil.java
@@ -71,7 +71,7 @@ public class OverloadUtil {
JetType superValueParameterType = OverridingUtil.getUpperBound(superValueParameters.get(i));
JetType subValueParameterType = OverridingUtil.getUpperBound(subValueParameters.get(i));
// TODO: compare erasure
- if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) {
+ if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) {
return OverridingUtil.OverrideCompatibilityInfo
.valueParameterTypeMismatch(superValueParameterType, subValueParameterType, INCOMPATIBLE);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java
index 2b091f3459f..e5b1be44da5 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java
@@ -733,7 +733,7 @@ public class OverrideResolver {
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
- return JetTypeChecker.INSTANCE.isSubtypeOf(subReturnType, substitutedSuperReturnType);
+ return JetTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
}
@Nullable
@@ -768,7 +768,7 @@ public class OverrideResolver {
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
- return JetTypeChecker.INSTANCE.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
+ return JetTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
}
private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java
index 91f2d1d64e8..3eba4a8a729 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ArgumentTypeResolver.java
@@ -74,7 +74,7 @@ public class ArgumentTypeResolver {
if (actualType == PLACEHOLDER_FUNCTION_TYPE) {
return isFunctionOrErrorType(expectedType) || KotlinBuiltIns.getInstance().isAnyOrNullableAny(expectedType); //todo function type extends
}
- return JetTypeChecker.INSTANCE.isSubtypeOf(actualType, expectedType);
+ return JetTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType);
}
private static boolean isFunctionOrErrorType(@NotNull JetType supertype) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java
index 1718a96ab8d..40f3d802061 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallTransformer.java
@@ -102,18 +102,22 @@ public class CallTransformer {
assert candidate.getDescriptor() instanceof VariableDescriptor;
boolean hasReceiver = candidate.getReceiverArgument().exists();
- Call variableCall = stripCallArguments(task);
+ Call variableCall = stripCallArguments(task.call);
+ ResolutionCandidate variableCandidate = getVariableCallCandidate(candidate, variableCall);
if (!hasReceiver) {
CallCandidateResolutionContext context = CallCandidateResolutionContext.create(
- ResolvedCallImpl.create(candidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
+ ResolvedCallImpl.create(variableCandidate, candidateTrace, task.tracing, task.dataFlowInfoForArguments), task, candidateTrace, task.tracing, variableCall);
return Collections.singleton(context);
}
CallCandidateResolutionContext contextWithReceiver = createContextWithChainedTrace(
- candidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
+ variableCandidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
Call variableCallWithoutReceiver = stripReceiver(variableCall);
ResolutionCandidate candidateWithoutReceiver = ResolutionCandidate.create(
- candidate.getCall(), candidate.getDescriptor(), candidate.getThisObject(), ReceiverValue.NO_RECEIVER,
+ variableCandidate.getCall(),
+ variableCandidate.getDescriptor(),
+ variableCandidate.getThisObject(),
+ ReceiverValue.NO_RECEIVER,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, false);
CallCandidateResolutionContext contextWithoutReceiver = createContextWithChainedTrace(
@@ -131,8 +135,22 @@ public class CallTransformer {
return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue);
}
- private Call stripCallArguments(@NotNull ResolutionTask task) {
- return new DelegatingCall(task.call) {
+ @NotNull
+ private ResolutionCandidate getVariableCallCandidate(
+ @NotNull ResolutionCandidate candidate,
+ @NotNull Call variableCall
+ ) {
+ return ResolutionCandidate.create(
+ variableCall,
+ candidate.getDescriptor(),
+ candidate.getThisObject(),
+ candidate.getReceiverArgument(),
+ candidate.getExplicitReceiverKind(),
+ candidate.isSafeCall());
+ }
+
+ private Call stripCallArguments(@NotNull Call call) {
+ return new DelegatingCall(call) {
@Override
public JetValueArgumentList getValueArgumentList() {
return null;
@@ -160,6 +178,15 @@ public class CallTransformer {
public JetTypeArgumentList getTypeArgumentList() {
return null;
}
+
+ @NotNull
+ @Override
+ public JetElement getCallElement() {
+ JetExpression calleeExpression = getCalleeExpression();
+ assert calleeExpression != null : "No callee expression: " + getCallElement().getText();
+
+ return calleeExpression;
+ }
};
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java
index 1fb1f127305..2259350c967 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java
@@ -735,7 +735,7 @@ public class CandidateResolver {
Set possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
if (possibleTypes.isEmpty()) return type;
- return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes);
+ return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
}
private ValueArgumentsCheckingResult checkAllValueArguments(
@@ -859,7 +859,7 @@ public class CandidateResolver {
List variants =
AutoCastUtils.getAutoCastVariantsExcludingReceiver(context.trace.getBindingContext(), context.dataFlowInfo, receiverToCast);
for (JetType possibleType : variants) {
- if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
return possibleType;
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java
index 2e6bdc26d93..4991d3c4785 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/AutoCastUtils.java
@@ -116,7 +116,7 @@ public class AutoCastUtils {
}
if (subTypes.isEmpty()) return null;
- JetType intersection = TypeUtils.intersect(JetTypeChecker.INSTANCE, subTypes);
+ JetType intersection = TypeUtils.intersect(JetTypeChecker.DEFAULT, subTypes);
if (intersection == null || !intersection.getConstructor().isDenotable()) {
return receiverParameterType;
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java
index aec3e3562d3..ccaaaf8b12b 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsUtil.java
@@ -94,7 +94,7 @@ public class ConstraintsUtil {
JetType substitutedUpperBound = constraintSystem.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT);
assert substitutedUpperBound != null : "We wanted to substitute projections as a result for " + typeParameter;
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(type, substitutedUpperBound)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(type, substitutedUpperBound)) {
return false;
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java
index 03901b7d70a..2bd6d32a3c8 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java
@@ -239,7 +239,7 @@ public class OverloadingConflictResolver {
}
private boolean typeMoreSpecific(@NotNull JetType specific, @NotNull JetType general) {
- return JetTypeChecker.INSTANCE.isSubtypeOf(specific, general) ||
+ return JetTypeChecker.DEFAULT.isSubtypeOf(specific, general) ||
numericTypeMoreSpecific(specific, general);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java
index 39eb7ff3f84..5166f22bd2a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetExpression;
-import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.psi.JetSuperExpression;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastUtils;
@@ -326,7 +325,7 @@ public class TaskPrioritizer {
if (expectedThisObject == null) return true;
List receivers = scope.getImplicitReceiversHierarchy();
for (ReceiverParameterDescriptor receiver : receivers) {
- if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
// TODO : Autocasts & nullability
candidate.setThisObject(expectedThisObject.getValue());
return true;
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java
index ade5431b98a..58b04689557 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/CompileTimeConstantChecker.java
@@ -90,7 +90,7 @@ public class CompileTimeConstantChecker {
if (!noExpectedTypeOrError(expectedType)) {
JetType valueType = value.getType(KotlinBuiltIns.getInstance());
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "integer", expectedType));
}
}
@@ -107,7 +107,7 @@ public class CompileTimeConstantChecker {
}
if (!noExpectedTypeOrError(expectedType)) {
JetType valueType = value.getType(KotlinBuiltIns.getInstance());
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(valueType, expectedType)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "floating-point", expectedType));
}
}
@@ -119,7 +119,7 @@ public class CompileTimeConstantChecker {
@NotNull JetConstantExpression expression
) {
if (!noExpectedTypeOrError(expectedType)
- && !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getBooleanType(), expectedType)) {
+ && !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getBooleanType(), expectedType)) {
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "boolean", expectedType));
}
return false;
@@ -127,7 +127,7 @@ public class CompileTimeConstantChecker {
private boolean checkCharValue(CompileTimeConstant> constant, JetType expectedType, JetConstantExpression expression) {
if (!noExpectedTypeOrError(expectedType)
- && !JetTypeChecker.INSTANCE.isSubtypeOf(builtIns.getCharType(), expectedType)) {
+ && !JetTypeChecker.DEFAULT.isSubtypeOf(builtIns.getCharType(), expectedType)) {
return reportError(CONSTANT_EXPECTED_TYPE_MISMATCH.on(expression, "character", expectedType));
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java
index 95e8f484b89..e9032ba4682 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/CastDiagnosticsUtil.java
@@ -66,8 +66,8 @@ public class CastDiagnosticsUtil {
for (JetType aType : aTypes) {
for (JetType bType : bTypes) {
- if (JetTypeChecker.INSTANCE.isSubtypeOf(aType, bType)) return true;
- if (JetTypeChecker.INSTANCE.isSubtypeOf(bType, aType)) return true;
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(aType, bType)) return true;
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(bType, aType)) return true;
}
}
@@ -100,7 +100,7 @@ public class CastDiagnosticsUtil {
}
private static boolean isFinal(@NotNull JetType type) {
- return !TypeUtils.canHaveSubtypes(JetTypeChecker.INSTANCE, type);
+ return !TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, type);
}
private static boolean isTrait(@NotNull JetType type) {
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java
index 9b836f765d3..edf331d8c97 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java
@@ -212,7 +212,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(CAST_NEVER_SUCCEEDS.on(expression.getOperationReference()));
}
else {
- JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
+ JetTypeChecker typeChecker = JetTypeChecker.DEFAULT;
// Upcast?
if (typeChecker.isSubtypeOf(actualType, targetType)) {
if (!typeChecker.isSubtypeOf(targetType, actualType)) {
@@ -378,8 +378,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (labelName != null) {
LabelResolver.LabeledReceiverResolutionResult resolutionResult =
LabelResolver.INSTANCE.resolveThisOrSuperLabel(expression, context, Name.identifier(labelName));
- if (onlyClassReceivers && resolutionResult.success()) {
- if (!isDeclaredInClass(resolutionResult.getReceiverParameterDescriptor())) {
+ if (resolutionResult.success()) {
+ ReceiverParameterDescriptor receiverParameterDescriptor = resolutionResult.getReceiverParameterDescriptor();
+ recordThisOrSuperCallInTraceAndCallExtension(context, receiverParameterDescriptor, expression);
+ if (onlyClassReceivers && !isDeclaredInClass(receiverParameterDescriptor)) {
return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(NO_RECEIVER_PARAMETER);
}
}
@@ -402,7 +404,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (result != NO_RECEIVER_PARAMETER) {
context.trace.record(REFERENCE_TARGET, expression.getInstanceReference(), result.getContainingDeclaration());
recordThisOrSuperCallInTraceAndCallExtension(context, result, expression);
-
}
return LabelResolver.LabeledReceiverResolutionResult.labelResolutionSuccess(result);
}
@@ -661,13 +662,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetType result;
if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) {
assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
- if (JetTypeChecker.INSTANCE.isSubtypeOf(returnType, KotlinBuiltIns.getInstance().getUnitType())) {
+ if (KotlinBuiltIns.getInstance().isUnit(returnType)) {
result = ErrorUtils.createErrorType(KotlinBuiltIns.getInstance().getUnit().getName().asString());
context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
}
else {
JetType receiverType = receiver.getType();
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, receiverType)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
}
else {
@@ -882,7 +883,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:", right);
traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType());
- Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right));
+ Call call = CallMaker.makeCallWithExpressions(expression, receiver, null, operationSign, Collections.singletonList(right));
ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny);
OverloadResolutionResults resolutionResults =
components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java
index 4bc6fd8baff..73331a549fb 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java
@@ -221,7 +221,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
if (typeReference != null) {
type = components.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true);
if (expectedType != null) {
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType));
}
}
@@ -278,7 +278,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
// This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
functionDescriptor.setReturnType(declaredReturnType);
if (expectedReturnType != null) {
- if (!JetTypeChecker.INSTANCE.isSubtypeOf(declaredReturnType, expectedReturnType)) {
+ if (!JetTypeChecker.DEFAULT.isSubtypeOf(declaredReturnType, expectedReturnType)) {
context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType));
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java
index c8b74780ff3..e0ce8f2fcc5 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java
@@ -355,7 +355,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
variableDescriptor = components.expressionTypingServices.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope, loopParameter, context.trace);
JetType actualParameterType = variableDescriptor.getType();
if (expectedParameterType != null &&
- !JetTypeChecker.INSTANCE.isSubtypeOf(expectedParameterType, actualParameterType)) {
+ !JetTypeChecker.DEFAULT.isSubtypeOf(expectedParameterType, actualParameterType)) {
context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java
index 270f4d1cba7..d8bf889087c 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java
@@ -164,7 +164,7 @@ public class DataFlowUtils {
recordExpectedType(trace, expression, expectedType);
if (expressionType == null || noExpectedType(expectedType) || !expectedType.getConstructor().isDenotable() ||
- JetTypeChecker.INSTANCE.isSubtypeOf(expressionType, expectedType)) {
+ JetTypeChecker.DEFAULT.isSubtypeOf(expressionType, expectedType)) {
return expressionType;
}
@@ -179,7 +179,7 @@ public class DataFlowUtils {
DataFlowValue dataFlowValue = DataFlowValueFactory.createDataFlowValue(expression, expressionType, trace.getBindingContext());
for (JetType possibleType : dataFlowInfo.getPossibleTypes(dataFlowValue)) {
- if (JetTypeChecker.INSTANCE.isSubtypeOf(possibleType, expectedType)) {
+ if (JetTypeChecker.DEFAULT.isSubtypeOf(possibleType, expectedType)) {
AutoCastUtils.recordCastOrError(expression, possibleType, trace, dataFlowValue.isStableIdentifier(), false);
return possibleType;
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java
index 852453f93cb..c56aee232cf 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java
@@ -96,7 +96,7 @@ public class ExpressionTypingUtils {
}
public static boolean isBoolean(@NotNull JetType type) {
- return JetTypeChecker.INSTANCE.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
+ return JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType());
}
public static boolean ensureBooleanResult(JetExpression operationSign, Name name, JetType resultType, ExpressionTypingContext context) {
@@ -401,7 +401,7 @@ public class ExpressionTypingUtils {
context.trace.record(COMPONENT_RESOLVED_CALL, entry, results.getResultingCall());
componentType = results.getResultingDescriptor().getReturnType();
if (componentType != null && !noExpectedType(expectedType)
- && !JetTypeChecker.INSTANCE.isSubtypeOf(componentType, expectedType)) {
+ && !JetTypeChecker.DEFAULT.isSubtypeOf(componentType, expectedType)) {
context.trace.report(
COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(reportErrorsOn, componentName, componentType, expectedType));
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java
index 87d10554c36..28e9841d690 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java
@@ -175,6 +175,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
scope, context.dataFlowInfo, context.trace, /* needCompleteAnalysis = */ true);
ModifiersChecker.create(context.trace).checkModifiersForLocalDeclaration(function, functionDescriptor);
+ if (!function.hasBody()) {
+ context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
+ }
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java
index 89dc437e390..f9b036c492a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java
@@ -100,21 +100,14 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowInfo elseDataFlowInfo = context.dataFlowInfo;
for (JetWhenEntry whenEntry : expression.getEntries()) {
DataFlowInfos infosForCondition = getDataFlowInfosForEntryCondition(
- whenEntry, context, subjectExpression, subjectType, subjectDataFlowValue);
- DataFlowInfo dataFlowInfoForEntryBody;
- if (infosForCondition == null) {
- dataFlowInfoForEntryBody = elseDataFlowInfo;
- }
- else {
- dataFlowInfoForEntryBody = infosForCondition.thenInfo.and(elseDataFlowInfo);
- elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo);
- }
+ whenEntry, context.replaceDataFlowInfo(elseDataFlowInfo), subjectExpression, subjectType, subjectDataFlowValue);
+ elseDataFlowInfo = elseDataFlowInfo.and(infosForCondition.elseInfo);
JetExpression bodyExpression = whenEntry.getExpression();
if (bodyExpression != null) {
WritableScope scopeToExtend = newWritableScopeImpl(context, "Scope extended in when entry");
ExpressionTypingContext newContext = contextWithExpectedType
- .replaceScope(scopeToExtend).replaceDataFlowInfo(dataFlowInfoForEntryBody).replaceContextDependency(INDEPENDENT);
+ .replaceScope(scopeToExtend).replaceDataFlowInfo(infosForCondition.thenInfo).replaceContextDependency(INDEPENDENT);
CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION;
JetTypeInfo typeInfo = components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace);
@@ -141,7 +134,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
return JetTypeInfo.create(null, commonDataFlowInfo);
}
- @Nullable
+ @NotNull
private DataFlowInfos getDataFlowInfosForEntryCondition(
@NotNull JetWhenEntry whenEntry,
@NotNull ExpressionTypingContext context,
@@ -149,13 +142,12 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
@NotNull JetType subjectType,
@NotNull DataFlowValue subjectDataFlowValue
) {
- JetWhenCondition[] conditions = whenEntry.getConditions();
if (whenEntry.isElse()) {
- return null;
+ return new DataFlowInfos(context.dataFlowInfo);
}
DataFlowInfos infos = null;
- for (JetWhenCondition condition : conditions) {
+ for (JetWhenCondition condition : whenEntry.getConditions()) {
DataFlowInfos conditionInfos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
context, subjectDataFlowValue);
if (infos != null) {
@@ -165,7 +157,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
infos = conditionInfos;
}
}
- return infos;
+ return infos != null ? infos : new DataFlowInfos(context.dataFlowInfo);
}
private DataFlowInfos checkWhenCondition(
@@ -238,6 +230,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
this.thenInfo = thenInfo;
this.elseInfo = elseInfo;
}
+
+ private DataFlowInfos(DataFlowInfo info) {
+ this(info, info);
+ }
}
private DataFlowInfos checkTypeForExpressionCondition(
@@ -258,7 +254,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
if (conditionExpected) {
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
- if (!JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) {
+ if (!JetTypeChecker.DEFAULT.equalTypes(booleanType, type)) {
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(expression, type));
}
else {
@@ -298,7 +294,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(Errors.USELESS_NULLABLE_CHECK.on(nullableType));
}
checkTypeCompatibility(context, type, subjectType, typeReferenceAfterIs);
- if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
+ if (CastDiagnosticsUtil.isCastErased(subjectType, type, JetTypeChecker.DEFAULT)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type));
}
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo);
diff --git a/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java b/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java
index 46b9dcfff8f..33fb189f141 100644
--- a/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java
+++ b/compiler/frontend/src/org/jetbrains/jet/plugin/MainFunctionDetector.java
@@ -80,7 +80,7 @@ public class MainFunctionDetector {
List typeArguments = parameterType.getArguments();
if (typeArguments.size() == 1) {
JetType typeArgument = typeArguments.get(0).getType();
- if (JetTypeChecker.INSTANCE.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) {
+ if (JetTypeChecker.DEFAULT.equalTypes(typeArgument, kotlinBuiltIns.getStringType())) {
return true;
}
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java
index bf3276e13e5..693e816088a 100644
--- a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java
+++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java
@@ -16,12 +16,14 @@
package org.jetbrains.jet.util.slicedmap;
+import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public class Slices {
+ private static final Logger LOG = Logger.getInstance(Slices.class);
public static final RewritePolicy ONLY_REWRITE_TO_EQUAL = new RewritePolicy() {
@Override
@@ -33,7 +35,7 @@ public class Slices {
public boolean processRewrite(WritableSlice slice, K key, V oldValue, V newValue) {
if (!((oldValue == null && newValue == null) || (oldValue != null && oldValue.equals(newValue)))) {
// NOTE: Use BindingTraceContext.TRACK_REWRITES to debug this exception
- throw new IllegalStateException("Rewrite at slice " + slice +
+ LOG.error("Rewrite at slice " + slice +
" key: " + key +
" old value: " + oldValue + '@' + System.identityHashCode(oldValue) +
" new value: " + newValue + '@' + System.identityHashCode(newValue));
diff --git a/compiler/testData/asJava/lightClasses/delegation/Function.java b/compiler/testData/asJava/lightClasses/delegation/Function.java
index 3f57046f3c5..8b07898697d 100644
--- a/compiler/testData/asJava/lightClasses/delegation/Function.java
+++ b/compiler/testData/asJava/lightClasses/delegation/Function.java
@@ -1,5 +1,4 @@
public final class Derived implements kotlin.jvm.internal.KObject, Base {
- @org.jetbrains.annotations.NotNull
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
diff --git a/compiler/testData/asJava/lightClasses/delegation/Property.java b/compiler/testData/asJava/lightClasses/delegation/Property.java
index 7a570ffd6b7..b5d491bd57f 100644
--- a/compiler/testData/asJava/lightClasses/delegation/Property.java
+++ b/compiler/testData/asJava/lightClasses/delegation/Property.java
@@ -1,5 +1,4 @@
public final class Derived implements kotlin.jvm.internal.KObject, Base {
- @org.jetbrains.annotations.NotNull
public Derived(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "x") Base x) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java
index 02944a909ca..fd52f2a3e75 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.java
@@ -34,7 +34,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.Nullable
public final java.lang.String getNullableVar() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -43,7 +42,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public final java.lang.String getNotNullVar() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -55,7 +53,6 @@ public final class Class implements kotlin.jvm.internal.KObject {
public final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
@org.jetbrains.annotations.Nullable
- @org.jetbrains.annotations.NotNull
public final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -69,6 +66,5 @@ public final class Class implements kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
public final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String v) { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public Class() { /* compiled code */ }
}
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java
index 60f5378a83c..4de2e6cccee 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.java
@@ -4,7 +4,6 @@ public final class ClassObjectField implements kotlin.jvm.internal.KObject {
private static final java.lang.String y = "";
public static final ClassObjectField.object object$;
- @org.jetbrains.annotations.NotNull
public ClassObjectField() { /* compiled code */ }
public static final class object implements kotlin.jvm.internal.KObject {
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java
index f781f98d627..3daedf91e11 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.java
@@ -1,4 +1,3 @@
public final class ClassWithConstructor implements kotlin.jvm.internal.KObject {
- @org.jetbrains.annotations.NotNull
public ClassWithConstructor(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
}
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java
index b59925f9a57..61917952f6e 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.java
@@ -10,6 +10,5 @@ public final class ClassWithConstructorAndProperties implements kotlin.jvm.inter
@org.jetbrains.annotations.NotNull
public final java.lang.String getNotNull() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public ClassWithConstructorAndProperties(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String nullable, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String notNull) { /* compiled code */ }
}
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java
new file mode 100644
index 00000000000..4a518c5ca97
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.java
@@ -0,0 +1,11 @@
+public final class C implements kotlin.jvm.internal.KObject, Tr {
+ private final int v = 1;
+
+ @org.jetbrains.annotations.NotNull
+ public java.lang.Integer foo() { /* compiled code */ }
+
+ @org.jetbrains.annotations.NotNull
+ public java.lang.Integer getV() { /* compiled code */ }
+
+ public C() { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt
new file mode 100644
index 00000000000..274a682a4f6
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt
@@ -0,0 +1,12 @@
+// C
+
+trait Tr {
+ fun foo(): Any
+ val v: Any
+}
+
+class C: Tr {
+ override fun foo() = 1
+ override val v = 1
+}
+
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java
new file mode 100644
index 00000000000..c4eae18b754
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.java
@@ -0,0 +1,4 @@
+public final class _DefaultPackage {
+ @org.jetbrains.annotations.Nullable
+ public static final kotlin.Unit foo() { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt
new file mode 100644
index 00000000000..ac605d0a0ae
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt
@@ -0,0 +1,3 @@
+// _DefaultPackage
+
+fun foo(): Unit? = null
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java
new file mode 100644
index 00000000000..ea46f1f8b4d
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.java
@@ -0,0 +1,5 @@
+public final class C implements kotlin.jvm.internal.KObject, Base {
+ public void foo() { /* compiled code */ }
+
+ public C() { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt
new file mode 100644
index 00000000000..1efb58ec710
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt
@@ -0,0 +1,9 @@
+// C
+
+trait Base {
+ fun foo(): Any
+}
+
+class C : Base {
+ override fun foo(): Unit {}
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java
index 4bbf5fb52b9..c9e411d88d4 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.java
@@ -1,14 +1,11 @@
public final class Synthetic implements kotlin.jvm.internal.KObject {
private final void foo() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public Synthetic() { /* compiled code */ }
public final class Inner implements kotlin.jvm.internal.KObject {
- @org.jetbrains.annotations.NotNull
public final void test() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public Inner() { /* compiled code */ }
}
}
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java
index ebe1ccec524..466a27bd758 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.java
@@ -25,7 +25,6 @@ public interface Trait extends kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.Nullable
java.lang.String getNullableVar();
- @org.jetbrains.annotations.NotNull
void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p);
@org.jetbrains.annotations.NotNull
@@ -34,6 +33,5 @@ public interface Trait extends kotlin.jvm.internal.KObject {
@org.jetbrains.annotations.NotNull
java.lang.String getNotNullVar();
- @org.jetbrains.annotations.NotNull
void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p);
}
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java
new file mode 100644
index 00000000000..51f7748cedb
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.java
@@ -0,0 +1,5 @@
+public final class C implements kotlin.jvm.internal.KObject, Base {
+ public void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "t") kotlin.Unit t) { /* compiled code */ }
+
+ public C() { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt
new file mode 100644
index 00000000000..be4e460f616
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt
@@ -0,0 +1,9 @@
+// C
+
+trait Base {
+ fun foo(t: T): T
+}
+
+class C : Base {
+ override fun foo(t: Unit) {}
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java
new file mode 100644
index 00000000000..f1fe4fc2028
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.java
@@ -0,0 +1,3 @@
+public final class _DefaultPackage {
+ public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") kotlin.Unit s) { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt
new file mode 100644
index 00000000000..b417517b964
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt
@@ -0,0 +1,3 @@
+// _DefaultPackage
+
+fun foo(s: Unit) {}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java
new file mode 100644
index 00000000000..b2e287c1e78
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.java
@@ -0,0 +1,3 @@
+public final class _DefaultPackage {
+ public static final void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "s") java.lang.String s) { /* compiled code */ }
+}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt
new file mode 100644
index 00000000000..4d2cdda1da3
--- /dev/null
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt
@@ -0,0 +1,3 @@
+// _DefaultPackage
+
+fun foo(s: String) {}
\ No newline at end of file
diff --git a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java
index 49af58748db..7c58f38e1fa 100644
--- a/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java
+++ b/compiler/testData/asJava/lightClasses/nullabilityAnnotations/_DefaultPackage.java
@@ -9,7 +9,6 @@ public final class _DefaultPackage {
@org.jetbrains.annotations.NotNull
public static final java.lang.String getNotNullVar() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public static final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -17,7 +16,6 @@ public final class _DefaultPackage {
public static final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ }
@org.jetbrains.annotations.Nullable
- @org.jetbrains.annotations.NotNull
public static final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String v) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
@@ -30,7 +28,6 @@ public final class _DefaultPackage {
@org.jetbrains.annotations.Nullable
public static final java.lang.String getNullableVar() { /* compiled code */ }
- @org.jetbrains.annotations.NotNull
public static final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions
index 2afa0f4bfc8..bc3499991b5 100644
--- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions
+++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.instructions
@@ -14,14 +14,14 @@ L0:
2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } })
v(val b: Boolean) INIT: in: {} out: {b=D}
mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D}
- mark(1 < 2)
r(1) ->
r(2) ->
+ mark(1 < 2)
call(<, compareTo|, ) ->
jf(L2|)
- 3 mark({ use(b) })
- mark(use(b)) USE: in: {b=READ} out: {b=READ}
+ 3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ}
r(b) -> USE: in: {} out: {b=READ}
+ mark(use(b))
call(use, use|) ->
2 jmp(L3) USE: in: {} out: {}
L2:
diff --git a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values
index 886eac6e86c..9e8d37ccb96 100644
--- a/compiler/testData/cfg-variables/basic/IfWithUninitialized.values
+++ b/compiler/testData/cfg-variables/basic/IfWithUninitialized.values
@@ -9,18 +9,18 @@ fun foo() {
}
}
---------------------
-1 NEW()
-2 NEW()
-1 < 2 NEW(, )
-b NEW()
-use(b) NEW()
-{ use(b) } COPY
-true NEW()
-if (1 < 2) { use(b) } else { b = true } COPY
-{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } COPY
+1 : {<: Comparable} NEW()
+2 : Int NEW()
+1 < 2 : Boolean NEW(, )
+b : {<: Any?} NEW()
+use(b) : * NEW()
+{ use(b) } : * COPY
+true : Boolean NEW()
+if (1 < 2) { use(b) } else { b = true } : * COPY
+{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } : * COPY
=====================
== use ==
fun use(vararg a: Any?) = a
---------------------
-a NEW()
+a : {<: Array} NEW()
=====================
diff --git a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values
index 13de2c9986d..6b99c7aaf59 100644
--- a/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values
+++ b/compiler/testData/cfg-variables/basic/InitializedNotDeclared.values
@@ -6,5 +6,5 @@ class A {
val x: Int
}
---------------------
-1 NEW()
+1 : Int NEW()
=====================
diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions
index da8b9a71781..c1df1eb55e0 100644
--- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions
+++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.instructions
@@ -39,14 +39,14 @@ L3:
magic(x: Int) -> INIT: in: {x=D} out: {x=D}
w(x|) INIT: in: {x=D} out: {x=ID}
4 mark(val y = x + a use(a)) INIT: in: {x=ID} out: {x=ID}
- v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D}
- mark(x + a) INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
- r(x) -> USE: in: {a=READ} out: {a=READ, x=READ}
+ v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
+ r(x) -> INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ} out: {a=READ, x=READ}
r(a) ->
+ mark(x + a)
call(+, plus|, ) ->
- w(y|) INIT: in: {x=ID, y=D} out: {x=ID, y=ID}
- mark(use(a)) INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
- r(a) -> USE: in: {} out: {a=READ}
+ w(y|) INIT: in: {x=ID, y=D} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
+ r(a) -> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ}
+ mark(use(a))
call(use, use|) ->
L4:
3 INIT: in: {x=ID} out: {x=ID}
diff --git a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values
index c7195b6fb36..4c2009adf92 100644
--- a/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values
+++ b/compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.values
@@ -7,8 +7,8 @@ fun foo() {
}
}
---------------------
-1