Merge master into idea14

Conflicts:
	.idea/runConfigurations/All_Tests.xml
	idea/src/org/jetbrains/jet/plugin/conversion/copy/ConvertJavaCopyPastePostProcessor.kt
	idea/tests/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/AbstractJetExtractionTest.kt
	idea/tests/org/jetbrains/jet/shortenRefs/AbstractShortenRefsTest.kt
This commit is contained in:
Nikolay Krasko
2014-06-25 16:26:01 +04:00
978 changed files with 15161 additions and 4205 deletions
+1
View File
@@ -22,6 +22,7 @@
<value defaultName="moduleWithDependencies" />
</option>
<envs>
<env name="kotlin.tests.actually.compile" value="true" />
<env name="NO_FS_ROOTS_ACCESS_CHECK" value="true" />
</envs>
<patterns />
@@ -0,0 +1,5 @@
<root>
<item name='com.intellij.codeInsight.CodeInsightSettings com.intellij.codeInsight.CodeInsightSettings getInstance()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -2,4 +2,8 @@
<item name='com.intellij.lang.ASTNode java.lang.String getText()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.lang.SmartEnterProcessorWithFixers.FixEnterProcessor boolean doEnter(com.intellij.psi.PsiElement, com.intellij.psi.PsiFile, com.intellij.openapi.editor.Editor, boolean) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
+10
View File
@@ -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;
}
]]></proguard>
</else>
</if>
@@ -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.<String>emptySet());
generateAdditionalAnnotations(annotated, returnType, Collections.<String>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<String> annotationDescriptorsAlreadyPresent) {
private void generateAdditionalAnnotations(
@NotNull Annotated annotated,
@Nullable Type returnType,
@NotNull Set<String> 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;
@@ -722,7 +722,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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());
@@ -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<JvmMethodParameterSignature> 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());
}
}
}
@@ -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
@@ -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) {
@@ -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;
}
@@ -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);
}
@@ -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(),
@@ -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<PsiClass> 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<PsiTypeParameter, PsiType> substMap = new HashMap<PsiTypeParameter, PsiType>();
for (Map.Entry<JavaTypeParameter, JavaType> 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);
}
}
@@ -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<PsiClassType> 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<JavaTypeParameter, JavaType> convertSubstitutionMap(@NotNull Map<PsiTypeParameter, PsiType> psiMap) {
Map<JavaTypeParameter, JavaType> substitutionMap = new HashMap<JavaTypeParameter, JavaType>();
for (Map.Entry<PsiTypeParameter, PsiType> 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<JavaClassifierType> getSupertypes() {
@@ -39,31 +39,31 @@ public abstract class JavaTypeImpl<Psi extends PsiType> implements JavaType {
return psiType.accept(new PsiTypeVisitor<JavaTypeImpl<?>>() {
@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);
}
});
@@ -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));
}
}
@@ -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<JavaTypeParameter, JavaType> substitutionMap;
private final Map<JavaTypeParameter, JavaType> substitutionMap;
public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor) {
this.psiSubstitutor = psiSubstitutor;
}
public JavaTypeSubstitutorImpl(@NotNull PsiSubstitutor psiSubstitutor, @NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
this(psiSubstitutor);
public JavaTypeSubstitutorImpl(@NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
this.substitutionMap = substitutionMap;
}
@NotNull
public static JavaTypeSubstitutor create(@NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
Map<PsiTypeParameter, PsiType> psiMap = new HashMap<PsiTypeParameter, PsiType>();
for (Map.Entry<JavaTypeParameter, JavaType> 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<JavaTypeParameter, JavaType> substMap = new HashMap<JavaTypeParameter, JavaType>();
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<JavaTypeParameter, JavaType> substMap) {
List<JavaTypeParameter> 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<JavaClassifierType> 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<JavaTypeParameter, JavaType> getSubstitutionMap() {
if (substitutionMap == null) {
Map<PsiTypeParameter, PsiType> psiMap = psiSubstitutor.getSubstitutionMap();
substitutionMap = new HashMap<JavaTypeParameter, JavaType>();
for (Map.Entry<PsiTypeParameter, PsiType> 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;
}
}
}
@@ -44,8 +44,8 @@ public class CheckerTestUtil {
public int compare(@NotNull Diagnostic o1, @NotNull Diagnostic o2) {
List<TextRange> ranges1 = o1.getTextRanges();
List<TextRange> 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("(<!\\w+(,\\s*\\w+)*!>)|(<!>)");
@@ -439,41 +439,39 @@ public class CheckerTestUtil {
}
}
private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(Collection<Diagnostic> diagnostics) {
List<Diagnostic> list = Lists.newArrayList(diagnostics);
Collections.sort(list, DIAGNOSTIC_COMPARATOR);
List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
DiagnosticDescriptor currentDiagnosticDescriptor = null;
for (Diagnostic diagnostic : list) {
List<TextRange> textRanges = diagnostic.getTextRanges();
@NotNull
private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(@NotNull Collection<Diagnostic> diagnostics) {
LinkedListMultimap<TextRange, Diagnostic> 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<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
for (TextRange range : diagnosticsGroupedByRanges.keySet()) {
diagnosticDescriptors.add(
new DiagnosticDescriptor(range.getStartOffset(), range.getEndOffset(), diagnosticsGroupedByRanges.get(range)));
}
Collections.sort(diagnosticDescriptors, new Comparator<DiagnosticDescriptor>() {
@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<Diagnostic> diagnostics = Lists.newArrayList();
private final List<Diagnostic> diagnostics;
DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) {
DiagnosticDescriptor(int start, int end, List<Diagnostic> 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<String> getDiagnosticTypeStrings() {
File diff suppressed because it is too large Load Diff
@@ -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<JetElement> 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<JetElement> collectUnreachableCode() {
Collection<JetElement> 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<JetElement> reachableElements = Sets.newHashSet();
Set<JetElement> 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);
}
////////////////////////////////////////////////////////////////////////////////
@@ -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
}
@@ -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<JetElement>
fun getUnreachableTextRanges(element: JetElement): List<TextRange>
}
class UnreachableCodeImpl(
private val reachableElements: Set<JetElement>,
private val unreachableElements: Set<JetElement>
) : 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<TextRange> {
return if (element.hasChildrenInSet(reachableElements)) {
element.getLeavesOrReachableChildren().removeReachableElementsWithMeaninglessSiblings().mergeAdjacentTextRanges()
}
else {
listOf(element.getTextRange()!!)
}
}
private fun JetElement.hasChildrenInSet(set: Set<JetElement>): Boolean {
return PsiTreeUtil.collectElements(this) { it != this }.any { it in set }
}
private fun JetElement.getLeavesOrReachableChildren(): List<PsiElement> {
val children = ArrayList<PsiElement>()
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<PsiElement>.removeReachableElementsWithMeaninglessSiblings(): List<PsiElement> {
fun PsiElement.isMeaningless() = this is PsiWhiteSpace
|| this.getNode()?.getElementType() == JetTokens.COMMA
|| this is PsiComment
val childrenToRemove = HashSet<PsiElement>()
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<PsiElement>.mergeAdjacentTextRanges(): List<TextRange> {
val result = ArrayList<TextRange>()
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
}
}
@@ -45,7 +45,7 @@ public interface Pseudocode {
List<Instruction> getReversedInstructions();
@NotNull
List<Instruction> getDeadInstructions();
List<Instruction> getInstructionsIncludingDeadCode();
@NotNull
SubroutineExitInstruction getExitInstruction();
@@ -183,30 +183,10 @@ public class PseudocodeImpl implements Pseudocode {
return Lists.newArrayList(traversedInstructions);
}
//for tests only
@NotNull
public List<Instruction> getAllInstructions() {
return mutableInstructionList;
}
@Override
@NotNull
public List<Instruction> getDeadInstructions() {
List<Instruction> 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<Instruction> getInstructionsIncludingDeadCode() {
return mutableInstructionList;
}
//for tests only
@@ -390,7 +370,7 @@ public class PseudocodeImpl implements Pseudocode {
Set<Instruction> 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);
}
@@ -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>): 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>): 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>): TypePredicate =
when (predicates.size) {
0 -> AllTypes
1 -> predicates.first()
else -> ForAllTypes(predicates.toList())
}
fun or(predicates: Collection<TypePredicate>): 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 <T> TypePredicate.expectedTypeFor(keys: Iterable<T>): Map<T, TypePredicate> =
@@ -23,14 +23,16 @@ import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue
public trait Instruction {
public var owner: Pseudocode
public val previousInstructions: MutableCollection<Instruction>
public val previousInstructions: Collection<Instruction>
public val nextInstructions: Collection<Instruction>
public val dead: Boolean
public val lexicalScope: LexicalScope
public val inputValues: List<PseudoValue>
public fun getCopies(): Collection<Instruction>
public val copies: Collection<Instruction>
public fun accept(visitor: InstructionVisitor)
public fun <R> accept(visitor: InstructionVisitorWithResult<R>): R
@@ -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<Instruction>()
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<InstructionImpl>? = null
override val copies: Collection<Instruction>
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<Instruction> = LinkedHashSet()
override val inputValues: List<PseudoValue> = Collections.emptyList()
override fun getCopies(): Collection<Instruction> {
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<PseudoValue> = Collections.emptyList()
}
@@ -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<JetFunctionLiteral>())?.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<PseudoValue, List<Instruction>> {
val map = HashMap<PseudoValue, MutableList<Instruction>>()
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<PseudoValue, List<Instruction>>,
bindingContext: BindingContext
): TypePredicate {
val typePredicates = HashSet<TypePredicate?>()
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())
}
@@ -27,6 +27,7 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
private final E psiElement;
private final DiagnosticFactoryWithPsiElement<E, ?> factory;
private final Severity severity;
private List<TextRange> textRanges;
public AbstractDiagnostic(@NotNull E psiElement,
@NotNull DiagnosticFactoryWithPsiElement<E, ?> factory,
@@ -63,6 +64,9 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
@Override
@NotNull
public List<TextRange> getTextRanges() {
if (textRanges != null) {
return textRanges;
}
return getFactory().getTextRanges(this);
}
@@ -71,4 +75,10 @@ public abstract class AbstractDiagnostic<E extends PsiElement> implements Parame
if (!getFactory().isValid(this)) return false;
return true;
}
@NotNull
public Diagnostic setTextRanges(@NotNull List<TextRange> textRanges) {
this.textRanges = textRanges;
return this;
}
}
@@ -30,7 +30,7 @@ public abstract class DiagnosticFactoryWithPsiElement<E extends PsiElement, D ex
}
protected List<TextRange> getTextRanges(ParametrizedDiagnostic<E> diagnostic) {
return positioningStrategy.mark(diagnostic.getPsiElement());
return positioningStrategy.markDiagnostic(diagnostic);
}
protected boolean isValid(ParametrizedDiagnostic<E> diagnostic) {
@@ -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<JetElement> UNREACHABLE_CODE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<JetElement, List<TextRange>> UNREACHABLE_CODE = DiagnosticFactory1.create(
WARNING, PositioningStrategies.markTextRangesFromDiagnostic(new Function1<Diagnostic, List<TextRange>>() {
@Override
public List<TextRange> invoke(Diagnostic diagnostic) {
return UNREACHABLE_CODE.cast(diagnostic).getA();
}
}));
DiagnosticFactory0<JetVariableDeclaration> VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, NAME_IDENTIFIER);
@@ -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<PsiElement> markTextRangesFromDiagnostic(
@NotNull final Function1<Diagnostic, List<TextRange>> getTextRanges
) {
return new PositioningStrategy<PsiElement>() {
@NotNull
@Override
public List<TextRange> markDiagnostic(@NotNull ParametrizedDiagnostic<? extends PsiElement> diagnostic) {
return getTextRanges.invoke(diagnostic);
}
};
}
private PositioningStrategies() {
}
}
@@ -27,7 +27,12 @@ import java.util.List;
public class PositioningStrategy<E extends PsiElement> {
@NotNull
public List<TextRange> mark(@NotNull E element) {
public List<TextRange> markDiagnostic(@NotNull ParametrizedDiagnostic<? extends E> diagnostic) {
return mark(diagnostic.getPsiElement());
}
@NotNull
protected List<TextRange> mark(@NotNull E element) {
return markElement(element);
}
@@ -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");
@@ -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;
}
@@ -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();
}
@@ -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, D> R accept(@NotNull JetVisitor<R, D> visitor, D data) {
return visitor.visitDoWhileExpression(this, data);
}
@Nullable
@IfNotParsed
public PsiElement getWhileKeywordElement() {
//noinspection ConstantConditions
return findChildByType(JetTokens.WHILE_KEYWORD);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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
@@ -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.
@@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.JetLanguage;
import java.io.IOException;
public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
public static final int STUB_VERSION = 28;
public static final int STUB_VERSION = 29;
public JetFileElementType() {
super("jet.FILE", JetLanguage.INSTANCE);
@@ -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<StubT extends StubElement, PsiT extends JetElementImplStub<?>> extends IStubElementType<StubT, PsiT> {
@SuppressWarnings("unchecked")
private static final Class<? extends PsiElement>[] ALWAYS_CREATE_STUB_FOR = new Class[] { JetClass.class, JetObjectDeclaration.class };
@NotNull
private final Constructor<PsiT> byNodeConstructor;
@NotNull
@@ -93,11 +91,14 @@ public abstract class JetStubElementType<StubT extends StubElement, PsiT extends
@Override
public boolean shouldCreateStub(ASTNode node) {
PsiElement psi = node.getPsi();
if (ArrayUtil.contains(psi.getClass(), (Object[]) ALWAYS_CREATE_STUB_FOR)) {
if (psi instanceof JetClassOrObject) {
return true;
}
if (psi instanceof JetDeclaration) {
return shouldCreateStubForDeclaration((JetDeclaration) psi);
if (psi instanceof JetFunction) {
return !((JetFunction) psi).isLocal();
}
if (psi instanceof JetProperty) {
return !((JetProperty) psi).isLocal();
}
return createStubDependingOnParent(node);
}
@@ -114,45 +115,6 @@ public abstract class JetStubElementType<StubT extends StubElement, PsiT extends
return false;
}
private static boolean shouldCreateStubForDeclaration(@NotNull JetDeclaration declaration) {
// Do not create stubs inside function literals
//noinspection unchecked
if (PsiTreeUtil.getParentOfType(declaration, JetFunctionLiteral.class, false, ALWAYS_CREATE_STUB_FOR) != null) {
return false;
}
// Don't create stubs if declaration is inside function or property accessor with block
//noinspection unchecked
JetBlockExpression blockExpression =
PsiTreeUtil.getParentOfType(declaration, JetBlockExpression.class, false, ALWAYS_CREATE_STUB_FOR);
if (blockExpression != null) {
return false;
}
// Don't create stubs if declaration is inside other declaration with expression initializer
Class<? extends PsiElement>[] 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
@@ -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 <code>a(), a[i], a.b.c(), +a, a + b, (a()), a(): Int, @label a()</code>
@@ -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<JetDeclarationWithBody>())]
val containingFunctionDescriptor = DescriptorUtils.getParentOfType(declarationDescriptor, javaClass<FunctionDescriptor>(), false)
if (containingFunctionDescriptor == null) return null
return stream(containingFunctionDescriptor) { DescriptorUtils.getParentOfType(it, javaClass<FunctionDescriptor>()) }
.dropWhile { it is AnonymousFunctionDescriptor }
.firstOrNull()
}
@@ -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);
}
};
@@ -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
@@ -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));
}
}
@@ -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);
}
@@ -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) {
@@ -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) {
@@ -102,18 +102,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
assert candidate.getDescriptor() instanceof VariableDescriptor;
boolean hasReceiver = candidate.getReceiverArgument().exists();
Call variableCall = stripCallArguments(task);
Call variableCall = stripCallArguments(task.call);
ResolutionCandidate<CallableDescriptor> variableCandidate = getVariableCallCandidate(candidate, variableCall);
if (!hasReceiver) {
CallCandidateResolutionContext<CallableDescriptor> 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<CallableDescriptor> contextWithReceiver = createContextWithChainedTrace(
candidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
variableCandidate, variableCall, candidateTrace, task, ReceiverValue.NO_RECEIVER);
Call variableCallWithoutReceiver = stripReceiver(variableCall);
ResolutionCandidate<CallableDescriptor> 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<CallableDescriptor> contextWithoutReceiver = createContextWithChainedTrace(
@@ -131,8 +135,22 @@ public class CallTransformer<D extends CallableDescriptor, F extends D> {
return CallCandidateResolutionContext.create(resolvedCall, task, chainedTrace, task.tracing, call, receiverValue);
}
private Call stripCallArguments(@NotNull ResolutionTask<CallableDescriptor, FunctionDescriptor> task) {
return new DelegatingCall(task.call) {
@NotNull
private ResolutionCandidate<CallableDescriptor> getVariableCallCandidate(
@NotNull ResolutionCandidate<CallableDescriptor> 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<D extends CallableDescriptor, F extends D> {
public JetTypeArgumentList getTypeArgumentList() {
return null;
}
@NotNull
@Override
public JetElement getCallElement() {
JetExpression calleeExpression = getCalleeExpression();
assert calleeExpression != null : "No callee expression: " + getCallElement().getText();
return calleeExpression;
}
};
}
@@ -735,7 +735,7 @@ public class CandidateResolver {
Set<JetType> possibleTypes = dataFlowInfoForArgument.getPossibleTypes(dataFlowValue);
if (possibleTypes.isEmpty()) return type;
return TypeUtils.intersect(JetTypeChecker.INSTANCE, possibleTypes);
return TypeUtils.intersect(JetTypeChecker.DEFAULT, possibleTypes);
}
private <D extends CallableDescriptor> ValueArgumentsCheckingResult checkAllValueArguments(
@@ -859,7 +859,7 @@ public class CandidateResolver {
List<JetType> 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;
}
}
@@ -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;
}
@@ -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;
}
}
@@ -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);
}
@@ -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<ReceiverParameterDescriptor> 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;
@@ -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));
}
@@ -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) {
@@ -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<FunctionDescriptor> resolutionResults =
components.callResolver.resolveCallWithGivenName(newContext, call, operationSign, OperatorConventions.EQUALS);
@@ -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));
}
}
@@ -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));
}
}
@@ -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;
}
@@ -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));
@@ -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);
}
@@ -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);
@@ -80,7 +80,7 @@ public class MainFunctionDetector {
List<TypeProjection> 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;
}
}
@@ -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 <K, V> boolean processRewrite(WritableSlice<K, V> 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));
@@ -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
@@ -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
@@ -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 = "<set-?>", 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 = "<set-?>") 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 */ }
}
@@ -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 {
@@ -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 */ }
}
@@ -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 */ }
}
@@ -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 */ }
}
@@ -0,0 +1,12 @@
// C
trait Tr {
fun foo(): Any
val v: Any
}
class C: Tr {
override fun foo() = 1
override val v = 1
}
@@ -0,0 +1,4 @@
public final class _DefaultPackage {
@org.jetbrains.annotations.Nullable
public static final kotlin.Unit foo() { /* compiled code */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(): Unit? = null
@@ -0,0 +1,5 @@
public final class C implements kotlin.jvm.internal.KObject, Base {
public void foo() { /* compiled code */ }
public C() { /* compiled code */ }
}
@@ -0,0 +1,9 @@
// C
trait Base {
fun foo(): Any
}
class C : Base {
override fun foo(): Unit {}
}
@@ -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 */ }
}
}
@@ -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 = "<set-?>", 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 = "<set-?>") java.lang.String p);
}
@@ -0,0 +1,5 @@
public final class C implements kotlin.jvm.internal.KObject, Base<kotlin.Unit> {
public void foo(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "t") kotlin.Unit t) { /* compiled code */ }
public C() { /* compiled code */ }
}
@@ -0,0 +1,9 @@
// C
trait Base<T> {
fun foo(t: T): T
}
class C : Base<Unit> {
override fun foo(t: Unit) {}
}
@@ -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 */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(s: Unit) {}
@@ -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 */ }
}
@@ -0,0 +1,3 @@
// _DefaultPackage
fun foo(s: String) {}
@@ -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 = "<set-?>") 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 = "<set-?>", type = "?") java.lang.String p) { /* compiled code */ }
@org.jetbrains.annotations.NotNull
@@ -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) -> <v0>
r(2) -> <v1>
mark(1 < 2)
call(<, compareTo|<v0>, <v1>) -> <v2>
jf(L2|<v2>)
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) -> <v3> USE: in: {} out: {b=READ}
mark(use(b))
call(use, use|<v3>) -> <v4>
2 jmp(L3) USE: in: {} out: {}
L2:
@@ -9,18 +9,18 @@ fun foo() {
}
}
---------------------
1 <v0> NEW()
2 <v1> NEW()
1 < 2 <v2> NEW(<v0>, <v1>)
b <v3> NEW()
use(b) <v4> NEW(<v3>)
{ use(b) } <v4> COPY
true <v5> NEW()
if (1 < 2) { use(b) } else { b = true } <v4> COPY
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v4> COPY
1 <v0>: {<: Comparable<Int>} NEW()
2 <v1>: Int NEW()
1 < 2 <v2>: Boolean NEW(<v0>, <v1>)
b <v3>: {<: Any?} NEW()
use(b) <v4>: * NEW(<v3>)
{ use(b) } <v4>: * COPY
true <v5>: Boolean NEW()
if (1 < 2) { use(b) } else { b = true } <v4>: * COPY
{ val b: Boolean if (1 < 2) { use(b) } else { b = true } } <v4>: * COPY
=====================
== use ==
fun use(vararg a: Any?) = a
---------------------
a <v1> NEW()
a <v1>: {<: Array<Any?>} NEW()
=====================
@@ -6,5 +6,5 @@ class A {
val x: Int
}
---------------------
1 <v1> NEW()
1 <v1>: Int NEW()
=====================
@@ -39,14 +39,14 @@ L3:
magic(x: Int) -> <v0> INIT: in: {x=D} out: {x=D}
w(x|<v0>) 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) -> <v1> 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) -> <v1> INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ} out: {a=READ, x=READ}
r(a) -> <v2>
mark(x + a)
call(+, plus|<v1>, <v2>) -> <v3>
w(y|<v3>) 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) -> <v4> USE: in: {} out: {a=READ}
w(y|<v3>) INIT: in: {x=ID, y=D} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
r(a) -> <v4> INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {} out: {a=READ}
mark(use(a))
call(use, use|<v4>) -> <v5>
L4:
3 <END> INIT: in: {x=ID} out: {x=ID}
@@ -7,8 +7,8 @@ fun foo() {
}
}
---------------------
1 <v0> NEW()
{ (x: Int) -> val y = x + a use(a) } <v1> NEW()
1 <v0>: Int NEW()
{ (x: Int) -> val y = x + a use(a) } <v1>: {<: (Int) -> Array<Any?>} NEW()
=====================
== anonymous_0 ==
{ (x: Int) ->
@@ -16,15 +16,15 @@ fun foo() {
use(a)
}
---------------------
x <v1> NEW()
a <v2> NEW()
x + a <v3> NEW(<v1>, <v2>)
a <v4> NEW()
use(a) <v5> NEW(<v4>)
val y = x + a use(a) <v5> COPY
x <v1>: Int NEW()
a <v2>: Int NEW()
x + a <v3>: Int NEW(<v1>, <v2>)
a <v4>: {<: Any?} NEW()
use(a) <v5>: {<: Array<Any?>} NEW(<v4>)
val y = x + a use(a) <v5>: {<: Array<Any?>} COPY
=====================
== use ==
fun use(vararg a: Any?) = a
---------------------
a <v1> NEW()
a <v1>: {<: Array<Any?>} NEW()
=====================
@@ -6,10 +6,10 @@ fun foo() {
42
}
---------------------
1 <v0> NEW()
2 <v1> NEW()
42 <v2> NEW()
{ val a = 1 val b: Int b = 2 42 } <v2> COPY
1 <v0>: Int NEW()
2 <v1>: Int NEW()
42 <v2>: * NEW()
{ val a = 1 val b: Int b = 2 42 } <v2>: * COPY
=====================
== bar ==
fun bar(foo: Foo) {
@@ -18,13 +18,13 @@ fun bar(foo: Foo) {
42
}
---------------------
foo <v1> NEW()
c <v2> NEW(<v1>)
foo.c <v2> COPY
foo <v3> NEW()
2 <v4> NEW()
42 <v5> NEW()
{ foo.c foo.c = 2 42 } <v5> COPY
foo <v1>: {<: Foo} NEW()
c <v2>: * NEW(<v1>)
foo.c <v2>: * COPY
foo <v3>: {<: Foo} NEW()
2 <v4>: Int NEW()
42 <v5>: * NEW()
{ foo.c foo.c = 2 42 } <v5>: * COPY
=====================
== Foo ==
trait Foo {
@@ -11,14 +11,14 @@ L0:
2 mark({ var a = 1 use(a) a = 2 use(a) })
v(var a = 1) INIT: in: {} out: {a=D}
r(1) -> <v0> INIT: in: {a=D} out: {a=D}
w(a|<v0>) INIT: in: {a=D} out: {a=ID}
mark(use(a)) INIT: in: {a=ID} out: {a=ID} USE: in: {a=READ} out: {a=READ}
r(a) -> <v1> USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ}
w(a|<v0>) INIT: in: {a=D} out: {a=ID} USE: in: {a=READ} out: {a=READ}
r(a) -> <v1> INIT: in: {a=ID} out: {a=ID} USE: in: {a=WRITTEN_AFTER_READ} out: {a=READ}
mark(use(a))
call(use, use|<v1>) -> <v2>
r(2) -> <v3> USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
w(a|<v3>) USE: in: {a=READ} out: {a=WRITTEN_AFTER_READ}
mark(use(a)) USE: in: {a=READ} out: {a=READ}
r(a) -> <v4> USE: in: {} out: {a=READ}
mark(use(a))
call(use, use|<v4>) -> <v5>
L1:
1 <END> INIT: in: {} out: {}
@@ -6,13 +6,13 @@ fun foo() {
use(a)
}
---------------------
1 <v0> NEW()
a <v1> NEW()
use(a) <v2> NEW(<v1>)
2 <v3> NEW()
a <v4> NEW()
use(a) <v5> NEW(<v4>)
{ var a = 1 use(a) a = 2 use(a) } <v5> COPY
1 <v0>: Int NEW()
a <v1>: Int NEW()
use(a) <v2>: * NEW(<v1>)
2 <v3>: Int NEW()
a <v4>: Int NEW()
use(a) <v5>: * NEW(<v4>)
{ var a = 1 use(a) a = 2 use(a) } <v5>: * COPY
=====================
== bar ==
fun bar() {
@@ -20,10 +20,10 @@ fun bar() {
b = 3
}
---------------------
3 <v0> NEW()
3 <v0>: Int NEW()
=====================
== use ==
fun use(a: Int) = a
---------------------
a <v1> NEW()
a <v1>: Int NEW()
=====================
@@ -32,16 +32,16 @@ L3:
magic(x: Int) -> <v0> INIT: in: {x=D} out: {x=D}
w(x|<v0>) INIT: in: {x=D} out: {x=ID}
3 mark(sum(x - 1) + x) INIT: in: {x=ID} out: {x=ID}
mark(sum(x - 1) + x)
mark(sum(x - 1))
magic(sum) -> <v1> USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ}
r(sum|<v1>) -> <v2> USE: in: {x=READ} out: {sum=READ, x=READ}
mark(x - 1)
r(x) -> <v3>
r(1) -> <v4>
mark(x - 1)
call(-, minus|<v3>, <v4>) -> <v5>
mark(sum(x - 1))
call(sum, invoke|<v2>, <v5>) -> <v6> USE: in: {x=READ} out: {x=READ}
r(x) -> <v7> USE: in: {} out: {x=READ}
mark(sum(x - 1) + x)
call(+, plus|<v6>, <v7>) -> <v8>
L4:
2 <END>
@@ -127,10 +127,10 @@ class TestOther {
L0:
1 <START> INIT: in: {} out: {}
v(val x: Int = x + 1) INIT: in: {} out: {x=D}
mark(x + 1) INIT: in: {x=D} out: {x=D}
magic(x) -> <v0> USE: in: {x=READ} out: {x=READ}
magic(x) -> <v0> INIT: in: {x=D} out: {x=D} USE: in: {x=READ} out: {x=READ}
r(x|<v0>) -> <v1> USE: in: {} out: {x=READ}
r(1) -> <v2>
mark(x + 1)
call(+, plus|<v1>, <v2>) -> <v3>
w(x|<v3>) INIT: in: {x=D} out: {x=ID}
L1:
@@ -5,21 +5,21 @@ class TestFunctionLiteral {
}
}
---------------------
{ (x: Int) -> sum(x - 1) + x } <v0> NEW()
{ (x: Int) -> sum(x - 1) + x } <v0>: {<: (Int) -> Int} NEW()
=====================
== anonymous_0 ==
{ (x: Int) ->
sum(x - 1) + x
}
---------------------
sum <v2> NEW(<v1>)
x <v3> NEW()
1 <v4> NEW()
x - 1 <v5> NEW(<v3>, <v4>)
sum(x - 1) <v6> NEW(<v2>, <v5>)
x <v7> NEW()
sum(x - 1) + x <v8> NEW(<v6>, <v7>)
sum(x - 1) + x <v8> COPY
sum <v2>: {<: (Int) -> Int} NEW(<v1>)
x <v3>: Int NEW()
1 <v4>: Int NEW()
x - 1 <v5>: Int NEW(<v3>, <v4>)
sum(x - 1) <v6>: Int NEW(<v2>, <v5>)
x <v7>: Int NEW()
sum(x - 1) + x <v8>: Int NEW(<v6>, <v7>)
sum(x - 1) + x <v8>: Int COPY
=====================
== A ==
open class A(val a: A)
@@ -37,23 +37,23 @@ class TestObjectLiteral {
}
}
---------------------
obj <v1> NEW(<v0>)
obj <v3> NEW(<v2>)
object: A(obj) { { val x = obj } fun foo() { val y = obj } } <v4> NEW()
obj <v1>: * NEW(<v0>)
obj <v3>: {<: A} NEW(<v2>)
object: A(obj) { { val x = obj } fun foo() { val y = obj } } <v4>: {<: A} NEW()
=====================
== foo ==
fun foo() {
val y = obj
}
---------------------
obj <v1> NEW(<v0>)
obj <v1>: {<: A} NEW(<v0>)
=====================
== TestOther ==
class TestOther {
val x: Int = x + 1
}
---------------------
x <v1> NEW(<v0>)
1 <v2> NEW()
x + 1 <v3> NEW(<v1>, <v2>)
x <v1>: Int NEW(<v0>)
1 <v2>: Int NEW()
x + 1 <v3>: Int NEW(<v1>, <v2>)
=====================
@@ -15,9 +15,9 @@ L0:
2 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) })
v(val b: Boolean) INIT: in: {} out: {b=D}
mark(if (1 < 2) { b = false } else { b = true }) INIT: in: {b=D} out: {b=D}
mark(1 < 2)
r(1) -> <v0>
r(2) -> <v1>
mark(1 < 2)
call(<, compareTo|<v0>, <v1>) -> <v2>
jf(L2|<v2>)
3 mark({ b = false })
@@ -29,10 +29,10 @@ L2:
r(true) -> <v4> USE: in: {b=WRITTEN_AFTER_READ} out: {b=WRITTEN_AFTER_READ}
w(b|<v4>) INIT: in: {b=D} out: {b=ID} USE: in: {b=READ} out: {b=WRITTEN_AFTER_READ}
L3:
2 mark(use(b)) INIT: in: {b=ID} out: {b=ID}
error(use, No resolved call) USE: in: {b=READ} out: {b=READ}
2 error(use, No resolved call) INIT: in: {b=ID} out: {b=ID} USE: in: {b=READ} out: {b=READ}
r(b) -> <v5> USE: in: {} out: {b=READ}
error(use, No resolved call)
mark(use(b))
magic(use(b)|<v5>) -> <v6>
L1:
1 <END> INIT: in: {} out: {}
@@ -10,12 +10,12 @@ fun foo() {
use(b)
}
---------------------
1 <v0> NEW()
2 <v1> NEW()
1 < 2 <v2> NEW(<v0>, <v1>)
false <v3> NEW()
true <v4> NEW()
b <v5> NEW()
use(b) <v6> NEW(<v5>)
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v6> COPY
1 <v0>: {<: Comparable<Int>} NEW()
2 <v1>: Int NEW()
1 < 2 <v2>: Boolean NEW(<v0>, <v1>)
false <v3>: Boolean NEW()
true <v4>: Boolean NEW()
b <v5>: * NEW()
use(b) <v6>: * NEW(<v5>)
{ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) } <v6>: * COPY
=====================

Some files were not shown because too many files have changed in this diff Show More